From 418633a990a11c34b97df85eff3847ff03e611aa Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 19 Nov 2010 12:52:42 +0800 Subject: [PATCH 001/768] Changing version to 0.9 --- boost/network/version.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boost/network/version.hpp b/boost/network/version.hpp index 3d296e27c..f22fb8628 100644 --- a/boost/network/version.hpp +++ b/boost/network/version.hpp @@ -10,7 +10,7 @@ #include #define BOOST_NETLIB_VERSION_MAJOR 0 -#define BOOST_NETLIB_VERSION_MINOR 8 +#define BOOST_NETLIB_VERSION_MINOR 9 #define BOOST_NETLIB_VERSION_INCREMENT 0 #ifndef BOOST_NETLIB_VERSION From 1c2a85ff82f8f1fcb6fc8a4c20909453f1bcb017 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 19 Nov 2010 12:54:51 +0800 Subject: [PATCH 002/768] Docs version from 0.8 to 0.9 --- libs/network/doc/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/network/doc/conf.py b/libs/network/doc/conf.py index 800daea6e..b15c462d9 100644 --- a/libs/network/doc/conf.py +++ b/libs/network/doc/conf.py @@ -54,9 +54,9 @@ # built documents. # # The short X.Y version. -version = '0.8' +version = '0.9' # The full version, including alpha/beta/rc tags. -release = '0.8' +release = '0.9' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From a418cf4a7e57808a7c2e11d98501ee4c03072515 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 19 Nov 2010 12:56:45 +0800 Subject: [PATCH 003/768] Adding server tag and is_server trait. --- .../protocol/http/support/is_server.hpp | 28 +++++++++++++++++++ boost/network/protocol/http/tags.hpp | 5 ++-- 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 boost/network/protocol/http/support/is_server.hpp diff --git a/boost/network/protocol/http/support/is_server.hpp b/boost/network/protocol/http/support/is_server.hpp new file mode 100644 index 000000000..865af3812 --- /dev/null +++ b/boost/network/protocol/http/support/is_server.hpp @@ -0,0 +1,28 @@ +#ifndef BOOST_NETWORK_PROTOCOL_SUPPORT_IS_SERVER_HPP_20101118 +#define BOOST_NETWORK_PROTOCOL_SUPPORT_IS_SERVER_HPP_20101118 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +namespace boost { namespace network { namespace http { + + template + struct is_server : + is_base_of< + tags::server, + Tag + > + {}; + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_SUPPORT_IS_SERVER_HPP_20101118 */ diff --git a/boost/network/protocol/http/tags.hpp b/boost/network/protocol/http/tags.hpp index 76974eb52..9803c840f 100644 --- a/boost/network/protocol/http/tags.hpp +++ b/boost/network/protocol/http/tags.hpp @@ -13,6 +13,7 @@ namespace boost { namespace network { namespace http { namespace tags { struct http {}; struct keepalive {}; struct simple {}; + struct server {}; using namespace boost::network::tags; @@ -25,8 +26,8 @@ namespace boost { namespace network { namespace http { namespace tags { typedef mpl::vector http_keepalive_8bit_udp_resolve_tags; typedef mpl::vector http_async_8bit_udp_resolve_tags; typedef mpl::vector http_async_8bit_tcp_resolve_tags; - typedef mpl::vector http_server_tags; - typedef mpl::vector http_async_server_tags; + typedef mpl::vector http_server_tags; + typedef mpl::vector http_async_server_tags; BOOST_NETWORK_DEFINE_TAG(http_default_8bit_tcp_resolve); BOOST_NETWORK_DEFINE_TAG(http_default_8bit_udp_resolve); From 24894496e0f14512fb1f0c342ee2d4a7a9e6217b Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 19 Nov 2010 12:57:52 +0800 Subject: [PATCH 004/768] WIP: Isolating ServerRequest Concept. --- boost/network/protocol/http/impl/request.hpp | 24 ++++++-- .../protocol/http/message/modifiers/body.hpp | 18 ++++++ .../http/message/modifiers/destination.hpp | 19 ++++++ .../http/message/modifiers/headers.hpp | 15 +++++ .../http/message/modifiers/method.hpp | 29 +++++++++ .../http/message/modifiers/source.hpp | 16 +++++ .../protocol/http/message/wrappers/helper.hpp | 1 + .../protocol/http/message/wrappers/method.hpp | 43 ++++++++++++++ .../network/protocol/http/request_concept.hpp | 59 ++++++++++++++----- boost/network/protocol/http/traits.hpp | 2 +- 10 files changed, 205 insertions(+), 21 deletions(-) create mode 100644 boost/network/protocol/http/message/modifiers/method.hpp create mode 100644 boost/network/protocol/http/message/wrappers/method.hpp diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index 654670319..6129203a9 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -22,6 +22,9 @@ #include #include +#include +#include + #include namespace boost { namespace network { namespace http { @@ -115,9 +118,12 @@ namespace boost { namespace network { namespace http { * basic_request template above to be * primarily and be solely a POD for performance * reasons. + * + * Reality check: This is not a POD because it contains a non-POD + * member, the headers vector. :( */ template - struct pod_request_base { + struct not_quite_pod_request_base { typedef Tag tag; typedef typename string::type string_type; typedef typename vector:: @@ -133,7 +139,7 @@ namespace boost { namespace network { namespace http { mutable vector_type headers; mutable string_type body; - void swap(pod_request_base & r) const { + void swap(not_quite_pod_request_base & r) const { using std::swap; swap(method, r.method); swap(source, r.source); @@ -146,10 +152,20 @@ namespace boost { namespace network { namespace http { }; template <> - struct basic_request : pod_request_base {}; + struct basic_request + : not_quite_pod_request_base + {}; template <> - struct basic_request : pod_request_base {}; + struct basic_request + : not_quite_pod_request_base + {}; + + template + struct ServerRequest; + + BOOST_CONCEPT_ASSERT((ServerRequest >)); + BOOST_CONCEPT_ASSERT((ServerRequest >)); template inline void swap(basic_request & lhs, basic_request & rhs) { diff --git a/boost/network/protocol/http/message/modifiers/body.hpp b/boost/network/protocol/http/message/modifiers/body.hpp index 9a0f94c2c..71f69a4f5 100644 --- a/boost/network/protocol/http/message/modifiers/body.hpp +++ b/boost/network/protocol/http/message/modifiers/body.hpp @@ -17,6 +17,9 @@ namespace boost { namespace network { namespace http { template struct basic_response; + template + struct basic_request; + namespace impl { template @@ -29,6 +32,11 @@ namespace boost { namespace network { namespace http { response.body(future); } + template + void body(basic_request & request, T const & value, tags::server const &) { + request.body = value; + } + } template @@ -39,6 +47,16 @@ namespace boost { namespace network { namespace http { impl::body(response, value, is_async()); } + template + struct ServerRequest; + + template + inline BOOST_CONCEPT_REQUIRES(((ServerRequest >)), + (void)) + body(basic_request & request, T const & value) { + impl::body(request, value, Tag()); + } + } // namespace http namespace impl { diff --git a/boost/network/protocol/http/message/modifiers/destination.hpp b/boost/network/protocol/http/message/modifiers/destination.hpp index 010b0896e..b54fb17c0 100644 --- a/boost/network/protocol/http/message/modifiers/destination.hpp +++ b/boost/network/protocol/http/message/modifiers/destination.hpp @@ -15,6 +15,9 @@ namespace boost { namespace network { namespace http { template struct basic_response; + template + struct basic_request; + namespace impl { template @@ -27,6 +30,11 @@ namespace boost { namespace network { namespace http { response.destination(future); } + template + void destination(basic_request & request, T const & value, tags::server const &) { + request.destination = value; + } + } template @@ -40,6 +48,17 @@ namespace boost { namespace network { namespace http { impl::destination(response, value, is_async()); } + template + struct ServerRequest; + + template + inline + BOOST_CONCEPT_REQUIRES(((ServerRequest >)), + (void)) + destination(basic_request & request, T const & value) { + impl::destination(request, value, Tag()); + } + } // namespace http namespace impl { diff --git a/boost/network/protocol/http/message/modifiers/headers.hpp b/boost/network/protocol/http/message/modifiers/headers.hpp index 3497d1727..3b781107c 100644 --- a/boost/network/protocol/http/message/modifiers/headers.hpp +++ b/boost/network/protocol/http/message/modifiers/headers.hpp @@ -15,6 +15,9 @@ namespace boost { namespace network { namespace http { template struct basic_response; + template + struct basic_request; + namespace impl { template @@ -27,6 +30,11 @@ namespace boost { namespace network { namespace http { response.headers(future); } + template + void headers(basic_request & request, T const & value, tags::server const &) { + request.headers = value; + } + } template @@ -37,6 +45,13 @@ namespace boost { namespace network { namespace http { impl::headers(response, value, is_async()); } + template + inline BOOST_CONCEPT_REQUIRES(((ServerRequest >)), + (void)) + headers(basic_request & request, T const & value) { + impl::headers(request, value, Tag()); + } + } // namespace http } // namespace network diff --git a/boost/network/protocol/http/message/modifiers/method.hpp b/boost/network/protocol/http/message/modifiers/method.hpp new file mode 100644 index 000000000..52afe2696 --- /dev/null +++ b/boost/network/protocol/http/message/modifiers/method.hpp @@ -0,0 +1,29 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_METHOD_HPP_20101118 +#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_METHOD_HPP_20101118 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +namespace boost { namespace network { namespace http { + + template + struct basic_request; + + template + inline typename enable_if, void>::type + method(basic_request & request, typename string::type const & method_) { + request.method = method_; + } + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_METHOD_HPP_20101118 */ diff --git a/boost/network/protocol/http/message/modifiers/source.hpp b/boost/network/protocol/http/message/modifiers/source.hpp index f53fa4ecc..40324291b 100644 --- a/boost/network/protocol/http/message/modifiers/source.hpp +++ b/boost/network/protocol/http/message/modifiers/source.hpp @@ -29,6 +29,11 @@ namespace boost { namespace network { namespace http { response.source(future); } + template + void source(basic_request & request, T const & value, tags::server const &) { + request.source = value; + } + } template @@ -42,6 +47,17 @@ namespace boost { namespace network { namespace http { impl::source(response, value, is_async()); } + template + struct ServerRequest; + + template + inline + BOOST_CONCEPT_REQUIRES(((ServerRequest >)), + (void)) + source(basic_request & request, T const & value) { + impl::source(request, value, Tag()); + } + } // namespace http namespace impl { diff --git a/boost/network/protocol/http/message/wrappers/helper.hpp b/boost/network/protocol/http/message/wrappers/helper.hpp index 6c4bb1cbb..e433249ee 100644 --- a/boost/network/protocol/http/message/wrappers/helper.hpp +++ b/boost/network/protocol/http/message/wrappers/helper.hpp @@ -65,6 +65,7 @@ name (basic_request const & message) { \ return name##_wrapper >(message); \ } + #endif /* BOOST_NETWORK_DEFINE_HTTP_WRAPPER */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_HELPER_20101013 */ diff --git a/boost/network/protocol/http/message/wrappers/method.hpp b/boost/network/protocol/http/message/wrappers/method.hpp new file mode 100644 index 000000000..8edb98692 --- /dev/null +++ b/boost/network/protocol/http/message/wrappers/method.hpp @@ -0,0 +1,43 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_METHOD_HPP_20101118 +#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_METHOD_HPP_20101118 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +namespace boost { namespace network { namespace http { + + template + struct basic_request; + + template + struct method_wrapper { + explicit method_wrapper(basic_request const & message) + : message_(message) {} + + basic_request const & message_; + + typedef typename basic_request::string_type string_type; + + operator string_type() { + return message_.method; + } + }; + + template + inline typename enable_if, typename string::type >::type + method(basic_request const & message) { + return method_wrapper(message); + } + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_METHOD_HPP_20101118 */ diff --git a/boost/network/protocol/http/request_concept.hpp b/boost/network/protocol/http/request_concept.hpp index 0632b2a3b..e8512b6d7 100644 --- a/boost/network/protocol/http/request_concept.hpp +++ b/boost/network/protocol/http/request_concept.hpp @@ -16,23 +16,62 @@ namespace boost { namespace network { namespace http { template - struct PodServerRequest - : boost::network::Message + struct ServerRequest { typedef typename R::string_type string_type; + typedef typename R::tag tag; + typedef typename R::headers_container_type headers_container_type; + + BOOST_CONCEPT_USAGE(ServerRequest) { + string_type source_, method_, destination_; + boost::uint8_t major_version_, minor_version_; + headers_container_type headers_; + string_type body_; + + source_ = source(request); + method_ = method(request); + destination_ = destination(request); + major_version_ = major_version(request); + minor_version_ = minor_version(request); + headers_ = headers(request); + body_ = body(request); + + source(request, source_); + method(request, method_); + destination(request, destination_); + major_version(request, major_version_); + minor_version(request, minor_version_); + headers(request, headers_); + body(request, body_); + + string_type name, value; + + request << ::boost::network::source(source_) + << ::boost::network::destination(destination_) + << ::boost::network::http::method(method_) + << ::boost::network::http::major_version(major_version_) + << ::boost::network::http::minor_version(minor_version_) + << ::boost::network::header(name, value) + << ::boost::network::remove_header(name) + << ::boost::network::http::body(body_); + + (void)source_;(void)method_;(void)destination_; + (void)major_version_;(void)minor_version_;(void)headers_; + (void)body_;(void)name;(void)value; + } private: R request; }; template - struct NormalClientRequest + struct ClientRequest : boost::network::Message { typedef typename R::string_type string_type; typedef typename R::port_type port_type; - BOOST_CONCEPT_USAGE(NormalClientRequest) { + BOOST_CONCEPT_USAGE(ClientRequest) { string_type tmp; R request_(tmp); swap(request, request_); // swappable via ADL @@ -60,18 +99,6 @@ namespace boost { namespace network { namespace http { R request; }; - template - struct Request : - mpl::if_< - is_base_of< - tags::pod, - typename R::tag - >, - boost::network::Message, - NormalClientRequest - >::type - {}; - } // namespace http } // namespace network diff --git a/boost/network/protocol/http/traits.hpp b/boost/network/protocol/http/traits.hpp index 3eb896181..b527a31cf 100644 --- a/boost/network/protocol/http/traits.hpp +++ b/boost/network/protocol/http/traits.hpp @@ -12,7 +12,7 @@ // Convenience header for including different traits implementations. #include -#include +//#include #include #endif // BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_HPP From 1ac4b50096f2c536706996864050950a21328bae Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 21 Nov 2010 00:16:29 +0800 Subject: [PATCH 005/768] Fixing server request concept, adding appropriate implementations. --- .../message/modifiers/clear_headers.hpp | 12 ++- boost/network/protocol/http/impl/request.hpp | 3 - boost/network/protocol/http/message.hpp | 1 - .../http/message/directives/major_version.hpp | 39 ++++++++ .../http/message/directives/method.hpp | 21 +++++ .../http/message/directives/minor_version.hpp | 40 ++++++++ .../http/message/directives/status.hpp | 94 +++++++++---------- .../http/message/modifiers/add_header.hpp | 2 +- .../http/message/modifiers/clear_headers.hpp | 28 ------ .../http/message/modifiers/major_version.hpp | 30 ++++++ .../http/message/modifiers/minor_version.hpp | 31 ++++++ .../http/message/modifiers/remove_header.hpp | 2 +- .../http/message/wrappers/major_version.hpp | 40 ++++++++ .../http/message/wrappers/minor_version.hpp | 41 ++++++++ boost/network/protocol/http/request.hpp | 13 +++ .../network/protocol/http/request_concept.hpp | 6 +- boost/network/protocol/http/tags.hpp | 2 +- boost/network/support/is_pod.hpp | 26 +++++ 18 files changed, 344 insertions(+), 87 deletions(-) create mode 100644 boost/network/protocol/http/message/directives/major_version.hpp create mode 100644 boost/network/protocol/http/message/directives/method.hpp create mode 100644 boost/network/protocol/http/message/directives/minor_version.hpp delete mode 100644 boost/network/protocol/http/message/modifiers/clear_headers.hpp create mode 100644 boost/network/protocol/http/message/modifiers/major_version.hpp create mode 100644 boost/network/protocol/http/message/modifiers/minor_version.hpp create mode 100644 boost/network/protocol/http/message/wrappers/major_version.hpp create mode 100644 boost/network/protocol/http/message/wrappers/minor_version.hpp create mode 100644 boost/network/support/is_pod.hpp diff --git a/boost/network/message/modifiers/clear_headers.hpp b/boost/network/message/modifiers/clear_headers.hpp index c705965f3..1f7a4fd58 100644 --- a/boost/network/message/modifiers/clear_headers.hpp +++ b/boost/network/message/modifiers/clear_headers.hpp @@ -7,16 +7,26 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#include #include +#include +#include namespace boost { namespace network { namespace impl { template - inline void clear_headers(Message const & message, Tag const &, mpl::false_ const &) { + inline typename enable_if >, void>::type + clear_headers(Message const & message, Tag const &, mpl::false_ const &) { (typename Message::headers_container_type()).swap(message.headers()); } + template + inline typename enable_if, void>::type + clear_headers(Message const & message, Tag const &, mpl::false_ const &) { + (typename Message::headers_container_type()).swap(message.headers); + } + template inline void clear_headers(Message const & message, Tag const &, mpl::true_ const &) { boost::promise header_promise; diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index 6129203a9..a66b6335b 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -22,9 +22,6 @@ #include #include -#include -#include - #include namespace boost { namespace network { namespace http { diff --git a/boost/network/protocol/http/message.hpp b/boost/network/protocol/http/message.hpp index 3a4cc5849..aa8c579a2 100644 --- a/boost/network/protocol/http/message.hpp +++ b/boost/network/protocol/http/message.hpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/boost/network/protocol/http/message/directives/major_version.hpp b/boost/network/protocol/http/message/directives/major_version.hpp new file mode 100644 index 000000000..dc83f46ba --- /dev/null +++ b/boost/network/protocol/http/message/directives/major_version.hpp @@ -0,0 +1,39 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MAJOR_VERSION_HPP_20101120 +#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MAJOR_VERSION_HPP_20101120 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +namespace boost { namespace network { namespace http { + + template + struct basic_request; + + struct major_version_directive { + boost::uint8_t major_version; + explicit major_version_directive(boost::uint8_t major_version) + : major_version(major_version) {} + template + void operator()(basic_request & request) const { + request.http_version_major = major_version; + } + }; + + inline major_version_directive + major_version(boost::uint8_t major_version_) { + return major_version_directive(major_version_); + } + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MAJOR_VERSION_HPP_20101120 */ diff --git a/boost/network/protocol/http/message/directives/method.hpp b/boost/network/protocol/http/message/directives/method.hpp new file mode 100644 index 000000000..2f9aac3a4 --- /dev/null +++ b/boost/network/protocol/http/message/directives/method.hpp @@ -0,0 +1,21 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_METHOD_HPP_20101120 +#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_METHOD_HPP_20101120 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +namespace boost { namespace network { namespace http { + + BOOST_NETWORK_STRING_DIRECTIVE(method, method_, + message.method(method_), + message.method=method_); + +} /* http */ + +} /* network */ + +} /* booet */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_METHOD_HPP_20101120 */ diff --git a/boost/network/protocol/http/message/directives/minor_version.hpp b/boost/network/protocol/http/message/directives/minor_version.hpp new file mode 100644 index 000000000..2dbfe0a55 --- /dev/null +++ b/boost/network/protocol/http/message/directives/minor_version.hpp @@ -0,0 +1,40 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MINOR_VERSION_HPP_20101120 +#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MINOR_VERSION_HPP_20101120 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +namespace boost { namespace network { namespace http { + + template + struct basic_request; + + struct minor_version_directive { + boost::uint8_t minor_version; + explicit minor_version_directive(boost::uint8_t minor_version) + : minor_version(minor_version) {} + template + void operator()(basic_request & request) const { + request.http_version_minor = minor_version; + } + }; + + inline minor_version_directive + minor_version(boost::uint8_t minor_version_) { + return minor_version_directive(minor_version_); + } + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_MINOR_VERSION_HPP_20101120 */ + diff --git a/boost/network/protocol/http/message/directives/status.hpp b/boost/network/protocol/http/message/directives/status.hpp index 8c15ffcf9..2f3b3916c 100644 --- a/boost/network/protocol/http/message/directives/status.hpp +++ b/boost/network/protocol/http/message/directives/status.hpp @@ -21,61 +21,57 @@ namespace boost { namespace network { namespace http { template struct basic_response; - namespace impl { - - struct status_directive { - - boost::variant< - boost::uint16_t, - boost::shared_future - > status_; - - status_directive(boost::uint16_t status) - : status_(status) {} - - status_directive(boost::shared_future const & status) - : status_(status) {} - - status_directive(status_directive const & other) - : status_(other.status_) {} - - template - struct value - : mpl::if_< - is_async, - boost::shared_future, - boost::uint16_t - > - {}; - - template - struct status_visitor : boost::static_visitor<> { - basic_response const & response; - status_visitor(basic_response const & response) - : response(response) {} - - void operator()(typename value::type const & status_) const { - response.status(status_); - } - - template - void operator()(T const &) const { - // FIXME fail here! - } - }; - - template basic_response const & operator() (basic_response const & response) const { - apply_visitor(status_visitor(response), status_); - return response; + struct status_directive { + + boost::variant< + boost::uint16_t, + boost::shared_future + > status_; + + explicit status_directive(boost::uint16_t status) + : status_(status) {} + + explicit status_directive(boost::shared_future const & status) + : status_(status) {} + + status_directive(status_directive const & other) + : status_(other.status_) {} + + template + struct value + : mpl::if_< + is_async, + boost::shared_future, + boost::uint16_t + > + {}; + + template + struct status_visitor : boost::static_visitor<> { + basic_response const & response; + status_visitor(basic_response const & response) + : response(response) {} + + void operator()(typename value::type const & status_) const { + response.status(status_); } + template + void operator()(T const &) const { + // FIXME fail here! + } }; - } // namespace impl + template basic_response const & operator() (basic_response const & response) const { + apply_visitor(status_visitor(response), status_); + return response; + } + + }; template - inline impl::status_directive const status(T const & status_) { - return impl::status_directive(status_); + inline status_directive const status(T const & status_) { + return status_directive(status_); } } // namespace http diff --git a/boost/network/protocol/http/message/modifiers/add_header.hpp b/boost/network/protocol/http/message/modifiers/add_header.hpp index 615ced025..abc1e63db 100644 --- a/boost/network/protocol/http/message/modifiers/add_header.hpp +++ b/boost/network/protocol/http/message/modifiers/add_header.hpp @@ -14,7 +14,7 @@ namespace boost { namespace network { namespace impl { template - inline void add_header(Message const & message, KeyType const & key, ValueType const & value, http::tags::http_server const &, Async const &) { + inline void add_header(Message const & message, KeyType const & key, ValueType const & value, http::tags::server const &, Async const &) { typedef typename Message::headers_container_type::value_type value_type; value_type header_ = { key, value }; message.headers.insert(message.headers.end(), header_); diff --git a/boost/network/protocol/http/message/modifiers/clear_headers.hpp b/boost/network/protocol/http/message/modifiers/clear_headers.hpp deleted file mode 100644 index 85ef302c3..000000000 --- a/boost/network/protocol/http/message/modifiers/clear_headers.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADERS_HPP_20101019 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADERS_HPP_20101019 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { - - namespace impl { - - template - inline void clear_headers(Message const & message, http::tags::http_server const &, Async const &) { - (typename Message::headers_container_type()).swap(message.headers); - } - - } /* impl */ - -} /* network */ - -} /* boost */ - -#include - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADERS_HPP_20101019 */ diff --git a/boost/network/protocol/http/message/modifiers/major_version.hpp b/boost/network/protocol/http/message/modifiers/major_version.hpp new file mode 100644 index 000000000..e1510c678 --- /dev/null +++ b/boost/network/protocol/http/message/modifiers/major_version.hpp @@ -0,0 +1,30 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MAJOR_VERSION_HPP_20101120 +#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MAJOR_VERSION_HPP_20101120 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +namespace boost { namespace network { namespace http { + + template + struct basic_request; + + template + inline typename enable_if, void>::type + major_version(basic_request & request, boost::uint8_t major_version_) { + request.http_version_major = major_version_; + } + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MAJOR_VERSION_HPP_20101120 */ diff --git a/boost/network/protocol/http/message/modifiers/minor_version.hpp b/boost/network/protocol/http/message/modifiers/minor_version.hpp new file mode 100644 index 000000000..e70c32a6d --- /dev/null +++ b/boost/network/protocol/http/message/modifiers/minor_version.hpp @@ -0,0 +1,31 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MINOR_VERSION_HPP_20101120 +#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MINOR_VERSION_HPP_20101120 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +namespace boost { namespace network { namespace http { + + template + struct basic_request; + + template + inline typename enable_if, void>::type + minor_version(basic_request & request, boost::uint8_t minor_version_) { + request.http_version_minor = minor_version_; + } + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_MINOR_VERSION_HPP_20101120 */ + diff --git a/boost/network/protocol/http/message/modifiers/remove_header.hpp b/boost/network/protocol/http/message/modifiers/remove_header.hpp index 5a771b816..886911f60 100644 --- a/boost/network/protocol/http/message/modifiers/remove_header.hpp +++ b/boost/network/protocol/http/message/modifiers/remove_header.hpp @@ -28,7 +28,7 @@ namespace boost { namespace network { }; template - inline void remove_header(Message const & message, KeyType const & key, http::tags::http_server const &, Async const &) { + inline void remove_header(Message const & message, KeyType const & key, http::tags::server const &, Async const &) { typedef typename Message::headers_container_type::iterator iterator; iterator end = message.headers.end(); iterator new_end = std::remove_if( diff --git a/boost/network/protocol/http/message/wrappers/major_version.hpp b/boost/network/protocol/http/message/wrappers/major_version.hpp new file mode 100644 index 000000000..7b71736a3 --- /dev/null +++ b/boost/network/protocol/http/message/wrappers/major_version.hpp @@ -0,0 +1,40 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MAJOR_VERSION_HPP_20101120 +#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MAJOR_VERSION_HPP_20101120 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +namespace boost { namespace network { namespace http { + + template + struct basic_request; + + template + struct major_version_wrapper { + basic_request const & request; + explicit major_version_wrapper(basic_request const & request) + : request(request) {} + operator boost::uint8_t () { + return request.http_version_major; + } + }; + + template + inline typename enable_if, major_version_wrapper >::type + major_version(basic_request const & request) { + return major_version_wrapper(request); + } + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MAJOR_VERSION_HPP_20101120 */ diff --git a/boost/network/protocol/http/message/wrappers/minor_version.hpp b/boost/network/protocol/http/message/wrappers/minor_version.hpp new file mode 100644 index 000000000..b105227a4 --- /dev/null +++ b/boost/network/protocol/http/message/wrappers/minor_version.hpp @@ -0,0 +1,41 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MINOR_VERSION_HPP_20101120 +#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MINOR_VERSION_HPP_20101120 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +namespace boost { namespace network { namespace http { + + template + struct basic_request; + + template + struct minor_version_wrapper { + basic_request const & request; + explicit minor_version_wrapper(basic_request const & request) + : request(request) {} + operator boost::uint8_t () { + return request.http_version_minor; + } + }; + + template + inline typename enable_if, minor_version_wrapper >::type + minor_version(basic_request const & request) { + return minor_version_wrapper(request); + } + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_MINOR_VERSION_HPP_20101120 */ + diff --git a/boost/network/protocol/http/request.hpp b/boost/network/protocol/http/request.hpp index b53d98fc0..2c6e99f67 100644 --- a/boost/network/protocol/http/request.hpp +++ b/boost/network/protocol/http/request.hpp @@ -12,6 +12,9 @@ #include #include #include +#include +#include + #include #include #include @@ -25,6 +28,16 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include diff --git a/boost/network/protocol/http/request_concept.hpp b/boost/network/protocol/http/request_concept.hpp index e8512b6d7..5b0ee99eb 100644 --- a/boost/network/protocol/http/request_concept.hpp +++ b/boost/network/protocol/http/request_concept.hpp @@ -42,6 +42,9 @@ namespace boost { namespace network { namespace http { major_version(request, major_version_); minor_version(request, minor_version_); headers(request, headers_); + add_header(request, string_type(), string_type()); + remove_header(request, string_type()); + clear_headers(request); body(request, body_); string_type name, value; @@ -52,8 +55,7 @@ namespace boost { namespace network { namespace http { << ::boost::network::http::major_version(major_version_) << ::boost::network::http::minor_version(minor_version_) << ::boost::network::header(name, value) - << ::boost::network::remove_header(name) - << ::boost::network::http::body(body_); + << ::boost::network::body(body_); (void)source_;(void)method_;(void)destination_; (void)major_version_;(void)minor_version_;(void)headers_; diff --git a/boost/network/protocol/http/tags.hpp b/boost/network/protocol/http/tags.hpp index 9803c840f..ce58d1701 100644 --- a/boost/network/protocol/http/tags.hpp +++ b/boost/network/protocol/http/tags.hpp @@ -27,7 +27,7 @@ namespace boost { namespace network { namespace http { namespace tags { typedef mpl::vector http_async_8bit_udp_resolve_tags; typedef mpl::vector http_async_8bit_tcp_resolve_tags; typedef mpl::vector http_server_tags; - typedef mpl::vector http_async_server_tags; + typedef mpl::vector http_async_server_tags; BOOST_NETWORK_DEFINE_TAG(http_default_8bit_tcp_resolve); BOOST_NETWORK_DEFINE_TAG(http_default_8bit_udp_resolve); diff --git a/boost/network/support/is_pod.hpp b/boost/network/support/is_pod.hpp new file mode 100644 index 000000000..60add37aa --- /dev/null +++ b/boost/network/support/is_pod.hpp @@ -0,0 +1,26 @@ +#ifndef BOOST_NETWORK_SUPPORT_IS_POD_HPP_20101120 +#define BOOST_NETWORK_SUPPORT_IS_POD_HPP_20101120 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +namespace boost { namespace network { + + template + struct is_pod : + is_base_of< + tags::pod, + Tag + > + {}; + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_SUPPORT_IS_POD_HPP_20101120 */ From 862b94a5913d4606427ea86171d3a6ed9c029695 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 22 Nov 2010 21:17:50 +0800 Subject: [PATCH 006/768] WIP: organizing and fixing base modifiers, using SFINAE for proper overload selection. --- .../directives/detail/string_directive.hpp | 2 +- .../message/modifiers/clear_headers.hpp | 24 ++++++-- .../message/modifiers/remove_header.hpp | 60 ++++++++++++++++--- .../protocol/http/algorithms/linearize.hpp | 6 +- boost/network/protocol/http/impl/request.hpp | 1 - boost/network/protocol/http/impl/response.ipp | 2 +- boost/network/protocol/http/message.hpp | 3 + .../protocol/http/{ => message}/header.hpp | 26 +++++++- .../http/{server => message}/header/name.hpp | 6 +- .../http/{server => message}/header/value.hpp | 6 +- .../header_concept.hpp} | 10 ++-- .../protocol/http/server/async_server.hpp | 1 - boost/network/protocol/http/server/header.hpp | 43 ------------- .../protocol/http/server/sync_connection.hpp | 1 - .../protocol/http/server/sync_server.hpp | 1 - boost/network/protocol/http/tags.hpp | 2 +- 16 files changed, 114 insertions(+), 80 deletions(-) rename boost/network/protocol/http/{ => message}/header.hpp (62%) rename boost/network/protocol/http/{server => message}/header/name.hpp (78%) rename boost/network/protocol/http/{server => message}/header/value.hpp (78%) rename boost/network/protocol/http/{server/header/concept.hpp => message/header_concept.hpp} (69%) delete mode 100644 boost/network/protocol/http/server/header.hpp diff --git a/boost/network/message/directives/detail/string_directive.hpp b/boost/network/message/directives/detail/string_directive.hpp index 0876d5142..ce5c2870c 100644 --- a/boost/network/message/directives/detail/string_directive.hpp +++ b/boost/network/message/directives/detail/string_directive.hpp @@ -93,7 +93,7 @@ namespace boost { namespace network { namespace detail { typename boost::network::detail::string_value< \ typename Message::tag \ >::type const & value \ - ) const { \ + ) { \ pod_body; \ } \ template void operator()(T const &) const { \ diff --git a/boost/network/message/modifiers/clear_headers.hpp b/boost/network/message/modifiers/clear_headers.hpp index 1f7a4fd58..b44ff1207 100644 --- a/boost/network/message/modifiers/clear_headers.hpp +++ b/boost/network/message/modifiers/clear_headers.hpp @@ -11,24 +11,38 @@ #include #include #include +#include namespace boost { namespace network { namespace impl { template - inline typename enable_if >, void>::type - clear_headers(Message const & message, Tag const &, mpl::false_ const &) { + inline typename enable_if< + mpl::and_< + mpl::not_ > + , mpl::not_ > + > + , void + >::type + clear_headers(Message const & message, Tag const &) { (typename Message::headers_container_type()).swap(message.headers()); } template inline typename enable_if, void>::type - clear_headers(Message const & message, Tag const &, mpl::false_ const &) { + clear_headers(Message const & message, Tag const &) { (typename Message::headers_container_type()).swap(message.headers); } template - inline void clear_headers(Message const & message, Tag const &, mpl::true_ const &) { + inline typename enable_if< + mpl::and_< + mpl::not_ > + , is_async + > + , void + >::type + clear_headers(Message const & message, Tag const &) { boost::promise header_promise; boost::shared_future headers_future(header_promise.get_future()); message.headers(headers_future); @@ -39,7 +53,7 @@ namespace boost { namespace network { template class Message> inline void clear_headers(Message const & message) { - impl::clear_headers(message, Tag(), is_async()); + impl::clear_headers(message, Tag()); } } // namespace network diff --git a/boost/network/message/modifiers/remove_header.hpp b/boost/network/message/modifiers/remove_header.hpp index 8175a8a9e..c2ab29bf1 100644 --- a/boost/network/message/modifiers/remove_header.hpp +++ b/boost/network/message/modifiers/remove_header.hpp @@ -8,32 +8,73 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#include +#include +#include +#include +#include namespace boost { namespace network { namespace impl { - template - inline void remove_header(Message const & message, KeyType const & key, tags::default_string const &, mpl::false_ const &) { + template + inline typename enable_if< + mpl::and_< + mpl::not_ > + , mpl::not_ > + > + , void + >::type + remove_header(Message & message, KeyType const & key, Tag) { message.headers().erase(key); } - template - inline void remove_header(Message const & message, KeyType const & key, tags::default_wstring const &, mpl::false_ const &) { - message.headers().erase(key); + template + inline typename enable_if< + mpl::and_< + mpl::not_ > + , is_async + > + , void + >::type + remove_header(Message & message, KeyType const & key, Tag) { + message.remove_header(key); } + template + struct iequals_pred { + KeyType const & key; + iequals_pred(KeyType const & key) + : key(key) {} + template + bool operator()(Header & other) const { + return boost::iequals(key, name(other)); + } + }; + template - inline void remove_header(Message const & message, KeyType const & key, Tag const &, mpl::true_ const &) { - message.remove_header(key); + inline typename enable_if< + is_pod + , void + >::type + remove_header(Message & message, KeyType const & key, Tag) { + typedef typename Message::headers_container_type headers; + message.headers.erase( + boost::remove_if( + message.headers, + iequals_pred(key) + ) + , message.headers.end() + ); } } // namespace impl template class Message, class KeyType> - inline void remove_header(Message const & message, KeyType const & key) { - impl::remove_header(message, key, Tag(), is_async()); + inline void remove_header(Message & message, KeyType const & key) { + impl::remove_header(message, key, Tag()); } } // namespace network @@ -41,3 +82,4 @@ namespace boost { namespace network { } // namespace boost #endif // BOOST_NETWORK_MESSAGE_MODIFIER_REMOVE_HEADER_HPP_20100824 + diff --git a/boost/network/protocol/http/algorithms/linearize.hpp b/boost/network/protocol/http/algorithms/linearize.hpp index 47260c468..01283c128 100644 --- a/boost/network/protocol/http/algorithms/linearize.hpp +++ b/boost/network/protocol/http/algorithms/linearize.hpp @@ -6,9 +6,9 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include -#include -#include +#include +#include +#include #include #include diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index a66b6335b..71a23cf27 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -15,7 +15,6 @@ #include #include -#include #include #include diff --git a/boost/network/protocol/http/impl/response.ipp b/boost/network/protocol/http/impl/response.ipp index 53b252347..49c6917a4 100644 --- a/boost/network/protocol/http/impl/response.ipp +++ b/boost/network/protocol/http/impl/response.ipp @@ -19,7 +19,7 @@ #include #include #include -#include +#include namespace boost { namespace network { namespace http { diff --git a/boost/network/protocol/http/message.hpp b/boost/network/protocol/http/message.hpp index aa8c579a2..10768f603 100644 --- a/boost/network/protocol/http/message.hpp +++ b/boost/network/protocol/http/message.hpp @@ -13,6 +13,9 @@ #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HPP #include +#include +#include +#include #include #include #include diff --git a/boost/network/protocol/http/header.hpp b/boost/network/protocol/http/message/header.hpp similarity index 62% rename from boost/network/protocol/http/header.hpp rename to boost/network/protocol/http/message/header.hpp index 5d808ec76..afe8e4495 100644 --- a/boost/network/protocol/http/header.hpp +++ b/boost/network/protocol/http/message/header.hpp @@ -10,8 +10,8 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef HTTP_SERVER3_HEADER_HPP -#define HTTP_SERVER3_HEADER_HPP +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_HPP_20101122 +#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_HPP_20101122 #include #include @@ -34,6 +34,19 @@ namespace boost { namespace network { namespace http { swap(l.value, r.value); } + template + struct response_header { + typedef Tag tag; + typedef typename string::type string_type; + string_type name, value; + }; + + template + void swap(response_header & l, response_header & r) { + std::swap(l.name, r.name); + std::swap(l.value, r.value); + } + } // namespace http } // namespace network @@ -47,4 +60,11 @@ BOOST_FUSION_ADAPT_TPL_STRUCT( (typename boost::network::string::type, value) ) -#endif // HTTP_SERVER3_HEADER_HPP +BOOST_FUSION_ADAPT_TPL_STRUCT( + (Tag), + (boost::network::http::response_header) (Tag), + (typename boost::network::string::type, name) + (typename boost::network::string::type, value) + ) + +#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_HPP_20101122 diff --git a/boost/network/protocol/http/server/header/name.hpp b/boost/network/protocol/http/message/header/name.hpp similarity index 78% rename from boost/network/protocol/http/server/header/name.hpp rename to boost/network/protocol/http/message/header/name.hpp index 9f731d8f7..cf92d4a59 100644 --- a/boost/network/protocol/http/server/header/name.hpp +++ b/boost/network/protocol/http/message/header/name.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_HEADER_NAME_HPP_20101028 -#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_HEADER_NAME_HPP_20101028 +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_NAME_HPP_20101028 +#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_NAME_HPP_20101028 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. @@ -40,4 +40,4 @@ namespace boost { namespace network { namespace http { } /* boost */ -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_HEADER_NAME_HPP_20101028 */ +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_NAME_HPP_20101028 */ diff --git a/boost/network/protocol/http/server/header/value.hpp b/boost/network/protocol/http/message/header/value.hpp similarity index 78% rename from boost/network/protocol/http/server/header/value.hpp rename to boost/network/protocol/http/message/header/value.hpp index aafe217da..f5f550298 100644 --- a/boost/network/protocol/http/server/header/value.hpp +++ b/boost/network/protocol/http/message/header/value.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_HEADER_VALUE_HPP_20101028 -#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_HEADER_VALUE_HPP_20101028 +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_VALUE_HPP_20101028 +#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_VALUE_HPP_20101028 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. @@ -39,5 +39,5 @@ namespace boost { namespace network { namespace http { } /* boost */ -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_HEADER_VALUE_HPP_20101028 */ +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_VALUE_HPP_20101028 */ diff --git a/boost/network/protocol/http/server/header/concept.hpp b/boost/network/protocol/http/message/header_concept.hpp similarity index 69% rename from boost/network/protocol/http/server/header/concept.hpp rename to boost/network/protocol/http/message/header_concept.hpp index 738bed065..99100b24f 100644 --- a/boost/network/protocol/http/server/header/concept.hpp +++ b/boost/network/protocol/http/message/header_concept.hpp @@ -1,5 +1,5 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_HEADER_CONCEPT_HPP_20101028 -#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_HEADER_CONCEPT_HPP_20101028 +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_CONCEPT_HPP_20101028 +#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_CONCEPT_HPP_20101028 // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. @@ -17,11 +17,13 @@ namespace boost { namespace network { namespace http { , CopyConstructible { typedef typename H::tag tag; - typedef typename string::type string_type; BOOST_CONCEPT_USAGE(Header) { + typedef typename string::type string_type; string_type name_ = name(header); string_type value_ = value(header); + H h1, h2; + swap(h1,h2); // ADL Swap! (void)name_; (void)value_; } @@ -36,4 +38,4 @@ namespace boost { namespace network { namespace http { } /* boost */ -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_HEADER_CONCEPT_HPP_20101028 */ +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_CONCEPT_HPP_20101028 */ diff --git a/boost/network/protocol/http/server/async_server.hpp b/boost/network/protocol/http/server/async_server.hpp index abc05d688..f1e7ad81c 100644 --- a/boost/network/protocol/http/server/async_server.hpp +++ b/boost/network/protocol/http/server/async_server.hpp @@ -7,7 +7,6 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include #include namespace boost { namespace network { namespace http { diff --git a/boost/network/protocol/http/server/header.hpp b/boost/network/protocol/http/server/header.hpp deleted file mode 100644 index b366156d5..000000000 --- a/boost/network/protocol/http/server/header.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_HEADER_HPP_20101027 -#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_HEADER_HPP_20101027 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct response_header { - typedef Tag tag; - typedef typename string::type string_type; - string_type name, value; - }; - - template - void swap(response_header & l, response_header & r) { - std::swap(l.name, r.name); - std::swap(l.value, r.value); - } - -} /* http */ - -} /* network */ - -} /* boost */ - -BOOST_FUSION_ADAPT_TPL_STRUCT( - (Tag), - (boost::network::http::response_header) (Tag), - (typename boost::network::string::type, name) - (typename boost::network::string::type, value) - ) - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_HEADER_HPP_20101027 */ diff --git a/boost/network/protocol/http/server/sync_connection.hpp b/boost/network/protocol/http/server/sync_connection.hpp index 6e8548afc..e93f0f511 100644 --- a/boost/network/protocol/http/server/sync_connection.hpp +++ b/boost/network/protocol/http/server/sync_connection.hpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/boost/network/protocol/http/server/sync_server.hpp b/boost/network/protocol/http/server/sync_server.hpp index bd231ba03..abd97f3e7 100644 --- a/boost/network/protocol/http/server/sync_server.hpp +++ b/boost/network/protocol/http/server/sync_server.hpp @@ -14,7 +14,6 @@ #include #include #include -#include #include namespace boost { namespace network { namespace http { diff --git a/boost/network/protocol/http/tags.hpp b/boost/network/protocol/http/tags.hpp index ce58d1701..9803c840f 100644 --- a/boost/network/protocol/http/tags.hpp +++ b/boost/network/protocol/http/tags.hpp @@ -27,7 +27,7 @@ namespace boost { namespace network { namespace http { namespace tags { typedef mpl::vector http_async_8bit_udp_resolve_tags; typedef mpl::vector http_async_8bit_tcp_resolve_tags; typedef mpl::vector http_server_tags; - typedef mpl::vector http_async_server_tags; + typedef mpl::vector http_async_server_tags; BOOST_NETWORK_DEFINE_TAG(http_default_8bit_tcp_resolve); BOOST_NETWORK_DEFINE_TAG(http_default_8bit_udp_resolve); From 4846166fbebeac5c518caa2d3c2281bb574dbd51 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Tue, 23 Nov 2010 18:30:43 +0800 Subject: [PATCH 007/768] Done with modifier organization. --- .../network/message/modifiers/add_header.hpp | 44 +++++++++++++---- boost/network/protocol/http/impl/request.hpp | 3 +- boost/network/protocol/http/message.hpp | 2 - .../protocol/http/message/async_message.hpp | 3 +- .../http/message/modifiers/add_header.hpp | 30 ------------ .../http/message/modifiers/remove_header.hpp | 49 ------------------- boost/network/protocol/http/request.hpp | 2 - 7 files changed, 38 insertions(+), 95 deletions(-) delete mode 100644 boost/network/protocol/http/message/modifiers/add_header.hpp delete mode 100644 boost/network/protocol/http/message/modifiers/remove_header.hpp diff --git a/boost/network/message/modifiers/add_header.hpp b/boost/network/message/modifiers/add_header.hpp index 432c6bdb6..f92e9c21f 100644 --- a/boost/network/message/modifiers/add_header.hpp +++ b/boost/network/message/modifiers/add_header.hpp @@ -8,30 +8,54 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#include +#include +#include +#include namespace boost { namespace network { namespace impl { - template - inline void add_header(Message const & message, KeyType const & key, ValueType const & value, tags::default_string const &, mpl::false_ const &) { + template + inline typename enable_if< + mpl::and_< + mpl::not_ > + , mpl::not_ > + > + , void + >::type + add_header(Message & message, KeyType const & key, ValueType const & value, Tag) { message.headers().insert(std::make_pair(key, value)); } - template - inline void add_header(Message const & message, KeyType const & key, ValueType const & value, tags::default_wstring const &, mpl::false_ const &) { - message.headers().insert(std::make_pair(key, value)); + template + inline typename enable_if< + mpl::and_< + mpl::not_ > + , is_async + > + , void + >::type + add_header(Message & message, KeyType const & key, ValueType const & value, Tag) { + typedef typename Message::header_type header_type; + message.add_header(header_type(key,value)); } - template - inline void add_header(Message const & message, KeyType const & key, ValueType const & value, tags::async const &, mpl::true_ const &) { - message.add_header(std::make_pair(key, value)); + template + inline typename enable_if< + is_pod + , void + >::type + add_header(Message & message, KeyType const & key, ValueType const & value, Tag) { + typename Message::header_type header = { key, value }; + message.headers.insert(message.headers.end(), header); } } template class Message, class KeyType, class ValueType> - inline void add_header(Message const & message, KeyType const & key, ValueType const & value) { - impl::add_header(message, key, value, Tag(), is_async()); + inline void add_header(Message & message, KeyType const & key, ValueType const & value) { + impl::add_header(message, key, value, Tag()); } } // namespace network diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index 71a23cf27..5af341999 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -122,8 +122,9 @@ namespace boost { namespace network { namespace http { struct not_quite_pod_request_base { typedef Tag tag; typedef typename string::type string_type; + typedef request_header header_type; typedef typename vector:: - template apply >::type + template apply::type vector_type; typedef vector_type headers_container_type; typedef boost::uint16_t port_type; diff --git a/boost/network/protocol/http/message.hpp b/boost/network/protocol/http/message.hpp index 10768f603..b7256c9d1 100644 --- a/boost/network/protocol/http/message.hpp +++ b/boost/network/protocol/http/message.hpp @@ -16,8 +16,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/boost/network/protocol/http/message/async_message.hpp b/boost/network/protocol/http/message/async_message.hpp index 713cdacd5..3e2849018 100644 --- a/boost/network/protocol/http/message/async_message.hpp +++ b/boost/network/protocol/http/message/async_message.hpp @@ -29,6 +29,7 @@ namespace boost { namespace network { namespace http { typedef typename string::type string_type; typedef typename headers_container::type headers_container_type; + typedef typename headers_container_type::value_type header_type; async_message() : status_message_(), @@ -104,7 +105,7 @@ namespace boost { namespace network { namespace http { } void add_header(typename headers_container_type::value_type const & pair_) const { - added_headers.insert(pair_); + added_headers.insert(added_headers.end(), pair_); } void remove_header(typename headers_container_type::key_type const & key_) const { diff --git a/boost/network/protocol/http/message/modifiers/add_header.hpp b/boost/network/protocol/http/message/modifiers/add_header.hpp deleted file mode 100644 index abc1e63db..000000000 --- a/boost/network/protocol/http/message/modifiers/add_header.hpp +++ /dev/null @@ -1,30 +0,0 @@ - -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_ADD_HEADER_HPP_20101019 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_ADD_HEADER_HPP_20101019 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { - - namespace impl { - - template - inline void add_header(Message const & message, KeyType const & key, ValueType const & value, http::tags::server const &, Async const &) { - typedef typename Message::headers_container_type::value_type value_type; - value_type header_ = { key, value }; - message.headers.insert(message.headers.end(), header_); - } - - } - -} /* network */ - -} /* boost */ - -#include -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_ADD_HEADER_HPP_20101019 */ diff --git a/boost/network/protocol/http/message/modifiers/remove_header.hpp b/boost/network/protocol/http/message/modifiers/remove_header.hpp deleted file mode 100644 index 886911f60..000000000 --- a/boost/network/protocol/http/message/modifiers/remove_header.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_REMOVE_HEADER_HPP_20101019 -#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_REMOVE_HEADER_HPP_20101019 - -// Copyright 2010 (c) Dean Michael Berris -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include - -namespace boost { namespace network { - - namespace impl { - - template - struct equals { - explicit equals(KeyType const & key_) - : key(key_) {} - equals(equals const & other) - : key(other.key) {} - template - bool operator()(RequestHeader const & header) { - return boost::iequals(header.name, key); - } - KeyType const & key; - }; - - template - inline void remove_header(Message const & message, KeyType const & key, http::tags::server const &, Async const &) { - typedef typename Message::headers_container_type::iterator iterator; - iterator end = message.headers.end(); - iterator new_end = std::remove_if( - message.headers.begin(), - message.headers.end(), - equals(key)); - message.headers.erase(new_end, end); - } - - } /* impl */ - -} /* network */ - -} /* boost */ - -#include - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_REMOVE_HEADER_HPP_20101019 */ diff --git a/boost/network/protocol/http/request.hpp b/boost/network/protocol/http/request.hpp index 2c6e99f67..cd4d8fc7a 100644 --- a/boost/network/protocol/http/request.hpp +++ b/boost/network/protocol/http/request.hpp @@ -12,8 +12,6 @@ #include #include #include -#include -#include #include #include From 159a22a9c14989a13883ebef1b05f8bf0f8306f1 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 27 Nov 2010 11:27:13 +0800 Subject: [PATCH 008/768] Adding newline at end of request.hpp --- boost/network/protocol/http/request.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/boost/network/protocol/http/request.hpp b/boost/network/protocol/http/request.hpp index cd4d8fc7a..a86a55b13 100644 --- a/boost/network/protocol/http/request.hpp +++ b/boost/network/protocol/http/request.hpp @@ -74,3 +74,4 @@ namespace boost { namespace network { namespace http { #include #endif // __NETWORK_PROTOCOL_HTTP_REQUEST_20070908-1_HPP__ + From 3049355f5e234837ed1ddfbee50a16aa721d7eef Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 27 Nov 2010 17:35:09 +0800 Subject: [PATCH 009/768] Implementing the Linearize Algorithm This first part of the patch removes the linearization of the HTTP Request algorithm from the bowels of the connection_helper detail that exposes the linearize function to be used for all the client implementations. This refactoring is crucial to make the linerize algorithm a top-level algorithm that deals with requests, responses, and normal messages. This paves the way for a single point of extension for messages that have to be linearized to a buffer. Documentation and support for linearization of response objects will follow. --- boost/network/constants.hpp | 30 ++++++ boost/network/message/wrappers/body.hpp | 27 ++++++ .../protocol/http/algorithms/linearize.hpp | 91 ++++++++++++++++++- .../http/detail/connection_helper.hpp | 88 ------------------ .../http/impl/http_sync_connection.hpp | 8 +- .../http/impl/https_sync_connection.hpp | 5 +- .../http/impl/sync_connection_base.hpp | 1 - .../protocol/http/message/header/name.hpp | 10 +- .../protocol/http/message/header/value.hpp | 10 +- .../protocol/http/message/wrappers/body.hpp | 17 +++- .../http/policies/async_connection.hpp | 1 - .../http/policies/pooled_connection.hpp | 1 - .../http/policies/simple_connection.hpp | 1 - .../protocol/http/server/async_connection.hpp | 2 +- .../http/traits/connection_keepalive.hpp | 15 +-- libs/network/example/http_client.cpp | 3 +- libs/network/test/http_localhost_tests.cpp | 32 ++++--- libs/network/test/http_message_test.cpp | 28 ++++-- libs/network/test/https_localhost_tests.cpp | 30 +++--- 19 files changed, 237 insertions(+), 163 deletions(-) delete mode 100644 boost/network/protocol/http/detail/connection_helper.hpp diff --git a/boost/network/constants.hpp b/boost/network/constants.hpp index 89ac7c1e9..11a38ecae 100644 --- a/boost/network/constants.hpp +++ b/boost/network/constants.hpp @@ -26,6 +26,8 @@ namespace boost { namespace network { return dot_; } + static char dot_char() { return '.'; } + static char const * http_slash() { static char http_slash_[] = { 'H', 'T', 'T', 'P', '/', 0 }; return http_slash_; @@ -36,11 +38,15 @@ namespace boost { namespace network { return space_; } + static char space_char() { return ' '; } + static char const * slash() { static char slash_[] = {'/', 0}; return slash_; } + static char slash_char() { return '/'; } + static char const * host() { static char host_[] = {'H', 'o', 's', 't', 0}; return host_; @@ -50,6 +56,8 @@ namespace boost { namespace network { static char colon_[] = {':', 0}; return colon_; } + + static char colon_char() { return ':'; } static char const * accept() { static char accept_[] = {'A', 'c', 'c', 'e', 'p', 't', 0}; @@ -91,6 +99,28 @@ namespace boost { namespace network { return cpp_netlib_slash_; } + static char question_mark_char() { + return '?'; + } + + static char hash_char() { + return '#'; + } + + static char const * connection() { + static char connection_[] = { + 'C','o','n','n','e','c','t','i','o','n',0 + }; + return connection_; + } + + static char const * close() { + static char close_[] = { + 'C','l','o','s','e', 0 + }; + return close_; + } + }; template diff --git a/boost/network/message/wrappers/body.hpp b/boost/network/message/wrappers/body.hpp index 71506df58..fa9fb8729 100644 --- a/boost/network/message/wrappers/body.hpp +++ b/boost/network/message/wrappers/body.hpp @@ -9,9 +9,15 @@ #include #include +#include namespace boost { namespace network { + template + struct body_range { + typedef typename boost::iterator_range type; + }; + namespace impl { template struct body_wrapper : public detail::wrapper_base > { @@ -30,6 +36,23 @@ namespace boost { namespace network { std::size_t size() const { return wrapper_base::_message.body().size(); } + + operator boost::iterator_range< + typename boost::range_iterator::type + > () const { + return boost::make_iterator_range(wrapper_base::_message.body()); + } + + typename string_type::const_iterator + begin() const { + return wrapper_base::_message.body().begin(); + } + + typename string_type::const_iterator + end() const { + return wrapper_base::_message.body().end(); + } + }; template @@ -49,6 +72,10 @@ namespace boost { namespace network { std::size_t size() const { return wrapper_base::_message.body().size(); } + + operator boost::range_iterator () const { + return boost::make_iterator_range(wrapper_base::_message.body()); + } }; } // namespace impl diff --git a/boost/network/protocol/http/algorithms/linearize.hpp b/boost/network/protocol/http/algorithms/linearize.hpp index 01283c128..ce9965ba3 100644 --- a/boost/network/protocol/http/algorithms/linearize.hpp +++ b/boost/network/protocol/http/algorithms/linearize.hpp @@ -11,11 +11,12 @@ #include #include #include +#include namespace boost { namespace network { namespace http { template - struct linearize { + struct linearize_header { typedef typename string::type string_type; template @@ -40,11 +41,97 @@ namespace boost { namespace network { namespace http { return header_line.str(); } }; + + template + OutputIterator linearize( + basic_request const & request, + typename string::type const & method, + unsigned version_major, + unsigned version_minor, + OutputIterator oi + ) + { + typedef constants consts; + typedef typename string::type string_type; + static string_type + http_slash = consts::http_slash() + , accept = consts::accept() + , accept_mime = consts::default_accept_mime() + , accept_encoding = consts::accept_encoding() + , default_accept_encoding = consts::default_accept_encoding() + , crlf = consts::crlf() + , host = consts::host() + , connection = consts::connection() + , close = consts::close() + ; + boost::copy(method, oi); + *oi = consts::space_char(); + if (request.path().empty() || request.path()[0] != consts::slash_char()) + *oi = consts::slash_char(); + boost::copy(request.path(), oi); + if (!request.query().empty()) { + *oi = consts::question_mark_char(); + boost::copy(request.query(), oi); + } + if (!request.anchor().empty()) { + *oi = consts::hash_char(); + boost::copy(request.anchor(), oi); + } + *oi = consts::space_char(); + boost::copy(http_slash, oi); + string_type version_major_str = boost::lexical_cast(version_major), + version_minor_str = boost::lexical_cast(version_minor); + boost::copy(version_major_str, oi); + *oi = consts::dot_char(); + boost::copy(version_minor_str, oi); + boost::copy(crlf, oi); + boost::copy(host, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + boost::copy(request.host(), oi); + boost::copy(host, oi); + boost::copy(accept, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + boost::copy(accept_mime, oi); + boost::copy(crlf, oi); + if (version_major == 1u && version_minor == 1u) { + boost::copy(accept_encoding, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + boost::copy(default_accept_encoding, oi); + } + typedef typename headers_range >::type headers_range; + typedef typename range_iterator::type headers_iterator; + headers_range request_headers = headers(request); + headers_iterator iterator = boost::begin(request_headers), + end = boost::end(request_headers); + for (; iterator != end; ++iterator) { + string_type header_name = name(*iterator), + header_value = value(*iterator); + boost::copy(header_name, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + boost::copy(header_value, oi); + boost::copy(crlf, oi); + } + if (!connection_keepalive::value) { + boost::copy(connection, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + boost::copy(close, oi); + boost::copy(crlf, oi); + } + boost::copy(crlf, oi); + typename body_range >::type body_data = body(request).range(); + return boost::copy(body_data, oi); + } -} /* linearize */ +} /* http */ } /* net */ } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 */ + diff --git a/boost/network/protocol/http/detail/connection_helper.hpp b/boost/network/protocol/http/detail/connection_helper.hpp deleted file mode 100644 index 9193d0bf4..000000000 --- a/boost/network/protocol/http/detail/connection_helper.hpp +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_DETAIL_CONNECTION_HELPER_20091217 -#define BOOST_NETWORK_PROTOCOL_HTTP_DETAIL_CONNECTION_HELPER_20091217 - -// Copyright Dean Michael Berris 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { namespace detail { - - template - struct connection_helper { - protected: - - typedef typename string::type string_type; - - void create_request(boost::asio::streambuf & request_buffer, string_type const & method, basic_request const & request_) const { - // TODO make this use Boost.Karma instead of an ad-hoc implementation - std::ostream request_stream(&request_buffer); - - request_stream - << method << " "; - - if (request_.path().empty() || request_.path()[0] != '/') - request_stream << '/'; - - request_stream - << request_.path() - ; - - if (!request_.query().empty()) - request_stream - << '?' - << request_.query() - ; - - if (!request_.anchor().empty()) - request_stream - << '#' - << request_.anchor() - ; - - request_stream << " HTTP/" << version_major << '.' << version_minor << "\r\n" - << "Host: " << request_.host() << "\r\n" - << "Accept: */*\r\n"; - - if (version_major == 1 && version_minor == 1) - request_stream - << "Accept-Encoding: identity;q=1.0, *;q=0\r\n"; // only accept identity encoding - - typename headers_range >::type range = headers(request_); - BOOST_FOREACH(typename headers_range >::type::value_type const & header, range) { - request_stream << header.first << ": " << header.second << "\r\n"; - }; - - range = headers(request_)["user-agent"]; - if (empty(range)) request_stream << "User-Agent: cpp-netlib/" << BOOST_NETLIB_VERSION << "\r\n"; - - if (!connection_keepalive::value) { - request_stream - << "Connection: close\r\n"; - } - request_stream - << "\r\n"; - - string_type body_ = body(request_); - if (!body_.empty()) - request_stream << body_; - } - - }; - -} // namespace detail - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_DETAIL_CONNECTION_HELPER_20091217 - diff --git a/boost/network/protocol/http/impl/http_sync_connection.hpp b/boost/network/protocol/http/impl/http_sync_connection.hpp index 885c33f78..445acb51d 100644 --- a/boost/network/protocol/http/impl/http_sync_connection.hpp +++ b/boost/network/protocol/http/impl/http_sync_connection.hpp @@ -7,6 +7,9 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include +#include + namespace boost { namespace network { namespace http { namespace impl { template @@ -16,7 +19,7 @@ namespace boost { namespace network { namespace http { namespace impl { struct sync_connection_base; template - struct http_sync_connection : public virtual sync_connection_base, detail::connection_helper, sync_connection_base_impl { + struct http_sync_connection : public virtual sync_connection_base, sync_connection_base_impl { typedef typename resolver_policy::type resolver_base; typedef typename resolver_base::resolver_type resolver_type; typedef typename string::type string_type; @@ -32,7 +35,8 @@ namespace boost { namespace network { namespace http { namespace impl { void send_request_impl(string_type const & method, basic_request const & request_) { boost::asio::streambuf request_buffer; - this->create_request(request_buffer, method, request_); + linearize(request_, method, version_major, version_minor, + std::ostreambuf_iterator::type>(&request_buffer)); connection_base::send_request_impl(socket_, method, request_buffer); } diff --git a/boost/network/protocol/http/impl/https_sync_connection.hpp b/boost/network/protocol/http/impl/https_sync_connection.hpp index fcb5ed28c..e323fc844 100644 --- a/boost/network/protocol/http/impl/https_sync_connection.hpp +++ b/boost/network/protocol/http/impl/https_sync_connection.hpp @@ -18,7 +18,7 @@ namespace boost { namespace network { namespace http { namespace impl { struct sync_connection_base; template - struct https_sync_connection : public virtual sync_connection_base, detail::connection_helper, sync_connection_base_impl { + struct https_sync_connection : public virtual sync_connection_base, sync_connection_base_impl { typedef typename resolver_policy::type resolver_base; typedef typename resolver_base::resolver_type resolver_type; typedef typename string::type string_type; @@ -42,7 +42,8 @@ namespace boost { namespace network { namespace http { namespace impl { void send_request_impl(string_type const & method, basic_request const & request_) { boost::asio::streambuf request_buffer; - this->create_request(request_buffer, method, request_); + linearize(request_, method, version_major, version_minor, + std::ostreambuf_iterator::type>(&request_buffer)); connection_base::send_request_impl(socket_, method, request_buffer); } diff --git a/boost/network/protocol/http/impl/sync_connection_base.hpp b/boost/network/protocol/http/impl/sync_connection_base.hpp index 060cadcf3..4b4b2e33f 100644 --- a/boost/network/protocol/http/impl/sync_connection_base.hpp +++ b/boost/network/protocol/http/impl/sync_connection_base.hpp @@ -7,7 +7,6 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include #include #include #include diff --git a/boost/network/protocol/http/message/header/name.hpp b/boost/network/protocol/http/message/header/name.hpp index cf92d4a59..aa4010c04 100644 --- a/boost/network/protocol/http/message/header/name.hpp +++ b/boost/network/protocol/http/message/header/name.hpp @@ -18,19 +18,19 @@ namespace boost { namespace network { namespace http { template T1 & - name(std::pair & p) { + name(std::pair const & p) { return p.first; } template - typename string::type & - name(response_header & h) { + typename string::type const & + name(response_header const & h) { return h.name; } template - typename string::type & - name(request_header & h) { + typename string::type const & + name(request_header const & h) { return h.name; } diff --git a/boost/network/protocol/http/message/header/value.hpp b/boost/network/protocol/http/message/header/value.hpp index f5f550298..c90a297ef 100644 --- a/boost/network/protocol/http/message/header/value.hpp +++ b/boost/network/protocol/http/message/header/value.hpp @@ -17,19 +17,19 @@ namespace boost { namespace network { namespace http { struct request_header; template - T1 & value(std::pair & p) { + T1 & value(std::pair const & p) { return p.second; } template - typename string::type & - value(response_header & h) { + typename string::type const & + value(response_header const & h) { return h.value; } template - typename string::type & - value(request_header & h) { + typename string::type const & + value(request_header const & h) { return h.value; } diff --git a/boost/network/protocol/http/message/wrappers/body.hpp b/boost/network/protocol/http/message/wrappers/body.hpp index 85a70d3e9..d73ddc5e9 100644 --- a/boost/network/protocol/http/message/wrappers/body.hpp +++ b/boost/network/protocol/http/message/wrappers/body.hpp @@ -24,23 +24,34 @@ namespace boost { namespace network { namespace http { : message_(message) {} body_wrapper(body_wrapper const & other) : message_(other.message_) {} - operator string_type () { + + operator string_type () const { return message_.body(); } + + size_t size() const { + return message_.body().size(); + } + + boost::iterator_range + range() const + { + return boost::make_iterator_range(message_.body()); + } }; } // namespace impl template inline - typename impl::body_wrapper >::string_type const + typename impl::body_wrapper > body(basic_response const & message) { return impl::body_wrapper >(message); } template inline - typename impl::body_wrapper >::string_type const + typename impl::body_wrapper > body(basic_request const & message) { return impl::body_wrapper >(message); } diff --git a/boost/network/protocol/http/policies/async_connection.hpp b/boost/network/protocol/http/policies/async_connection.hpp index 700536e10..a4414ff41 100644 --- a/boost/network/protocol/http/policies/async_connection.hpp +++ b/boost/network/protocol/http/policies/async_connection.hpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/boost/network/protocol/http/policies/pooled_connection.hpp b/boost/network/protocol/http/policies/pooled_connection.hpp index 3db6bdc74..195dc7dda 100644 --- a/boost/network/protocol/http/policies/pooled_connection.hpp +++ b/boost/network/protocol/http/policies/pooled_connection.hpp @@ -10,7 +10,6 @@ #include #include -#include #include #include #include diff --git a/boost/network/protocol/http/policies/simple_connection.hpp b/boost/network/protocol/http/policies/simple_connection.hpp index d734cee65..1d0221d6f 100644 --- a/boost/network/protocol/http/policies/simple_connection.hpp +++ b/boost/network/protocol/http/policies/simple_connection.hpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index 77245e72a..faf6a504f 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -169,7 +169,7 @@ namespace boost { namespace network { namespace http { typedef typename string::type string_type; boost::transform(headers, std::ostream_iterator(stream), - linearize()); + linearize_header()); } else { stream << consts::crlf(); } diff --git a/boost/network/protocol/http/traits/connection_keepalive.hpp b/boost/network/protocol/http/traits/connection_keepalive.hpp index 605bb8457..55d929020 100644 --- a/boost/network/protocol/http/traits/connection_keepalive.hpp +++ b/boost/network/protocol/http/traits/connection_keepalive.hpp @@ -7,23 +7,12 @@ #define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_CONECTION_KEEPALIVE_20091218 #include +#include namespace boost { namespace network { namespace http { template - struct connection_keepalive { - static bool const value = false; - }; - - template <> - struct connection_keepalive { - static bool const value = true; - }; - - template <> - struct connection_keepalive { - static bool const value = true; - }; + struct connection_keepalive : is_keepalive {}; } /* http */ diff --git a/libs/network/example/http_client.cpp b/libs/network/example/http_client.cpp index 2f71f896d..683156440 100644 --- a/libs/network/example/http_client.cpp +++ b/libs/network/example/http_client.cpp @@ -82,7 +82,8 @@ int main(int argc, char * argv[]) { cout << endl; }; - cout << body(response) << endl; + body_range::type body_ = body(response).range(); + boost::copy(body_, std::ostream_iterator::type>(cout)); return EXIT_SUCCESS; } diff --git a/libs/network/test/http_localhost_tests.cpp b/libs/network/test/http_localhost_tests.cpp index 3349041a2..0be6b92e1 100644 --- a/libs/network/test/http_localhost_tests.cpp +++ b/libs/network/test/http_localhost_tests.cpp @@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE(body_test) { http::client::request request_(base_url); http::client client_; http::client::response response_ = client_.get(request_); - BOOST_CHECK(body(response_).length() != 0); + BOOST_CHECK(body(response_).size() != 0); } BOOST_AUTO_TEST_CASE(text_content_type_test) { @@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(content_length_header_test) { headers_range::type range = headers(response_)["Content-Length"]; BOOST_CHECK_EQUAL(boost::begin(range)->first, "Content-Length"); BOOST_CHECK_EQUAL(boost::begin(range)->second, "113"); - BOOST_CHECK(body(response_).length() != 0); + BOOST_CHECK(body(response_).size() != 0); } BOOST_AUTO_TEST_CASE(text_query_preserves_crlf) { @@ -146,7 +146,8 @@ BOOST_AUTO_TEST_CASE(text_query_preserves_crlf) { http::client client_; http::client::response response_ = client_.get(request_); - BOOST_CHECK(body(response_).length() != 0); + http::client::response::string_type body_ = body(response_); + BOOST_CHECK(body(response_).size() != 0); using std::ios; @@ -162,10 +163,10 @@ BOOST_AUTO_TEST_CASE(text_query_preserves_crlf) { std::size_t size = readfile(file, memblock); BOOST_CHECK(size != 0); - BOOST_CHECK_EQUAL(body(response_).length(), size); + BOOST_CHECK_EQUAL(body_.size(), size); - if (body(response_).length() == size) { - std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body(response_).begin()); + if (body(response_).size() == size) { + std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body_.begin()); BOOST_CHECK_EQUAL(boost::numeric_cast(diff_pos.first - memblock.begin()), size); } } @@ -178,7 +179,8 @@ BOOST_AUTO_TEST_CASE(binary_file_query) { http::client::response response_; BOOST_CHECK_NO_THROW(response_ = client_.get(request_)); - BOOST_CHECK(body(response_).length() != 0); + http::client::response::string_type body_ = body(response_); + BOOST_CHECK(body_.size() != 0); using std::ios; @@ -194,9 +196,9 @@ BOOST_AUTO_TEST_CASE(binary_file_query) { std::size_t size = readfile(file, memblock); BOOST_CHECK(size != 0); - BOOST_CHECK_EQUAL(body(response_).length(), size); + BOOST_CHECK_EQUAL(body_.size(), size); - std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body(response_).begin()); + std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body_.begin()); BOOST_CHECK_EQUAL(boost::numeric_cast(diff_pos.first - memblock.begin()), size); } @@ -209,7 +211,7 @@ BOOST_AUTO_TEST_CASE(cgi_query) { http::client c; http::client::response r; BOOST_REQUIRE_NO_THROW(r = c.get(req)); - BOOST_CHECK(body(r).length() != 0); + BOOST_CHECK(body(r).size() != 0); BOOST_CHECK(boost::empty(headers(r)["Content-Length"])); } @@ -220,7 +222,7 @@ BOOST_AUTO_TEST_CASE(cgi_multi_line_headers) { http::client c; http::client::response r; BOOST_REQUIRE_NO_THROW(r = c.get(req)); - BOOST_CHECK(body(r).length() != 0); + BOOST_CHECK(body(r).size() != 0); BOOST_CHECK(boost::empty(headers(r)["Content-Type"])); headers_range::type range=headers(r)["X-CppNetlib-Test"]; BOOST_REQUIRE(boost::begin(range) != boost::end(range)); @@ -238,7 +240,7 @@ BOOST_AUTO_TEST_CASE(file_not_found) { http::client c; http::client::response r = c.get(req); - BOOST_CHECK(body(r).length() != 0); + BOOST_CHECK(body(r).size() != 0); } BOOST_AUTO_TEST_CASE(head_test) { @@ -250,7 +252,7 @@ BOOST_AUTO_TEST_CASE(head_test) { headers_range::type range = headers(response_)["Content-Length"]; BOOST_CHECK_EQUAL(boost::begin(range)->first, "Content-Length"); BOOST_CHECK_EQUAL(boost::begin(range)->second, "113"); - BOOST_CHECK(body(response_).length() == 0); + BOOST_CHECK(body(response_).size() == 0); } BOOST_AUTO_TEST_CASE(post_with_explicit_headers) { @@ -325,8 +327,8 @@ BOOST_AUTO_TEST_CASE(post_body_default_content_type) { http::client c; http::client::response r; BOOST_REQUIRE_NO_THROW(r = c.post(req, postdata)); - - BOOST_CHECK_EQUAL(postdata, body(r)); + http::client::response::string_type body_ = body(r); + BOOST_CHECK_EQUAL(postdata, body_); } BOOST_AUTO_TEST_CASE(post_with_custom_headers) { diff --git a/libs/network/test/http_message_test.cpp b/libs/network/test/http_message_test.cpp index 898c36cd2..dde3a9303 100644 --- a/libs/network/test/http_message_test.cpp +++ b/libs/network/test/http_message_test.cpp @@ -56,10 +56,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE (request_copy_constructor_test, T, tag_types) { copy_port = http::port(copy); string_type orig_path = http::path(request), copy_path = http::path(copy); + string_type orig_body = body(request), + copy_body = body(copy); BOOST_CHECK_EQUAL ( orig_host, copy_host ); BOOST_CHECK_EQUAL ( orig_port, copy_port ); BOOST_CHECK_EQUAL ( orig_path, copy_path ); - BOOST_CHECK_EQUAL ( body(request), body(copy) ); + BOOST_CHECK_EQUAL ( orig_body, copy_body ); } BOOST_AUTO_TEST_CASE_TEMPLATE (request_assignment_test, T, tag_types) { @@ -76,10 +78,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE (request_assignment_test, T, tag_types) { copy_port = http::port(copy); string_type orig_path = http::path(request), copy_path = http::path(copy); + string_type orig_body = body(request), + copy_body = body(copy); BOOST_CHECK_EQUAL ( orig_host, copy_host ); BOOST_CHECK_EQUAL ( orig_port, copy_port ); BOOST_CHECK_EQUAL ( orig_path, copy_path ); - BOOST_CHECK_EQUAL ( body(request), body(copy) ); + BOOST_CHECK_EQUAL ( orig_body, copy_body ); } BOOST_AUTO_TEST_CASE_TEMPLATE (request_swap_test, T, tag_types) { @@ -110,7 +114,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE (request_uri_directive_test, T, tag_types) { BOOST_AUTO_TEST_CASE_TEMPLATE (response_constructor_test, T, tag_types) { http::basic_response response; - BOOST_CHECK_EQUAL ( body(response), std::string() ); + typename http::basic_response::string_type body_ = body(response); + BOOST_CHECK_EQUAL ( body_, std::string() ); } BOOST_AUTO_TEST_CASE_TEMPLATE (response_copy_construct_test, T, tag_types) { @@ -132,9 +137,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE (response_copy_construct_test, T, tag_types) { BOOST_CHECK_EQUAL ( status_orig, status_copy ); typename http::basic_response::string_type status_message_orig = status_message(response) - , status_message_copy = status_message(copy); + , status_message_copy = status_message(copy) + , body_orig = body(response) + , body_copy = body(copy); BOOST_CHECK_EQUAL ( status_message_orig, status_message_copy ); - BOOST_CHECK_EQUAL ( body(response), body(copy) ); + BOOST_CHECK_EQUAL ( body_orig, body_copy ); } BOOST_AUTO_TEST_CASE_TEMPLATE (response_assignment_construct_test, T, tag_types) { @@ -155,7 +162,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE (response_assignment_construct_test, T, tag_types) string_type status_message_orig = status_message(response) , status_message_copy = status_message(copy); BOOST_CHECK_EQUAL ( status_message_orig, status_message_copy ); - BOOST_CHECK_EQUAL ( body(response), body(copy) ); + string_type body_orig = body(response) + , body_copy = body(copy); + BOOST_CHECK_EQUAL ( body_orig, body_copy ); } BOOST_AUTO_TEST_CASE_TEMPLATE (response_swap_test, T, tag_types) { @@ -170,11 +179,14 @@ BOOST_AUTO_TEST_CASE_TEMPLATE (response_swap_test, T, tag_types) { BOOST_CHECK_EQUAL ( response.version(), std::string() ); BOOST_CHECK_EQUAL ( response.status(), 0u ); BOOST_CHECK_EQUAL ( response.status_message(), std::string() ); - BOOST_CHECK_EQUAL ( body(response), std::string() ); + typename http::basic_response::string_type + orig_body = body(response) + , swapped_body = body(swapped); + BOOST_CHECK_EQUAL ( orig_body, std::string() ); BOOST_CHECK_EQUAL ( swapped.version(), std::string("HTTP/1.1") ); BOOST_CHECK_EQUAL ( swapped.status(), 200u ); BOOST_CHECK_EQUAL ( swapped.status_message(), std::string("OK") ); - BOOST_CHECK_EQUAL ( body(swapped), std::string("RESPONSE") ); + BOOST_CHECK_EQUAL ( swapped_body, std::string("RESPONSE") ); } BOOST_AUTO_TEST_SUITE_END() diff --git a/libs/network/test/https_localhost_tests.cpp b/libs/network/test/https_localhost_tests.cpp index 6dc03f559..808bd6db6 100644 --- a/libs/network/test/https_localhost_tests.cpp +++ b/libs/network/test/https_localhost_tests.cpp @@ -79,7 +79,7 @@ namespace { } std::string get_content_length(std::string const& content) { - return boost::lexical_cast(content.length()); + return boost::lexical_cast(content.size()); } } @@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE(body_test) { http::client::request request_(base_url); http::client client_; http::client::response response_ = client_.get(request_); - BOOST_CHECK(body(response_).length() != 0); + BOOST_CHECK(body(response_).size() != 0); } BOOST_AUTO_TEST_CASE(text_content_type_test) { @@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(content_length_header_test) { headers_range::type range = headers(response_)["Content-Length"]; BOOST_CHECK_EQUAL(boost::begin(range)->first, "Content-Length"); BOOST_CHECK_EQUAL(boost::begin(range)->second, "113"); - BOOST_CHECK(body(response_).length() != 0); + BOOST_CHECK(body(response_).size() != 0); } BOOST_AUTO_TEST_CASE(text_query_preserves_crlf) { @@ -146,7 +146,8 @@ BOOST_AUTO_TEST_CASE(text_query_preserves_crlf) { http::client client_; http::client::response response_ = client_.get(request_); - BOOST_CHECK(body(response_).length() != 0); + http::client::response::string_type body_ = body(response_); + BOOST_CHECK(body_.size() != 0); using std::ios; @@ -162,10 +163,10 @@ BOOST_AUTO_TEST_CASE(text_query_preserves_crlf) { std::size_t size = readfile(file, memblock); BOOST_CHECK(size != 0); - BOOST_CHECK_EQUAL(body(response_).length(), size); + BOOST_CHECK_EQUAL(body(response_).size(), size); - if (body(response_).length() == size) { - std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body(response_).begin()); + if (body(response_).size() == size) { + std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body_.begin()); BOOST_CHECK_EQUAL(boost::numeric_cast(diff_pos.first - memblock.begin()), size); } } @@ -178,7 +179,8 @@ BOOST_AUTO_TEST_CASE(binary_file_query) { http::client::response response_; BOOST_CHECK_NO_THROW(response_ = client_.get(request_)); - BOOST_CHECK(body(response_).length() != 0); + http::client::response::string_type body_ = body(response_); + BOOST_CHECK(body_.size() != 0); using std::ios; @@ -194,9 +196,9 @@ BOOST_AUTO_TEST_CASE(binary_file_query) { std::size_t size = readfile(file, memblock); BOOST_CHECK(size != 0); - BOOST_CHECK_EQUAL(body(response_).length(), size); + BOOST_CHECK_EQUAL(body(response_).size(), size); - std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body(response_).begin()); + std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body_.begin()); BOOST_CHECK_EQUAL(boost::numeric_cast(diff_pos.first - memblock.begin()), size); } @@ -209,7 +211,7 @@ BOOST_AUTO_TEST_CASE(binary_file_query) { // http::client c; // http::client::response r; // BOOST_REQUIRE_NO_THROW(r = c.get(req)); -// BOOST_CHECK(body(r).length() != 0); +// BOOST_CHECK(body(r).size() != 0); // BOOST_CHECK(headers(r)["Content-Type"].begin() != headers(r)["Content-Type"].end()); //} // @@ -220,7 +222,7 @@ BOOST_AUTO_TEST_CASE(binary_file_query) { // http::client c; // http::client::response r; // BOOST_REQUIRE_NO_THROW(r = c.get(req)); -// BOOST_CHECK(body(r).length() != 0); +// BOOST_CHECK(body(r).size() != 0); // BOOST_CHECK(headers(r)["Content-Type"].begin() != headers(r)["Content-Type"].end()); // headers_range::type range=headers(r)["X-CppNetlib-Test"]; // BOOST_REQUIRE(boost::begin(range) != boost::end(range)); @@ -238,7 +240,7 @@ BOOST_AUTO_TEST_CASE(file_not_found) { http::client c; http::client::response r = c.get(req); - BOOST_CHECK(body(r).length() != 0); + BOOST_CHECK(body(r).size() != 0); } BOOST_AUTO_TEST_CASE(head_test) { @@ -250,7 +252,7 @@ BOOST_AUTO_TEST_CASE(head_test) { headers_range::type range = headers(response_)["Content-Length"]; BOOST_CHECK_EQUAL(boost::begin(range)->first, "Content-Length"); BOOST_CHECK_EQUAL(boost::begin(range)->second, "113"); - BOOST_CHECK(body(response_).length() == 0); + BOOST_CHECK(body(response_).size() == 0); } //BOOST_AUTO_TEST_CASE(post_with_explicit_headers) { From 28e523f09e3ab0a0dc817e0cf71188a2b7d0a1dd Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 27 Nov 2010 18:23:36 +0800 Subject: [PATCH 010/768] Fixes to the linearize implementation, and the request include header. --- .../protocol/http/algorithms/linearize.hpp | 5 ++-- boost/network/protocol/http/impl/request.hpp | 29 ++++++++++--------- boost/network/protocol/http/request.hpp | 8 ++++- boost/network/traits/vector.hpp | 13 +++++++-- libs/network/test/CMakeLists.txt | 1 + 5 files changed, 37 insertions(+), 19 deletions(-) diff --git a/boost/network/protocol/http/algorithms/linearize.hpp b/boost/network/protocol/http/algorithms/linearize.hpp index ce9965ba3..e3338419d 100644 --- a/boost/network/protocol/http/algorithms/linearize.hpp +++ b/boost/network/protocol/http/algorithms/linearize.hpp @@ -6,11 +6,12 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include #include #include #include #include -#include +#include #include namespace boost { namespace network { namespace http { @@ -89,7 +90,7 @@ namespace boost { namespace network { namespace http { *oi = consts::colon_char(); *oi = consts::space_char(); boost::copy(request.host(), oi); - boost::copy(host, oi); + boost::copy(crlf, oi); boost::copy(accept, oi); *oi = consts::colon_char(); *oi = consts::space_char(); diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index 5af341999..c98a1269e 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -9,6 +9,7 @@ #define __NETWORK_PROTOCOL_HTTP_REQUEST_IMPL_20070908_1_HPP__ #include +#include #include #include @@ -23,7 +24,20 @@ #include -namespace boost { namespace network { namespace http { +namespace boost { namespace network { + + /** Specialize the traits for the http_server tag. */ + template <> + struct headers_container : + vector::apply > + {}; + + template <> + struct headers_container : + vector::apply > + {}; + +namespace http { /** request.hpp * @@ -123,7 +137,7 @@ namespace boost { namespace network { namespace http { typedef Tag tag; typedef typename string::type string_type; typedef request_header header_type; - typedef typename vector:: + typedef typename vector:: template apply::type vector_type; typedef vector_type headers_container_type; @@ -171,17 +185,6 @@ namespace boost { namespace network { namespace http { } // namespace http - /** Specialize the traits for the http_server tag. */ - template <> - struct headers_container : - vector::apply > - {}; - - template <> - struct headers_container : - vector::apply > - {}; - namespace http { namespace impl { template <> diff --git a/boost/network/protocol/http/request.hpp b/boost/network/protocol/http/request.hpp index a86a55b13..71d78e5bb 100644 --- a/boost/network/protocol/http/request.hpp +++ b/boost/network/protocol/http/request.hpp @@ -27,14 +27,20 @@ #include #include #include -#include #include #include #include +#include #include #include +#include +#include +#include +#include #include #include +#include +#include #include #include diff --git a/boost/network/traits/vector.hpp b/boost/network/traits/vector.hpp index d816921c9..210a13c68 100644 --- a/boost/network/traits/vector.hpp +++ b/boost/network/traits/vector.hpp @@ -6,6 +6,9 @@ #ifndef BOOST_NETWORK_TRAITS_VECTOR_HPP #define BOOST_NETWORK_TRAITS_VECTOR_HPP +#include +#include + namespace boost { namespace network { template @@ -15,9 +18,13 @@ namespace boost { namespace network { struct vector { template - struct apply { - typedef unsupported_tag type; - }; + struct apply : + mpl::if_< + is_default_string + , std::vector + , unsupported_tag + > + {}; }; diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index abb2477e3..49d94ab70 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -30,6 +30,7 @@ if (Boost_FOUND) http_url_test utils_thread_pool http_async_message_ready + http_request_linearize ) foreach (test ${TESTS}) set_source_files_properties(${test}.cpp From e182a57997eabec418471dd7aa30b8f2f91d82f6 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 27 Nov 2010 20:38:33 +0800 Subject: [PATCH 011/768] Fixing bug with HTTP/1.1 accept encoding header. --- .../protocol/http/algorithms/linearize.hpp | 1 + libs/network/test/http_request_linearize.cpp | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 libs/network/test/http_request_linearize.cpp diff --git a/boost/network/protocol/http/algorithms/linearize.hpp b/boost/network/protocol/http/algorithms/linearize.hpp index e3338419d..f7d6cff10 100644 --- a/boost/network/protocol/http/algorithms/linearize.hpp +++ b/boost/network/protocol/http/algorithms/linearize.hpp @@ -101,6 +101,7 @@ namespace boost { namespace network { namespace http { *oi = consts::colon_char(); *oi = consts::space_char(); boost::copy(default_accept_encoding, oi); + boost::copy(crlf, oi); } typedef typename headers_range >::type headers_range; typedef typename range_iterator::type headers_iterator; diff --git a/libs/network/test/http_request_linearize.cpp b/libs/network/test/http_request_linearize.cpp new file mode 100644 index 000000000..c2151a054 --- /dev/null +++ b/libs/network/test/http_request_linearize.cpp @@ -0,0 +1,31 @@ + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE HTTP Request Linearize Test +#include +#include +#include +#include +#include + +namespace http = boost::network::http; +namespace tags = boost::network::http::tags; +namespace mpl = boost::mpl; +namespace net = boost::network; + +typedef mpl::list< + tags::http_default_8bit_tcp_resolve + , tags::http_default_8bit_udp_resolve + , tags::http_async_8bit_tcp_resolve + , tags::http_async_8bit_udp_resolve + > tag_types; + +BOOST_AUTO_TEST_CASE_TEMPLATE(linearize_request, T, tag_types) { + http::basic_request request("http://www.boost.org/"); + linearize(request, "GET", 1, 0, std::ostream_iterator::type>(std::cout)); + linearize(request, "GET", 1, 1, std::ostream_iterator::type>(std::cout)); +} + From 5e47beaef39becde84e7366e243f535813cade1f Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 28 Nov 2010 09:48:27 +0800 Subject: [PATCH 012/768] Implementing an overload to the top-level clear_headers algorithm. --- .../http/message/modifiers/clear_headers.hpp | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 boost/network/protocol/http/message/modifiers/clear_headers.hpp diff --git a/boost/network/protocol/http/message/modifiers/clear_headers.hpp b/boost/network/protocol/http/message/modifiers/clear_headers.hpp new file mode 100644 index 000000000..1d45682a6 --- /dev/null +++ b/boost/network/protocol/http/message/modifiers/clear_headers.hpp @@ -0,0 +1,45 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADER_HPP_20101128 +#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADER_HPP_20101128 + +#include +#include +#include + +namespace boost { namespace network { namespace http { + + namespace impl { + + template + inline typename enable_if< + is_client + , void + >::type + clear_headers(basic_request & request) { + request.headers(typename basic_request::headers_container_type()); + } + + } /* impl */ + + template + inline void clear_headers_impl(basic_request & request, tags::client) { + impl::clear_headers(request); + } + + template + inline void clear_headers_impl(basic_request & request, tags::server) { + typedef typename basic_request::headers_container_type headers_container; + headers_container().swap(request.headers); + } + + template + inline void clear_headers(basic_request & request) { + clear_headers_impl(request, typename client_or_server::type()); + } + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADER_HPP_20101128 */ From 00b27b7a4843f73097b8d96a07b4a3b1a6b53b7c Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 28 Nov 2010 09:49:19 +0800 Subject: [PATCH 013/768] Client or Server Tag Selector This change introduces a selector metafunction that takes a tag, and checks whether it is meant to be a client or server tag. The selector metafunction then yields the actual tag found (whether it is a client or server tag) so that it can be used for function tag dispatch purposes. --- .../http/support/client_or_server.hpp | 35 +++++++++++++++++++ .../protocol/http/support/is_client.hpp | 29 +++++++++++++++ boost/network/protocol/http/tags.hpp | 13 +++---- 3 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 boost/network/protocol/http/support/client_or_server.hpp create mode 100644 boost/network/protocol/http/support/is_client.hpp diff --git a/boost/network/protocol/http/support/client_or_server.hpp b/boost/network/protocol/http/support/client_or_server.hpp new file mode 100644 index 000000000..083b59c78 --- /dev/null +++ b/boost/network/protocol/http/support/client_or_server.hpp @@ -0,0 +1,35 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_CLIENT_OR_SERVER_HPP_20101127 +#define BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_CLIENT_OR_SERVER_HPP_20101127 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +namespace boost { namespace network { namespace http { + + template + struct client_or_server : + mpl::if_< + is_server, + tags::server, + typename mpl::if_< + is_client, + tags::client, + unsupported_tag + >::type + > + {}; + + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_CLIENT_OR_SERVER_HPP_20101127 */ diff --git a/boost/network/protocol/http/support/is_client.hpp b/boost/network/protocol/http/support/is_client.hpp new file mode 100644 index 000000000..c479abaf1 --- /dev/null +++ b/boost/network/protocol/http/support/is_client.hpp @@ -0,0 +1,29 @@ +#ifndef BOOST_NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_HPP_20101118 +#define BOOST_NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_HPP_20101118 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +namespace boost { namespace network { namespace http { + + template + struct is_client : + is_base_of< + tags::client, + Tag + > + {}; + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_SUPPORT_IS_CLIENT_HPP_20101118 */ + diff --git a/boost/network/protocol/http/tags.hpp b/boost/network/protocol/http/tags.hpp index 9803c840f..65287e895 100644 --- a/boost/network/protocol/http/tags.hpp +++ b/boost/network/protocol/http/tags.hpp @@ -14,18 +14,19 @@ namespace boost { namespace network { namespace http { namespace tags { struct keepalive {}; struct simple {}; struct server {}; + struct client {}; using namespace boost::network::tags; template struct components; - typedef mpl::vector http_default_8bit_tcp_resolve_tags; - typedef mpl::vector http_default_8bit_udp_resolve_tags; - typedef mpl::vector http_keepalive_8bit_tcp_resolve_tags; - typedef mpl::vector http_keepalive_8bit_udp_resolve_tags; - typedef mpl::vector http_async_8bit_udp_resolve_tags; - typedef mpl::vector http_async_8bit_tcp_resolve_tags; + typedef mpl::vector http_default_8bit_tcp_resolve_tags; + typedef mpl::vector http_default_8bit_udp_resolve_tags; + typedef mpl::vector http_keepalive_8bit_tcp_resolve_tags; + typedef mpl::vector http_keepalive_8bit_udp_resolve_tags; + typedef mpl::vector http_async_8bit_udp_resolve_tags; + typedef mpl::vector http_async_8bit_tcp_resolve_tags; typedef mpl::vector http_server_tags; typedef mpl::vector http_async_server_tags; From e1cee5641c87b90175decf769a100c3a73644036 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 28 Nov 2010 09:51:00 +0800 Subject: [PATCH 014/768] Making Linearize more Generic This implementation of linearize turns it into a generic algorithm that works on types that model the Client Request concept. This is important because it means any type that models the Client Request concept can then be linearized into an output iterator. --- boost/network/message.hpp | 1 + .../protocol/http/algorithms/linearize.hpp | 17 ++++++---- .../protocol/http/message/modifiers/body.hpp | 29 +++++++++++++---- .../http/message/modifiers/destination.hpp | 31 ++++++++++++------ .../http/message/modifiers/headers.hpp | 7 ++-- .../http/message/modifiers/source.hpp | 32 ++++++++++++------- boost/network/protocol/http/request.hpp | 1 + 7 files changed, 78 insertions(+), 40 deletions(-) diff --git a/boost/network/message.hpp b/boost/network/message.hpp index 9d044a8d9..42821fdac 100644 --- a/boost/network/message.hpp +++ b/boost/network/message.hpp @@ -44,6 +44,7 @@ namespace boost { namespace network { typedef Tag tag; typedef typename headers_container::type headers_container_type; + typedef typename headers_container_type::value_type header_type; typedef typename string::type string_type; basic_message() diff --git a/boost/network/protocol/http/algorithms/linearize.hpp b/boost/network/protocol/http/algorithms/linearize.hpp index f7d6cff10..8010f19bd 100644 --- a/boost/network/protocol/http/algorithms/linearize.hpp +++ b/boost/network/protocol/http/algorithms/linearize.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -43,15 +44,19 @@ namespace boost { namespace network { namespace http { } }; - template - OutputIterator linearize( - basic_request const & request, - typename string::type const & method, + template + BOOST_CONCEPT_REQUIRES( + ((ClientRequest)), + (OutputIterator) + ) linearize( + Request const & request, + typename Request::string_type const & method, unsigned version_major, unsigned version_minor, OutputIterator oi ) { + typedef typename Request::tag Tag; typedef constants consts; typedef typename string::type string_type; static string_type @@ -103,7 +108,7 @@ namespace boost { namespace network { namespace http { boost::copy(default_accept_encoding, oi); boost::copy(crlf, oi); } - typedef typename headers_range >::type headers_range; + typedef typename headers_range::type headers_range; typedef typename range_iterator::type headers_iterator; headers_range request_headers = headers(request); headers_iterator iterator = boost::begin(request_headers), @@ -125,7 +130,7 @@ namespace boost { namespace network { namespace http { boost::copy(crlf, oi); } boost::copy(crlf, oi); - typename body_range >::type body_data = body(request).range(); + typename body_range::type body_data = body(request).range(); return boost::copy(body_data, oi); } diff --git a/boost/network/protocol/http/message/modifiers/body.hpp b/boost/network/protocol/http/message/modifiers/body.hpp index 71f69a4f5..1b7b5b7a2 100644 --- a/boost/network/protocol/http/message/modifiers/body.hpp +++ b/boost/network/protocol/http/message/modifiers/body.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -37,26 +38,40 @@ namespace boost { namespace network { namespace http { request.body = value; } + template + void body(basic_request & request, T const & value, tags::client const &) { + request << ::boost::network::body(value); + } + } template - inline - BOOST_CONCEPT_REQUIRES(((Response >)), - (void)) + inline void body(basic_response & response, T const & value) { impl::body(response, value, is_async()); } + template + inline void + body_impl(basic_request & request, T const & value, tags::server) { + impl::body(request, value, Tag()); + } + template - struct ServerRequest; + struct ClientRequest; template - inline BOOST_CONCEPT_REQUIRES(((ServerRequest >)), - (void)) - body(basic_request & request, T const & value) { + inline void + body_impl(basic_request & request, T const & value, tags::client) { impl::body(request, value, Tag()); } + template + inline void + body(basic_request & request, T const & value) { + body_impl(request, value, typename client_or_server::type()); + } + } // namespace http namespace impl { diff --git a/boost/network/protocol/http/message/modifiers/destination.hpp b/boost/network/protocol/http/message/modifiers/destination.hpp index b54fb17c0..f8107de80 100644 --- a/boost/network/protocol/http/message/modifiers/destination.hpp +++ b/boost/network/protocol/http/message/modifiers/destination.hpp @@ -6,6 +6,7 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include #include #include #include @@ -35,15 +36,15 @@ namespace boost { namespace network { namespace http { request.destination = value; } - } + template + void destination(basic_request & request, T const & value, tags::client const &) { + request << ::boost::network::destination(value); + } - template - struct Response; + } template - inline - BOOST_CONCEPT_REQUIRES(((Response >)), - (void)) + inline void destination(basic_response & response, T const & value) { impl::destination(response, value, is_async()); } @@ -52,13 +53,23 @@ namespace boost { namespace network { namespace http { struct ServerRequest; template - inline - BOOST_CONCEPT_REQUIRES(((ServerRequest >)), - (void)) - destination(basic_request & request, T const & value) { + inline void + destination_impl(basic_request & request, T const & value, tags::server) { + impl::destination(request, value, Tag()); + } + + template + inline void + destination_impl(basic_request & request, T const & value, tags::client) { impl::destination(request, value, Tag()); } + template + inline void + destination(basic_request & request, T const & value) { + destination_impl(request, value, typename client_or_server::type()); + } + } // namespace http namespace impl { diff --git a/boost/network/protocol/http/message/modifiers/headers.hpp b/boost/network/protocol/http/message/modifiers/headers.hpp index 3b781107c..d789a7452 100644 --- a/boost/network/protocol/http/message/modifiers/headers.hpp +++ b/boost/network/protocol/http/message/modifiers/headers.hpp @@ -38,16 +38,13 @@ namespace boost { namespace network { namespace http { } template - inline - BOOST_CONCEPT_REQUIRES(((Response >)), - (void)) + inline void headers(basic_response & response, T const & value) { impl::headers(response, value, is_async()); } template - inline BOOST_CONCEPT_REQUIRES(((ServerRequest >)), - (void)) + inline void headers(basic_request & request, T const & value) { impl::headers(request, value, Tag()); } diff --git a/boost/network/protocol/http/message/modifiers/source.hpp b/boost/network/protocol/http/message/modifiers/source.hpp index 40324291b..0f4df485d 100644 --- a/boost/network/protocol/http/message/modifiers/source.hpp +++ b/boost/network/protocol/http/message/modifiers/source.hpp @@ -7,6 +7,7 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#include #include #include #include @@ -34,28 +35,35 @@ namespace boost { namespace network { namespace http { request.source = value; } - } + template + void source(basic_request & request, T const & value, tags::client const &) { + request << ::boost::network::source(value); + } - template - struct Response; + } template - inline - BOOST_CONCEPT_REQUIRES(((Response >)), - (void)) + inline void source(basic_response & response, T const & value) { impl::source(response, value, is_async()); } - template - struct ServerRequest; + template + inline void + source_impl(basic_request & request, T const & value, tags::server) { + impl::source(request, value, Tag()); + } + + template + inline void + source_impl(basic_request & request, T const & value, tags::client) { + impl::source(request, value, Tag()); + } template - inline - BOOST_CONCEPT_REQUIRES(((ServerRequest >)), - (void)) + inline void source(basic_request & request, T const & value) { - impl::source(request, value, Tag()); + source_impl(request, value, typename client_or_server::type()); } } // namespace http diff --git a/boost/network/protocol/http/request.hpp b/boost/network/protocol/http/request.hpp index 71d78e5bb..7ac1fa412 100644 --- a/boost/network/protocol/http/request.hpp +++ b/boost/network/protocol/http/request.hpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include From e462ae1094783d423d7bc1e590f08cc2f87291e5 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 28 Nov 2010 14:06:31 +0800 Subject: [PATCH 015/768] Adding a selector for pod-like or normal tags for messages. --- boost/network/support/pod_or_normal.hpp | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 boost/network/support/pod_or_normal.hpp diff --git a/boost/network/support/pod_or_normal.hpp b/boost/network/support/pod_or_normal.hpp new file mode 100644 index 000000000..1de090d4b --- /dev/null +++ b/boost/network/support/pod_or_normal.hpp @@ -0,0 +1,28 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_POD_OR_NORMAL_HPP_20101128 +#define BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_POD_OR_NORMAL_HPP_20101128 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +namespace boost { namespace network { + + template + struct pod_or_normal : + mpl::if_< + is_pod + , tags::pod + , tags::normal + > + {}; + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SUPPORT_POD_OR_NORMAL_HPP_20101128 */ From 3133d244951f189dca19cf5d8a3009c5fbee7895 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 28 Nov 2010 14:06:59 +0800 Subject: [PATCH 016/768] Adding the normal tag. --- boost/network/tags.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/boost/network/tags.hpp b/boost/network/tags.hpp index 0312542a0..b652b1b87 100644 --- a/boost/network/tags.hpp +++ b/boost/network/tags.hpp @@ -16,6 +16,7 @@ namespace boost { namespace network { namespace tags { struct pod {}; + struct normal {}; struct async {}; struct tcp {}; struct udp {}; From 2af5fb0b36284c216e75cd6cfc82b6014f3e48cc Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 28 Nov 2010 14:07:59 +0800 Subject: [PATCH 017/768] Cleaning up tag dispatch of HTTP-specific modifiers. --- .../protocol/http/message/modifiers/body.hpp | 17 ++--------- .../http/message/modifiers/clear_headers.hpp | 28 +++++++++++-------- .../http/message/modifiers/destination.hpp | 27 ++++++++++-------- 3 files changed, 33 insertions(+), 39 deletions(-) diff --git a/boost/network/protocol/http/message/modifiers/body.hpp b/boost/network/protocol/http/message/modifiers/body.hpp index 1b7b5b7a2..d88961dd3 100644 --- a/boost/network/protocol/http/message/modifiers/body.hpp +++ b/boost/network/protocol/http/message/modifiers/body.hpp @@ -33,16 +33,6 @@ namespace boost { namespace network { namespace http { response.body(future); } - template - void body(basic_request & request, T const & value, tags::server const &) { - request.body = value; - } - - template - void body(basic_request & request, T const & value, tags::client const &) { - request << ::boost::network::body(value); - } - } template @@ -54,16 +44,13 @@ namespace boost { namespace network { namespace http { template inline void body_impl(basic_request & request, T const & value, tags::server) { - impl::body(request, value, Tag()); + request.body = value; } - template - struct ClientRequest; - template inline void body_impl(basic_request & request, T const & value, tags::client) { - impl::body(request, value, Tag()); + request << ::boost::network::body(value); } template diff --git a/boost/network/protocol/http/message/modifiers/clear_headers.hpp b/boost/network/protocol/http/message/modifiers/clear_headers.hpp index 1d45682a6..33e9f5854 100644 --- a/boost/network/protocol/http/message/modifiers/clear_headers.hpp +++ b/boost/network/protocol/http/message/modifiers/clear_headers.hpp @@ -1,28 +1,32 @@ #ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADER_HPP_20101128 #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_MODIFIERS_CLEAR_HEADER_HPP_20101128 +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + #include +#include #include #include namespace boost { namespace network { namespace http { - namespace impl { - - template - inline typename enable_if< - is_client - , void - >::type - clear_headers(basic_request & request) { - request.headers(typename basic_request::headers_container_type()); - } + template + inline void clear_headers_impl(basic_request & request, tags::pod) { + typedef typename basic_request::headers_container_type headers_container; + headers_container().swap(request.headers); + } - } /* impl */ + template + inline void clear_headers_impl(basic_request & request, tags::normal) { + request.headers(typename basic_request::headers_container_type()); + } template inline void clear_headers_impl(basic_request & request, tags::client) { - impl::clear_headers(request); + clear_headers_impl(request, typename pod_or_normal::type()); } template diff --git a/boost/network/protocol/http/message/modifiers/destination.hpp b/boost/network/protocol/http/message/modifiers/destination.hpp index f8107de80..f0532abba 100644 --- a/boost/network/protocol/http/message/modifiers/destination.hpp +++ b/boost/network/protocol/http/message/modifiers/destination.hpp @@ -7,6 +7,7 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#include #include #include #include @@ -31,16 +32,6 @@ namespace boost { namespace network { namespace http { response.destination(future); } - template - void destination(basic_request & request, T const & value, tags::server const &) { - request.destination = value; - } - - template - void destination(basic_request & request, T const & value, tags::client const &) { - request << ::boost::network::destination(value); - } - } template @@ -55,13 +46,25 @@ namespace boost { namespace network { namespace http { template inline void destination_impl(basic_request & request, T const & value, tags::server) { - impl::destination(request, value, Tag()); + request.destination = value; + } + + template + inline void + destination_impl(basic_request & request, T const & value, tags::pod) { + request.destination = value; + } + + template + inline void + destination_impl(basic_request & request, T const & value, tags::normal) { + request.destination(value); } template inline void destination_impl(basic_request & request, T const & value, tags::client) { - impl::destination(request, value, Tag()); + destination_impl(request, value, typename pod_or_normal::type()); } template From 1ba80791c8e6a7ce31b8ab675f739a9f0b2c62c1 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 28 Nov 2010 14:08:45 +0800 Subject: [PATCH 018/768] Simplifying tag dispatch for body modifier. --- boost/network/message/modifiers/body.hpp | 26 ++++++++++-------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/boost/network/message/modifiers/body.hpp b/boost/network/message/modifiers/body.hpp index a403a938c..317264c68 100644 --- a/boost/network/message/modifiers/body.hpp +++ b/boost/network/message/modifiers/body.hpp @@ -6,28 +6,24 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#include #include namespace boost { namespace network { - namespace impl { - - template - inline void body(Message const & message, ValueType const & body_, Tag const &, mpl::false_ const &) { - message.body(body_); - } - - template - inline void body(Message const & message, ValueType const & body_, Tag const &, mpl::true_ const &) { - message.body(body_); - } + template class Message, class ValueType> + inline void body_impl(Message & message, ValueType const & body, tags::pod) { + message.body = body; + } - } // namespace impl + template class Message, class ValueType> + inline void body_impl(Message & message, ValueType const & body, tags::normal) { + message.body(body); + } template class Message, class ValueType> - inline void body(Message const & message, ValueType const & body_) { - impl::body(message, body_, Tag(), is_async()); + inline void body(Message & message, ValueType const & body_) { + body_impl(message, body_, typename pod_or_normal::type()); } } // namespace network From 3b89b673d8d46d9f5fa7988377be2a59e9f5d488 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 28 Nov 2010 14:09:21 +0800 Subject: [PATCH 019/768] Removing Boost.Variant from Directives This commit removes the reliance on Boost.Variant, and turns directives into SFINAE aware directives based on the tag of the message. Basically, what we want to happen is for code like the following to fail to compile: basic_message m; std::wstring w; m << source(w); The reason it should fail to compile is because the default_string tag tells basic_message to encapsulate std::string, not std::wstring objects for the source. Previously, with the Boost.Variant solution this code would compile and is therefore a serious bug. --- boost/network/message/directives.hpp | 3 - .../directives/detail/string_directive.hpp | 157 +++++------------- 2 files changed, 37 insertions(+), 123 deletions(-) diff --git a/boost/network/message/directives.hpp b/boost/network/message/directives.hpp index d6195802c..005a91e14 100644 --- a/boost/network/message/directives.hpp +++ b/boost/network/message/directives.hpp @@ -7,9 +7,6 @@ #ifndef __NETWORK_MESSAGE_DIRECTIVES_HPP__ #define __NETWORK_MESSAGE_DIRECTIVES_HPP__ -/** Include all the various directive headers. - */ - #include #include #include diff --git a/boost/network/message/directives/detail/string_directive.hpp b/boost/network/message/directives/detail/string_directive.hpp index ce5c2870c..6f2da4430 100644 --- a/boost/network/message/directives/detail/string_directive.hpp +++ b/boost/network/message/directives/detail/string_directive.hpp @@ -10,134 +10,51 @@ #include #include #include +#include +#include #include #include -#include -namespace boost { namespace network { namespace detail { - - /** This directive template technically implements a decorator pattern - * which takes a concrete implementation and uses that as a base. This - * particular directive template requires the Base type to just include - * a nested template named `string_visitor` that takes a single template - * class parameter which is supposed to be a Message class/struct. - * - * A typical directive implementation of the visitor will take a reference - * to a message as the constructor parameter and then performs operations - * on that message. - * - * To create your own string directive, you can use the preprocessor macro - * BOOST_NETWORK_STRING_DIRECTIVE which takes three parameters: the name of - * the directive, a name for the variable to use in the directive visitor, - * and the body to be implemented in the visitor. An example directive for - * setting the source of a message would look something like this given the - * BOOST_NETWORK_STRING_DIRECTIVE macro: - * - * BOOST_NETWORK_STRING_DIRECTIVE(source, source_, - * message.source(source_) - * , message.source=source_); - * - */ - template - struct string_directive : public Base { - boost::variant< - string::type, - string::type, - boost::shared_future::type>, - boost::shared_future::type> - > string_; - - explicit string_directive(string::type const & input) - : string_(input) {} - explicit string_directive(string::type const & input) - : string_(input) {} - explicit string_directive(boost::shared_future::type> const & input) - : string_(input) {} - explicit string_directive(boost::shared_future::type> const & input) - : string_(input) {} - - string_directive(string_directive const & other) - : string_(other.string_) {} - - template class Message> - void operator()(Message const & message) const { - apply_visitor(typename Base::template string_visitor >(message), string_); - } - }; +/** + * + * To create your own string directive, you can use the preprocessor macro + * BOOST_NETWORK_STRING_DIRECTIVE which takes three parameters: the name of + * the directive, a name for the variable to use in the directive visitor, + * and the body to be implemented in the visitor. An example directive for + * setting the source of a message would look something like this given the + * BOOST_NETWORK_STRING_DIRECTIVE macro: + * + * BOOST_NETWORK_STRING_DIRECTIVE(source, source_, + * message.source(source_) + * , message.source=source_); + * + */ +#ifndef BOOST_NETWORK_STRING_DIRECTIVE #define BOOST_NETWORK_STRING_DIRECTIVE(name, value, body, pod_body) \ - struct name##_directive_base { \ - \ - template \ - struct normal_visitor : boost::static_visitor<> { \ - Message const & message; \ - explicit normal_visitor(Message const & message) : \ - message(message) {} \ - void operator()( \ - typename boost::network::detail::string_value< \ - typename Message::tag \ - >::type const & value \ - ) const { \ - body; \ - } \ - template void operator()(T const &) const { \ - } \ - }; \ - \ - template \ - struct pod_visitor : boost::static_visitor<> { \ - Message const & message; \ - explicit pod_visitor(Message const & message) : \ - message(message) {} \ - void operator()( \ - typename boost::network::detail::string_value< \ - typename Message::tag \ - >::type const & value \ - ) { \ - pod_body; \ - } \ - template void operator()(T const &) const { \ - } \ - }; \ - \ - template \ - struct string_visitor : \ - mpl::if_< \ - is_base_of< \ - tags::pod, \ - typename Message::tag \ - >, \ - pod_visitor, \ - normal_visitor \ - >::type \ - { \ - typedef typename mpl::if_< \ - is_base_of< \ - tags::pod, \ - typename Message::tag \ - >, \ - pod_visitor, \ - normal_visitor \ - >::type base; \ - explicit string_visitor(Message const & message): \ - base(message) {} \ - string_visitor(string_visitor const & other): \ - base(other) {} \ - using base::operator(); \ - }; \ + template \ + struct name##_directive { \ + ValueType const & value; \ + explicit name##_directive(ValueType const & value_) \ + : value(value_) {} \ + name##_directive(name##_directive const & other) \ + : value(other.value) {} \ + template class Message> \ + typename enable_if, void>::type \ + operator()(Message & message) const { \ + pod_body; \ + } \ + template class Message> \ + typename enable_if >, void>::type \ + operator()(Message & message) const { \ + body; \ + } \ }; \ \ - typedef boost::network::detail::string_directive \ - name##_directive; \ - template inline name##_directive const \ + template inline name##_directive \ name (T const & input) { \ - return name##_directive(input); \ + return name##_directive(input); \ } - -} /* detail */ - -} /* network */ - -} /* boost */ +#endif /* BOOST_NETWORK_STRING_DIRECTIVE */ #endif /* BOOST_NETWORK_MESSAGE_DIRECTIVES_DETAIL_STRING_DIRECTIVE_HPP_20100915 */ From 411bac0d60edfb9d2a463a14dc0a22ca6589edd9 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Wed, 1 Dec 2010 20:48:55 +0800 Subject: [PATCH 020/768] Adding missing include for Boost.MPL or_ --- boost/network/protocol/http/message/traits/version.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/boost/network/protocol/http/message/traits/version.hpp b/boost/network/protocol/http/message/traits/version.hpp index 089e8a12e..7e32ab20c 100644 --- a/boost/network/protocol/http/message/traits/version.hpp +++ b/boost/network/protocol/http/message/traits/version.hpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace boost { namespace network { namespace http { From 48e511e4b9eac3b3526b1df8ed121819a9bd727d Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Wed, 1 Dec 2010 20:49:34 +0800 Subject: [PATCH 021/768] Making the grammar instantiation static to avoid construction/destruction of the grammar on multiple calls to parse_uri. --- boost/network/uri/detail/parse_uri.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boost/network/uri/detail/parse_uri.hpp b/boost/network/uri/detail/parse_uri.hpp index f11872d86..dbbe7d427 100644 --- a/boost/network/uri/detail/parse_uri.hpp +++ b/boost/network/uri/detail/parse_uri.hpp @@ -247,7 +247,7 @@ bool parse_uri(Range & range, uri_parts & parts) { iterator start_ = boost::begin(range); iterator end_ = boost::end(range); - uri_grammar grammar; + static uri_grammar grammar; bool ok = qi::parse(start_, end_, grammar, parts); From 8c6a08a4b0bd2354326530e0957bb5ef31cecdac Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 3 Dec 2010 11:13:11 +0800 Subject: [PATCH 022/768] Starting to break down the HTTP client tests to reduce test build times. --- libs/network/test/CMakeLists.txt | 20 ++---- libs/network/test/http/CMakeLists.txt | 64 +++++++++++++++++++ .../test/http/client_constructor_test.cpp | 27 ++++++++ .../http/client_get_different_port_test.cpp | 35 ++++++++++ libs/network/test/http/client_get_test.cpp | 42 ++++++++++++ .../test/http/client_get_timeout_test.cpp | 32 ++++++++++ .../server_async.cpp} | 0 .../server_hello_world.cpp} | 0 libs/network/test/http/tag_types.hpp | 22 +++++++ 9 files changed, 226 insertions(+), 16 deletions(-) create mode 100644 libs/network/test/http/CMakeLists.txt create mode 100644 libs/network/test/http/client_constructor_test.cpp create mode 100644 libs/network/test/http/client_get_different_port_test.cpp create mode 100644 libs/network/test/http/client_get_test.cpp create mode 100644 libs/network/test/http/client_get_timeout_test.cpp rename libs/network/test/{http_async_server.cpp => http/server_async.cpp} (100%) rename libs/network/test/{hello_world.cpp => http/server_hello_world.cpp} (100%) create mode 100644 libs/network/test/http/tag_types.hpp diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index 49d94ab70..ff7500b6b 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -14,6 +14,8 @@ find_package( Threads ) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) +add_subdirectory(http) + if (Boost_FOUND) set( TESTS @@ -41,22 +43,8 @@ if (Boost_FOUND) target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) endif() set_target_properties(cpp-netlib-${test} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ../../../build/tests) - add_test(cpp-netlib-${test} ../../../build/tests/cpp-netlib-${test}) - endforeach (test) - - set(SERVER_TESTS - hello_world - http_async_server - ) - foreach (test ${SERVER_TESTS}) - set_source_files_properties(${test}.cpp - PROPERTIES COMPILE_FLAGS "-Wall") - add_executable(cpp-netlib-${test} ${test}.cpp) - target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) - set_target_properties(cpp-netlib-${test} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ../../../build/tests) - add_test(cpp-netlib-${test} python httplib_acceptance.py ../../../build/tests/cpp-netlib-${test} ../../../build/tests/cpp-netlib-${test}.passed) + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) endforeach (test) endif() diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt new file mode 100644 index 000000000..42e92f180 --- /dev/null +++ b/libs/network/test/http/CMakeLists.txt @@ -0,0 +1,64 @@ + +# Copyright 2010 Dean Michael Berris. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +include_directories(${CPP-NETLIB_SOURCE_DIR}) +find_package( Boost 1.43.0 COMPONENTS unit_test_framework system regex thread filesystem ) +find_package( OpenSSL ) + +if (OPENSSL_FOUND) + include_directories( ${OPENSSL_INCLUDE_DIR} ) + add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) +endif() + +find_package( Threads ) +set(Boost_USE_STATIC_LIBS ON) +set(Boost_USE_MULTITHREADED ON) + +if (Boost_FOUND) + set ( TESTS + client_constructor_test + client_get_test + client_get_different_port_test + client_get_timeout_test + ) + foreach ( test ${TESTS} ) + if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") + endif() + add_executable(cpp-netlib-http-${test} ${test}.cpp) + target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + if (OPENSSL_FOUND) + target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) + endif() + set_target_properties(cpp-netlib-http-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-http-${test} + %{CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) + endforeach (test) + + set ( SERVER_TESTS + server_hello_world + server_async + ) + foreach ( test ${SERVER_TESTS} ) + if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") + endif() + add_executable(cpp-netlib-http-${test} ${test}.cpp) + target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + set_target_properties(cpp-netlib-http-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-${test} + python + ${CPP-NETLIB_SOURCE_DIR}/libs/network/httplib_acceptance.py + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test} + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}.passed) + endforeach (test) + +endif() diff --git a/libs/network/test/http/client_constructor_test.cpp b/libs/network/test/http/client_constructor_test.cpp new file mode 100644 index 000000000..41bb06d44 --- /dev/null +++ b/libs/network/test/http/client_constructor_test.cpp @@ -0,0 +1,27 @@ + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE HTTP 1.0 Client Constructor Test +#include +#include +#include "tag_types.hpp" + +namespace http = boost::network::http; + +BOOST_AUTO_TEST_CASE_TEMPLATE(http_1_0_constructor_test, T, tag_types) { + typedef http::basic_client client; + client instance; + boost::asio::io_service io_service; + client instance2(io_service); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(http_1_1_constructor_test, T, tag_types) { + typedef http::basic_client client; + client instance; + boost::asio::io_service io_service; + client instance2(io_service); +} + diff --git a/libs/network/test/http/client_get_different_port_test.cpp b/libs/network/test/http/client_get_different_port_test.cpp new file mode 100644 index 000000000..53e8b1b83 --- /dev/null +++ b/libs/network/test/http/client_get_different_port_test.cpp @@ -0,0 +1,35 @@ + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE HTTP Client Get Different Port Test +#include +#include +#include "tag_types.hpp" + +namespace net = boost::network; +namespace http = boost::network::http; + +BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_different_port_1_0, T, tag_types) { + typedef http::basic_client client; + typename client::request request("http://www.boost.org/"); + client client_; + typename client::response response_ = client_.get(request); + typename net::headers_range >::type range = headers(response_)["Content-Type"]; + BOOST_CHECK ( boost::begin(range) != boost::end(range) ); + BOOST_CHECK ( body(response_).size() != 0 ); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_different_port_1_1, T, tag_types) { + typedef http::basic_client client; + typename client::request request("http://www.boost.org/"); + typename client::response response_; + client client_; + BOOST_CHECK_NO_THROW ( response_ = client_.get(request) ); + typename net::headers_range::type range = headers(response_)["Content-Type"]; + BOOST_CHECK ( boost::begin(range) != boost::end(range) ); + BOOST_CHECK ( body(response_).size() != 0 ); +} + diff --git a/libs/network/test/http/client_get_test.cpp b/libs/network/test/http/client_get_test.cpp new file mode 100644 index 000000000..383bf5d0d --- /dev/null +++ b/libs/network/test/http/client_get_test.cpp @@ -0,0 +1,42 @@ +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE HTTP 1.0 Get Test +#include +#include +#include "tag_types.hpp" + +namespace net = boost::network; +namespace http = boost::network::http; + + +BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_test, T, tag_types) { + typedef http::basic_client client; + typename client::request request("http://www.boost.org/"); + client client_; + typename client::response response; + BOOST_CHECK_NO_THROW ( response = client_.get(request) ); + typename net::headers_range::type range = headers(response)["Content-Type"]; + BOOST_CHECK ( !boost::empty(range) ); + BOOST_CHECK ( body(response).size() != 0 ); + BOOST_CHECK_EQUAL ( response.version().substr(0,7), std::string("HTTP/1.") ); + BOOST_CHECK_EQUAL ( response.status(), 200u ); + BOOST_CHECK_EQUAL ( response.status_message(), std::string("OK") ); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test, T, tag_types) { + typedef http::basic_client client; + typename client::request request("http://www.boost.org/"); + typename client::response response_; + client client_; + BOOST_CHECK_NO_THROW ( response_ = client_.get(request) ); + typename net::headers_range::type range = headers(response_)["Content-Type"]; + BOOST_CHECK ( boost::begin(range) != boost::end(range) ); + BOOST_CHECK ( body(response_).size() != 0 ); + BOOST_CHECK_EQUAL ( response_.version().substr(0,7), std::string("HTTP/1.") ); + BOOST_CHECK_EQUAL ( response_.status(), 200u ); + BOOST_CHECK_EQUAL ( response_.status_message(), std::string("OK") ); +} + diff --git a/libs/network/test/http/client_get_timeout_test.cpp b/libs/network/test/http/client_get_timeout_test.cpp new file mode 100644 index 000000000..a5ec69f20 --- /dev/null +++ b/libs/network/test/http/client_get_timeout_test.cpp @@ -0,0 +1,32 @@ + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE HTTP Client Get Timeout Test +#include +#include +#include "tag_types.hpp" + +namespace http = boost::network::http; + +BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_timeout_1_0, T, tag_types) { + typedef http::basic_client client; + typename client::request request("http://localhost:12121/"); + client client_; + typename client::response response_; + boost::uint16_t port_ = port(request); + BOOST_CHECK_EQUAL ( 12121, port_ ); + BOOST_CHECK_THROW ( response_ = client_.get(request); body(response_); , std::exception ); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_timeout_1_1, T, tag_types) { + typedef http::basic_client client_type; + typename client_type::request request("http://localhost:12121/"); + typename client_type::response response_; + boost::uint16_t port_ = port(request); + BOOST_CHECK_EQUAL ( 12121, port_ ); + client_type client_; + BOOST_CHECK_THROW ( response_ = client_.get(request); body(response_); , std::exception ); +} diff --git a/libs/network/test/http_async_server.cpp b/libs/network/test/http/server_async.cpp similarity index 100% rename from libs/network/test/http_async_server.cpp rename to libs/network/test/http/server_async.cpp diff --git a/libs/network/test/hello_world.cpp b/libs/network/test/http/server_hello_world.cpp similarity index 100% rename from libs/network/test/hello_world.cpp rename to libs/network/test/http/server_hello_world.cpp diff --git a/libs/network/test/http/tag_types.hpp b/libs/network/test/http/tag_types.hpp new file mode 100644 index 000000000..8e842b2e0 --- /dev/null +++ b/libs/network/test/http/tag_types.hpp @@ -0,0 +1,22 @@ +#ifndef TAG_TYPES_4NNM8B5T +#define TAG_TYPES_4NNM8B5T + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +namespace http = boost::network::http; + +typedef boost::mpl::list< + http::tags::http_default_8bit_tcp_resolve + , http::tags::http_default_8bit_udp_resolve + , http::tags::http_async_8bit_udp_resolve + , http::tags::http_async_8bit_tcp_resolve +> tag_types; + + +#endif /* TAG_TYPES_4NNM8B5T */ From a0b53b619ed67f6c485301336a3060fe0f20321d Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 3 Dec 2010 11:25:11 +0800 Subject: [PATCH 023/768] Adding include for MPL or_. --- boost/network/message/traits/body.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/boost/network/message/traits/body.hpp b/boost/network/message/traits/body.hpp index edd2efbb9..25cb14961 100644 --- a/boost/network/message/traits/body.hpp +++ b/boost/network/message/traits/body.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace boost { namespace network { From d9e2dee4f1e59bf426705d9673c18e83ff0dc426 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 3 Dec 2010 11:36:09 +0800 Subject: [PATCH 024/768] Fixing performance problem with pooled connections not getting properly closed when the handle is destroyed. --- boost/network/protocol/http/policies/pooled_connection.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/boost/network/protocol/http/policies/pooled_connection.hpp b/boost/network/protocol/http/policies/pooled_connection.hpp index 195dc7dda..28d85541a 100644 --- a/boost/network/protocol/http/policies/pooled_connection.hpp +++ b/boost/network/protocol/http/policies/pooled_connection.hpp @@ -44,6 +44,7 @@ namespace boost { namespace network { namespace http { } ~connection_impl () { + pimpl->close_socket(); pimpl.reset(); } From c565cec523a580a2e4c3bb9d1a427af81b77b15f Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 3 Dec 2010 12:12:26 +0800 Subject: [PATCH 025/768] Adding the optional HTTPS support. --- libs/network/test/http/client_get_test.cpp | 25 +++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/libs/network/test/http/client_get_test.cpp b/libs/network/test/http/client_get_test.cpp index 383bf5d0d..26dc01259 100644 --- a/libs/network/test/http/client_get_test.cpp +++ b/libs/network/test/http/client_get_test.cpp @@ -11,7 +11,6 @@ namespace net = boost::network; namespace http = boost::network::http; - BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_test, T, tag_types) { typedef http::basic_client client; typename client::request request("http://www.boost.org/"); @@ -40,3 +39,27 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test, T, tag_types) { BOOST_CHECK_EQUAL ( response_.status_message(), std::string("OK") ); } +#ifdef BOOST_NETWORK_ENABLE_HTTPS + +BOOST_AUTO_TEST_CASE_TEMPLATE(https_get_test_1_0, T, tag_types) { + typedef http::basic_client client; + typename client::request request("https://www.google.com/"); + client client_; + typename client::response response_ = client_.get(request); + typename net::headers_range >::type range = headers(response_)["Content-Type"]; + BOOST_CHECK ( boost::begin(range) != boost::end(range) ); + BOOST_CHECK ( body(response_).size() != 0 ); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(https_get_test_1_1, T, tag_types) { + typedef http::basic_client client; + typename client::request request("https://www.google.com/"); + client client_; + typename client::response response_ = client_.get(request); + typename net::headers_range >::type range = headers(response_)["Content-Type"]; + BOOST_CHECK ( boost::begin(range) != boost::end(range) ); + BOOST_CHECK ( body(response_).size() != 0 ); +} + +#endif + From 8fd3034ab0d9072d6b0c1382c138cb25307e4e12 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 3 Dec 2010 12:13:16 +0800 Subject: [PATCH 026/768] Fixing the test to force the explicit conversion of the body, to get the according exception. --- libs/network/test/http/client_get_timeout_test.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libs/network/test/http/client_get_timeout_test.cpp b/libs/network/test/http/client_get_timeout_test.cpp index a5ec69f20..b58f59c62 100644 --- a/libs/network/test/http/client_get_timeout_test.cpp +++ b/libs/network/test/http/client_get_timeout_test.cpp @@ -14,11 +14,12 @@ namespace http = boost::network::http; BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_timeout_1_0, T, tag_types) { typedef http::basic_client client; typename client::request request("http://localhost:12121/"); - client client_; typename client::response response_; + client client_; boost::uint16_t port_ = port(request); + typename client::response::string_type temp; BOOST_CHECK_EQUAL ( 12121, port_ ); - BOOST_CHECK_THROW ( response_ = client_.get(request); body(response_); , std::exception ); + BOOST_CHECK_THROW ( response_ = client_.get(request); temp = body(response_); , std::exception ); } BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_timeout_1_1, T, tag_types) { @@ -26,7 +27,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_timeout_1_1, T, tag_types) { typename client_type::request request("http://localhost:12121/"); typename client_type::response response_; boost::uint16_t port_ = port(request); + typename client_type::response::string_type temp; BOOST_CHECK_EQUAL ( 12121, port_ ); client_type client_; - BOOST_CHECK_THROW ( response_ = client_.get(request); body(response_); , std::exception ); + BOOST_CHECK_THROW ( response_ = client_.get(request); temp = body(response_); , std::exception ); } From 6ba2f466e37cb8e7dc7b6a30aa6ca99950c7e823 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 3 Dec 2010 12:13:50 +0800 Subject: [PATCH 027/768] Using mpl::vector instead of an mpl::list. --- libs/network/test/http/tag_types.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/network/test/http/tag_types.hpp b/libs/network/test/http/tag_types.hpp index 8e842b2e0..219ae9303 100644 --- a/libs/network/test/http/tag_types.hpp +++ b/libs/network/test/http/tag_types.hpp @@ -6,14 +6,16 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#include #include namespace http = boost::network::http; -typedef boost::mpl::list< +typedef boost::mpl::vector< http::tags::http_default_8bit_tcp_resolve , http::tags::http_default_8bit_udp_resolve + , http::tags::http_keepalive_8bit_tcp_resolve + , http::tags::http_keepalive_8bit_udp_resolve , http::tags::http_async_8bit_udp_resolve , http::tags::http_async_8bit_tcp_resolve > tag_types; From 8171e39c897c00cf97caf419c525e700e4ee1cbb Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 3 Dec 2010 12:25:30 +0800 Subject: [PATCH 028/768] Deprecating interface to HTTP redirection and resolved IP caching now. --- libs/network/test/CMakeLists.txt | 2 - libs/network/test/http_1_0_test.cpp | 123 ---------------------------- libs/network/test/http_1_1_test.cpp | 95 --------------------- 3 files changed, 220 deletions(-) delete mode 100644 libs/network/test/http_1_0_test.cpp delete mode 100644 libs/network/test/http_1_1_test.cpp diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index ff7500b6b..7580123a2 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -21,8 +21,6 @@ if (Boost_FOUND) TESTS http_incremental_parser http_incremental_request_parser - http_1_0_test - http_1_1_test http_localhost_tests https_localhost_tests message_test diff --git a/libs/network/test/http_1_0_test.cpp b/libs/network/test/http_1_0_test.cpp deleted file mode 100644 index 6c9df641d..000000000 --- a/libs/network/test/http_1_0_test.cpp +++ /dev/null @@ -1,123 +0,0 @@ - -// Copyright Dean Michael Berris 2007-2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE http 1.0 test -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace boost::network; - -typedef boost::mpl::list< - http::tags::http_default_8bit_tcp_resolve - , http::tags::http_default_8bit_udp_resolve - , http::tags::http_async_8bit_udp_resolve - , http::tags::http_async_8bit_tcp_resolve -> tag_types; - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_constructor_test, T, tag_types) { - typedef http::basic_client client; - client client1; //default constructed - boost::asio::io_service io_service; - client client2(io_service); // construct with a provided io_service -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test, T, tag_types) { - typedef http::basic_client client; - typename client::request request("http://www.boost.org/"); - client client_; - typename client::response response_ = client_.get(request); - typename headers_range >::type range = headers(response_)["Content-Type"]; - BOOST_CHECK ( boost::begin(range) != boost::end(range) ); - BOOST_CHECK ( body(response_).size() != 0 ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_different_port, T, tag_types) { - typedef http::basic_client client; - typename client::request request("http://www.boost.org/"); - client client_; - typename client::response response_ = client_.get(request); - typename headers_range >::type range = headers(response_)["Content-Type"]; - BOOST_CHECK ( boost::begin(range) != boost::end(range) ); - BOOST_CHECK ( body(response_).size() != 0 ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_timeout, T, tag_types) { - typedef http::basic_client client; - typename client::request request("http://localhost:12121/"); - client client_; - typename client::response response_; - boost::uint16_t port_ = port(request); - BOOST_CHECK_EQUAL ( 12121, port_ ); - BOOST_CHECK_THROW ( response_ = client_.get(request); body(response_); , boost::system::system_error ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_details, T, tag_types) { - typedef http::basic_client client; - typename client::request request("http://www.boost.org/"); - client client_; - typename client::response response_; - BOOST_CHECK_NO_THROW ( response_ = client_.get(request) ); - BOOST_CHECK_EQUAL ( response_.version().substr(0,7), std::string("HTTP/1.") ); - BOOST_CHECK_EQUAL ( response_.status(), 200u ); - BOOST_CHECK_EQUAL ( response_.status_message(), std::string("OK") ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_cached_resolve, T, tag_types) { - typedef http::basic_client client; - typename client::request request("http://www.boost.org/"); - typename client::request other_request("http://www.boost.org/users/license.html"); - client client_(client::cache_resolved); - typename client::response response_; - BOOST_CHECK_NO_THROW ( response_ = client_.get(request) ); - BOOST_CHECK_NO_THROW ( response_ = client_.get(other_request) ); -} - -// NOTE: This is a hack to make the test pass for asynchronous -// HTTP requests. The reason is because the implementation currently -// makes it hard to "back-track" in case a redirection is supposed -// to be granted. Because we're using futures, it's going to be a little -// more involved to check whether a request should be redirected somewhere -// else. That's fine in the synchronous case, but the asynchronous implementation -// means we're going to have to make a special case path for redirection to -// happen. I'm more interested in releasing something that can be tested -// than making it perfect before releasing anything. HTH -- Dean -template -struct status_ : - boost::mpl::if_< - boost::network::is_async, - boost::mpl::integral_c, - boost::mpl::integral_c - >::type -{}; - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_redirection_test, T, tag_types) { - typedef http::basic_client client; - typename client::request request("http://boost.org/"); - client client_(client::follow_redirect); - typename client::response response_; - BOOST_CHECK_NO_THROW ( response_ = client_.get(request) ); - BOOST_CHECK_EQUAL ( response_.status(), status_::value ); -} - -#ifdef BOOST_NETWORK_ENABLE_HTTPS - -BOOST_AUTO_TEST_CASE_TEMPLATE(https_get_test, T, tag_types) { - typedef http::basic_client client; - typename client::request request("https://www.google.com/"); - client client_; - typename client::response response_ = client_.get(request); - typename headers_range >::type range = headers(response_)["Content-Type"]; - BOOST_CHECK ( boost::begin(range) != boost::end(range) ); - BOOST_CHECK ( body(response_).size() != 0 ); -} - -#endif diff --git a/libs/network/test/http_1_1_test.cpp b/libs/network/test/http_1_1_test.cpp deleted file mode 100644 index b44cbf24c..000000000 --- a/libs/network/test/http_1_1_test.cpp +++ /dev/null @@ -1,95 +0,0 @@ - -// Copyright Dean Michael Berris 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_TEST_MODULE http 1.1 test -#include -#include -#include -#include -#include - -using namespace boost::network; - -typedef boost::mpl::list< - http::tags::http_default_8bit_tcp_resolve, - http::tags::http_default_8bit_udp_resolve, - http::tags::http_keepalive_8bit_tcp_resolve, - http::tags::http_keepalive_8bit_udp_resolve, - http::tags::http_async_8bit_tcp_resolve, - http::tags::http_async_8bit_udp_resolve -> tag_types; - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test, T, tag_types) { - typedef http::basic_client client_type; - typename client_type::request request("http://www.boost.org/"); - typename client_type::response response_; - client_type client_; - BOOST_CHECK_NO_THROW ( response_ = client_.get(request) ); - typename headers_range::type range = headers(response_)["Content-Type"]; - BOOST_CHECK ( boost::begin(range) != boost::end(range) ); - BOOST_CHECK ( body(response_).size() != 0 ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_different_port, T, tag_types) { - typedef http::basic_client client_type; - typename client_type::request request("http://www.boost.org/"); - typename client_type::response response_; - client_type client_; - BOOST_CHECK_NO_THROW ( response_ = client_.get(request) ); - typename headers_range::type range = headers(response_)["Content-Type"]; - BOOST_CHECK ( boost::begin(range) != boost::end(range) ); - BOOST_CHECK ( body(response_).size() != 0 ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_timeout, T, tag_types) { - typedef http::basic_client client_type; - typename client_type::request request("http://localhost:12121/"); - typename client_type::response response_; - client_type client_; - BOOST_CHECK_THROW ( response_ = client_.get(request); body(response_); , boost::system::system_error ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_details, T, tag_types) { - typedef http::basic_client client_type; - typename client_type::request request("http://www.boost.org/"); - typename client_type::response response_; - client_type client_; - BOOST_CHECK_NO_THROW ( response_ = client_.get(request) ); - BOOST_CHECK_EQUAL ( response_.version().substr(0,7), std::string("HTTP/1.") ); - BOOST_CHECK_EQUAL ( response_.status(), 200u ); - BOOST_CHECK_EQUAL ( response_.status_message(), std::string("OK") ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_cached_resolve, T, tag_types) { - typedef http::basic_client client_type; - typename client_type::request request("http://www.boost.org/"), - other_request("http://www.boost.org/users/license.html"); - typename client_type::response response_; - client_type client_(client_type::cache_resolved); - BOOST_CHECK_NO_THROW ( response_ = client_.get(request) ); - BOOST_CHECK_NO_THROW ( response_ = client_.get(other_request) ); - response_ = client_.get(other_request); -} - -template -struct status_ : - boost::mpl::if_< - boost::network::is_async, - boost::mpl::integral_c, - boost::mpl::integral_c - >::type -{}; - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_redirection_test, T, tag_types) { - typedef http::basic_client client_type; - typename client_type::request request("http://boost.org/"); - typename client_type::response response_; - client_type client_(client_type::follow_redirect); - BOOST_CHECK_NO_THROW ( response_ = client_.get(request) ); - BOOST_CHECK_EQUAL ( response_.status(), status_::value ); -} - - From b74ce4c5deadaeb74d997919efea3141d71040cd Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 3 Dec 2010 16:12:37 +0800 Subject: [PATCH 029/768] Moving URI Parsers to Static Lib This commit moves out the implementation of the URI parsing routines out from the headers and into a single .cpp file. Now it means that cpp-netlib is no longer just a header-only library. It also means that this is proof enough that the compile times are really greatly affected by the template metaprogramming happening under the hood of Boost.Spirit. Now things to do because of this commit: * Overhaul the documentation regarding the installation and the distribution of the library. * Re-think the implementation of certain things like the static dispatch of whether to use an asynchronous or synchronous client. * Start making larger changes now that the compile-times are down when building the tests. That's it folks, header-only was fun while it lasted, unfortunately the Boost.Spirit parts are taking too much a toll on the library's usability. Hopefully this change makes the library more usable in a larger context. --- CMakeLists.txt | 3 + boost/network/uri/detail/parse_uri.hpp | 265 +++---------------------- boost/network/uri/detail/uri_parts.hpp | 41 +++- libs/network/build/Jamfile.v2 | 1 + libs/network/example/CMakeLists.txt | 18 +- libs/network/src/parse_uri_impl.cpp | 206 +++++++++++++++++++ libs/network/test/CMakeLists.txt | 3 +- libs/network/test/http/CMakeLists.txt | 3 +- 8 files changed, 279 insertions(+), 261 deletions(-) create mode 100644 libs/network/src/parse_uri_impl.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 70baede4a..da469b718 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,12 +6,15 @@ cmake_minimum_required(VERSION 2.6) project(CPP-NETLIB) find_package( Boost 1.41.0 ) +set(CMAKE_VERBOSE_MAKEFILE true) if (Boost_FOUND) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTI_THREADED ON) include_directories(${Boost_INCLUDE_DIRS}) endif() enable_testing() +add_subdirectory(libs/network/build) add_subdirectory(libs/network/test) add_subdirectory(libs/mime/test) add_subdirectory(libs/network/example) + diff --git a/boost/network/uri/detail/parse_uri.hpp b/boost/network/uri/detail/parse_uri.hpp index dbbe7d427..73d68bd5e 100644 --- a/boost/network/uri/detail/parse_uri.hpp +++ b/boost/network/uri/detail/parse_uri.hpp @@ -6,256 +6,39 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include - - -namespace boost { namespace spirit { namespace traits { -template -struct transform_attribute< - boost::network::uri::detail::uri_parts, - typename boost::network::uri::detail::uri_parts_tuple::type -#if SPIRIT_VERSION >= 0x2030 - , boost::spirit::qi::domain -#endif - > -{ - typedef typename boost::network::uri::detail::uri_parts_tuple::type type; - - static type pre(boost::network::uri::detail::uri_parts & parts) { - typedef typename boost::network::string::type string_type; - - boost::fusion::tuple< - boost::optional &, - boost::optional &, - boost::optional &, - string_type & - > hier_part = - boost::fusion::tie( - parts.user_info, - parts.host, - parts.port, - parts.path - ); - - return boost::fusion::tie( - parts.scheme, - hier_part, - parts.query, - parts.fragment - ); -} - -static void post(boost::network::uri::detail::uri_parts &, type const &) { } - -#if SPIRIT_VERSION >= 0x2030 -static void fail(boost::network::uri::detail::uri_parts & val) { } -#endif -}; - -#if SPIRIT_VERSION < 0x2030 -template -struct transform_attribute< - optional, - Transformed, - typename disable_if, Transformed> >::type - > -{ - typedef Transformed & type; - - static Transformed & pre(optional & val) { - if (!val) - val = Transformed(); - return boost::get(val); - } - - static void post(optional &, Transformed const &) { } -}; -#endif -} // namespace traits -} // namespace spirit -} // namespace boost +#include +#include namespace boost { namespace network { namespace uri { namespace detail { -namespace qi = boost::spirit::qi; - -template -struct uri_grammar : qi::grammar()> { - uri_grammar() : uri_grammar::base_type(start, "uri") { - // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" - gen_delims %= qi::char_(":/?#[]@"); - // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" - sub_delims %= qi::char_("!$&'()*+,;="); - // reserved = gen-delims / sub-delims - reserved %= gen_delims | sub_delims; - // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - unreserved %= qi::alnum | qi::char_("-._~"); - // pct-encoded = "%" HEXDIG HEXDIG - pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; - - // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - pchar %= qi::raw[ - unreserved | pct_encoded | sub_delims | qi::char_(":@") - ]; - - // segment = *pchar - segment %= qi::raw[*pchar]; - // segment-nz = 1*pchar - segment_nz %= qi::raw[+pchar]; - // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) - segment_nz_nc %= qi::raw[ - +(unreserved | pct_encoded | sub_delims | qi::char_("@")) - ]; - // path-abempty = *( "/" segment ) - path_abempty %= qi::raw[*(qi::char_("/") >> segment)]; - // path-absolute = "/" [ segment-nz *( "/" segment ) ] - path_absolute %= qi::raw[ - qi::char_("/") - >> -(segment_nz >> *(qi::char_("/") >> segment)) - ]; - // path-rootless = segment-nz *( "/" segment ) - path_rootless %= qi::raw[ - segment_nz >> *(qi::char_("/") >> segment) - ]; - // path-empty = 0 - path_empty %= qi::eps; - - // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) - scheme %= qi::alpha >> *(qi::alnum | qi::char_("+.-")); - - // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) - user_info %= qi::raw[ - *(unreserved | pct_encoded | sub_delims | qi::char_(":")) - ]; - - // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 - dec_octet %= - !(qi::lit('0') >> qi::digit) - >> qi::raw[ - qi::uint_parser() - ]; - // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet - ipv4address %= qi::raw[ - dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] - ]; - // reg-name = *( unreserved / pct-encoded / sub-delims ) - reg_name %= qi::raw[ - *(unreserved | pct_encoded | sub_delims) - ]; - // TODO, host = IP-literal / IPv4address / reg-name - host %= ipv4address | reg_name; - - // query = *( pchar / "/" / "?" ) - query %= qi::raw[*(pchar | qi::char_("/?"))]; - // fragment = *( pchar / "/" / "?" ) - fragment %= qi::raw[*(pchar | qi::char_("/?"))]; - - // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty - // authority = [ userinfo "@" ] host [ ":" port ] - hier_part %= - ( - "//" - >> -(user_info >> '@') - >> host - >> -(':' >> qi::ushort_) - // >> -(':' >> *qi::digit) - >> path_abempty - ) - | - ( - qi::attr(optional::type>()) - >> qi::attr(optional::type>()) - // >> qi::attr(optional::type>()) - >> qi::attr(optional()) - >> ( - path_absolute - | path_rootless - | path_empty - ) - ); - - uri %= - scheme >> ':' - >> hier_part - >> -('?' >> query) - >> -('#' >> fragment); - - start %= uri.alias(); - } - - typedef typename string::type string_type; - - qi::rule - gen_delims, sub_delims, reserved, unreserved; - qi::rule - pct_encoded, pchar; - - qi::rule - segment, segment_nz, segment_nz_nc; - qi::rule - path_abempty, path_absolute, path_rootless, path_empty; - - qi::rule - dec_octet, ipv4address, reg_name, host; - - qi::rule - scheme, user_info, query, fragment; - - qi::rule &, - optional &, - // optional &, - optional &, - string_type & - >()> hier_part; - -// start rule of grammar -qi::rule()> start; - -// actual uri parser -qi::rule::type()> uri; -}; - -template < - class Tag - > -inline -bool parse_specific(uri_parts & parts) { +template +inline bool parse_specific(uri_parts & parts) { return true; } -template < - class Range, - class Tag - > -inline -bool parse_uri(Range & range, uri_parts & parts) { - typedef typename range_iterator::type iterator; - - // Qualified boost::begin and boost::end because MSVC complains - // of ambiguity on call to begin(range) and end(rand). - iterator start_ = boost::begin(range); - iterator end_ = boost::end(range); +extern bool parse_uri_impl(boost::iterator_range & range, uri_parts_default_base & parts, tags::default_string); +extern bool parse_uri_impl(boost::iterator_range & range, uri_parts_wide_base & parts, tags::default_wstring); - static uri_grammar grammar; - - bool ok = qi::parse(start_, end_, grammar, parts); - - if (ok) - ok = parse_specific(parts); - - return ok && start_ == end_; +template +struct unsupported_tag; + +template +inline bool parse_uri(Range & range, uri_parts & parts) { + typedef typename range_iterator::type iterator; + boost::iterator_range local_range = boost::make_iterator_range(range); + return parse_uri_impl(local_range, parts, + typename mpl::if_< + is_default_string, + tags::default_string, + typename mpl::if_< + is_default_wstring, + tags::default_wstring, + unsupported_tag + >::type + >::type()); } + } // namespace detail } // namespace uri } // namespace network diff --git a/boost/network/uri/detail/uri_parts.hpp b/boost/network/uri/detail/uri_parts.hpp index 37a4f9274..ba0021a43 100644 --- a/boost/network/uri/detail/uri_parts.hpp +++ b/boost/network/uri/detail/uri_parts.hpp @@ -10,24 +10,43 @@ #include #include +#include #include namespace boost { namespace network { namespace uri { namespace detail { + + struct uri_parts_default_base { + typedef std::string string_type; + string_type scheme; + optional user_info; + optional host; + optional port; + string_type path; + optional query; + optional fragment; + }; -template -struct uri_parts { - typedef typename string::type string_type; + struct uri_parts_wide_base { + typedef std::wstring string_type; + string_type scheme; + optional user_info; + optional host; + optional port; + string_type path; + optional query; + optional fragment; + }; - string_type scheme; - optional user_info; - optional host; - optional port; - string_type path; - optional query; - optional fragment; -}; +template +struct uri_parts : + mpl::if_< + is_default_string + , uri_parts_default_base + , uri_parts_wide_base + >::type +{}; template struct uri_parts_tuple { diff --git a/libs/network/build/Jamfile.v2 b/libs/network/build/Jamfile.v2 index 6602dc89b..289ae859b 100644 --- a/libs/network/build/Jamfile.v2 +++ b/libs/network/build/Jamfile.v2 @@ -13,6 +13,7 @@ project cpp-netlib : cpp-pch client : boost/network/include/http/client.hpp ; cpp-pch server : boost/network/include/http/server.hpp ; +lib cppnetlib-uri-parsers : libs/network/src/parse_uri_impl.cpp ; install headers : client server : ../../../boost/network/include/http ; diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index b867c1376..7cdd97723 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -17,13 +17,17 @@ if (Boost_FOUND) add_executable(hello_world_server http/hello_world_server.cpp) add_executable(fileserver http/fileserver.cpp) add_executable(uri uri.cpp) - target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} ) - target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} ) + add_dependencies(http_client cppnetlib-uri-parsers) + add_dependencies(simple_wget cppnetlib-uri-parsers) + add_dependencies(uri cppnetlib-uri-parsers) + target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers) + target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers) target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} ) target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) - set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ../../../build/example) - set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ../../../build/example) - set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ../../../build/example) - set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ../../../build/example) - set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ../../../build/example) + target_link_libraries(uri cppnetlib-uri-parsers) + set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) endif() diff --git a/libs/network/src/parse_uri_impl.cpp b/libs/network/src/parse_uri_impl.cpp new file mode 100644 index 000000000..dfd53db6d --- /dev/null +++ b/libs/network/src/parse_uri_impl.cpp @@ -0,0 +1,206 @@ + +// Copyright 2010 Dean Michael Berris. +// Copyright 2009 Jeroen Habraken. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +BOOST_FUSION_ADAPT_STRUCT(boost::network::uri::detail::uri_parts_default_base, + (std::string, scheme) + (optional, user_info) + (optional, host) + (optional, port) + (optional, path) + (optional, query) + (optional, fragment) +) + +BOOST_FUSION_ADAPT_STRUCT(boost::network::uri::detail::uri_parts_wide_base, + (std::wstring, scheme) + (optional, user_info) + (optional, host) + (optional, port) + (optional, path) + (optional, query) + (optional, fragment) +) + +namespace boost { namespace network { namespace uri { namespace detail { + +namespace qi = boost::spirit::qi; + +template +struct uri_grammar_default : qi::grammar { + uri_grammar_default() : uri_grammar_default::base_type(start, "uri") { + // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" + gen_delims %= qi::char_(":/?#[]@"); + // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + sub_delims %= qi::char_("!$&'()*+,;="); + // reserved = gen-delims / sub-delims + reserved %= gen_delims | sub_delims; + // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + unreserved %= qi::alnum | qi::char_("-._~"); + // pct-encoded = "%" HEXDIG HEXDIG + pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; + + // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + pchar %= qi::raw[ + unreserved | pct_encoded | sub_delims | qi::char_(":@") + ]; + + // segment = *pchar + segment %= qi::raw[*pchar]; + // segment-nz = 1*pchar + segment_nz %= qi::raw[+pchar]; + // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) + segment_nz_nc %= qi::raw[ + +(unreserved | pct_encoded | sub_delims | qi::char_("@")) + ]; + // path-abempty = *( "/" segment ) + path_abempty %= qi::raw[*(qi::char_("/") >> segment)]; + // path-absolute = "/" [ segment-nz *( "/" segment ) ] + path_absolute %= qi::raw[ + qi::char_("/") + >> -(segment_nz >> *(qi::char_("/") >> segment)) + ]; + // path-rootless = segment-nz *( "/" segment ) + path_rootless %= qi::raw[ + segment_nz >> *(qi::char_("/") >> segment) + ]; + // path-empty = 0 + path_empty %= qi::eps; + + // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + scheme %= qi::alpha >> *(qi::alnum | qi::char_("+.-")); + + // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) + user_info %= qi::raw[ + *(unreserved | pct_encoded | sub_delims | qi::char_(":")) + ]; + + // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 + dec_octet %= + !(qi::lit('0') >> qi::digit) + >> qi::raw[ + qi::uint_parser() + ]; + // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet + ipv4address %= qi::raw[ + dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] + ]; + // reg-name = *( unreserved / pct-encoded / sub-delims ) + reg_name %= qi::raw[ + *(unreserved | pct_encoded | sub_delims) + ]; + // TODO, host = IP-literal / IPv4address / reg-name + host %= ipv4address | reg_name; + + // query = *( pchar / "/" / "?" ) + query %= qi::raw[*(pchar | qi::char_("/?"))]; + // fragment = *( pchar / "/" / "?" ) + fragment %= qi::raw[*(pchar | qi::char_("/?"))]; + + // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty + // authority = [ userinfo "@" ] host [ ":" port ] + hier_part %= + ( + "//" + >> -(user_info >> '@') + >> host + >> -(':' >> qi::ushort_) + >> path_abempty + ) + | + ( + qi::attr(optional()) + >> qi::attr(optional()) + >> qi::attr(optional()) + >> ( + path_absolute + | path_rootless + | path_empty + ) + ); + + uri %= + scheme >> ':' + >> hier_part + >> -('?' >> query) + >> -('#' >> fragment); + + start %= uri.alias(); + } + + typedef std::string string_type; + + qi::rule + gen_delims, sub_delims, reserved, unreserved; + qi::rule + pct_encoded, pchar; + + qi::rule + segment, segment_nz, segment_nz_nc; + qi::rule + path_abempty, path_absolute, path_rootless, path_empty; + + qi::rule + dec_octet, ipv4address, reg_name, host; + + qi::rule + scheme, user_info, query, fragment; + + qi::rule, + optional, + optional, + string_type + >()> hier_part; + +// start rule of grammar +qi::rule start; + +// actual uri parser +qi::rule uri; +}; + +bool parse_uri_impl(boost::iterator_range & range, uri_parts_default_base & parts, boost::network::tags::default_string) { + // Qualified boost::begin and boost::end because MSVC complains + // of ambiguity on call to begin(range) and end(rand). + std::string::const_iterator start_ = boost::begin(range); + std::string::const_iterator end_ = boost::end(range); + + static uri_grammar_default grammar; + + bool ok = qi::parse(start_, end_, grammar, parts); + + return ok && start_ == end_; +} + +bool parse_uri_impl(boost::iterator_range & range, uri_parts_wide_base & parts, boost::network::tags::default_wstring) { + // TODO implement the grammar that supports wide strings + return false; // this always fails because it's not supported yet! +} + +} /* detail */ + +} /* uri */ + +} /* network */ + +} /* boost */ diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index 7580123a2..490d42ade 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -36,7 +36,8 @@ if (Boost_FOUND) set_source_files_properties(${test}.cpp PROPERTIES COMPILE_FLAGS "-Wall") add_executable(cpp-netlib-${test} ${test}.cpp) - target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) + target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) endif() diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 42e92f180..9bc3070ba 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -30,7 +30,8 @@ if (Boost_FOUND) PROPERTIES COMPILE_FLAGS "-Wall") endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) - target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + add_dependencies(cpp-netlib-http-${test} cppnetlib-uri-parsers) + target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) endif() From 5d01f3dfe55ec21d04063fd765e8bd7ec584a3ca Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 3 Dec 2010 16:30:06 +0800 Subject: [PATCH 030/768] Darned typos --- libs/network/test/http/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 9bc3070ba..3b9282502 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -38,7 +38,7 @@ if (Boost_FOUND) set_target_properties(cpp-netlib-http-${test} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) add_test(cpp-netlib-http-${test} - %{CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) endforeach (test) set ( SERVER_TESTS From 7b383aa2a3a2d855bf28d9f8f8b39caa64f65c6a Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 6 Dec 2010 13:27:44 +0800 Subject: [PATCH 031/768] Fixing issue with fetching the raw URI from a basic_uri, adding forwarding functions to base implementations. --- boost/network/uri/basic_uri.hpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/boost/network/uri/basic_uri.hpp b/boost/network/uri/basic_uri.hpp index 9ddbe9dfd..0f152d189 100644 --- a/boost/network/uri/basic_uri.hpp +++ b/boost/network/uri/basic_uri.hpp @@ -78,7 +78,7 @@ struct uri_base { } string_type raw() const { - return string(); + return raw_; } string_type string() const { @@ -116,6 +116,18 @@ class basic_uri : public uri_base { basic_uri() : uri_base() {} basic_uri(typename uri_base::string_type const & uri) : uri_base(uri) {} + basic_uri & operator= (basic_uri & rhs) { + rhs.swap(*this); + return *this; + } + + void swap(basic_uri & other) { + uri_base::swap(other); + } + + using uri_base::operator==; + using uri_base::operator!=; + }; template From 1ece316790bf14a2fd7ab3c077a15e7853c196ab Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 6 Dec 2010 13:28:28 +0800 Subject: [PATCH 032/768] Fixing the parser to use the correct transforms. --- libs/network/src/parse_uri_impl.cpp | 118 +++++++++++++++++++++++++--- 1 file changed, 109 insertions(+), 9 deletions(-) diff --git a/libs/network/src/parse_uri_impl.cpp b/libs/network/src/parse_uri_impl.cpp index dfd53db6d..7d6433950 100644 --- a/libs/network/src/parse_uri_impl.cpp +++ b/libs/network/src/parse_uri_impl.cpp @@ -41,12 +41,98 @@ BOOST_FUSION_ADAPT_STRUCT(boost::network::uri::detail::uri_parts_wide_base, (optional, fragment) ) +namespace boost { namespace spirit { namespace traits { +template <> +struct transform_attribute< + boost::network::uri::detail::uri_parts_default_base, + boost::fusion::tuple< + std::string &, + boost::fusion::tuple< + boost::optional&, + boost::optional&, + boost::optional &, + std::string & + >, + optional&, + optional& + > +#if SPIRIT_VERSION >= 0x2030 + , boost::spirit::qi::domain +#endif + > +{ + typedef + boost::fusion::tuple< + std::string &, + boost::fusion::tuple< + boost::optional&, + boost::optional&, + boost::optional &, + std::string & + >, + optional&, + optional& + > type; + + static type pre(boost::network::uri::detail::uri_parts_default_base & parts) { + boost::fusion::tuple< + boost::optional &, + boost::optional &, + boost::optional &, + std::string & + > hier_part = + boost::fusion::tie( + parts.user_info, + parts.host, + parts.port, + parts.path + ); + + return boost::fusion::tie( + parts.scheme, + hier_part, + parts.query, + parts.fragment + ); +} + +static void post(boost::network::uri::detail::uri_parts_default_base &, type const &) { } + +#if SPIRIT_VERSION >= 0x2030 +static void fail(boost::network::uri::detail::uri_parts_default_base & val) { } +#endif +}; + +#if SPIRIT_VERSION < 0x2030 +template +struct transform_attribute< + optional, + Transformed, + typename disable_if, Transformed> >::type + > +{ + typedef Transformed & type; + + static Transformed & pre(optional & val) { + if (!val) + val = Transformed(); + return boost::get(val); + } + + static void post(optional &, Transformed const &) { } +}; +#endif +} // namespace traits +} // namespace spirit +} // namespace boost + + namespace boost { namespace network { namespace uri { namespace detail { namespace qi = boost::spirit::qi; template -struct uri_grammar_default : qi::grammar { +struct uri_grammar_default : qi::grammar { uri_grammar_default() : uri_grammar_default::base_type(start, "uri") { // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" gen_delims %= qi::char_(":/?#[]@"); @@ -166,17 +252,31 @@ struct uri_grammar_default : qi::grammar { scheme, user_info, query, fragment; qi::rule, - optional, - optional, - string_type + optional&, + optional&, + optional&, + string_type & >()> hier_part; -// start rule of grammar -qi::rule start; + // start rule of grammar + qi::rule start; + + // actual uri parser + qi::rule< + Iterator, + boost::fusion::tuple< + string_type&, + boost::fusion::tuple< + optional&, + optional&, + optional&, + string_type & + >, + optional&, + optional& + >() + > uri; -// actual uri parser -qi::rule uri; }; bool parse_uri_impl(boost::iterator_range & range, uri_parts_default_base & parts, boost::network::tags::default_string) { From 73935a6e8187ace6944320da3b9c12ed596ef04f Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 6 Dec 2010 13:28:53 +0800 Subject: [PATCH 033/768] Adding check for the scheme in the HTTP URL test. --- libs/network/test/http_url_test.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/network/test/http_url_test.cpp b/libs/network/test/http_url_test.cpp index dcd53de23..279a11859 100644 --- a/libs/network/test/http_url_test.cpp +++ b/libs/network/test/http_url_test.cpp @@ -25,6 +25,9 @@ BOOST_AUTO_TEST_CASE(http_url_test) { uri_type instance(string_type(boost::begin(url), boost::end(url))); BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK_EQUAL(instance.raw(), url); + string_type scheme_ = uri::scheme(instance); + BOOST_CHECK_EQUAL(scheme_, scheme); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK_EQUAL(uri::port(instance), port); From ee7666769f2f644dbf24976d61ad3d46d43ae310 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 6 Dec 2010 15:13:04 +0800 Subject: [PATCH 034/768] Upgrading to Filesystem V3 interface. --- libs/network/test/server/http_test_server.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/network/test/server/http_test_server.hpp b/libs/network/test/server/http_test_server.hpp index 7540dc14d..0f3f86ff4 100644 --- a/libs/network/test/server/http_test_server.hpp +++ b/libs/network/test/server/http_test_server.hpp @@ -82,7 +82,7 @@ struct http_test_server script_handle_t launch_python_script(const boost::filesystem::path& python_script_path) { using namespace boost::filesystem; - path::string_type script_name = python_script_path.filename(); + path::string_type script_name = python_script_path.filename().string(); path::string_type script_dir = python_script_path.parent_path().string(); #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) @@ -139,7 +139,7 @@ struct http_test_server // set the CGI script execute permission for (directory_iterator i(cgibin_path); i != directory_iterator(); ++i) { if (is_regular_file(i->status())) { - path::string_type file_path = i->path().file_string(); + path::string_type file_path = i->path().string(); if (chmod(file_path.c_str(), S_IWUSR|S_IXUSR|S_IXGRP|S_IXOTH|S_IRUSR|S_IRGRP|S_IROTH) != 0) return false; } From 85eb3dd486a701ef4ba8cafa7ff6d9e840c96d90 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 6 Dec 2010 15:29:50 +0800 Subject: [PATCH 035/768] Re-arranging the client connection headers. --- .../connection/async_base.hpp} | 4 ++-- .../connection/async_normal.hpp} | 2 +- .../connection/async_protocol_handler.hpp} | 0 .../connection/async_ssl.hpp} | 2 +- .../connection/sync_base.hpp} | 4 ++-- .../connection/sync_normal.hpp} | 0 .../connection/sync_ssl.hpp} | 0 boost/network/protocol/http/policies/async_connection.hpp | 2 +- boost/network/protocol/http/policies/pooled_connection.hpp | 2 +- boost/network/protocol/http/policies/simple_connection.hpp | 2 +- 10 files changed, 9 insertions(+), 9 deletions(-) rename boost/network/protocol/http/{impl/async_connection_base.hpp => client/connection/async_base.hpp} (93%) rename boost/network/protocol/http/{impl/http_async_connection.hpp => client/connection/async_normal.hpp} (99%) rename boost/network/protocol/http/{impl/http_async_protocol_handler.hpp => client/connection/async_protocol_handler.hpp} (100%) rename boost/network/protocol/http/{impl/https_async_connection.hpp => client/connection/async_ssl.hpp} (99%) rename boost/network/protocol/http/{impl/sync_connection_base.hpp => client/connection/sync_base.hpp} (98%) rename boost/network/protocol/http/{impl/http_sync_connection.hpp => client/connection/sync_normal.hpp} (100%) rename boost/network/protocol/http/{impl/https_sync_connection.hpp => client/connection/sync_ssl.hpp} (100%) diff --git a/boost/network/protocol/http/impl/async_connection_base.hpp b/boost/network/protocol/http/client/connection/async_base.hpp similarity index 93% rename from boost/network/protocol/http/impl/async_connection_base.hpp rename to boost/network/protocol/http/client/connection/async_base.hpp index f9a35ae6d..6ea2b9f5a 100644 --- a/boost/network/protocol/http/impl/async_connection_base.hpp +++ b/boost/network/protocol/http/client/connection/async_base.hpp @@ -8,9 +8,9 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include #ifdef BOOST_NETWORK_ENABLE_HTTPS -#include +#include #endif namespace boost { namespace network { namespace http { namespace impl { diff --git a/boost/network/protocol/http/impl/http_async_connection.hpp b/boost/network/protocol/http/client/connection/async_normal.hpp similarity index 99% rename from boost/network/protocol/http/impl/http_async_connection.hpp rename to boost/network/protocol/http/client/connection/async_normal.hpp index 2e80cdddc..1151988fe 100644 --- a/boost/network/protocol/http/impl/http_async_connection.hpp +++ b/boost/network/protocol/http/client/connection/async_normal.hpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/boost/network/protocol/http/impl/http_async_protocol_handler.hpp b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp similarity index 100% rename from boost/network/protocol/http/impl/http_async_protocol_handler.hpp rename to boost/network/protocol/http/client/connection/async_protocol_handler.hpp diff --git a/boost/network/protocol/http/impl/https_async_connection.hpp b/boost/network/protocol/http/client/connection/async_ssl.hpp similarity index 99% rename from boost/network/protocol/http/impl/https_async_connection.hpp rename to boost/network/protocol/http/client/connection/async_ssl.hpp index 8bab5d2c1..90364529b 100644 --- a/boost/network/protocol/http/impl/https_async_connection.hpp +++ b/boost/network/protocol/http/client/connection/async_ssl.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include namespace boost { namespace network { namespace http { namespace impl { diff --git a/boost/network/protocol/http/impl/sync_connection_base.hpp b/boost/network/protocol/http/client/connection/sync_base.hpp similarity index 98% rename from boost/network/protocol/http/impl/sync_connection_base.hpp rename to boost/network/protocol/http/client/connection/sync_base.hpp index 4b4b2e33f..8c0d450ac 100644 --- a/boost/network/protocol/http/impl/sync_connection_base.hpp +++ b/boost/network/protocol/http/client/connection/sync_base.hpp @@ -16,9 +16,9 @@ #include #include -#include +#include #ifdef BOOST_NETWORK_ENABLE_HTTPS -#include +#include #endif namespace boost { namespace network { namespace http { namespace impl { diff --git a/boost/network/protocol/http/impl/http_sync_connection.hpp b/boost/network/protocol/http/client/connection/sync_normal.hpp similarity index 100% rename from boost/network/protocol/http/impl/http_sync_connection.hpp rename to boost/network/protocol/http/client/connection/sync_normal.hpp diff --git a/boost/network/protocol/http/impl/https_sync_connection.hpp b/boost/network/protocol/http/client/connection/sync_ssl.hpp similarity index 100% rename from boost/network/protocol/http/impl/https_sync_connection.hpp rename to boost/network/protocol/http/client/connection/sync_ssl.hpp diff --git a/boost/network/protocol/http/policies/async_connection.hpp b/boost/network/protocol/http/policies/async_connection.hpp index a4414ff41..12a2d070a 100644 --- a/boost/network/protocol/http/policies/async_connection.hpp +++ b/boost/network/protocol/http/policies/async_connection.hpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/boost/network/protocol/http/policies/pooled_connection.hpp b/boost/network/protocol/http/policies/pooled_connection.hpp index 28d85541a..a15c0017b 100644 --- a/boost/network/protocol/http/policies/pooled_connection.hpp +++ b/boost/network/protocol/http/policies/pooled_connection.hpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include diff --git a/boost/network/protocol/http/policies/simple_connection.hpp b/boost/network/protocol/http/policies/simple_connection.hpp index 1d0221d6f..613c5f26c 100644 --- a/boost/network/protocol/http/policies/simple_connection.hpp +++ b/boost/network/protocol/http/policies/simple_connection.hpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include From 72d6d02d8d4e25803d70ceb459af93b82827d101 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 6 Dec 2010 15:48:49 +0800 Subject: [PATCH 036/768] Refactoring the request linearization to use the linearize algorithm in asynchronous client connections. --- .../http/client/connection/async_normal.hpp | 12 +++-- .../connection/async_protocol_handler.hpp | 48 +------------------ .../http/client/connection/async_ssl.hpp | 11 +++-- libs/network/test/https_localhost_tests.cpp | 27 ----------- 4 files changed, 17 insertions(+), 81 deletions(-) diff --git a/boost/network/protocol/http/client/connection/async_normal.hpp b/boost/network/protocol/http/client/connection/async_normal.hpp index 1151988fe..0c19c11d1 100644 --- a/boost/network/protocol/http/client/connection/async_normal.hpp +++ b/boost/network/protocol/http/client/connection/async_normal.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -60,7 +61,8 @@ namespace boost { namespace network { namespace http { namespace impl { virtual response start(request const & request, string_type const & method, bool get_body) { response response_; this->init_response(response_, get_body); - command_string_ = this->init_command_stream(request, method); + linearize(request, method, version_major, version_minor, + std::ostreambuf_iterator::type>(&command_streambuf)); this->method = method; boost::uint16_t port_ = port(request); resolve_(resolver_, host(request), @@ -107,8 +109,10 @@ namespace boost { namespace network { namespace http { namespace impl { void handle_connected(boost::uint16_t port, bool get_body, resolver_iterator_pair endpoint_range, boost::system::error_code const & ec) { if (!ec) { - boost::asio::async_write(*socket_, boost::asio::buffer(command_string_.data(), command_string_.size()), - request_strand_.wrap( + boost::asio::async_write( + *socket_ + , command_streambuf + , request_strand_.wrap( boost::bind( &http_async_connection::handle_sent_request, http_async_connection::shared_from_this(), @@ -308,7 +312,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::shared_ptr socket_; resolve_function resolve_; boost::asio::io_service::strand request_strand_; - string_type command_string_; + boost::asio::streambuf command_streambuf; string_type method; }; diff --git a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp index 5b84b5713..8d67de527 100644 --- a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp +++ b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp @@ -6,6 +6,8 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include + namespace boost { namespace network { namespace http { namespace impl { template @@ -48,52 +50,6 @@ namespace boost { namespace network { namespace http { namespace impl { } }; - template - string_type init_command_stream(RequestType const & request, string_type const & method) { - typename ostringstream::type command_stream; - string_type path_str; - path_str = path(request); - typedef constants constants; - command_stream - << method << constants::space() - << path_str << constants::space() - << constants::http_slash() << version_major - << constants::dot() << version_minor - << constants::crlf(); - - typedef typename headers_range::type headers_range_type; - headers_range_type headers_ = headers(request); - boost::range::transform( - headers_, - typename ostream_iterator::type (command_stream), - to_http_headers()); - - if (boost::empty(headers(request)[constants::host()])) { - string_type host_str = host(request); - command_stream - << constants::host() << constants::colon() << constants::space() << host_str << constants::crlf(); - } - - if (boost::empty(headers(request)[constants::accept()])) { - command_stream - << constants::accept() << constants::colon() << constants::space() << constants::default_accept_mime() << constants::crlf(); - } - - if (version_major == 1u && version_minor == 1u && boost::empty(headers(request)[constants::accept_encoding()])) { - command_stream - << constants::accept_encoding() << constants::colon() << constants::space() << constants::default_accept_encoding() << constants::crlf(); - } - - if (boost::empty(headers(request)[constants::user_agent()])) { - command_stream - << constants::user_agent() << constants::colon() << constants::space() << constants::cpp_netlib_slash() << BOOST_NETLIB_VERSION << constants::crlf(); - } - - command_stream << constants::crlf(); - - return command_stream.str(); - } - template logic::tribool parse_version(Socket & socket_, Callback callback) { logic::tribool parsed_ok; diff --git a/boost/network/protocol/http/client/connection/async_ssl.hpp b/boost/network/protocol/http/client/connection/async_ssl.hpp index 90364529b..dc8360453 100644 --- a/boost/network/protocol/http/client/connection/async_ssl.hpp +++ b/boost/network/protocol/http/client/connection/async_ssl.hpp @@ -50,7 +50,8 @@ namespace boost { namespace network { namespace http { namespace impl { virtual response start(request const & request, string_type const & method, bool get_body) { response response_; this->init_response(response_, get_body); - command_string_ = this->init_command_stream(request, method); + linearize(request, method, version_major, version_minor, + std::ostreambuf_iterator::type>(&command_streambuf)); this->method = method; boost::uint16_t port_ = port(request); resolve_(resolver_, host(request), @@ -159,8 +160,10 @@ namespace boost { namespace network { namespace http { namespace impl { void handle_handshake(boost::uint16_t port, bool get_body, boost::system::error_code const & ec) { if (!ec) { - boost::asio::async_write(*socket_, boost::asio::buffer(command_string_.data(), command_string_.size()), - request_strand_.wrap( + boost::asio::async_write( + *socket_ + , command_streambuf + , request_strand_.wrap( boost::bind( &https_async_connection::handle_sent_request, https_async_connection::shared_from_this(), @@ -344,7 +347,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::shared_ptr context_; boost::shared_ptr > socket_; boost::asio::io_service::strand request_strand_; - string_type command_string_; + boost::asio::streambuf command_streambuf; string_type method; }; diff --git a/libs/network/test/https_localhost_tests.cpp b/libs/network/test/https_localhost_tests.cpp index 808bd6db6..c2efe14e3 100644 --- a/libs/network/test/https_localhost_tests.cpp +++ b/libs/network/test/https_localhost_tests.cpp @@ -55,33 +55,6 @@ namespace { return buffer.size(); } - std::map parse_headers(std::string const& body) { - std::map headers; - - std::istringstream stream(body); - while (stream.good()) - { - std::string line; - std::getline(stream, line); - if (!stream.eof()) - { - std::size_t colon = line.find(':'); - if (colon != std::string::npos) - { - std::string header = line.substr(0, colon); - std::string value = line.substr(colon + 2); - headers[header] = value; - } - } - } - - return headers; - } - - std::string get_content_length(std::string const& content) { - return boost::lexical_cast(content.size()); - } - } #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) From 76afcf48b1da54bb31271d3b8bfc06f2def2c127 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 6 Dec 2010 17:01:15 +0800 Subject: [PATCH 037/768] Moving Server-Specific Parsers to Static Lib In line with the changes introduced to move the Boost.Spirit requiring code out to static libraries, the parsers used by the HTTP server implementation particularly the parsing of headers and the version have been moved out into a static library. This requires that all servers be linked against the static lib going forward. --- boost/network/protocol/http/impl/request.hpp | 6 +- .../protocol/http/impl/request_parser.ipp | 2 +- boost/network/protocol/http/impl/response.ipp | 4 +- .../network/protocol/http/message/header.hpp | 99 ++++++++++++++----- .../protocol/http/message/header/name.hpp | 28 +++--- .../protocol/http/message/header/value.hpp | 29 +++--- .../protocol/http/message/header_concept.hpp | 3 +- .../protocol/http/server/async_connection.hpp | 29 +----- .../protocol/http/server/async_server.hpp | 2 +- .../protocol/http/server/sync_connection.hpp | 2 +- .../protocol/http/server/sync_server.hpp | 2 +- libs/network/example/CMakeLists.txt | 2 +- .../src/server_request_parsers_impl.cpp | 45 +++++++++ libs/network/test/http/CMakeLists.txt | 3 +- libs/network/test/http/server_hello_world.cpp | 1 + 15 files changed, 173 insertions(+), 84 deletions(-) create mode 100644 libs/network/src/server_request_parsers_impl.cpp diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index c98a1269e..cbeed1e97 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -29,12 +29,12 @@ namespace boost { namespace network { /** Specialize the traits for the http_server tag. */ template <> struct headers_container : - vector::apply > + vector::apply::type> {}; template <> struct headers_container : - vector::apply > + vector::apply::type> {}; namespace http { @@ -136,7 +136,7 @@ namespace http { struct not_quite_pod_request_base { typedef Tag tag; typedef typename string::type string_type; - typedef request_header header_type; + typedef typename request_header::type header_type; typedef typename vector:: template apply::type vector_type; diff --git a/boost/network/protocol/http/impl/request_parser.ipp b/boost/network/protocol/http/impl/request_parser.ipp index 58b832b22..071e64f20 100644 --- a/boost/network/protocol/http/impl/request_parser.ipp +++ b/boost/network/protocol/http/impl/request_parser.ipp @@ -207,7 +207,7 @@ boost::tribool basic_request_parser::consume(basic_request & req, char } else { - req.headers.push_back(request_header()); + req.headers.push_back(typename request_header::type()); req.headers.back().name.push_back(input); state_ = header_name; return boost::indeterminate; diff --git a/boost/network/protocol/http/impl/response.ipp b/boost/network/protocol/http/impl/response.ipp index 49c6917a4..f91dc4611 100644 --- a/boost/network/protocol/http/impl/response.ipp +++ b/boost/network/protocol/http/impl/response.ipp @@ -51,7 +51,7 @@ namespace boost { namespace network { namespace http { } status; /// The headers to be included in the reply. - typedef vector::apply >::type headers_vector; + typedef vector::apply::type>::type headers_vector; headers_vector headers; /// The content to be sent in the reply. @@ -69,7 +69,7 @@ namespace boost { namespace network { namespace http { std::vector buffers; buffers.push_back(to_buffer(status)); for (std::size_t i = 0; i < headers.size(); ++i) { - request_header & h = headers[i]; + typename request_header::type & h = headers[i]; buffers.push_back(buffer(h.name)); buffers.push_back(buffer(name_value_separator)); buffers.push_back(buffer(h.value)); diff --git a/boost/network/protocol/http/message/header.hpp b/boost/network/protocol/http/message/header.hpp index afe8e4495..22de2a728 100644 --- a/boost/network/protocol/http/message/header.hpp +++ b/boost/network/protocol/http/message/header.hpp @@ -14,57 +14,110 @@ #define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_HPP_20101122 #include -#include #include #include +#include +#include namespace boost { namespace network { namespace http { template - struct request_header - { - typedef Tag tag; - typedef typename string::type string_type; - string_type name, value; + struct unsupported_tag; + + struct request_header_narrow { + typedef std::string string_type; + std::string name, value; + }; + + struct request_header_wide { + typedef std::wstring string_type; + std::wstring name, value; }; template - inline void swap(request_header & l, request_header & r) { + struct request_header + : mpl::if_< + is_default_string, + request_header_narrow, + typename mpl::if_< + is_default_wstring, + request_header_wide, + unsupported_tag + >::type + > + {}; + + inline void swap(request_header_narrow & l, request_header_narrow & r) { swap(l.name, r.name); swap(l.value, r.value); } - template - struct response_header { - typedef Tag tag; - typedef typename string::type string_type; - string_type name, value; + inline void swap(request_header_wide & l, request_header_wide & r) { + swap(l.name, r.name); + swap(l.value, r.value); + } + + struct response_header_narrow { + typedef std::string string_type; + std::string name, value; + }; + + struct response_header_wide { + typedef std::wstring string_type; + std::wstring name, value; }; template - void swap(response_header & l, response_header & r) { + struct response_header + : mpl::if_< + is_default_string, + response_header_narrow, + typename mpl::if_< + is_default_wstring, + response_header_wide, + unsupported_tag + >::type + > + {}; + + inline void swap(response_header_narrow & l, response_header_narrow & r) { std::swap(l.name, r.name); std::swap(l.value, r.value); } + inline void swap(response_header_wide & l, response_header_wide & r) { + std::swap(l.name, r.name); + std::swap(l.value, r.value); + } + } // namespace http } // namespace network } // namespace boost -BOOST_FUSION_ADAPT_TPL_STRUCT( - (Tag), - (boost::network::http::request_header)(Tag), - (typename boost::network::string::type, name) - (typename boost::network::string::type, value) +BOOST_FUSION_ADAPT_STRUCT( + boost::network::http::request_header_narrow, + (std::string, name) + (std::string, value) + ) + +BOOST_FUSION_ADAPT_STRUCT( + boost::network::http::request_header_wide, + (std::wstring, name) + (std::wstring, value) + ) + +BOOST_FUSION_ADAPT_STRUCT( + boost::network::http::response_header_narrow, + (std::string, name) + (std::string, value) ) -BOOST_FUSION_ADAPT_TPL_STRUCT( - (Tag), - (boost::network::http::response_header) (Tag), - (typename boost::network::string::type, name) - (typename boost::network::string::type, value) +BOOST_FUSION_ADAPT_STRUCT( + boost::network::http::response_header_wide, + (std::wstring, name) + (std::wstring, value) ) #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_HEADER_HPP_20101122 diff --git a/boost/network/protocol/http/message/header/name.hpp b/boost/network/protocol/http/message/header/name.hpp index aa4010c04..e7c26d17c 100644 --- a/boost/network/protocol/http/message/header/name.hpp +++ b/boost/network/protocol/http/message/header/name.hpp @@ -6,34 +6,38 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include #include namespace boost { namespace network { namespace http { - template - struct response_header; - - template - struct request_header; - template T1 & name(std::pair const & p) { return p.first; } - template - typename string::type const & - name(response_header const & h) { + inline std::string const & + name(request_header_narrow const & h) { return h.name; } - template - typename string::type const & - name(request_header const & h) { + inline std::wstring const & + name(request_header_wide const &h) { return h.name; } + + inline std::string const & + name(response_header_narrow const & h) { + return h.name; + } + + inline std::wstring const & + name(response_header_wide const &h) { + return h.name; + } + } /* http */ } /* network */ diff --git a/boost/network/protocol/http/message/header/value.hpp b/boost/network/protocol/http/message/header/value.hpp index c90a297ef..3769ec2ab 100644 --- a/boost/network/protocol/http/message/header/value.hpp +++ b/boost/network/protocol/http/message/header/value.hpp @@ -10,26 +10,33 @@ namespace boost { namespace network { namespace http { - template - struct response_header; - - template - struct request_header; + struct request_header_narrow; + struct request_header_wide; + struct response_header_narrow; + struct response_header_wide; template T1 & value(std::pair const & p) { return p.second; } - template - typename string::type const & - value(response_header const & h) { + inline request_header_narrow::string_type const & + value(request_header_narrow const & h) { + return h.value; + } + + inline request_header_wide::string_type const & + value(request_header_wide const & h) { + return h.value; + } + + inline response_header_narrow::string_type const & + value(response_header_narrow const & h) { return h.value; } - template - typename string::type const & - value(request_header const & h) { + inline response_header_wide::string_type const & + value(response_header_wide const & h) { return h.value; } diff --git a/boost/network/protocol/http/message/header_concept.hpp b/boost/network/protocol/http/message/header_concept.hpp index 99100b24f..9a14d47fd 100644 --- a/boost/network/protocol/http/message/header_concept.hpp +++ b/boost/network/protocol/http/message/header_concept.hpp @@ -16,10 +16,9 @@ namespace boost { namespace network { namespace http { , Assignable , CopyConstructible { - typedef typename H::tag tag; BOOST_CONCEPT_USAGE(Header) { - typedef typename string::type string_type; + typedef typename H::string_type string_type; string_type name_ = name(header); string_type value_ = value(header); H h1, h2; diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index faf6a504f..5edef7f72 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -42,6 +41,9 @@ namespace boost { namespace network { namespace http { + extern void parse_version(std::string const & partial_parsed, fusion::tuple & version_pair); + extern void parse_headers(std::string const & input, std::vector & container); + template struct async_connection : boost::enable_shared_from_this > { @@ -374,17 +376,8 @@ namespace boost { namespace network { namespace http { break; } else if (parsed_ok == true) { fusion::tuple version_pair; - using namespace boost::spirit::qi; partial_parsed.append(boost::begin(result_range), boost::end(result_range)); - parse( - partial_parsed.begin(), partial_parsed.end(), - ( - lit("HTTP/") - >> ushort_ - >> '.' - >> ushort_ - ) - , version_pair); + parse_version(partial_parsed, version_pair); request_.http_version_major = fusion::get<0>(version_pair); request_.http_version_minor = fusion::get<1>(version_pair); new_start = boost::end(result_range); @@ -472,20 +465,6 @@ namespace boost { namespace network { namespace http { } } - void parse_headers(string_type & input, typename request::headers_container_type & container) { - using namespace boost::spirit::qi; - parse( - input.begin(), input.end(), - *( - +(alnum|(punct-':')) - >> lit(": ") - >> +(alnum|space|punct) - >> lit("\r\n") - ) - , container - ); - } - void do_nothing() {} template diff --git a/boost/network/protocol/http/server/async_server.hpp b/boost/network/protocol/http/server/async_server.hpp index f1e7ad81c..4e1d3a703 100644 --- a/boost/network/protocol/http/server/async_server.hpp +++ b/boost/network/protocol/http/server/async_server.hpp @@ -16,7 +16,7 @@ namespace boost { namespace network { namespace http { typedef basic_request request; typedef basic_response response; typedef typename string::type string_type; - typedef boost::network::http::response_header response_header; + typedef typename boost::network::http::response_header::type response_header; typedef async_connection connection; typedef shared_ptr connection_ptr; diff --git a/boost/network/protocol/http/server/sync_connection.hpp b/boost/network/protocol/http/server/sync_connection.hpp index e93f0f511..86154369d 100644 --- a/boost/network/protocol/http/server/sync_connection.hpp +++ b/boost/network/protocol/http/server/sync_connection.hpp @@ -85,7 +85,7 @@ namespace boost { namespace network { namespace http { if (done) { if (request_.method[0] == 'P') { // look for the content-length header - typename std::vector >::iterator it = + typename std::vector::type >::iterator it = std::find_if( request_.headers.begin(), request_.headers.end(), diff --git a/boost/network/protocol/http/server/sync_server.hpp b/boost/network/protocol/http/server/sync_server.hpp index abd97f3e7..4c2fef0df 100644 --- a/boost/network/protocol/http/server/sync_server.hpp +++ b/boost/network/protocol/http/server/sync_server.hpp @@ -23,7 +23,7 @@ namespace boost { namespace network { namespace http { typedef typename string::type string_type; typedef basic_request request; typedef basic_response response; - typedef boost::network::http::response_header response_header; + typedef typename boost::network::http::response_header::type response_header; sync_server_base(string_type const & address, string_type const & port, diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 7cdd97723..293a6ad30 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -23,7 +23,7 @@ if (Boost_FOUND) target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers) target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers) target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} ) - target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) target_link_libraries(uri cppnetlib-uri-parsers) set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) diff --git a/libs/network/src/server_request_parsers_impl.cpp b/libs/network/src/server_request_parsers_impl.cpp new file mode 100644 index 000000000..436eb5e1f --- /dev/null +++ b/libs/network/src/server_request_parsers_impl.cpp @@ -0,0 +1,45 @@ +#include + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +namespace boost { namespace network { namespace http { + + void parse_version(std::string const & partial_parsed, fusion::tuple & version_pair) { + using namespace boost::spirit::qi; + parse( + partial_parsed.begin(), partial_parsed.end(), + ( + lit("HTTP/") + >> ushort_ + >> '.' + >> ushort_ + ) + , version_pair); + } + + void parse_headers(std::string const & input, std::vector & container) { + using namespace boost::spirit::qi; + parse( + input.begin(), input.end(), + *( + +(alnum|(punct-':')) + >> lit(": ") + >> +(alnum|space|punct) + >> lit("\r\n") + ) + , container + ); + } + +} /* http */ + +} /* network */ + +} /* boost */ diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 3b9282502..37ff871f8 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -51,7 +51,8 @@ if (Boost_FOUND) PROPERTIES COMPILE_FLAGS "-Wall") endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) - target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + add_dependencies(cpp-netlib-http-${test} cppnetlib-server-parsers) + target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) set_target_properties(cpp-netlib-http-${test} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) diff --git a/libs/network/test/http/server_hello_world.cpp b/libs/network/test/http/server_hello_world.cpp index 7c72f6fe0..02ceba4bb 100644 --- a/libs/network/test/http/server_hello_world.cpp +++ b/libs/network/test/http/server_hello_world.cpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace http = boost::network::http; using boost::assign::list_of; From 7e9df06f628b045d0684046bb64356cd11f7df00 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 6 Dec 2010 17:41:12 +0800 Subject: [PATCH 038/768] Updating the Jamfiles to support the external libs, and the new location of tests. --- libs/network/build/Jamfile.v2 | 6 +++++- libs/network/test/Jamfile.v2 | 23 ++++++++++++++--------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/libs/network/build/Jamfile.v2 b/libs/network/build/Jamfile.v2 index 289ae859b..57da68e1e 100644 --- a/libs/network/build/Jamfile.v2 +++ b/libs/network/build/Jamfile.v2 @@ -7,16 +7,20 @@ project cpp-netlib : requirements ../../../ - $BOOST_ROOT + $(BOOST_ROOT) + 256 : source-location ../../../ ; cpp-pch client : boost/network/include/http/client.hpp ; cpp-pch server : boost/network/include/http/server.hpp ; lib cppnetlib-uri-parsers : libs/network/src/parse_uri_impl.cpp ; +lib cppnetlib-server-parsers : libs/network/src/server_request_parsers_impl.cpp ; install headers : client server : ../../../boost/network/include/http ; +install libraries : cppnetlib-uri-parsers cppnetlib-server-parsers ; + alias all : headers ; diff --git a/libs/network/test/Jamfile.v2 b/libs/network/test/Jamfile.v2 index c285a41bf..5abc556dd 100644 --- a/libs/network/test/Jamfile.v2 +++ b/libs/network/test/Jamfile.v2 @@ -22,6 +22,7 @@ project network_test : /boost//regex /boost//thread /boost//filesystem + BOOST_NETWORK_ENABLE_HTTPS gcc:-lpthread gcc:-lssl gcc:-lcrypto @@ -39,20 +40,24 @@ project network_test : static ; -unit-test http_localhost_tests : http_localhost_tests.cpp ; -unit-test https_localhost_tests : https_localhost_tests.cpp ; +unit-test http_localhost_tests : http_localhost_tests.cpp /cpp-netlib//cppnetlib-uri-parsers ; +unit-test https_localhost_tests : https_localhost_tests.cpp /cpp-netlib//cppnetlib-uri-parsers ; unit-test message_test : message_test.cpp ; unit-test message_transform_test : message_transform_test.cpp ; -unit-test http_1_0_test : http_1_0_test.cpp ; -unit-test http_1_1_test : http_1_1_test.cpp ; -unit-test http_message_test : http_message_test.cpp ; -unit-test url_test : url_test.cpp ; +unit-test http_message_test : http_message_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +unit-test url_test : url_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; unit-test client_server_include_failure : client_server_include_failure.cpp ; unit-test http_incremental_parser : http_incremental_parser.cpp ; unit-test http_incremental_request_parser : http_incremental_request_parser.cpp ; -unit-test http_async_message_ready : http_async_message_ready.cpp ; -exe http_async_server : http_async_server.cpp ; -exe hello_world : hello_world.cpp ; +unit-test http_async_message_ready : http_async_message_ready.cpp /cpp-netlib//cppnetlib-uri-parsers ; + +unit-test http_client_constructor_test : http/client_constructor_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +unit-test http_client_get_test : http/client_get_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +unit-test http_client_get_different_port_test : http/client_get_different_port_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +unit-test http_client_get_timeout_test : http/client_get_timeout_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; + +exe http_async_server : http/server_async.cpp /cpp-netlib//cppnetlib-server-parsers ; +exe hello_world : http/server_hello_world.cpp /cpp-netlib//cppnetlib-server-parsers ; make httplib_acceptance.passed : httplib_acceptance.py hello_world : @python_runner ; make httplib_async_acceptance.passed : httplib_acceptance.py http_async_server : @python_runner ; From 017d0f6f34a7fcc56222d1dfa1cb9d412103216e Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Tue, 7 Dec 2010 13:45:57 +0800 Subject: [PATCH 039/768] Simplifying client template instantiations. --- libs/network/test/http/client_types.hpp | 44 +++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 libs/network/test/http/client_types.hpp diff --git a/libs/network/test/http/client_types.hpp b/libs/network/test/http/client_types.hpp new file mode 100644 index 000000000..4dc069e26 --- /dev/null +++ b/libs/network/test/http/client_types.hpp @@ -0,0 +1,44 @@ +#ifndef CLIENT_TYPES_ROOWQCLE +#define CLIENT_TYPES_ROOWQCLE + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "tag_types.hpp" +#include +#include +#include +#include + +namespace mpl = boost::mpl ; + +template +struct client_adapter { + template + struct apply { + typedef boost::network::http::basic_client type; + }; +}; + +typedef + mpl::transform< + tag_types, + client_adapter<1,0> + >::type + client_1_0; + +typedef + mpl::transform< + tag_types, + client_adapter<1,1> + >::type + client_1_1; + +typedef mpl::joint_view< + client_1_0 + , client_1_1 +>::type client_types; + +#endif /* CLIENT_TYPES_ROOWQCLE */ From 4169f811cd50f9deb471eb4762c9b149d580673f Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Tue, 7 Dec 2010 13:46:34 +0800 Subject: [PATCH 040/768] Reducing code duplication by using the unified client_types MPL joint_view of all supported overloads of the HTTP client template. --- .../test/http/client_constructor_test.cpp | 12 ++----- .../http/client_get_different_port_test.cpp | 18 ++-------- libs/network/test/http/client_get_test.cpp | 34 +++---------------- .../test/http/client_get_timeout_test.cpp | 15 ++------ 4 files changed, 11 insertions(+), 68 deletions(-) diff --git a/libs/network/test/http/client_constructor_test.cpp b/libs/network/test/http/client_constructor_test.cpp index 41bb06d44..e80182945 100644 --- a/libs/network/test/http/client_constructor_test.cpp +++ b/libs/network/test/http/client_constructor_test.cpp @@ -7,19 +7,11 @@ #define BOOST_TEST_MODULE HTTP 1.0 Client Constructor Test #include #include -#include "tag_types.hpp" +#include "client_types.hpp" namespace http = boost::network::http; -BOOST_AUTO_TEST_CASE_TEMPLATE(http_1_0_constructor_test, T, tag_types) { - typedef http::basic_client client; - client instance; - boost::asio::io_service io_service; - client instance2(io_service); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_1_1_constructor_test, T, tag_types) { - typedef http::basic_client client; +BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_constructor_test, client, client_types) { client instance; boost::asio::io_service io_service; client instance2(io_service); diff --git a/libs/network/test/http/client_get_different_port_test.cpp b/libs/network/test/http/client_get_different_port_test.cpp index 53e8b1b83..9feee918f 100644 --- a/libs/network/test/http/client_get_different_port_test.cpp +++ b/libs/network/test/http/client_get_different_port_test.cpp @@ -7,28 +7,16 @@ #define BOOST_TEST_MODULE HTTP Client Get Different Port Test #include #include -#include "tag_types.hpp" +#include "client_types.hpp" namespace net = boost::network; namespace http = boost::network::http; -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_different_port_1_0, T, tag_types) { - typedef http::basic_client client; +BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_different_port, client, client_types) { typename client::request request("http://www.boost.org/"); client client_; typename client::response response_ = client_.get(request); - typename net::headers_range >::type range = headers(response_)["Content-Type"]; - BOOST_CHECK ( boost::begin(range) != boost::end(range) ); - BOOST_CHECK ( body(response_).size() != 0 ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_different_port_1_1, T, tag_types) { - typedef http::basic_client client; - typename client::request request("http://www.boost.org/"); - typename client::response response_; - client client_; - BOOST_CHECK_NO_THROW ( response_ = client_.get(request) ); - typename net::headers_range::type range = headers(response_)["Content-Type"]; + typename net::headers_range::type range = headers(response_)["Content-Type"]; BOOST_CHECK ( boost::begin(range) != boost::end(range) ); BOOST_CHECK ( body(response_).size() != 0 ); } diff --git a/libs/network/test/http/client_get_test.cpp b/libs/network/test/http/client_get_test.cpp index 26dc01259..fbbf04505 100644 --- a/libs/network/test/http/client_get_test.cpp +++ b/libs/network/test/http/client_get_test.cpp @@ -6,13 +6,12 @@ #define BOOST_TEST_MODULE HTTP 1.0 Get Test #include #include -#include "tag_types.hpp" +#include "client_types.hpp" namespace net = boost::network; namespace http = boost::network::http; -BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_test, T, tag_types) { - typedef http::basic_client client; +BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_test, client, client_types) { typename client::request request("http://www.boost.org/"); client client_; typename client::response response; @@ -25,38 +24,13 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_test, T, tag_types) { BOOST_CHECK_EQUAL ( response.status_message(), std::string("OK") ); } -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test, T, tag_types) { - typedef http::basic_client client; - typename client::request request("http://www.boost.org/"); - typename client::response response_; - client client_; - BOOST_CHECK_NO_THROW ( response_ = client_.get(request) ); - typename net::headers_range::type range = headers(response_)["Content-Type"]; - BOOST_CHECK ( boost::begin(range) != boost::end(range) ); - BOOST_CHECK ( body(response_).size() != 0 ); - BOOST_CHECK_EQUAL ( response_.version().substr(0,7), std::string("HTTP/1.") ); - BOOST_CHECK_EQUAL ( response_.status(), 200u ); - BOOST_CHECK_EQUAL ( response_.status_message(), std::string("OK") ); -} - #ifdef BOOST_NETWORK_ENABLE_HTTPS -BOOST_AUTO_TEST_CASE_TEMPLATE(https_get_test_1_0, T, tag_types) { - typedef http::basic_client client; - typename client::request request("https://www.google.com/"); - client client_; - typename client::response response_ = client_.get(request); - typename net::headers_range >::type range = headers(response_)["Content-Type"]; - BOOST_CHECK ( boost::begin(range) != boost::end(range) ); - BOOST_CHECK ( body(response_).size() != 0 ); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(https_get_test_1_1, T, tag_types) { - typedef http::basic_client client; +BOOST_AUTO_TEST_CASE_TEMPLATE(https_client_get_test, client, client_types) { typename client::request request("https://www.google.com/"); client client_; typename client::response response_ = client_.get(request); - typename net::headers_range >::type range = headers(response_)["Content-Type"]; + typename net::headers_range::type range = headers(response_)["Content-Type"]; BOOST_CHECK ( boost::begin(range) != boost::end(range) ); BOOST_CHECK ( body(response_).size() != 0 ); } diff --git a/libs/network/test/http/client_get_timeout_test.cpp b/libs/network/test/http/client_get_timeout_test.cpp index b58f59c62..4f8aa5e1b 100644 --- a/libs/network/test/http/client_get_timeout_test.cpp +++ b/libs/network/test/http/client_get_timeout_test.cpp @@ -7,12 +7,11 @@ #define BOOST_TEST_MODULE HTTP Client Get Timeout Test #include #include -#include "tag_types.hpp" +#include "client_types.hpp" namespace http = boost::network::http; -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_timeout_1_0, T, tag_types) { - typedef http::basic_client client; +BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_timeout_1_0, client, client_types) { typename client::request request("http://localhost:12121/"); typename client::response response_; client client_; @@ -22,13 +21,3 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_timeout_1_0, T, tag_types) { BOOST_CHECK_THROW ( response_ = client_.get(request); temp = body(response_); , std::exception ); } -BOOST_AUTO_TEST_CASE_TEMPLATE(http_get_test_timeout_1_1, T, tag_types) { - typedef http::basic_client client_type; - typename client_type::request request("http://localhost:12121/"); - typename client_type::response response_; - boost::uint16_t port_ = port(request); - typename client_type::response::string_type temp; - BOOST_CHECK_EQUAL ( 12121, port_ ); - client_type client_; - BOOST_CHECK_THROW ( response_ = client_.get(request); temp = body(response_); , std::exception ); -} From 3c6c0aa8a185191dfa6cb4cc91d8f7e5916661cc Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Tue, 7 Dec 2010 15:08:30 +0800 Subject: [PATCH 041/768] Using Boost.Parameter for the client constructors instead of the adhoc method used earlier. --- boost/network/protocol/http/client.hpp | 81 ++++++------------- boost/network/protocol/http/client/facade.hpp | 63 ++++++++++++--- .../protocol/http/client/parameters.hpp | 23 ++++++ libs/network/example/http_client.cpp | 2 +- .../test/http/client_constructor_test.cpp | 13 +++ 5 files changed, 114 insertions(+), 68 deletions(-) create mode 100644 boost/network/protocol/http/client/parameters.hpp diff --git a/boost/network/protocol/http/client.hpp b/boost/network/protocol/http/client.hpp index c202deac9..bc751f7f5 100644 --- a/boost/network/protocol/http/client.hpp +++ b/boost/network/protocol/http/client.hpp @@ -24,81 +24,48 @@ #include #include -#include +#include namespace boost { namespace network { namespace http { template struct basic_client - : basic_client_facade > + : basic_client_facade { private: - typedef basic_client_impl pimpl_type; - typedef basic_client_facade > base_facade_type; + typedef basic_client_facade + base_facade_type; public: typedef basic_request request; typedef basic_response response; typedef typename string::type string_type; typedef Tag tag_type; - struct cache_resolved_type { }; - - static cache_resolved_type cache_resolved() { - return cache_resolved_type(); - }; - - struct follow_redirect_type { }; - - static follow_redirect_type follow_redirects() { - return follow_redirect_type(); - }; - - static follow_redirect_type follow_redirect() { - return follow_redirect_type(); - }; - - // Constructors + // Constructor // ================================================================= - basic_client() - : base_facade_type(), pimpl(new pimpl_type(false, false)) - {} - - explicit basic_client(cache_resolved_type (*)()) - : base_facade_type(), pimpl(new pimpl_type(true, false)) - {} - - explicit basic_client(follow_redirect_type (*)()) - : base_facade_type(), pimpl(new pimpl_type(false, true)) - {} - - basic_client(cache_resolved_type (*)(), follow_redirect_type (*)()) - : base_facade_type(), pimpl(new pimpl_type(true, true)) - {} - - explicit basic_client(boost::asio::io_service & io_service) - : base_facade_type(), pimpl(new pimpl_type(false, false, io_service)) - {} + // This is a Boost.Parameter-based constructor forwarder, whose + // implementation is actually forwarded to the base type. + // + // The supported parameters are: + // _follow_redirects : bool -- whether to follow HTTP redirect + // responses (default: false) + // _cache_resolved : bool -- whether to cache the resolved + // endpoints (default: false) + // _io_service : boost::asio::io_service & + // -- supply an io_service to the + // client + + BOOST_PARAMETER_CONSTRUCTOR( + basic_client, (base_facade_type), tag, + (optional + (in_out(io_service), (boost::asio::io_service)) + (follow_redirects, (bool)) + (cache_resolved, (bool)) + )) // // ================================================================= - ~basic_client() - {} - - private: - - boost::shared_ptr pimpl; - - friend struct basic_client_facade > ; - - basic_response const request_skeleton(request const & request_, string_type method, bool get_body) { - return pimpl->request_skeleton(request_, method, get_body); - } - - void clear_resolved_cache() { - pimpl->clear_resolved_cache(); - } - }; typedef basic_client client; diff --git a/boost/network/protocol/http/client/facade.hpp b/boost/network/protocol/http/client/facade.hpp index f6a79fa64..da484b4fa 100644 --- a/boost/network/protocol/http/client/facade.hpp +++ b/boost/network/protocol/http/client/facade.hpp @@ -8,6 +8,8 @@ #include #include +#include +#include namespace boost { namespace network { namespace http { @@ -17,26 +19,39 @@ namespace boost { namespace network { namespace http { template struct basic_response; - template + template struct basic_client_facade { typedef typename string::type string_type; typedef basic_request request; typedef basic_response response; - - basic_client_facade() - {} + typedef basic_client_impl pimpl_type; + + template + basic_client_facade(ArgPack const & args) + { + init_pimpl(args, + typename mpl::if_< + is_same< + typename parameter::value_type::type, + void + >, + no_io_service, + has_io_service + >::type()); + + } response const head (request const & request_) { - return static_cast(this)->request_skeleton(request_, "HEAD", false); + return pimpl->request_skeleton(request_, "HEAD", false); } response const get (request const & request_) { - return static_cast(this)->request_skeleton(request_, "GET", true); + return pimpl->request_skeleton(request_, "GET", true); } response const post (request const & request_) { - return static_cast(this)->request_skeleton(request_, "POST", true); + return pimpl->request_skeleton(request_, "POST", true); } response const post (request request_, string_type const & content_type, string_type const & body_) { @@ -51,7 +66,7 @@ namespace boost { namespace network { namespace http { } response const put (request const & request_) { - return static_cast(this)->request_skeleton(request_, "PUT", true); + return pimpl->request_skeleton(request_, "PUT", true); } response const put (request const & request_, string_type const & body_) { @@ -66,11 +81,39 @@ namespace boost { namespace network { namespace http { } response const delete_ (request const & request_) { - return static_cast(this)->request_skeleton(request_, "DELETE", true); + return pimpl->request_skeleton(request_, "DELETE", true); } void clear_resolved_cache() { - static_cast(this)->clear_resolved_cache(); + pimpl->clear_resolved_cache(); + } + + protected: + + struct no_io_service {}; + struct has_io_service {}; + + boost::shared_ptr pimpl; + + template + void init_pimpl(ArgPack const & args, no_io_service) { + pimpl.reset( + new pimpl_type( + args[_cache_resolved|false] + , args[_follow_redirects|false] + ) + ); + } + + template + void init_pimpl(ArgPack const & args, has_io_service) { + pimpl.reset( + new pimpl_type( + args[_cache_resolved|false] + , args[_follow_redirects|false] + , args[_io_service] + ) + ); } }; diff --git a/boost/network/protocol/http/client/parameters.hpp b/boost/network/protocol/http/client/parameters.hpp new file mode 100644 index 000000000..ae0cbe6b5 --- /dev/null +++ b/boost/network/protocol/http/client/parameters.hpp @@ -0,0 +1,23 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PARAMETERS_HPP_2010127 +#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PARAMETERS_HPP_2010127 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +namespace boost { namespace network { namespace http { + + BOOST_PARAMETER_NAME(follow_redirects) + BOOST_PARAMETER_NAME(io_service) + BOOST_PARAMETER_NAME(cache_resolved) + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PARAMETERS_HPP_2010127 */ diff --git a/libs/network/example/http_client.cpp b/libs/network/example/http_client.cpp index 683156440..76c246aa3 100644 --- a/libs/network/example/http_client.cpp +++ b/libs/network/example/http_client.cpp @@ -72,7 +72,7 @@ int main(int argc, char * argv[]) { http_client::string_type destination_ = host(request); request << ::boost::network::header("Connection", "close"); - http_client client(http_client::follow_redirects); + http_client client(http::_follow_redirects=true); http_client::response response = client.get(request); if (show_headers) { diff --git a/libs/network/test/http/client_constructor_test.cpp b/libs/network/test/http/client_constructor_test.cpp index e80182945..2cb304bdf 100644 --- a/libs/network/test/http/client_constructor_test.cpp +++ b/libs/network/test/http/client_constructor_test.cpp @@ -17,3 +17,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_constructor_test, client, client_types client instance2(io_service); } +BOOST_AUTO_TEST_CASE_TEMPLATE(http_cient_constructor_params_test, client, client_types) { + client instance( + http::_follow_redirects=true, + http::_cache_resolved=true + ); + boost::asio::io_service io_service; + client instance2( + http::_follow_redirects=true, + http::_io_service=io_service, + http::_cache_resolved=true + ); +} + From 9e5706675bc5099fe2a4b22a839faef4e58b6caa Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 10 Dec 2010 12:38:37 +0800 Subject: [PATCH 042/768] Fixing mis-use of typename, where GCC complains. --- boost/network/protocol/http/impl/request.hpp | 4 ++-- boost/network/protocol/http/impl/response.ipp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index cbeed1e97..e24850206 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -29,12 +29,12 @@ namespace boost { namespace network { /** Specialize the traits for the http_server tag. */ template <> struct headers_container : - vector::apply::type> + vector::apply::type> {}; template <> struct headers_container : - vector::apply::type> + vector::apply::type> {}; namespace http { diff --git a/boost/network/protocol/http/impl/response.ipp b/boost/network/protocol/http/impl/response.ipp index f91dc4611..5c4714709 100644 --- a/boost/network/protocol/http/impl/response.ipp +++ b/boost/network/protocol/http/impl/response.ipp @@ -51,7 +51,7 @@ namespace boost { namespace network { namespace http { } status; /// The headers to be included in the reply. - typedef vector::apply::type>::type headers_vector; + typedef vector::apply::type>::type headers_vector; headers_vector headers; /// The content to be sent in the reply. @@ -69,7 +69,7 @@ namespace boost { namespace network { namespace http { std::vector buffers; buffers.push_back(to_buffer(status)); for (std::size_t i = 0; i < headers.size(); ++i) { - typename request_header::type & h = headers[i]; + request_header::type & h = headers[i]; buffers.push_back(buffer(h.name)); buffers.push_back(buffer(name_value_separator)); buffers.push_back(buffer(h.value)); From 15484ba6f7f87bcc718032f723409e8ffea95b82 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 10 Dec 2010 12:39:14 +0800 Subject: [PATCH 043/768] Adding Server API tests. --- libs/network/test/http/CMakeLists.txt | 19 ++++++- .../test/http/server_constructor_test.cpp | 50 +++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 libs/network/test/http/server_constructor_test.cpp diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 37ff871f8..ead618177 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -41,6 +41,23 @@ if (Boost_FOUND) ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) endforeach (test) + set ( SERVER_API_TESTS + server_constructor_test + ) + foreach ( test ${SERVER_API_TESTS} ) + if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") + endif() + add_executable(cpp-netlib-http-${test} ${test}.cpp) + add_dependencies(cpp-netlib-http-${test} cppnetlib-server-parsers) + target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) + set_target_properties(cpp-netlib-http-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-http-${test} + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) + endforeach (test) + set ( SERVER_TESTS server_hello_world server_async @@ -58,7 +75,7 @@ if (Boost_FOUND) ${CPP-NETLIB_BINARY_DIR}/tests) add_test(cpp-netlib-${test} python - ${CPP-NETLIB_SOURCE_DIR}/libs/network/httplib_acceptance.py + ${CPP-NETLIB_SOURCE_DIR}/libs/network/test/httplib_acceptance.py ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}.passed) endforeach (test) diff --git a/libs/network/test/http/server_constructor_test.cpp b/libs/network/test/http/server_constructor_test.cpp new file mode 100644 index 000000000..390337631 --- /dev/null +++ b/libs/network/test/http/server_constructor_test.cpp @@ -0,0 +1,50 @@ + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE HTTP Server Construtor Tests + +#include +#include + +namespace http = boost::network::http; +namespace util = boost::network::utils; + +struct dummy_sync_handler; +struct dummy_async_handler; +typedef http::server sync_server; +typedef http::async_server async_server; + +struct dummy_sync_handler { + void operator()(sync_server::request const & req, + sync_server::response & res) { + // Really, this is just for testing purposes + } + + void log(char const *) { + } +}; + +struct dummy_async_handler { + void operator()(async_server::request const & req, + async_server::connection_ptr conn) { + // Really, this is just for testing purposes + } +}; + +BOOST_AUTO_TEST_CASE(minimal_constructor) { + dummy_sync_handler sync_handler; + dummy_async_handler async_handler; + util::thread_pool pool; + + BOOST_CHECK_NO_THROW(sync_server sync_instance("127.0.0.1", "80", sync_handler) ); + BOOST_CHECK_NO_THROW(async_server async_instance("127.0.0.1", "80", async_handler, pool) ); +} + +BOOST_AUTO_TEST_CASE(with_io_service_parameter) { +} + +BOOST_AUTO_TEST_CASE(with_socket_options_parameter) { +} From 9e692d3a8fa6bd427268c2a80cf25562129936ed Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 10 Dec 2010 12:39:38 +0800 Subject: [PATCH 044/768] Making the server constructors not throw. --- .../protocol/http/server/async_server.hpp | 46 ++++++++++++------ .../protocol/http/server/sync_server.hpp | 47 +++++++++++++------ 2 files changed, 63 insertions(+), 30 deletions(-) diff --git a/boost/network/protocol/http/server/async_server.hpp b/boost/network/protocol/http/server/async_server.hpp index 4e1d3a703..e81f52d01 100644 --- a/boost/network/protocol/http/server/async_server.hpp +++ b/boost/network/protocol/http/server/async_server.hpp @@ -25,27 +25,22 @@ namespace boost { namespace network { namespace http { , Handler & handler , utils::thread_pool & thread_pool) : handler(handler) + , address_(address) + , port_(port) , thread_pool(thread_pool) + , self_service(new asio::io_service()) , io_service() , acceptor(io_service) , stopping(false) - { - using boost::asio::ip::tcp; - tcp::resolver resolver(io_service); - tcp::resolver::query query(address, port); - tcp::endpoint endpoint = *resolver.resolve(query); - acceptor.open(endpoint.protocol()); - acceptor.bind(endpoint); - acceptor.listen(); - new_connection.reset(new connection(io_service, handler, thread_pool)); - acceptor.async_accept(new_connection->socket(), - boost::bind( - &async_server_base::handle_accept - , this - , boost::asio::placeholders::error)); - } + , new_connection() + , listening_mutex_() + , listening(false) + {} void run() { + boost::unique_lock listening_lock(listening_mutex_); + if (!listening) start_listening(); + listening_lock.unlock(); io_service.run(); }; @@ -58,11 +53,15 @@ namespace boost { namespace network { namespace http { private: Handler & handler; + string_type address_, port_; utils::thread_pool & thread_pool; + std::auto_ptr self_service; asio::io_service io_service; asio::ip::tcp::acceptor acceptor; bool stopping; connection_ptr new_connection; + boost::mutex listening_mutex_; + bool listening; void handle_accept(boost::system::error_code const & ec) { if (!ec) { @@ -85,6 +84,23 @@ namespace boost { namespace network { namespace http { } } } + + void start_listening() { + using boost::asio::ip::tcp; + tcp::resolver resolver(io_service); + tcp::resolver::query query(address_, port_); + tcp::endpoint endpoint = *resolver.resolve(query); + acceptor.open(endpoint.protocol()); + acceptor.bind(endpoint); + acceptor.listen(); + listening = true; + new_connection.reset(new connection(io_service, handler, thread_pool)); + acceptor.async_accept(new_connection->socket(), + boost::bind( + &async_server_base::handle_accept + , this + , boost::asio::placeholders::error)); + } }; } /* http */ diff --git a/boost/network/protocol/http/server/sync_server.hpp b/boost/network/protocol/http/server/sync_server.hpp index 4c2fef0df..8df9139fa 100644 --- a/boost/network/protocol/http/server/sync_server.hpp +++ b/boost/network/protocol/http/server/sync_server.hpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace boost { namespace network { namespace http { @@ -29,23 +30,20 @@ namespace boost { namespace network { namespace http { string_type const & port, Handler & handler) : handler_(handler) - , service_() + , address_(address) + , port_(port) + , self_service_(new boost::asio::io_service()) + , service_(*self_service_) , acceptor_(service_) - , new_connection(new sync_connection(service_, handler)) - { - using boost::asio::ip::tcp; - tcp::resolver resolver(service_); - tcp::resolver::query query(address, port); - tcp::endpoint endpoint = *resolver.resolve(query); - acceptor_.open(endpoint.protocol()); - acceptor_.bind(endpoint); - acceptor_.listen(); - acceptor_.async_accept(new_connection->socket(), - boost::bind(&sync_server_base::handle_accept, - this, boost::asio::placeholders::error)); - } + , new_connection() + , listening_mutex_() + , listening_(false) + {} void run() { + boost::unique_lock listening_lock(listening_mutex_); + if (!listening_) start_listening(); + listening_lock.unlock(); service_.run(); } @@ -57,9 +55,13 @@ namespace boost { namespace network { namespace http { private: Handler & handler_; - boost::asio::io_service service_; + string_type address_, port_; + std::auto_ptr self_service_; + boost::asio::io_service & service_; boost::asio::ip::tcp::acceptor acceptor_; boost::shared_ptr > new_connection; + boost::mutex listening_mutex_; + bool listening_; void handle_accept(boost::system::error_code const & ec) { if (!ec) { @@ -70,6 +72,21 @@ namespace boost { namespace network { namespace http { this, boost::asio::placeholders::error)); } } + + void start_listening() { + using boost::asio::ip::tcp; + tcp::resolver resolver(service_); + tcp::resolver::query query(address_, port_); + tcp::endpoint endpoint = *resolver.resolve(query); + acceptor_.open(endpoint.protocol()); + acceptor_.bind(endpoint); + acceptor_.listen(); + listening_ = true; + new_connection.reset(new sync_connection(service_, handler_)); + acceptor_.async_accept(new_connection->socket(), + boost::bind(&sync_server_base::handle_accept, + this, boost::asio::placeholders::error)); + } }; } /* http */ From f829f7df5399a52a005043f23f93274968e557c7 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 10 Dec 2010 12:43:20 +0800 Subject: [PATCH 045/768] Adding missing CMakeLists.txt file in libs/network/build/, darned .gitignore. --- .gitignore | 5 +---- libs/network/build/CMakeLists.txt | 6 ++++++ 2 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 libs/network/build/CMakeLists.txt diff --git a/.gitignore b/.gitignore index cf77aae6d..0a0b40a64 100644 --- a/.gitignore +++ b/.gitignore @@ -5,9 +5,6 @@ CMakeCache.txt CMakeFiles Makefile Testing -build -_build -bin *.gch libs/mime/test/mime-roundtrip - +*.a diff --git a/libs/network/build/CMakeLists.txt b/libs/network/build/CMakeLists.txt new file mode 100644 index 000000000..3ed21b20d --- /dev/null +++ b/libs/network/build/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories(${CPP-NETLIB_SOURCE_DIR}) +find_package( Boost 1.43.0 COMPONENTS unit_test_framework system regex thread filesystem ) + +add_library(cppnetlib-uri-parsers STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/parse_uri_impl.cpp) +add_library(cppnetlib-server-parsers STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/server_request_parsers_impl.cpp) + From 2b1870eb3cdd1d6cdd1355ab745f1ef796495d3b Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 10 Dec 2010 14:05:04 +0800 Subject: [PATCH 046/768] Using Boost.Parameter in the HTTP Server constructor interface. --- .../protocol/http/client/parameters.hpp | 3 +- boost/network/protocol/http/parameters.hpp | 24 +++++++++++ boost/network/protocol/http/server.hpp | 32 +++++++++----- .../protocol/http/server/async_server.hpp | 41 +++++++++++------- .../protocol/http/server/parameters.hpp | 25 +++++++++++ .../protocol/http/server/storage_base.hpp | 40 ++++++++++++++++++ .../protocol/http/server/sync_server.hpp | 42 ++++++++++++------- .../test/http/server_constructor_test.cpp | 7 ++++ 8 files changed, 171 insertions(+), 43 deletions(-) create mode 100644 boost/network/protocol/http/parameters.hpp create mode 100644 boost/network/protocol/http/server/parameters.hpp create mode 100644 boost/network/protocol/http/server/storage_base.hpp diff --git a/boost/network/protocol/http/client/parameters.hpp b/boost/network/protocol/http/client/parameters.hpp index ae0cbe6b5..912255820 100644 --- a/boost/network/protocol/http/client/parameters.hpp +++ b/boost/network/protocol/http/client/parameters.hpp @@ -6,12 +6,11 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#include namespace boost { namespace network { namespace http { BOOST_PARAMETER_NAME(follow_redirects) - BOOST_PARAMETER_NAME(io_service) BOOST_PARAMETER_NAME(cache_resolved) } /* http */ diff --git a/boost/network/protocol/http/parameters.hpp b/boost/network/protocol/http/parameters.hpp new file mode 100644 index 000000000..51891a4e0 --- /dev/null +++ b/boost/network/protocol/http/parameters.hpp @@ -0,0 +1,24 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARAMETERS_HPP_20101210 +#define BOOST_NETWORK_PROTOCOL_HTTP_PARAMETERS_HPP_20101210 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_PARAMETER_MAX_ARITY) + #define BOOST_PARAMETER_MAX_ARITY 6 +#endif +#include + +namespace boost { namespace network { namespace http { + + BOOST_PARAMETER_NAME(io_service) + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_PARAMETERS_HPP_20101210 */ diff --git a/boost/network/protocol/http/server.hpp b/boost/network/protocol/http/server.hpp index fecebf342..4a0fe2000 100644 --- a/boost/network/protocol/http/server.hpp +++ b/boost/network/protocol/http/server.hpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace boost { namespace network { namespace http { @@ -38,11 +39,16 @@ namespace boost { namespace network { namespace http { typedef typename server_base::type server_base; - server(typename server_base::string_type const & address, - typename server_base::string_type const & port, - Handler & handler) - : server_base(address, port, handler) {} - + BOOST_PARAMETER_CONSTRUCTOR( + server, (server_base), tag, + (required + (address, (typename server_base::string_type const &)) + (port, (typename server_base::string_type const &)) + (in_out(handler), (Handler &))) + (optional + (in_out(io_service), (boost::asio::io_service &)) + (socket_options, *)) + ) }; template @@ -51,11 +57,17 @@ namespace boost { namespace network { namespace http { typedef typename server_base::type server_base; - async_server(typename server_base::string_type const & address, - typename server_base::string_type const & port, - Handler & handler, - utils::thread_pool & thread_pool) - : server_base(address, port, handler, thread_pool) {} + BOOST_PARAMETER_CONSTRUCTOR( + async_server, (server_base), tag, + (required + (address, (typename server_base::string_type const &)) + (port, (typename server_base::string_type const &)) + (in_out(handler), (Handler&)) + (in_out(thread_pool), (utils::thread_pool&))) + (optional + (in_out(io_service), (boost::asio::io_service&)) + (socket_options, *)) + ) }; } // namespace http diff --git a/boost/network/protocol/http/server/async_server.hpp b/boost/network/protocol/http/server/async_server.hpp index e81f52d01..a3f1e8d6c 100644 --- a/boost/network/protocol/http/server/async_server.hpp +++ b/boost/network/protocol/http/server/async_server.hpp @@ -7,12 +7,14 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#include +#include #include namespace boost { namespace network { namespace http { template - struct async_server_base { + struct async_server_base : server_storage_base { typedef basic_request request; typedef basic_response response; typedef typename string::type string_type; @@ -20,17 +22,22 @@ namespace boost { namespace network { namespace http { typedef async_connection connection; typedef shared_ptr connection_ptr; - async_server_base(string_type const & address - , string_type const & port - , Handler & handler - , utils::thread_pool & thread_pool) - : handler(handler) - , address_(address) - , port_(port) - , thread_pool(thread_pool) - , self_service(new asio::io_service()) - , io_service() - , acceptor(io_service) + template + async_server_base(ArgPack const & args) + : server_storage_base(args, + typename mpl::if_< + is_same< + typename parameter::value_type::type, + void + >, + server_storage_base::no_io_service, + server_storage_base::has_io_service + >::type()) + , handler(args[_handler]) + , address_(args[_address]) + , port_(args[_port]) + , thread_pool(args[_thread_pool]) + , acceptor(server_storage_base::service_) , stopping(false) , new_connection() , listening_mutex_() @@ -38,9 +45,7 @@ namespace boost { namespace network { namespace http { {} void run() { - boost::unique_lock listening_lock(listening_mutex_); - if (!listening) start_listening(); - listening_lock.unlock(); + listen(); io_service.run(); }; @@ -51,6 +56,12 @@ namespace boost { namespace network { namespace http { acceptor.cancel(); } + void listen() { + boost::unique_lock listening_lock(listening_mutex_); + if (!listening) start_listening(); + listening_lock.unlock(); + } + private: Handler & handler; string_type address_, port_; diff --git a/boost/network/protocol/http/server/parameters.hpp b/boost/network/protocol/http/server/parameters.hpp new file mode 100644 index 000000000..8a4856cbc --- /dev/null +++ b/boost/network/protocol/http/server/parameters.hpp @@ -0,0 +1,25 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_PARAMETERS_HPP_20101210 +#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_PARAMETERS_HPP_20101210 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +namespace boost { namespace network { namespace http { + + BOOST_PARAMETER_NAME(address) + BOOST_PARAMETER_NAME(port) + BOOST_PARAMETER_NAME(handler) + BOOST_PARAMETER_NAME(thread_pool) + BOOST_PARAMETER_NAME(socket_options) + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_PARAMETERS_HPP_20101210 */ diff --git a/boost/network/protocol/http/server/storage_base.hpp b/boost/network/protocol/http/server/storage_base.hpp new file mode 100644 index 000000000..25896dd25 --- /dev/null +++ b/boost/network/protocol/http/server/storage_base.hpp @@ -0,0 +1,40 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_STORAGE_BASE_HPP_20101210 +#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_STORAGE_BASE_HPP_20101210 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +namespace boost { namespace network { namespace http { + + struct server_storage_base { + struct no_io_service {}; + struct has_io_service {}; + protected: + template + server_storage_base(ArgPack const & args, no_io_service) + : self_service_(new boost::asio::io_service()) + , service_(*self_service_) + {} + + template + server_storage_base(ArgPack const & args, has_io_service) + : self_service_() + , service_(args[_io_service]) + {} + + std::auto_ptr self_service_; + asio::io_service & service_; + }; + + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_STORAGE_BASE_HPP_20101210 */ diff --git a/boost/network/protocol/http/server/sync_server.hpp b/boost/network/protocol/http/server/sync_server.hpp index 8df9139fa..4afcfb1be 100644 --- a/boost/network/protocol/http/server/sync_server.hpp +++ b/boost/network/protocol/http/server/sync_server.hpp @@ -14,36 +14,42 @@ #include #include #include +#include +#include #include #include namespace boost { namespace network { namespace http { - + template - struct sync_server_base { + struct sync_server_base : server_storage_base { typedef typename string::type string_type; typedef basic_request request; typedef basic_response response; typedef typename boost::network::http::response_header::type response_header; - sync_server_base(string_type const & address, - string_type const & port, - Handler & handler) - : handler_(handler) - , address_(address) - , port_(port) - , self_service_(new boost::asio::io_service()) - , service_(*self_service_) - , acceptor_(service_) + template + sync_server_base(ArgPack const & args) + : server_storage_base(args, + typename mpl::if_< + is_same< + typename parameter::value_type::type, + void + >, + server_storage_base::no_io_service, + server_storage_base::has_io_service + >::type()) + , handler_(args[_handler]) + , address_(args[_address]) + , port_(args[_port]) + , acceptor_(server_storage_base::service_) , new_connection() , listening_mutex_() , listening_(false) {} void run() { - boost::unique_lock listening_lock(listening_mutex_); - if (!listening_) start_listening(); - listening_lock.unlock(); + listen(); service_.run(); } @@ -52,12 +58,16 @@ namespace boost { namespace network { namespace http { acceptor_.cancel(); } + void listen() { + boost::unique_lock listening_lock(listening_mutex_); + if (!listening_) start_listening(); + listening_lock.unlock(); + } + private: Handler & handler_; string_type address_, port_; - std::auto_ptr self_service_; - boost::asio::io_service & service_; boost::asio::ip::tcp::acceptor acceptor_; boost::shared_ptr > new_connection; boost::mutex listening_mutex_; diff --git a/libs/network/test/http/server_constructor_test.cpp b/libs/network/test/http/server_constructor_test.cpp index 390337631..fe4cff094 100644 --- a/libs/network/test/http/server_constructor_test.cpp +++ b/libs/network/test/http/server_constructor_test.cpp @@ -44,6 +44,13 @@ BOOST_AUTO_TEST_CASE(minimal_constructor) { } BOOST_AUTO_TEST_CASE(with_io_service_parameter) { + dummy_sync_handler sync_handler; + dummy_async_handler async_handler; + util::thread_pool pool; + boost::asio::io_service io_service; + + BOOST_CHECK_NO_THROW(sync_server sync_instance("127.0.0.1", "80", sync_handler, io_service)); + BOOST_CHECK_NO_THROW(async_server async_instance("127.0.0.1", "80", async_handler, pool, io_service)); } BOOST_AUTO_TEST_CASE(with_socket_options_parameter) { From a2fb9fec127db0c20f1fb9ad1012a8dcedd8c178 Mon Sep 17 00:00:00 2001 From: Oleg Malashenko Date: Fri, 10 Dec 2010 16:58:50 +1000 Subject: [PATCH 047/768] Fixed async_connection::read() First read() returns remainder of the data that is in read_buffer_ after handle_read_data() and is not the part of HTTP message header. Subsequent reads do actual read from socket. --- .../protocol/http/server/async_connection.hpp | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index 5edef7f72..c5eb46f46 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -227,6 +227,23 @@ namespace boost { namespace network { namespace http { void read(read_callback_function callback) { if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); + if (new_start != read_buffer_.begin()) + { + input_range input = boost::make_iterator_range(new_start, read_buffer_.end()); + thread_pool().post( + strand.wrap( + boost::bind( + callback + , input + , boost::system::error_code() + , data_end - new_start + , async_connection::shared_from_this()) + ) + ); + new_start = read_buffer_.begin(); + return; + } + socket().async_read_some( asio::buffer(read_buffer_) , strand.wrap( @@ -250,6 +267,8 @@ namespace boost { namespace network { namespace http { thread_pool().post( boost::bind( callback + , boost::make_iterator_range(read_buffer_.begin() + ,read_buffer_.begin() + bytes_transferred) , ec , bytes_transferred , async_connection::shared_from_this())); @@ -279,7 +298,7 @@ namespace boost { namespace network { namespace http { status_t status; request_parser_type parser; request request_; - buffer_type::iterator new_start; + buffer_type::iterator new_start, data_end; string_type partial_parsed; optional error_encountered; pending_actions_list pending_actions; @@ -317,10 +336,11 @@ namespace boost { namespace network { namespace http { if (!ec) { logic::tribool parsed_ok; iterator_range result_range, input_range; + data_end = new_start + bytes_transferred; switch (state) { case method: input_range = boost::make_iterator_range( - new_start, read_buffer_.end()); + new_start, data_end); fusion::tie(parsed_ok, result_range) = parser.parse_until( request_parser_type::method_done, input_range); if (!parsed_ok) { @@ -343,7 +363,7 @@ namespace boost { namespace network { namespace http { } case uri: input_range = boost::make_iterator_range( - new_start, read_buffer_.end()); + new_start, data_end); fusion::tie(parsed_ok, result_range) = parser.parse_until( request_parser_type::uri_done, input_range); @@ -367,7 +387,7 @@ namespace boost { namespace network { namespace http { } case version: input_range = boost::make_iterator_range( - new_start, read_buffer_.end()); + new_start, data_end); fusion::tie(parsed_ok, result_range) = parser.parse_until( request_parser_type::version_done, input_range); @@ -391,7 +411,7 @@ namespace boost { namespace network { namespace http { } case headers: input_range = boost::make_iterator_range( - new_start, read_buffer_.end()); + new_start, data_end); fusion::tie(parsed_ok, result_range) = parser.parse_until( request_parser_type::headers_done, input_range); From abe9b594eb368bf02dcbf772a9b8522863a95e6e Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 10 Dec 2010 21:54:42 +0800 Subject: [PATCH 048/768] Adding support for socket options to be passed in the constructor via Boost.Parameter enabled constructor. Needs documentation!; --- boost/network/protocol/http/parameters.hpp | 2 +- boost/network/protocol/http/server.hpp | 20 ++++++++- .../protocol/http/server/parameters.hpp | 11 ++++- .../protocol/http/server/sync_server.hpp | 43 ++++++++++++++++++- .../test/http/server_constructor_test.cpp | 27 ++++++++++++ 5 files changed, 98 insertions(+), 5 deletions(-) diff --git a/boost/network/protocol/http/parameters.hpp b/boost/network/protocol/http/parameters.hpp index 51891a4e0..9bf0ae97e 100644 --- a/boost/network/protocol/http/parameters.hpp +++ b/boost/network/protocol/http/parameters.hpp @@ -7,7 +7,7 @@ // http://www.boost.org/LICENSE_1_0.txt) #if !defined(BOOST_PARAMETER_MAX_ARITY) - #define BOOST_PARAMETER_MAX_ARITY 6 + #define BOOST_PARAMETER_MAX_ARITY 16 #endif #include diff --git a/boost/network/protocol/http/server.hpp b/boost/network/protocol/http/server.hpp index 4a0fe2000..0ab3e47b4 100644 --- a/boost/network/protocol/http/server.hpp +++ b/boost/network/protocol/http/server.hpp @@ -47,7 +47,15 @@ namespace boost { namespace network { namespace http { (in_out(handler), (Handler &))) (optional (in_out(io_service), (boost::asio::io_service &)) - (socket_options, *)) + (reuse_address, (bool)) + (report_aborted, (bool)) + (receive_buffer_size, (int)) + (send_buffer_size, (int)) + (receive_low_watermark, (int)) + (send_low_watermark, (int)) + (non_blocking_io, (int)) + (linger, (bool)) + (linger_timeout, (int))) ) }; @@ -66,7 +74,15 @@ namespace boost { namespace network { namespace http { (in_out(thread_pool), (utils::thread_pool&))) (optional (in_out(io_service), (boost::asio::io_service&)) - (socket_options, *)) + (reuse_address, (bool)) + (report_aborted, (bool)) + (receive_buffer_size, (int)) + (send_buffer_size, (int)) + (receive_low_watermark, (int)) + (send_low_watermark, (int)) + (non_blocking_io, (int)) + (linger, (bool)) + (linger_timeout, (int))) ) }; diff --git a/boost/network/protocol/http/server/parameters.hpp b/boost/network/protocol/http/server/parameters.hpp index 8a4856cbc..06b59b174 100644 --- a/boost/network/protocol/http/server/parameters.hpp +++ b/boost/network/protocol/http/server/parameters.hpp @@ -14,7 +14,16 @@ namespace boost { namespace network { namespace http { BOOST_PARAMETER_NAME(port) BOOST_PARAMETER_NAME(handler) BOOST_PARAMETER_NAME(thread_pool) - BOOST_PARAMETER_NAME(socket_options) + + BOOST_PARAMETER_NAME(reuse_address) + BOOST_PARAMETER_NAME(report_aborted) + BOOST_PARAMETER_NAME(receive_buffer_size) + BOOST_PARAMETER_NAME(send_buffer_size) + BOOST_PARAMETER_NAME(receive_low_watermark) + BOOST_PARAMETER_NAME(send_low_watermark) + BOOST_PARAMETER_NAME(non_blocking_io) + BOOST_PARAMETER_NAME(linger) + BOOST_PARAMETER_NAME(linger_timeout) } /* http */ diff --git a/boost/network/protocol/http/server/sync_server.hpp b/boost/network/protocol/http/server/sync_server.hpp index 4afcfb1be..8efa99ce7 100644 --- a/boost/network/protocol/http/server/sync_server.hpp +++ b/boost/network/protocol/http/server/sync_server.hpp @@ -21,8 +21,46 @@ namespace boost { namespace network { namespace http { + struct socket_options_base { + protected: + asio::socket_base::reuse_address acceptor_reuse_address; + asio::socket_base::enable_connection_aborted acceptor_report_aborted; + asio::socket_base::receive_buffer_size receive_buffer_size; + asio::socket_base::send_buffer_size send_buffer_size; + asio::socket_base::receive_low_watermark receive_low_watermark; + asio::socket_base::send_low_watermark send_low_watermark; + asio::socket_base::non_blocking_io non_blocking_io; + asio::socket_base::linger linger; + + template + socket_options_base(ArgPack const & args) + : acceptor_reuse_address(args[_reuse_address|false]) + , acceptor_report_aborted(args[_report_aborted|false]) + , receive_buffer_size(args[_receive_buffer_size|1024]) + , send_buffer_size(args[_send_buffer_size|1024]) + , receive_low_watermark(args[_receive_low_watermark|512]) + , send_low_watermark(args[_send_low_watermark|512]) + , non_blocking_io(args[_non_blocking_io|true]) + , linger(args[_linger|true], args[_linger_timeout|0]) + {} + + void acceptor_options(boost::asio::ip::tcp::acceptor & acceptor) { + acceptor.set_option(acceptor_reuse_address); + acceptor.set_option(acceptor_report_aborted); + } + + void socket_options(boost::asio::ip::tcp::socket & socket) { + socket.set_option(receive_buffer_size); + socket.set_option(receive_low_watermark); + socket.set_option(send_buffer_size); + socket.set_option(send_low_watermark); + socket.io_control(non_blocking_io); + socket.set_option(linger); + } + }; + template - struct sync_server_base : server_storage_base { + struct sync_server_base : server_storage_base, socket_options_base { typedef typename string::type string_type; typedef basic_request request; typedef basic_response response; @@ -39,6 +77,7 @@ namespace boost { namespace network { namespace http { server_storage_base::no_io_service, server_storage_base::has_io_service >::type()) + , socket_options_base(args) , handler_(args[_handler]) , address_(args[_address]) , port_(args[_port]) @@ -75,6 +114,7 @@ namespace boost { namespace network { namespace http { void handle_accept(boost::system::error_code const & ec) { if (!ec) { + socket_options_base::socket_options(new_connection->socket()); new_connection->start(); new_connection.reset(new sync_connection(service_, handler_)); acceptor_.async_accept(new_connection->socket(), @@ -90,6 +130,7 @@ namespace boost { namespace network { namespace http { tcp::endpoint endpoint = *resolver.resolve(query); acceptor_.open(endpoint.protocol()); acceptor_.bind(endpoint); + socket_options_base::acceptor_options(acceptor_); acceptor_.listen(); listening_ = true; new_connection.reset(new sync_connection(service_, handler_)); diff --git a/libs/network/test/http/server_constructor_test.cpp b/libs/network/test/http/server_constructor_test.cpp index fe4cff094..b2b4fe8eb 100644 --- a/libs/network/test/http/server_constructor_test.cpp +++ b/libs/network/test/http/server_constructor_test.cpp @@ -54,4 +54,31 @@ BOOST_AUTO_TEST_CASE(with_io_service_parameter) { } BOOST_AUTO_TEST_CASE(with_socket_options_parameter) { + dummy_sync_handler sync_handler; + dummy_async_handler async_handler; + util::thread_pool pool; + + BOOST_CHECK_NO_THROW(sync_server sync_instance("127.0.0.1", "80", sync_handler, + http::_reuse_address=true, + http::_report_aborted=true, + http::_receive_buffer_size=4096, + http::_send_buffer_size=4096, + http::_receive_low_watermark=1024, + http::_send_low_watermark=1024, + http::_non_blocking_io=true, + http::_linger=true, + http::_linger_timeout=0 + )); + BOOST_CHECK_NO_THROW(async_server async_instance("127.0.0.1", "80", async_handler, pool, + http::_reuse_address=true, + http::_report_aborted=true, + http::_receive_buffer_size=4096, + http::_send_buffer_size=4096, + http::_receive_low_watermark=1024, + http::_send_low_watermark=1024, + http::_non_blocking_io=true, + http::_linger=true, + http::_linger_timeout=0 + )); + } From 7205bcd3899be7d0e368c4fdece8bee217ede7ad Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 10 Dec 2010 22:26:09 +0800 Subject: [PATCH 049/768] Making the HTTP Async Server use the socket_options_base for setting parameter-set customizations on the socket options handled by the HTTP server. --- .../protocol/http/server/async_server.hpp | 8 ++- .../http/server/socket_options_base.hpp | 57 +++++++++++++++++++ .../protocol/http/server/sync_server.hpp | 40 +------------ 3 files changed, 65 insertions(+), 40 deletions(-) create mode 100644 boost/network/protocol/http/server/socket_options_base.hpp diff --git a/boost/network/protocol/http/server/async_server.hpp b/boost/network/protocol/http/server/async_server.hpp index a3f1e8d6c..d08b62469 100644 --- a/boost/network/protocol/http/server/async_server.hpp +++ b/boost/network/protocol/http/server/async_server.hpp @@ -9,12 +9,13 @@ #include #include #include +#include #include namespace boost { namespace network { namespace http { template - struct async_server_base : server_storage_base { + struct async_server_base : server_storage_base, socket_options_base { typedef basic_request request; typedef basic_response response; typedef typename string::type string_type; @@ -33,6 +34,7 @@ namespace boost { namespace network { namespace http { server_storage_base::no_io_service, server_storage_base::has_io_service >::type()) + , socket_options_base(args) , handler(args[_handler]) , address_(args[_address]) , port_(args[_port]) @@ -57,9 +59,9 @@ namespace boost { namespace network { namespace http { } void listen() { + if (listening) return; boost::unique_lock listening_lock(listening_mutex_); if (!listening) start_listening(); - listening_lock.unlock(); } private: @@ -76,6 +78,7 @@ namespace boost { namespace network { namespace http { void handle_accept(boost::system::error_code const & ec) { if (!ec) { + socket_options_base::socket_options(new_connection->socket()); new_connection->start(); if (!stopping) { new_connection.reset( @@ -103,6 +106,7 @@ namespace boost { namespace network { namespace http { tcp::endpoint endpoint = *resolver.resolve(query); acceptor.open(endpoint.protocol()); acceptor.bind(endpoint); + socket_options_base::acceptor_options(acceptor); acceptor.listen(); listening = true; new_connection.reset(new connection(io_service, handler, thread_pool)); diff --git a/boost/network/protocol/http/server/socket_options_base.hpp b/boost/network/protocol/http/server/socket_options_base.hpp new file mode 100644 index 000000000..73fd7144f --- /dev/null +++ b/boost/network/protocol/http/server/socket_options_base.hpp @@ -0,0 +1,57 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 +#define BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +namespace boost { namespace network { namespace http { + + struct socket_options_base { + protected: + asio::socket_base::reuse_address acceptor_reuse_address; + asio::socket_base::enable_connection_aborted acceptor_report_aborted; + asio::socket_base::receive_buffer_size receive_buffer_size; + asio::socket_base::send_buffer_size send_buffer_size; + asio::socket_base::receive_low_watermark receive_low_watermark; + asio::socket_base::send_low_watermark send_low_watermark; + asio::socket_base::non_blocking_io non_blocking_io; + asio::socket_base::linger linger; + + template + socket_options_base(ArgPack const & args) + : acceptor_reuse_address(args[_reuse_address|false]) + , acceptor_report_aborted(args[_report_aborted|false]) + , receive_buffer_size(args[_receive_buffer_size|1024]) + , send_buffer_size(args[_send_buffer_size|1024]) + , receive_low_watermark(args[_receive_low_watermark|512]) + , send_low_watermark(args[_send_low_watermark|512]) + , non_blocking_io(args[_non_blocking_io|true]) + , linger(args[_linger|true], args[_linger_timeout|0]) + {} + + void acceptor_options(boost::asio::ip::tcp::acceptor & acceptor) { + acceptor.set_option(acceptor_reuse_address); + acceptor.set_option(acceptor_report_aborted); + } + + void socket_options(boost::asio::ip::tcp::socket & socket) { + socket.set_option(receive_buffer_size); + socket.set_option(receive_low_watermark); + socket.set_option(send_buffer_size); + socket.set_option(send_low_watermark); + socket.io_control(non_blocking_io); + socket.set_option(linger); + } + }; + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_SOCKET_OPTIONS_BASE_HPP_20101210 */ diff --git a/boost/network/protocol/http/server/sync_server.hpp b/boost/network/protocol/http/server/sync_server.hpp index 8efa99ce7..5d5518d10 100644 --- a/boost/network/protocol/http/server/sync_server.hpp +++ b/boost/network/protocol/http/server/sync_server.hpp @@ -16,49 +16,12 @@ #include #include #include +#include #include #include namespace boost { namespace network { namespace http { - struct socket_options_base { - protected: - asio::socket_base::reuse_address acceptor_reuse_address; - asio::socket_base::enable_connection_aborted acceptor_report_aborted; - asio::socket_base::receive_buffer_size receive_buffer_size; - asio::socket_base::send_buffer_size send_buffer_size; - asio::socket_base::receive_low_watermark receive_low_watermark; - asio::socket_base::send_low_watermark send_low_watermark; - asio::socket_base::non_blocking_io non_blocking_io; - asio::socket_base::linger linger; - - template - socket_options_base(ArgPack const & args) - : acceptor_reuse_address(args[_reuse_address|false]) - , acceptor_report_aborted(args[_report_aborted|false]) - , receive_buffer_size(args[_receive_buffer_size|1024]) - , send_buffer_size(args[_send_buffer_size|1024]) - , receive_low_watermark(args[_receive_low_watermark|512]) - , send_low_watermark(args[_send_low_watermark|512]) - , non_blocking_io(args[_non_blocking_io|true]) - , linger(args[_linger|true], args[_linger_timeout|0]) - {} - - void acceptor_options(boost::asio::ip::tcp::acceptor & acceptor) { - acceptor.set_option(acceptor_reuse_address); - acceptor.set_option(acceptor_report_aborted); - } - - void socket_options(boost::asio::ip::tcp::socket & socket) { - socket.set_option(receive_buffer_size); - socket.set_option(receive_low_watermark); - socket.set_option(send_buffer_size); - socket.set_option(send_low_watermark); - socket.io_control(non_blocking_io); - socket.set_option(linger); - } - }; - template struct sync_server_base : server_storage_base, socket_options_base { typedef typename string::type string_type; @@ -98,6 +61,7 @@ namespace boost { namespace network { namespace http { } void listen() { + if (listening_) return; boost::unique_lock listening_lock(listening_mutex_); if (!listening_) start_listening(); listening_lock.unlock(); From 1013faa2d7a390d36d98eb47e1a925d90436402a Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 11 Dec 2010 00:25:25 +0800 Subject: [PATCH 050/768] Tweaking and debugging HTTP server implementations. --- boost/network/protocol/http/impl/response.ipp | 5 +++-- .../protocol/http/server/async_server.hpp | 13 +++++------- .../http/server/socket_options_base.hpp | 21 ++++++++++--------- .../protocol/http/server/sync_server.hpp | 6 ++---- libs/network/test/http/server_async.cpp | 2 +- libs/network/test/http/server_hello_world.cpp | 6 ++++-- 6 files changed, 26 insertions(+), 27 deletions(-) diff --git a/boost/network/protocol/http/impl/response.ipp b/boost/network/protocol/http/impl/response.ipp index 5c4714709..2eb669dba 100644 --- a/boost/network/protocol/http/impl/response.ipp +++ b/boost/network/protocol/http/impl/response.ipp @@ -27,6 +27,7 @@ namespace boost { namespace network { namespace http { template <> struct basic_response { typedef tags::http_server tag; + typedef response_header::type header_type; /// The status of the reply. enum status_type { @@ -51,7 +52,7 @@ namespace boost { namespace network { namespace http { } status; /// The headers to be included in the reply. - typedef vector::apply::type>::type headers_vector; + typedef vector::apply::type headers_vector; headers_vector headers; /// The content to be sent in the reply. @@ -69,7 +70,7 @@ namespace boost { namespace network { namespace http { std::vector buffers; buffers.push_back(to_buffer(status)); for (std::size_t i = 0; i < headers.size(); ++i) { - request_header::type & h = headers[i]; + header_type & h = headers[i]; buffers.push_back(buffer(h.name)); buffers.push_back(buffer(name_value_separator)); buffers.push_back(buffer(h.value)); diff --git a/boost/network/protocol/http/server/async_server.hpp b/boost/network/protocol/http/server/async_server.hpp index d08b62469..ec105abcb 100644 --- a/boost/network/protocol/http/server/async_server.hpp +++ b/boost/network/protocol/http/server/async_server.hpp @@ -48,7 +48,7 @@ namespace boost { namespace network { namespace http { void run() { listen(); - io_service.run(); + service_.run(); }; void stop() { @@ -59,7 +59,6 @@ namespace boost { namespace network { namespace http { } void listen() { - if (listening) return; boost::unique_lock listening_lock(listening_mutex_); if (!listening) start_listening(); } @@ -68,8 +67,6 @@ namespace boost { namespace network { namespace http { Handler & handler; string_type address_, port_; utils::thread_pool & thread_pool; - std::auto_ptr self_service; - asio::io_service io_service; asio::ip::tcp::acceptor acceptor; bool stopping; connection_ptr new_connection; @@ -83,7 +80,7 @@ namespace boost { namespace network { namespace http { if (!stopping) { new_connection.reset( new connection( - io_service + service_ , handler , thread_pool ) @@ -101,20 +98,20 @@ namespace boost { namespace network { namespace http { void start_listening() { using boost::asio::ip::tcp; - tcp::resolver resolver(io_service); + tcp::resolver resolver(service_); tcp::resolver::query query(address_, port_); tcp::endpoint endpoint = *resolver.resolve(query); acceptor.open(endpoint.protocol()); acceptor.bind(endpoint); socket_options_base::acceptor_options(acceptor); acceptor.listen(); - listening = true; - new_connection.reset(new connection(io_service, handler, thread_pool)); + new_connection.reset(new connection(service_, handler, thread_pool)); acceptor.async_accept(new_connection->socket(), boost::bind( &async_server_base::handle_accept , this , boost::asio::placeholders::error)); + listening = true; } }; diff --git a/boost/network/protocol/http/server/socket_options_base.hpp b/boost/network/protocol/http/server/socket_options_base.hpp index 73fd7144f..13c8ebc07 100644 --- a/boost/network/protocol/http/server/socket_options_base.hpp +++ b/boost/network/protocol/http/server/socket_options_base.hpp @@ -25,10 +25,10 @@ namespace boost { namespace network { namespace http { socket_options_base(ArgPack const & args) : acceptor_reuse_address(args[_reuse_address|false]) , acceptor_report_aborted(args[_report_aborted|false]) - , receive_buffer_size(args[_receive_buffer_size|1024]) - , send_buffer_size(args[_send_buffer_size|1024]) - , receive_low_watermark(args[_receive_low_watermark|512]) - , send_low_watermark(args[_send_low_watermark|512]) + , receive_buffer_size(args[_receive_buffer_size|4096]) + , send_buffer_size(args[_send_buffer_size|4096]) + , receive_low_watermark(args[_receive_low_watermark|1024]) + , send_low_watermark(args[_send_low_watermark|1024]) , non_blocking_io(args[_non_blocking_io|true]) , linger(args[_linger|true], args[_linger_timeout|0]) {} @@ -39,12 +39,13 @@ namespace boost { namespace network { namespace http { } void socket_options(boost::asio::ip::tcp::socket & socket) { - socket.set_option(receive_buffer_size); - socket.set_option(receive_low_watermark); - socket.set_option(send_buffer_size); - socket.set_option(send_low_watermark); - socket.io_control(non_blocking_io); - socket.set_option(linger); + boost::system::error_code ignored; + socket.io_control(non_blocking_io, ignored); + socket.set_option(linger, ignored); + socket.set_option(receive_buffer_size, ignored); + socket.set_option(receive_low_watermark, ignored); + socket.set_option(send_buffer_size, ignored); + socket.set_option(send_low_watermark, ignored); } }; diff --git a/boost/network/protocol/http/server/sync_server.hpp b/boost/network/protocol/http/server/sync_server.hpp index 5d5518d10..f92965e8c 100644 --- a/boost/network/protocol/http/server/sync_server.hpp +++ b/boost/network/protocol/http/server/sync_server.hpp @@ -61,10 +61,8 @@ namespace boost { namespace network { namespace http { } void listen() { - if (listening_) return; boost::unique_lock listening_lock(listening_mutex_); if (!listening_) start_listening(); - listening_lock.unlock(); } private: @@ -93,14 +91,14 @@ namespace boost { namespace network { namespace http { tcp::resolver::query query(address_, port_); tcp::endpoint endpoint = *resolver.resolve(query); acceptor_.open(endpoint.protocol()); - acceptor_.bind(endpoint); socket_options_base::acceptor_options(acceptor_); + acceptor_.bind(endpoint); acceptor_.listen(); - listening_ = true; new_connection.reset(new sync_connection(service_, handler_)); acceptor_.async_accept(new_connection->socket(), boost::bind(&sync_server_base::handle_accept, this, boost::asio::placeholders::error)); + listening_ = true; } }; diff --git a/libs/network/test/http/server_async.cpp b/libs/network/test/http/server_async.cpp index 3dfcad69b..2b7016a76 100644 --- a/libs/network/test/http/server_async.cpp +++ b/libs/network/test/http/server_async.cpp @@ -42,7 +42,7 @@ struct async_hello_world { int main(int argc, char * argv[]) { utils::thread_pool thread_pool(2); async_hello_world handler; - server instance("127.0.0.1", "8000", handler, thread_pool); + server instance("127.0.0.1", "8000", handler, thread_pool, http::_reuse_address=true); instance.run(); return 0; } diff --git a/libs/network/test/http/server_hello_world.cpp b/libs/network/test/http/server_hello_world.cpp index 02ceba4bb..823fb35e9 100644 --- a/libs/network/test/http/server_hello_world.cpp +++ b/libs/network/test/http/server_hello_world.cpp @@ -26,9 +26,11 @@ typedef http::server server; struct hello_world { void operator()(server::request const & request, server::response & response) { + static server::response::header_type header = {"Connection", "close"}; response = server::response::stock_reply(server::response::ok, "Hello, World!"); + response.headers.push_back(header); assert(response.status == server::response::ok); - assert(response.headers.size() == 2); + assert(response.headers.size() == 3); assert(response.content == "Hello, World!"); } @@ -41,7 +43,7 @@ struct hello_world { int main(int argc, char * argv[]) { hello_world handler; - server server_("127.0.0.1", "8000", handler); + server server_("127.0.0.1", "8000", handler, http::_reuse_address=true); server_.run(); return EXIT_SUCCESS; } From 02d6e81372608b1482c512077538a94fb145a9fb Mon Sep 17 00:00:00 2001 From: Oleg Malashenko Date: Sat, 11 Dec 2010 18:12:12 +1000 Subject: [PATCH 051/768] Use std::distance() and std::advance() instead of iterator arithmetic. --- .../protocol/http/server/async_connection.hpp | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index c5eb46f46..92132a33f 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -231,14 +231,12 @@ namespace boost { namespace network { namespace http { { input_range input = boost::make_iterator_range(new_start, read_buffer_.end()); thread_pool().post( - strand.wrap( - boost::bind( - callback - , input - , boost::system::error_code() - , data_end - new_start - , async_connection::shared_from_this()) - ) + boost::bind( + callback + , input + , boost::system::error_code() + , std::distance(new_start, data_end) + , async_connection::shared_from_this()) ); new_start = read_buffer_.begin(); return; @@ -264,11 +262,13 @@ namespace boost { namespace network { namespace http { void wrap_read_handler(read_callback_function callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { if (ec) error_encountered = in_place(ec); + buffer_type::const_iterator data_start = read_buffer_.begin() + ,data_end = read_buffer_.begin(); + std::advance(data_end, bytes_transferred); thread_pool().post( boost::bind( callback - , boost::make_iterator_range(read_buffer_.begin() - ,read_buffer_.begin() + bytes_transferred) + , boost::make_iterator_range(data_start, data_end) , ec , bytes_transferred , async_connection::shared_from_this())); @@ -336,7 +336,8 @@ namespace boost { namespace network { namespace http { if (!ec) { logic::tribool parsed_ok; iterator_range result_range, input_range; - data_end = new_start + bytes_transferred; + data_end = read_buffer_.begin(); + std::advance(data_end, bytes_transferred); switch (state) { case method: input_range = boost::make_iterator_range( From 19efd8cf4478c963e3421edc644b8d165ab3881a Mon Sep 17 00:00:00 2001 From: Oleg Malashenko Date: Mon, 27 Dec 2010 11:35:42 +1000 Subject: [PATCH 052/768] Fixed HTTP headers parsing for async_server Ported commit 20fded1393420367be0f26a3726b9329bacde1b2 --- boost/network/protocol/http/server/async_connection.hpp | 2 +- libs/network/src/server_request_parsers_impl.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index 92132a33f..c986c99f3 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -402,6 +402,7 @@ namespace boost { namespace network { namespace http { request_.http_version_major = fusion::get<0>(version_pair); request_.http_version_minor = fusion::get<1>(version_pair); new_start = boost::end(result_range); + partial_parsed.clear(); } else { partial_parsed.append( boost::begin(result_range), @@ -423,7 +424,6 @@ namespace boost { namespace network { namespace http { partial_parsed.append( boost::begin(result_range), boost::end(result_range)); - trim(partial_parsed); parse_headers(partial_parsed, request_.headers); new_start = boost::end(result_range); thread_pool().post( diff --git a/libs/network/src/server_request_parsers_impl.cpp b/libs/network/src/server_request_parsers_impl.cpp index 436eb5e1f..78bca4c82 100644 --- a/libs/network/src/server_request_parsers_impl.cpp +++ b/libs/network/src/server_request_parsers_impl.cpp @@ -31,9 +31,10 @@ namespace boost { namespace network { namespace http { *( +(alnum|(punct-':')) >> lit(": ") - >> +(alnum|space|punct) + >> +((alnum|space|punct) - '\r' - '\n') >> lit("\r\n") ) + >> lit("\r\n") , container ); } From 5ac2d4d09a6542b9d299a9c9e9bb1c8b71a46bac Mon Sep 17 00:00:00 2001 From: Oleg Malashenko Date: Fri, 24 Dec 2010 12:27:34 +1000 Subject: [PATCH 053/768] Fixed http::async_connection::write_first_line() Use persistent buffer for boost::asio::async_write --- .../protocol/http/server/async_connection.hpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index c986c99f3..f36597b5f 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -291,7 +291,7 @@ namespace boost { namespace network { namespace http { Handler & handler; utils::thread_pool & thread_pool_; volatile bool headers_already_sent, first_line_already_sent, headers_in_progress, first_line_in_progress; - asio::streambuf headers_buffer; + asio::streambuf headers_buffer, first_line_buffer; boost::recursive_mutex headers_mutex; buffer_type read_buffer_; @@ -503,19 +503,18 @@ namespace boost { namespace network { namespace http { if (first_line_in_progress) return; first_line_in_progress = true; - std::vector buffers; typedef constants consts; - typename ostringstream::type first_line_stream; - first_line_stream + first_line_buffer.consume(first_line_buffer.size()); + std::ostream first_line_stream(&first_line_buffer); + first_line_stream << consts::http_slash() << 1<< consts::dot() << 1 << consts::space() << status << consts::space() << status_message(status) << consts::crlf() + << std::flush ; - std::string first_line = first_line_stream.str(); - buffers.push_back(asio::buffer(first_line)); asio::async_write( socket() - , buffers + , first_line_buffer , callback); } From ec91e0ae2c3ee105925a6cf3d41c27bcb3c0b57e Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 27 Dec 2010 10:15:19 +0800 Subject: [PATCH 054/768] Slowly moving to the optional<> exposed URI wrappers. --- libs/network/test/http_url_test.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/network/test/http_url_test.cpp b/libs/network/test/http_url_test.cpp index 279a11859..627b538f7 100644 --- a/libs/network/test/http_url_test.cpp +++ b/libs/network/test/http_url_test.cpp @@ -26,11 +26,13 @@ BOOST_AUTO_TEST_CASE(http_url_test) { uri_type instance(string_type(boost::begin(url), boost::end(url))); BOOST_REQUIRE(uri::is_valid(instance)); BOOST_CHECK_EQUAL(instance.raw(), url); + boost::optional host_ = uri::host(instance); + boost::optional port_ = uri::port(instance); + BOOST_CHECK( !port_ ); string_type scheme_ = uri::scheme(instance); BOOST_CHECK_EQUAL(scheme_, scheme); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK_EQUAL(uri::port(instance), port); BOOST_CHECK(boost::equal(uri::path(instance), path)); } From c3c69ad58c32838ce4e0bb177660df8dd28f9be2 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Thu, 30 Dec 2010 20:22:57 +0800 Subject: [PATCH 055/768] Fixing Performance-Affecting Regression Apparently, with the introduction of settings for the receive_buffer, send_buffer, and send/receive low watermarks, responsiveness on previously responsive request handling suffers significantly based on local benchmarks leading to more timeouts from the client side. By making these options truly optional instead of making them actually default to some value reverses the regression. --- .../http/server/socket_options_base.hpp | 58 ++++++++++++++----- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/boost/network/protocol/http/server/socket_options_base.hpp b/boost/network/protocol/http/server/socket_options_base.hpp index 13c8ebc07..0563272a6 100644 --- a/boost/network/protocol/http/server/socket_options_base.hpp +++ b/boost/network/protocol/http/server/socket_options_base.hpp @@ -7,6 +7,8 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#include +#include namespace boost { namespace network { namespace http { @@ -14,10 +16,10 @@ namespace boost { namespace network { namespace http { protected: asio::socket_base::reuse_address acceptor_reuse_address; asio::socket_base::enable_connection_aborted acceptor_report_aborted; - asio::socket_base::receive_buffer_size receive_buffer_size; - asio::socket_base::send_buffer_size send_buffer_size; - asio::socket_base::receive_low_watermark receive_low_watermark; - asio::socket_base::send_low_watermark send_low_watermark; + boost::optional receive_buffer_size; + boost::optional send_buffer_size; + boost::optional receive_low_watermark; + boost::optional send_low_watermark; asio::socket_base::non_blocking_io non_blocking_io; asio::socket_base::linger linger; @@ -25,13 +27,14 @@ namespace boost { namespace network { namespace http { socket_options_base(ArgPack const & args) : acceptor_reuse_address(args[_reuse_address|false]) , acceptor_report_aborted(args[_report_aborted|false]) - , receive_buffer_size(args[_receive_buffer_size|4096]) - , send_buffer_size(args[_send_buffer_size|4096]) - , receive_low_watermark(args[_receive_low_watermark|1024]) - , send_low_watermark(args[_send_low_watermark|1024]) , non_blocking_io(args[_non_blocking_io|true]) , linger(args[_linger|true], args[_linger_timeout|0]) - {} + { + set_optional(receive_buffer_size, args, _receive_buffer_size); + set_optional(send_buffer_size, args, _send_buffer_size); + set_optional(receive_low_watermark, args, _receive_low_watermark); + set_optional(send_low_watermark, args, _send_low_watermark); + } void acceptor_options(boost::asio::ip::tcp::acceptor & acceptor) { acceptor.set_option(acceptor_reuse_address); @@ -42,11 +45,40 @@ namespace boost { namespace network { namespace http { boost::system::error_code ignored; socket.io_control(non_blocking_io, ignored); socket.set_option(linger, ignored); - socket.set_option(receive_buffer_size, ignored); - socket.set_option(receive_low_watermark, ignored); - socket.set_option(send_buffer_size, ignored); - socket.set_option(send_low_watermark, ignored); + if (receive_buffer_size) socket.set_option(*receive_buffer_size, ignored); + if (receive_low_watermark) socket.set_option(*receive_low_watermark, ignored); + if (send_buffer_size) socket.set_option(*send_buffer_size, ignored); + if (send_low_watermark) socket.set_option(*send_low_watermark, ignored); + } + + private: + + template + typename boost::enable_if< + mpl::not_< + boost::is_same< + typename boost::parameter::value_type::type + , void + > + > + , void + >::type + set_optional(Optional & option, Args const & args, Keyword const & keyword) { + option = in_place(args[keyword]); } + + template + typename boost::enable_if< + boost::is_same< + typename boost::parameter::value_type::type + , void + > + , void + >::type + set_optional(Optional &, Args const &, Keyword const &) { + // do nothing + } + }; } /* http */ From 7132a9983a1287ef0f3ca2d794a54fd7ecbb6403 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Thu, 30 Dec 2010 20:26:39 +0800 Subject: [PATCH 056/768] Acceptance Test Improvements - Make the tests properly catch errors - Report whether there were actual failures instead of silently passing --- libs/network/test/httplib_acceptance.py | 34 ++++++++++++++++--------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/libs/network/test/httplib_acceptance.py b/libs/network/test/httplib_acceptance.py index c248ca1b2..1ec853a56 100644 --- a/libs/network/test/httplib_acceptance.py +++ b/libs/network/test/httplib_acceptance.py @@ -28,22 +28,32 @@ expected = b'Hello, World!' def test(url, method, expected, headers={}, body=''): - resp, content = client.request(url, method, headers=headers, body=body) - print('Request: {method} {url} body=\'{body}\''.format(method=method, url=url, body=body)), - if content != expected: - print('ERROR: \'{0}\' != \'{1}\''.format(content, expected)) + global status + try: + print('Request: {method} {url} body=\'{body}\''.format(method=method, url=url, body=body)), + resp, content = client.request(url, method, headers=headers, body=body) + if content != expected: + print('ERROR: \'{0}\' != \'{1}\''.format(content, expected)) + status = 1 + else: + print('... passed.') + except Exception as e: + print('Caught Exception: {0}'.format(e)) status = 1 - else: - print('... passed.') def test_status(url, method, expected, headers={}, body=''): - resp, content = client.request('http://localhost:8000/', 'PUT', body='') - print('Request: {method} {url} body=\'{body}\''.format(method=method, url=url, body=body)), - if resp['status'] != expected: - print('ERROR: response status ({0}) != 400'.format(resp['status'])) + global status + try: + print('Request: {method} {url} body=\'{body}\''.format(method=method, url=url, body=body)), + resp, content = client.request('http://localhost:8000/', 'PUT', body='') + if resp['status'] != expected: + print('ERROR: response status ({0}) != 400'.format(resp['status'])) + status = 1 + else: + print('... passed.') + except Exception as e: + print('Caught Exception: {0}'.format(e)) status = 1 - else: - print('... passed.') url = 'http://localhost:8000/' test(url, 'GET', expected) From 1bf1ce53a18d93b566a980120d7dcfecd62b8912 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Thu, 30 Dec 2010 20:28:09 +0800 Subject: [PATCH 057/768] Using Boost.Filesystem v3 interface. --- libs/network/test/server/http_test_server.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/network/test/server/http_test_server.hpp b/libs/network/test/server/http_test_server.hpp index 0f3f86ff4..0f19ce95c 100644 --- a/libs/network/test/server/http_test_server.hpp +++ b/libs/network/test/server/http_test_server.hpp @@ -5,9 +5,11 @@ // http://www.boost.org/LICENSE_1_0.txt) // // Changes by Allister Levi Sanchez 2008 +// Changes by Dean Michael Berris 2010 #ifndef __NETWORK_TEST_HTTP_TEST_SERVER_HPP__ #define __NETWORK_TEST_HTTP_TEST_SERVER_HPP__ +#define BOOST_FILESYSTEM_VERSION 3 #include #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(MIN) From 3affdbd17d8c30bd8df987515500c1fe62b4ce78 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Thu, 30 Dec 2010 20:28:43 +0800 Subject: [PATCH 058/768] Commenting out Lorem-Ipsum text in favor of Hello, World! --- libs/network/test/http/server_async.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/network/test/http/server_async.cpp b/libs/network/test/http/server_async.cpp index 2b7016a76..476f312cd 100644 --- a/libs/network/test/http/server_async.cpp +++ b/libs/network/test/http/server_async.cpp @@ -27,7 +27,8 @@ struct async_hello_world { connection->set_status(server::connection::ok); connection->set_headers(boost::make_iterator_range(headers, headers+3)); } else if (request.method == "GET") { - static char const lorem_ipsum_10k[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non eros nisl. Proin in risus quam, non pellentesque est. Suspendisse vehicula condimentum odio, id suscipit libero vehicula id. Mauris quis cursus tellus. Sed interdum pretium rutrum. Etiam sagittis dolor sit amet lacus fermentum volutpat. Sed fermentum accumsan ante id aliquet. Morbi cursus imperdiet eros, vitae molestie nibh luctus quis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec quis nulla elit, vitae consequat felis. Mauris in blandit nibh. Aenean ac ultricies magna. Quisque aliquet tellus vitae ipsum egestas vitae semper turpis consectetur. Mauris vitae mauris id mi pulvinar ullamcorper. Cras iaculis, orci tempor aliquet malesuada, lacus enim consequat augue, ut consectetur orci mauris nec justo. Nulla metus libero, tempor et lobortis quis, cursus eu sapien. Morbi volutpat odio sed elit tincidunt sed imperdiet sem sagittis.Donec sapien enim, pharetra vehicula blandit ac, faucibus eu ipsum. Integer vehicula dolor nisi. Nunc quis quam eget lectus feugiat interdum id at quam. Donec hendrerit neque a lorem elementum elementum. Ut non ornare neque. Nulla venenatis tempus leo lobortis condimentum. Fusce eros magna, pellentesque non mollis interdum, porttitor a tellus. Suspendisse at erat non lorem aliquam aliquet ornare id felis. Praesent tincidunt, lectus nec dignissim pharetra, ipsum elit sodales massa, eget accumsan eros purus at metus. Sed sodales dolor vitae magna blandit eget bibendum sapien consectetur. Mauris a viverra felis. Donec sodales tempor lorem, vitae mollis tellus scelerisque quis. Praesent ullamcorper auctor sapien sit amet condimentum. In hac habitasse platea dictumst. In nec laoreet nisi.Nulla facilisi. Nunc varius lectus in nisl condimentum ut bibendum turpis dapibus. Nam a lacus sem. Integer ultricies varius eros, viverra scelerisque diam semper non. In risus est, mattis sed condimentum at, scelerisque at urna. Sed nunc lorem, convallis quis accumsan et, aliquam eu mauris. Nulla fringilla orci metus. Etiam ut purus metus, sed placerat lacus. Morbi porta mauris eget nunc vehicula consectetur. In scelerisque pharetra lacinia. Curabitur ultrices vestibulum ante eget consectetur. Donec nec augue sapien. Donec at feugiat risus. Nulla sit amet justo ac tortor ullamcorper pharetra at sit amet enim. Suspendisse ac massa metus. Quisque pretium, nunc eu vehicula lobortis, lorem ante posuere nisl, sit amet iaculis felis odio quis massa. Duis nec lorem urna, ac porttitor mauris. Nunc blandit, massa vel tincidunt interdum, turpis libero tincidunt eros, sit amet posuere nisi ipsum a nunc. In porta adipiscing sodales. Etiam blandit, nisl eget ultrices laoreet, mauris massa commodo leo, in interdum metus elit vel velit. Quisque sodales lectus eu ligula auctor at scelerisque lectus commodo. Sed luctus nunc vel dui pretium posuere. Donec a ullamcorper odio. Integer eget nunc leo. Nulla facilisi. Vestibulum bibendum, sem quis porttitor lobortis, felis diam convallis diam, id malesuada lorem mi ut libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent cursus metus sit amet neque gravida eu ullamcorper mi fermentum. Sed ut erat ac sem facilisis blandit sit amet eget odio. Morbi a tortor lectus. Phasellus et erat vel tellus pharetra luctus. Nulla molestie sollicitudin sapien vitae commodo. Sed molestie fringilla velit eget varius. Nam augue augue, ultrices eget viverra quis, mattis a mi. Morbi varius sagittis tempor. Praesent a cursus elit. Etiam non molestie enim. Nullam eleifend, sapien ac varius suscipit, lectus orci bibendum nisl, eu pretium lectus dolor at nisl. Etiam posuere viverra condimentum. Etiam nulla urna, consequat eget laoreet vel, tempus nec lorem. Donec ut risus quam. Praesent vitae felis justo. Suspendisse eget magna sed leo suscipit semper. Suspendisse eget mauris lacus, sit amet viverra mauris. Cras sed ligula a tellus faucibus tincidunt. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dictum nisi eget dolor faucibus eu scelerisque ipsum posuere. Aenean varius ultricies est, non tristique lectus auctor a. Curabitur a augue non ligula mollis gravida. Aliquam erat volutpat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam pellentesque vehicula augue, quis posuere nunc dapibus a. Phasellus urna purus, dapibus ultricies iaculis a, laoreet nec sem. Nulla gravida purus eget urna elementum faucibus. Etiam magna neque, iaculis eget egestas et, consequat rutrum urna. Quisque euismod tempus enim, id pulvinar orci cursus a. Vestibulum in urna sapien, nec tempor ligula. Quisque viverra sapien eget justo elementum nec egestas erat placerat. Sed elementum mauris vel felis mattis id adipiscing tellus commodo. Quisque sapien odio, pharetra non accumsan ac, aliquam nec tortor. Sed vitae aliquam magna. Curabitur quam leo, eleifend id bibendum sit amet, viverra et elit. Duis elementum nulla quis nulla rhoncus consectetur. Cras id ante faucibus est viverra facilisis. Fusce vitae odio tortor. Etiam vitae est nunc, et molestie metus. Proin pellentesque, metus sed luctus venenatis, magna metus facilisis lectus, quis bibendum libero turpis eu arcu. Nunc dapibus nibh id eros ultrices vehicula. Vestibulum porta mauris et est vulputate vitae euismod sem ullamcorper. Pellentesque id accumsan sapien. Curabitur sodales viverra arcu ac facilisis. Sed congue facilisis sapien a tempus. Pellentesque elementum, metus sit amet rutrum volutpat, massa enim rutrum purus, ac rhoncus velit erat ac leo. Duis ornare sem vulputate ligula cursus volutpat. Aenean posuere accumsan elit non vestibulum. Duis nunc ligula, vulputate nec iaculis vitae, fermentum vel ante. Sed eget purus ipsum. Cras condimentum mattis hendrerit. Mauris congue arcu sed ante bibendum eget mattis odio feugiat. Donec felis turpis, dignissim mattis varius non, auctor a risus. Pellentesque elit mi, molestie et posuere non, volutpat adipiscing libero. Curabitur in interdum neque. Maecenas luctus pulvinar est, posuere pharetra magna placerat non. Fusce mollis elementum est ac venenatis. Nam quis metus id libero euismod faucibus eget ut tortor. Integer est nibh, hendrerit eget hendrerit in, pretium ac purus. Suspendisse sagittis, erat a placerat malesuada, risus sem condimentum magna, non congue nisi tellus at massa. Aliquam mattis erat id lorem tincidunt sagittis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin scelerisque tempus blandit. Cras dignissim, nibh elementum tempor tempor, nisi odio iaculis lectus, eget suscipit dui lacus eu nunc. Aliquam quis sem turpis, quis condimentum nunc. Nunc ac justo leo, ut tempus elit. Cras in tempus ante. Suspendisse porttitor libero sit amet felis hendrerit ullamcorper. Ut tellus nunc, fermentum in tristique et, malesuada eget arcu. Nam mi massa, vehicula id fermentum vitae, vehicula quis diam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla arcu lorem, ultrices ac ullamcorper id, aliquet vitae eros. Quisque ut arcu augue, eu faucibus leo. Ut mollis interdum felis vitae aliquam. Mauris metus nisi, dictum quis ornare ac, pellentesque in magna. Mauris tincidunt, justo vitae sollicitudin vehicula, sem arcu ullamcorper nunc, vitae tincidunt tellus massa nec diam. Duis pharetra venenatis convallis. Maecenas vulputate, orci eget adipiscing venenatis, nunc turpis congue odio, et lacinia nisi dolor varius lectus. Pellentesque vehicula, nulla in ultricies ullamcorper, magna enim lobortis velit, sed ornare arcu eros quis dui. Donec laoreet sem imperdiet ligula blandit sagittis. Suspendisse nisl felis, ultrices eget tristique quis, feugiat quis nisi. Curabitur iaculis blandit dui, vitae euismod lectus commodo vitae. Nam at tortor non ipsum commodo consequat. Donec tristique tellus id sem dignissim non pharetra nibh tristique. Duis a massa viverra odio ornare rhoncus. Curabitur et quam nisi, sagittis convallis odio. Vivamus justo justo, laoreet nec pellentesque vitae, porta non lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean ac nulla id turpis pharetra luctus in convallis magna. Curabitur id dolor ac tortor congue convallis varius eget lectus. Duis ultricies, tortor tincidunt porttitor condimentum, dui felis viverra magna, nec egestas libero lorem nec tellus. Integer viverra mauris id elit egestas rutrum et at turpis. Praesent pellentesque dignissim accumsan. Suspendisse cursus tempor ipsum, ut tempor lorem vehicula sit amet. Fusce feugiat blandit mauris sit amet dictum. Integer tempor vestibulum turpis, at rhoncus lectus sollicitudin et. Morbi nec sollicitudin sem. Nulla nisl nisl, fringilla in sollicitudin eu, lobortis ut nunc. Quisque euismod felis enim, at blandit velit. In tristique mollis quam, in faucibus mi hendrerit non. Phasellus laoreet posuere nunc sit amet congue. Nam laoreet, sapien eget lacinia lacinia, turpis erat tristique magna, id pellentesque turpis odio non augue. Donec tristique pharetra arcu, sed faucibus lorem tempus ac. Nulla facilisi. Aliquam sagittis, est eget dignissim pretium, massa lacus pulvinar diam, id pretium nibh urna quis tellus. Ut tristique volutpat libero id porta. Vivamus congue nisi vel nisi sagittis ut facilisis lorem facilisis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent et nunc et ligula interdum mattis. Sed bibendum cursus nisl, ut tempus magna placerat vel. Sed porttitor lobortis tristique. Ut mauris orci, aliquet in pharetra et, volutpat vel metus. Quisque tincidunt, nisi at tempus consequat, lorem ligula consequat purus, vel ullamcorper lacus ligula in diam. Nulla a semper dolor. Integer porttitor lectus dolor, eget imperdiet tortor. Integer vitae feugiat nibh. Quisque nisi arcu, auctor pellentesque luctus dapibus, euismod vitae ligula. Aliquam quis purus sit amet orci porta auctor eu at mauris. Quisque ac justo nisl viverra fusce."; + //static char const lorem_ipsum_10k[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non eros nisl. Proin in risus quam, non pellentesque est. Suspendisse vehicula condimentum odio, id suscipit libero vehicula id. Mauris quis cursus tellus. Sed interdum pretium rutrum. Etiam sagittis dolor sit amet lacus fermentum volutpat. Sed fermentum accumsan ante id aliquet. Morbi cursus imperdiet eros, vitae molestie nibh luctus quis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec quis nulla elit, vitae consequat felis. Mauris in blandit nibh. Aenean ac ultricies magna. Quisque aliquet tellus vitae ipsum egestas vitae semper turpis consectetur. Mauris vitae mauris id mi pulvinar ullamcorper. Cras iaculis, orci tempor aliquet malesuada, lacus enim consequat augue, ut consectetur orci mauris nec justo. Nulla metus libero, tempor et lobortis quis, cursus eu sapien. Morbi volutpat odio sed elit tincidunt sed imperdiet sem sagittis.Donec sapien enim, pharetra vehicula blandit ac, faucibus eu ipsum. Integer vehicula dolor nisi. Nunc quis quam eget lectus feugiat interdum id at quam. Donec hendrerit neque a lorem elementum elementum. Ut non ornare neque. Nulla venenatis tempus leo lobortis condimentum. Fusce eros magna, pellentesque non mollis interdum, porttitor a tellus. Suspendisse at erat non lorem aliquam aliquet ornare id felis. Praesent tincidunt, lectus nec dignissim pharetra, ipsum elit sodales massa, eget accumsan eros purus at metus. Sed sodales dolor vitae magna blandit eget bibendum sapien consectetur. Mauris a viverra felis. Donec sodales tempor lorem, vitae mollis tellus scelerisque quis. Praesent ullamcorper auctor sapien sit amet condimentum. In hac habitasse platea dictumst. In nec laoreet nisi.Nulla facilisi. Nunc varius lectus in nisl condimentum ut bibendum turpis dapibus. Nam a lacus sem. Integer ultricies varius eros, viverra scelerisque diam semper non. In risus est, mattis sed condimentum at, scelerisque at urna. Sed nunc lorem, convallis quis accumsan et, aliquam eu mauris. Nulla fringilla orci metus. Etiam ut purus metus, sed placerat lacus. Morbi porta mauris eget nunc vehicula consectetur. In scelerisque pharetra lacinia. Curabitur ultrices vestibulum ante eget consectetur. Donec nec augue sapien. Donec at feugiat risus. Nulla sit amet justo ac tortor ullamcorper pharetra at sit amet enim. Suspendisse ac massa metus. Quisque pretium, nunc eu vehicula lobortis, lorem ante posuere nisl, sit amet iaculis felis odio quis massa. Duis nec lorem urna, ac porttitor mauris. Nunc blandit, massa vel tincidunt interdum, turpis libero tincidunt eros, sit amet posuere nisi ipsum a nunc. In porta adipiscing sodales. Etiam blandit, nisl eget ultrices laoreet, mauris massa commodo leo, in interdum metus elit vel velit. Quisque sodales lectus eu ligula auctor at scelerisque lectus commodo. Sed luctus nunc vel dui pretium posuere. Donec a ullamcorper odio. Integer eget nunc leo. Nulla facilisi. Vestibulum bibendum, sem quis porttitor lobortis, felis diam convallis diam, id malesuada lorem mi ut libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent cursus metus sit amet neque gravida eu ullamcorper mi fermentum. Sed ut erat ac sem facilisis blandit sit amet eget odio. Morbi a tortor lectus. Phasellus et erat vel tellus pharetra luctus. Nulla molestie sollicitudin sapien vitae commodo. Sed molestie fringilla velit eget varius. Nam augue augue, ultrices eget viverra quis, mattis a mi. Morbi varius sagittis tempor. Praesent a cursus elit. Etiam non molestie enim. Nullam eleifend, sapien ac varius suscipit, lectus orci bibendum nisl, eu pretium lectus dolor at nisl. Etiam posuere viverra condimentum. Etiam nulla urna, consequat eget laoreet vel, tempus nec lorem. Donec ut risus quam. Praesent vitae felis justo. Suspendisse eget magna sed leo suscipit semper. Suspendisse eget mauris lacus, sit amet viverra mauris. Cras sed ligula a tellus faucibus tincidunt. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dictum nisi eget dolor faucibus eu scelerisque ipsum posuere. Aenean varius ultricies est, non tristique lectus auctor a. Curabitur a augue non ligula mollis gravida. Aliquam erat volutpat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam pellentesque vehicula augue, quis posuere nunc dapibus a. Phasellus urna purus, dapibus ultricies iaculis a, laoreet nec sem. Nulla gravida purus eget urna elementum faucibus. Etiam magna neque, iaculis eget egestas et, consequat rutrum urna. Quisque euismod tempus enim, id pulvinar orci cursus a. Vestibulum in urna sapien, nec tempor ligula. Quisque viverra sapien eget justo elementum nec egestas erat placerat. Sed elementum mauris vel felis mattis id adipiscing tellus commodo. Quisque sapien odio, pharetra non accumsan ac, aliquam nec tortor. Sed vitae aliquam magna. Curabitur quam leo, eleifend id bibendum sit amet, viverra et elit. Duis elementum nulla quis nulla rhoncus consectetur. Cras id ante faucibus est viverra facilisis. Fusce vitae odio tortor. Etiam vitae est nunc, et molestie metus. Proin pellentesque, metus sed luctus venenatis, magna metus facilisis lectus, quis bibendum libero turpis eu arcu. Nunc dapibus nibh id eros ultrices vehicula. Vestibulum porta mauris et est vulputate vitae euismod sem ullamcorper. Pellentesque id accumsan sapien. Curabitur sodales viverra arcu ac facilisis. Sed congue facilisis sapien a tempus. Pellentesque elementum, metus sit amet rutrum volutpat, massa enim rutrum purus, ac rhoncus velit erat ac leo. Duis ornare sem vulputate ligula cursus volutpat. Aenean posuere accumsan elit non vestibulum. Duis nunc ligula, vulputate nec iaculis vitae, fermentum vel ante. Sed eget purus ipsum. Cras condimentum mattis hendrerit. Mauris congue arcu sed ante bibendum eget mattis odio feugiat. Donec felis turpis, dignissim mattis varius non, auctor a risus. Pellentesque elit mi, molestie et posuere non, volutpat adipiscing libero. Curabitur in interdum neque. Maecenas luctus pulvinar est, posuere pharetra magna placerat non. Fusce mollis elementum est ac venenatis. Nam quis metus id libero euismod faucibus eget ut tortor. Integer est nibh, hendrerit eget hendrerit in, pretium ac purus. Suspendisse sagittis, erat a placerat malesuada, risus sem condimentum magna, non congue nisi tellus at massa. Aliquam mattis erat id lorem tincidunt sagittis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin scelerisque tempus blandit. Cras dignissim, nibh elementum tempor tempor, nisi odio iaculis lectus, eget suscipit dui lacus eu nunc. Aliquam quis sem turpis, quis condimentum nunc. Nunc ac justo leo, ut tempus elit. Cras in tempus ante. Suspendisse porttitor libero sit amet felis hendrerit ullamcorper. Ut tellus nunc, fermentum in tristique et, malesuada eget arcu. Nam mi massa, vehicula id fermentum vitae, vehicula quis diam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla arcu lorem, ultrices ac ullamcorper id, aliquet vitae eros. Quisque ut arcu augue, eu faucibus leo. Ut mollis interdum felis vitae aliquam. Mauris metus nisi, dictum quis ornare ac, pellentesque in magna. Mauris tincidunt, justo vitae sollicitudin vehicula, sem arcu ullamcorper nunc, vitae tincidunt tellus massa nec diam. Duis pharetra venenatis convallis. Maecenas vulputate, orci eget adipiscing venenatis, nunc turpis congue odio, et lacinia nisi dolor varius lectus. Pellentesque vehicula, nulla in ultricies ullamcorper, magna enim lobortis velit, sed ornare arcu eros quis dui. Donec laoreet sem imperdiet ligula blandit sagittis. Suspendisse nisl felis, ultrices eget tristique quis, feugiat quis nisi. Curabitur iaculis blandit dui, vitae euismod lectus commodo vitae. Nam at tortor non ipsum commodo consequat. Donec tristique tellus id sem dignissim non pharetra nibh tristique. Duis a massa viverra odio ornare rhoncus. Curabitur et quam nisi, sagittis convallis odio. Vivamus justo justo, laoreet nec pellentesque vitae, porta non lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean ac nulla id turpis pharetra luctus in convallis magna. Curabitur id dolor ac tortor congue convallis varius eget lectus. Duis ultricies, tortor tincidunt porttitor condimentum, dui felis viverra magna, nec egestas libero lorem nec tellus. Integer viverra mauris id elit egestas rutrum et at turpis. Praesent pellentesque dignissim accumsan. Suspendisse cursus tempor ipsum, ut tempor lorem vehicula sit amet. Fusce feugiat blandit mauris sit amet dictum. Integer tempor vestibulum turpis, at rhoncus lectus sollicitudin et. Morbi nec sollicitudin sem. Nulla nisl nisl, fringilla in sollicitudin eu, lobortis ut nunc. Quisque euismod felis enim, at blandit velit. In tristique mollis quam, in faucibus mi hendrerit non. Phasellus laoreet posuere nunc sit amet congue. Nam laoreet, sapien eget lacinia lacinia, turpis erat tristique magna, id pellentesque turpis odio non augue. Donec tristique pharetra arcu, sed faucibus lorem tempus ac. Nulla facilisi. Aliquam sagittis, est eget dignissim pretium, massa lacus pulvinar diam, id pretium nibh urna quis tellus. Ut tristique volutpat libero id porta. Vivamus congue nisi vel nisi sagittis ut facilisis lorem facilisis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent et nunc et ligula interdum mattis. Sed bibendum cursus nisl, ut tempus magna placerat vel. Sed porttitor lobortis tristique. Ut mauris orci, aliquet in pharetra et, volutpat vel metus. Quisque tincidunt, nisi at tempus consequat, lorem ligula consequat purus, vel ullamcorper lacus ligula in diam. Nulla a semper dolor. Integer porttitor lectus dolor, eget imperdiet tortor. Integer vitae feugiat nibh. Quisque nisi arcu, auctor pellentesque luctus dapibus, euismod vitae ligula. Aliquam quis purus sit amet orci porta auctor eu at mauris. Quisque ac justo nisl viverra fusce."; + static char lorem_ipsum_10k[] = "Hello, World!"; connection->set_status(server::connection::ok); connection->set_headers(boost::make_iterator_range(headers, headers+3)); connection->write(lorem_ipsum_10k); From e13b7b475e28687fa96bec8e42dab8cdb7e627e1 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 1 Jan 2011 19:54:39 +0800 Subject: [PATCH 059/768] Re-arranging tests for HTTP, renaming accordingly. --- libs/network/test/CMakeLists.txt | 12 ------------ libs/network/test/http/CMakeLists.txt | 8 ++++++++ .../client_localhost_normal_test.cpp} | 4 ++-- .../client_localhost_ssl_test.cpp} | 2 +- .../test/{server => http}/http_test_server.hpp | 0 .../message_async_ready_test.cpp} | 0 .../{http_message_test.cpp => http/message_test.cpp} | 0 .../request_incremental_parser_test.cpp} | 0 .../request_linearize_test.cpp} | 0 .../response_incremental_parser_test.cpp} | 0 .../test/{http_url_test.cpp => http/url_test.cpp} | 0 11 files changed, 11 insertions(+), 15 deletions(-) rename libs/network/test/{http_localhost_tests.cpp => http/client_localhost_normal_test.cpp} (99%) rename libs/network/test/{https_localhost_tests.cpp => http/client_localhost_ssl_test.cpp} (99%) rename libs/network/test/{server => http}/http_test_server.hpp (100%) rename libs/network/test/{http_async_message_ready.cpp => http/message_async_ready_test.cpp} (100%) rename libs/network/test/{http_message_test.cpp => http/message_test.cpp} (100%) rename libs/network/test/{http_incremental_request_parser.cpp => http/request_incremental_parser_test.cpp} (100%) rename libs/network/test/{http_request_linearize.cpp => http/request_linearize_test.cpp} (100%) rename libs/network/test/{http_incremental_parser.cpp => http/response_incremental_parser_test.cpp} (100%) rename libs/network/test/{http_url_test.cpp => http/url_test.cpp} (100%) diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index 490d42ade..5ed915509 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -6,10 +6,6 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) find_package( Boost 1.41.0 COMPONENTS unit_test_framework system regex date_time thread filesystem ) find_package( OpenSSL ) -if (OPENSSL_FOUND) - include_directories(${OPENSSL_INCLUDE_DIR}}) - add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) -endif() find_package( Threads ) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) @@ -19,18 +15,10 @@ add_subdirectory(http) if (Boost_FOUND) set( TESTS - http_incremental_parser - http_incremental_request_parser - http_localhost_tests - https_localhost_tests message_test - http_message_test message_transform_test url_test - http_url_test utils_thread_pool - http_async_message_ready - http_request_linearize ) foreach (test ${TESTS}) set_source_files_properties(${test}.cpp diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index ead618177..5fa8f567d 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -23,6 +23,14 @@ if (Boost_FOUND) client_get_test client_get_different_port_test client_get_timeout_test + client_localhost_ssl_test + client_localhost_normal_test + message_async_ready_test + message_test + request_linearize_test + request_incremental_parser_test + response_incremental_parser_test + url_test ) foreach ( test ${TESTS} ) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) diff --git a/libs/network/test/http_localhost_tests.cpp b/libs/network/test/http/client_localhost_normal_test.cpp similarity index 99% rename from libs/network/test/http_localhost_tests.cpp rename to libs/network/test/http/client_localhost_normal_test.cpp index 0be6b92e1..4302db03d 100644 --- a/libs/network/test/http_localhost_tests.cpp +++ b/libs/network/test/http/client_localhost_normal_test.cpp @@ -5,7 +5,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // // Changes by Kim Grasman 2008 -// Changes by Dean Michael Berris 2008 +// Changes by Dean Michael Berris 2008, 2010 #define BOOST_TEST_MODULE http 1.0 localhost tests @@ -19,7 +19,7 @@ #include #include -#include "server/http_test_server.hpp" +#include "http_test_server.hpp" using std::cout; using std::endl; diff --git a/libs/network/test/https_localhost_tests.cpp b/libs/network/test/http/client_localhost_ssl_test.cpp similarity index 99% rename from libs/network/test/https_localhost_tests.cpp rename to libs/network/test/http/client_localhost_ssl_test.cpp index c2efe14e3..5bbf20390 100644 --- a/libs/network/test/https_localhost_tests.cpp +++ b/libs/network/test/http/client_localhost_ssl_test.cpp @@ -19,7 +19,7 @@ #include #define HTTPS_SERVER_TEST -#include "server/http_test_server.hpp" +#include "http_test_server.hpp" using std::cout; using std::endl; diff --git a/libs/network/test/server/http_test_server.hpp b/libs/network/test/http/http_test_server.hpp similarity index 100% rename from libs/network/test/server/http_test_server.hpp rename to libs/network/test/http/http_test_server.hpp diff --git a/libs/network/test/http_async_message_ready.cpp b/libs/network/test/http/message_async_ready_test.cpp similarity index 100% rename from libs/network/test/http_async_message_ready.cpp rename to libs/network/test/http/message_async_ready_test.cpp diff --git a/libs/network/test/http_message_test.cpp b/libs/network/test/http/message_test.cpp similarity index 100% rename from libs/network/test/http_message_test.cpp rename to libs/network/test/http/message_test.cpp diff --git a/libs/network/test/http_incremental_request_parser.cpp b/libs/network/test/http/request_incremental_parser_test.cpp similarity index 100% rename from libs/network/test/http_incremental_request_parser.cpp rename to libs/network/test/http/request_incremental_parser_test.cpp diff --git a/libs/network/test/http_request_linearize.cpp b/libs/network/test/http/request_linearize_test.cpp similarity index 100% rename from libs/network/test/http_request_linearize.cpp rename to libs/network/test/http/request_linearize_test.cpp diff --git a/libs/network/test/http_incremental_parser.cpp b/libs/network/test/http/response_incremental_parser_test.cpp similarity index 100% rename from libs/network/test/http_incremental_parser.cpp rename to libs/network/test/http/response_incremental_parser_test.cpp diff --git a/libs/network/test/http_url_test.cpp b/libs/network/test/http/url_test.cpp similarity index 100% rename from libs/network/test/http_url_test.cpp rename to libs/network/test/http/url_test.cpp From fe28613fc13a5446405fdec8bfe372b81b709aa7 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 1 Jan 2011 23:59:22 +0800 Subject: [PATCH 060/768] Fixing Asynchronous Server Test to look like the Hello World Server test. --- libs/network/test/http/server_async.cpp | 34 ++++++++++++++++++------- libs/network/test/httplib_acceptance.py | 7 +++-- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/libs/network/test/http/server_async.cpp b/libs/network/test/http/server_async.cpp index 476f312cd..e9e906982 100644 --- a/libs/network/test/http/server_async.cpp +++ b/libs/network/test/http/server_async.cpp @@ -9,7 +9,9 @@ #include #include #include +#include +namespace net = boost::network; namespace http = boost::network::http; namespace utils = boost::network::utils; @@ -17,25 +19,39 @@ struct async_hello_world; typedef http::async_server server; struct async_hello_world { + + struct is_content_length { + template + bool operator()(Header const & header) { + return boost::iequals(name(header), "content-length"); + } + }; + void operator()(server::request const & request, server::connection_ptr connection) { static server::response_header headers[] = { {"Connection", "close"} , {"Content-Type", "text/plain"} - , {"Server", "cpp-netlib/0.8-devel"} + , {"Server", "cpp-netlib/0.9-devel"} }; if (request.method == "HEAD") { connection->set_status(server::connection::ok); connection->set_headers(boost::make_iterator_range(headers, headers+3)); - } else if (request.method == "GET") { - //static char const lorem_ipsum_10k[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non eros nisl. Proin in risus quam, non pellentesque est. Suspendisse vehicula condimentum odio, id suscipit libero vehicula id. Mauris quis cursus tellus. Sed interdum pretium rutrum. Etiam sagittis dolor sit amet lacus fermentum volutpat. Sed fermentum accumsan ante id aliquet. Morbi cursus imperdiet eros, vitae molestie nibh luctus quis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec quis nulla elit, vitae consequat felis. Mauris in blandit nibh. Aenean ac ultricies magna. Quisque aliquet tellus vitae ipsum egestas vitae semper turpis consectetur. Mauris vitae mauris id mi pulvinar ullamcorper. Cras iaculis, orci tempor aliquet malesuada, lacus enim consequat augue, ut consectetur orci mauris nec justo. Nulla metus libero, tempor et lobortis quis, cursus eu sapien. Morbi volutpat odio sed elit tincidunt sed imperdiet sem sagittis.Donec sapien enim, pharetra vehicula blandit ac, faucibus eu ipsum. Integer vehicula dolor nisi. Nunc quis quam eget lectus feugiat interdum id at quam. Donec hendrerit neque a lorem elementum elementum. Ut non ornare neque. Nulla venenatis tempus leo lobortis condimentum. Fusce eros magna, pellentesque non mollis interdum, porttitor a tellus. Suspendisse at erat non lorem aliquam aliquet ornare id felis. Praesent tincidunt, lectus nec dignissim pharetra, ipsum elit sodales massa, eget accumsan eros purus at metus. Sed sodales dolor vitae magna blandit eget bibendum sapien consectetur. Mauris a viverra felis. Donec sodales tempor lorem, vitae mollis tellus scelerisque quis. Praesent ullamcorper auctor sapien sit amet condimentum. In hac habitasse platea dictumst. In nec laoreet nisi.Nulla facilisi. Nunc varius lectus in nisl condimentum ut bibendum turpis dapibus. Nam a lacus sem. Integer ultricies varius eros, viverra scelerisque diam semper non. In risus est, mattis sed condimentum at, scelerisque at urna. Sed nunc lorem, convallis quis accumsan et, aliquam eu mauris. Nulla fringilla orci metus. Etiam ut purus metus, sed placerat lacus. Morbi porta mauris eget nunc vehicula consectetur. In scelerisque pharetra lacinia. Curabitur ultrices vestibulum ante eget consectetur. Donec nec augue sapien. Donec at feugiat risus. Nulla sit amet justo ac tortor ullamcorper pharetra at sit amet enim. Suspendisse ac massa metus. Quisque pretium, nunc eu vehicula lobortis, lorem ante posuere nisl, sit amet iaculis felis odio quis massa. Duis nec lorem urna, ac porttitor mauris. Nunc blandit, massa vel tincidunt interdum, turpis libero tincidunt eros, sit amet posuere nisi ipsum a nunc. In porta adipiscing sodales. Etiam blandit, nisl eget ultrices laoreet, mauris massa commodo leo, in interdum metus elit vel velit. Quisque sodales lectus eu ligula auctor at scelerisque lectus commodo. Sed luctus nunc vel dui pretium posuere. Donec a ullamcorper odio. Integer eget nunc leo. Nulla facilisi. Vestibulum bibendum, sem quis porttitor lobortis, felis diam convallis diam, id malesuada lorem mi ut libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent cursus metus sit amet neque gravida eu ullamcorper mi fermentum. Sed ut erat ac sem facilisis blandit sit amet eget odio. Morbi a tortor lectus. Phasellus et erat vel tellus pharetra luctus. Nulla molestie sollicitudin sapien vitae commodo. Sed molestie fringilla velit eget varius. Nam augue augue, ultrices eget viverra quis, mattis a mi. Morbi varius sagittis tempor. Praesent a cursus elit. Etiam non molestie enim. Nullam eleifend, sapien ac varius suscipit, lectus orci bibendum nisl, eu pretium lectus dolor at nisl. Etiam posuere viverra condimentum. Etiam nulla urna, consequat eget laoreet vel, tempus nec lorem. Donec ut risus quam. Praesent vitae felis justo. Suspendisse eget magna sed leo suscipit semper. Suspendisse eget mauris lacus, sit amet viverra mauris. Cras sed ligula a tellus faucibus tincidunt. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi dictum nisi eget dolor faucibus eu scelerisque ipsum posuere. Aenean varius ultricies est, non tristique lectus auctor a. Curabitur a augue non ligula mollis gravida. Aliquam erat volutpat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam pellentesque vehicula augue, quis posuere nunc dapibus a. Phasellus urna purus, dapibus ultricies iaculis a, laoreet nec sem. Nulla gravida purus eget urna elementum faucibus. Etiam magna neque, iaculis eget egestas et, consequat rutrum urna. Quisque euismod tempus enim, id pulvinar orci cursus a. Vestibulum in urna sapien, nec tempor ligula. Quisque viverra sapien eget justo elementum nec egestas erat placerat. Sed elementum mauris vel felis mattis id adipiscing tellus commodo. Quisque sapien odio, pharetra non accumsan ac, aliquam nec tortor. Sed vitae aliquam magna. Curabitur quam leo, eleifend id bibendum sit amet, viverra et elit. Duis elementum nulla quis nulla rhoncus consectetur. Cras id ante faucibus est viverra facilisis. Fusce vitae odio tortor. Etiam vitae est nunc, et molestie metus. Proin pellentesque, metus sed luctus venenatis, magna metus facilisis lectus, quis bibendum libero turpis eu arcu. Nunc dapibus nibh id eros ultrices vehicula. Vestibulum porta mauris et est vulputate vitae euismod sem ullamcorper. Pellentesque id accumsan sapien. Curabitur sodales viverra arcu ac facilisis. Sed congue facilisis sapien a tempus. Pellentesque elementum, metus sit amet rutrum volutpat, massa enim rutrum purus, ac rhoncus velit erat ac leo. Duis ornare sem vulputate ligula cursus volutpat. Aenean posuere accumsan elit non vestibulum. Duis nunc ligula, vulputate nec iaculis vitae, fermentum vel ante. Sed eget purus ipsum. Cras condimentum mattis hendrerit. Mauris congue arcu sed ante bibendum eget mattis odio feugiat. Donec felis turpis, dignissim mattis varius non, auctor a risus. Pellentesque elit mi, molestie et posuere non, volutpat adipiscing libero. Curabitur in interdum neque. Maecenas luctus pulvinar est, posuere pharetra magna placerat non. Fusce mollis elementum est ac venenatis. Nam quis metus id libero euismod faucibus eget ut tortor. Integer est nibh, hendrerit eget hendrerit in, pretium ac purus. Suspendisse sagittis, erat a placerat malesuada, risus sem condimentum magna, non congue nisi tellus at massa. Aliquam mattis erat id lorem tincidunt sagittis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin scelerisque tempus blandit. Cras dignissim, nibh elementum tempor tempor, nisi odio iaculis lectus, eget suscipit dui lacus eu nunc. Aliquam quis sem turpis, quis condimentum nunc. Nunc ac justo leo, ut tempus elit. Cras in tempus ante. Suspendisse porttitor libero sit amet felis hendrerit ullamcorper. Ut tellus nunc, fermentum in tristique et, malesuada eget arcu. Nam mi massa, vehicula id fermentum vitae, vehicula quis diam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla arcu lorem, ultrices ac ullamcorper id, aliquet vitae eros. Quisque ut arcu augue, eu faucibus leo. Ut mollis interdum felis vitae aliquam. Mauris metus nisi, dictum quis ornare ac, pellentesque in magna. Mauris tincidunt, justo vitae sollicitudin vehicula, sem arcu ullamcorper nunc, vitae tincidunt tellus massa nec diam. Duis pharetra venenatis convallis. Maecenas vulputate, orci eget adipiscing venenatis, nunc turpis congue odio, et lacinia nisi dolor varius lectus. Pellentesque vehicula, nulla in ultricies ullamcorper, magna enim lobortis velit, sed ornare arcu eros quis dui. Donec laoreet sem imperdiet ligula blandit sagittis. Suspendisse nisl felis, ultrices eget tristique quis, feugiat quis nisi. Curabitur iaculis blandit dui, vitae euismod lectus commodo vitae. Nam at tortor non ipsum commodo consequat. Donec tristique tellus id sem dignissim non pharetra nibh tristique. Duis a massa viverra odio ornare rhoncus. Curabitur et quam nisi, sagittis convallis odio. Vivamus justo justo, laoreet nec pellentesque vitae, porta non lorem. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean ac nulla id turpis pharetra luctus in convallis magna. Curabitur id dolor ac tortor congue convallis varius eget lectus. Duis ultricies, tortor tincidunt porttitor condimentum, dui felis viverra magna, nec egestas libero lorem nec tellus. Integer viverra mauris id elit egestas rutrum et at turpis. Praesent pellentesque dignissim accumsan. Suspendisse cursus tempor ipsum, ut tempor lorem vehicula sit amet. Fusce feugiat blandit mauris sit amet dictum. Integer tempor vestibulum turpis, at rhoncus lectus sollicitudin et. Morbi nec sollicitudin sem. Nulla nisl nisl, fringilla in sollicitudin eu, lobortis ut nunc. Quisque euismod felis enim, at blandit velit. In tristique mollis quam, in faucibus mi hendrerit non. Phasellus laoreet posuere nunc sit amet congue. Nam laoreet, sapien eget lacinia lacinia, turpis erat tristique magna, id pellentesque turpis odio non augue. Donec tristique pharetra arcu, sed faucibus lorem tempus ac. Nulla facilisi. Aliquam sagittis, est eget dignissim pretium, massa lacus pulvinar diam, id pretium nibh urna quis tellus. Ut tristique volutpat libero id porta. Vivamus congue nisi vel nisi sagittis ut facilisis lorem facilisis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent et nunc et ligula interdum mattis. Sed bibendum cursus nisl, ut tempus magna placerat vel. Sed porttitor lobortis tristique. Ut mauris orci, aliquet in pharetra et, volutpat vel metus. Quisque tincidunt, nisi at tempus consequat, lorem ligula consequat purus, vel ullamcorper lacus ligula in diam. Nulla a semper dolor. Integer porttitor lectus dolor, eget imperdiet tortor. Integer vitae feugiat nibh. Quisque nisi arcu, auctor pellentesque luctus dapibus, euismod vitae ligula. Aliquam quis purus sit amet orci porta auctor eu at mauris. Quisque ac justo nisl viverra fusce."; - static char lorem_ipsum_10k[] = "Hello, World!"; - connection->set_status(server::connection::ok); - connection->set_headers(boost::make_iterator_range(headers, headers+3)); - connection->write(lorem_ipsum_10k); } else { - connection->set_status(server::connection::not_supported); + if (request.method == "PUT" || request.method == "POST") { + static std::string bad_request("Bad Request."); + server::request::headers_container_type::iterator found = + boost::find_if(request.headers, is_content_length()); + if (found == request.headers.end()) { + connection->set_status(server::connection::bad_request); + connection->set_headers(boost::make_iterator_range(headers, headers+3)); + connection->write(bad_request); + return; + } + } + static std::string hello_world("Hello, World!"); + connection->set_status(server::connection::ok); connection->set_headers(boost::make_iterator_range(headers, headers+3)); - connection->write("Unsupported method."); + connection->write(hello_world); } } }; diff --git a/libs/network/test/httplib_acceptance.py b/libs/network/test/httplib_acceptance.py index 1ec853a56..52ba176f8 100644 --- a/libs/network/test/httplib_acceptance.py +++ b/libs/network/test/httplib_acceptance.py @@ -6,6 +6,7 @@ #!/bin/env python from sys import argv +from time import sleep import httplib2 as httplib from subprocess import Popen,PIPE @@ -19,6 +20,8 @@ try: pipe = Popen(argv[1], executable=argv[1], stdin=PIPE, stdout=PIPE, close_fds=True) print('Done with spawning {0}.'.format(argv[1])) + print('Sleeping to give the server a chance to run...') + sleep(1) except: print('I cannot spawn \'{0}\' properly.'.format(argv[1])) exit(1) @@ -33,7 +36,7 @@ def test(url, method, expected, headers={}, body=''): print('Request: {method} {url} body=\'{body}\''.format(method=method, url=url, body=body)), resp, content = client.request(url, method, headers=headers, body=body) if content != expected: - print('ERROR: \'{0}\' != \'{1}\''.format(content, expected)) + print('ERROR: \'{0}\' != \'{1}\'; sizes: {2} != {3}'.format(content, expected, len(content), len(expected))) status = 1 else: print('... passed.') @@ -47,7 +50,7 @@ def test_status(url, method, expected, headers={}, body=''): print('Request: {method} {url} body=\'{body}\''.format(method=method, url=url, body=body)), resp, content = client.request('http://localhost:8000/', 'PUT', body='') if resp['status'] != expected: - print('ERROR: response status ({0}) != 400'.format(resp['status'])) + print('ERROR: response status (got {0}) != expecting {1}'.format(resp['status'], expected)) status = 1 else: print('... passed.') From 53254c48d50f3c50ef8432cd29d786d8c60069c1 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 8 Jan 2011 22:54:54 +0800 Subject: [PATCH 061/768] Removing std::auto_ptr from 0.9-devel Because compilers in C++0x mode complain that std::auto_ptr is actually deprecated, this patch changes the implementation to use raw pointers instead. This is in the interim until unique_ptr<> is actually made part of the standard or Boost so that it can be used instead. --- boost/network/protocol/http/client/async_impl.hpp | 5 +++-- boost/network/protocol/http/client/pimpl.hpp | 8 +++++--- boost/network/protocol/http/server/storage_base.hpp | 9 +++++++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/boost/network/protocol/http/client/async_impl.hpp b/boost/network/protocol/http/client/async_impl.hpp index 8405caf1f..4b92928ca 100644 --- a/boost/network/protocol/http/client/async_impl.hpp +++ b/boost/network/protocol/http/client/async_impl.hpp @@ -49,7 +49,7 @@ namespace boost { namespace network { namespace http { async_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service) : connection_base(cache_resolved, follow_redirect), - service_ptr(), + service_ptr(0), service_(service), resolver_(service_), sentinel_(new boost::asio::io_service::work(service_)) @@ -63,6 +63,7 @@ namespace boost { namespace network { namespace http { lifetime_thread_->join(); lifetime_thread_.reset(); } + delete service_ptr; } basic_response const request_skeleton( @@ -76,7 +77,7 @@ namespace boost { namespace network { namespace http { return connection_->send_request(method, request_, get_body); } - std::auto_ptr service_ptr; + boost::asio::io_service * service_ptr; boost::asio::io_service & service_; resolver_type resolver_; boost::shared_ptr sentinel_; diff --git a/boost/network/protocol/http/client/pimpl.hpp b/boost/network/protocol/http/client/pimpl.hpp index d37489395..1afef118c 100644 --- a/boost/network/protocol/http/client/pimpl.hpp +++ b/boost/network/protocol/http/client/pimpl.hpp @@ -35,7 +35,7 @@ namespace boost { namespace network { namespace http { typedef typename resolver::type resolver_type; friend struct basic_client_impl; - std::auto_ptr service_ptr; + boost::asio::io_service * service_ptr; boost::asio::io_service & service_; resolver_type resolver_; @@ -48,12 +48,14 @@ namespace boost { namespace network { namespace http { sync_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service) : connection_base(cache_resolved, follow_redirect), - service_ptr(), + service_ptr(0), service_(service), resolver_(service_) {} - ~sync_client() {} + ~sync_client() { + delete service_ptr; + } basic_response const request_skeleton(basic_request const & request_, string_type method, bool get_body) { typename connection_base::connection_ptr connection_; diff --git a/boost/network/protocol/http/server/storage_base.hpp b/boost/network/protocol/http/server/storage_base.hpp index 25896dd25..e8b7c62c9 100644 --- a/boost/network/protocol/http/server/storage_base.hpp +++ b/boost/network/protocol/http/server/storage_base.hpp @@ -22,11 +22,16 @@ namespace boost { namespace network { namespace http { template server_storage_base(ArgPack const & args, has_io_service) - : self_service_() + : self_service_(0) , service_(args[_io_service]) {} - std::auto_ptr self_service_; + ~server_storage_base() { + delete self_service_; + self_service_ = 0; + } + + asio::io_service * self_service_; asio::io_service & service_; }; From 6abafda631df4ef5b008e9ea564b6c478501a158 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 9 Jan 2011 22:54:58 +0800 Subject: [PATCH 062/768] Making uri::port(...) return a convertible wrapper To address the issue with regard to the Host header being sent by the client to not include custom (or user-provided) port, the uri::port(...) free function should instead return a convertible wrapper to either a boost::optional or a boost::uint16_t. The rationale for this is so that the client can eventually get for the boost::optional instead of just a boost::uint16_t and include that as part of the client's Host header forming routine. That change will have to go into the linearize algorithm, and should be done in the next commit. This change to the interface would still have to be documented, but should otherwise not break any existing code relying on uri::port(...) returning just a boost::uint16_t. --- boost/network/constants.hpp | 11 ++++++++ boost/network/protocol/http/impl/request.hpp | 3 +-- boost/network/uri/basic_uri.hpp | 27 +++++++++++++++++--- boost/network/uri/http/uri.hpp | 9 +++---- libs/network/test/http/url_test.cpp | 20 +++++++-------- 5 files changed, 49 insertions(+), 21 deletions(-) diff --git a/boost/network/constants.hpp b/boost/network/constants.hpp index 11a38ecae..f2b100760 100644 --- a/boost/network/constants.hpp +++ b/boost/network/constants.hpp @@ -121,10 +121,21 @@ namespace boost { namespace network { return close_; } + static char const * https() { + static char https_[] = "https"; + return https_; + } + }; template struct constants_wide { + + static wchar_t const * https() { + static wchar_t https_[] = L"https"; + return https_; + } + }; } diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index e24850206..cfe5bddfc 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -92,8 +92,7 @@ namespace http { } port_type port() const { - // string_type port() const { - return uri_.port(); + return uri::port(uri_); } string_type const path() const { diff --git a/boost/network/uri/basic_uri.hpp b/boost/network/uri/basic_uri.hpp index 0f152d189..9ad7d3013 100644 --- a/boost/network/uri/basic_uri.hpp +++ b/boost/network/uri/basic_uri.hpp @@ -10,7 +10,8 @@ #include #include - +#include +#include namespace boost { namespace network { namespace uri { @@ -157,11 +158,31 @@ host(basic_uri const & uri) { return uri.host(); } +template +struct port_wrapper { + basic_uri const & uri; + explicit port_wrapper(basic_uri const & uri) + : uri(uri) + {} + + operator boost::optional() const { + return uri.port(); + } + + operator boost::uint16_t() const { + boost::optional const & port_ = uri.port(); + typedef typename string::type string_type; + typedef constants consts; + if (port_) return *port_; + return boost::iequals(uri.scheme(), string_type(consts::https())) ? 443 : 80; + } +}; + template inline -uint16_t +port_wrapper const port(basic_uri const & uri) { - return uri.port(); + return port_wrapper(uri); } template diff --git a/boost/network/uri/http/uri.hpp b/boost/network/uri/http/uri.hpp index e2d2e3749..9b8ffcd65 100644 --- a/boost/network/uri/http/uri.hpp +++ b/boost/network/uri/http/uri.hpp @@ -15,6 +15,7 @@ namespace boost { namespace network { namespace uri { + template <> class basic_uri : public uri_base { @@ -23,7 +24,8 @@ class basic_uri basic_uri() : uri_base() {} basic_uri(uri_base::string_type const & uri) : uri_base(uri) {} - boost::uint16_t port() const { + boost::optional port() const { + return parts_.port; return parts_.port ? *(parts_.port) : (boost::iequals(parts_.scheme, string_type("https")) ? 443 : 80); } @@ -33,11 +35,6 @@ class basic_uri } }; -inline -boost::uint16_t -port(basic_uri const & uri) { - return uri.port(); -} } // namespace uri } // namespace network } // namespace boost diff --git a/libs/network/test/http/url_test.cpp b/libs/network/test/http/url_test.cpp index 627b538f7..20714fd78 100644 --- a/libs/network/test/http/url_test.cpp +++ b/libs/network/test/http/url_test.cpp @@ -20,14 +20,14 @@ BOOST_AUTO_TEST_CASE(http_url_test) { const std::string url("http://www.boost.org/"); const std::string scheme("http"); const std::string host("www.boost.org"); - const boost::uint16_t port = 80; const std::string path("/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); - BOOST_CHECK_EQUAL(instance.raw(), url); boost::optional host_ = uri::host(instance); boost::optional port_ = uri::port(instance); + + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK_EQUAL(instance.raw(), url); BOOST_CHECK( !port_ ); string_type scheme_ = uri::scheme(instance); BOOST_CHECK_EQUAL(scheme_, scheme); @@ -78,12 +78,12 @@ BOOST_AUTO_TEST_CASE(https_url_test) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE(invalid_http_url_test) { - typedef uri::basic_uri uri_type; - typedef uri_type::string_type string_type; +//BOOST_AUTO_TEST_CASE(invalid_http_url_test) { +// typedef uri::basic_uri uri_type; +// typedef uri_type::string_type string_type; - const std::string url("/service/ftp://www.boost.org/"); +// const std::string url("/service/ftp://www.boost.org/"); - uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_CHECK(!uri::is_valid(instance)); -} +// uri_type instance(string_type(boost::begin(url), boost::end(url))); +// BOOST_CHECK(!uri::is_valid(instance)); +//} From 37efecc252ad6d884eb3aff254addd96a16c5a8b Mon Sep 17 00:00:00 2001 From: Oleg Malashenko Date: Thu, 13 Jan 2011 14:53:03 +1000 Subject: [PATCH 063/768] Introduced non-copying async_connection::write_vec() write_impl() rewritten using write_vec_impl(). Fixed race on user data in write_impl() by linearizing data before scheduling any async operations. --- .../protocol/http/server/async_connection.hpp | 91 +++++++++---------- 1 file changed, 44 insertions(+), 47 deletions(-) diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index f36597b5f..6d7b929dd 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -214,10 +214,15 @@ namespace boost { namespace network { namespace http { void write(Range const & range, Callback const & callback) { lock_guard lock(headers_mutex); if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); - boost::function f = callback; write_impl(boost::make_iterator_range(range), callback); } + template + void write_vec(ConstBufferSeq const & seq, Callback const & callback) + { + write_vec_impl(seq, callback, shared_array_list(), shared_buffers()); + } + private: typedef boost::array buffer_type; @@ -488,15 +493,6 @@ namespace boost { namespace network { namespace http { void do_nothing() {} - template - void continue_write(Range range, boost::function callback) { - thread_pool().post( - boost::bind( - &async_connection::write_impl - , async_connection::shared_from_this() - , range, callback)); - } - template void write_first_line(Callback callback) { lock_guard lock(headers_mutex); @@ -581,27 +577,6 @@ namespace boost { namespace network { namespace http { template void write_impl(Range range, boost::function callback) { - lock_guard lock(headers_mutex); - boost::function callback_function = - callback; - - if (!headers_already_sent && !headers_in_progress) { - write_headers_only( - boost::bind( - &async_connection::continue_write - , async_connection::shared_from_this() - , range, callback_function - )); - return; - } else if (headers_in_progress && !headers_already_sent) { - pending_actions.push_back( - boost::bind( - &async_connection::continue_write - , async_connection::shared_from_this() - , range, callback_function)); - return; - } - // linearize the whole range into a vector // of fixed-sized buffers, then schedule an asynchronous // write of these buffers -- make sure they are live @@ -648,25 +623,47 @@ namespace boost { namespace network { namespace http { } if (!buffers->empty()) { - boost::function f = callback; - asio::async_write( - socket_ - , *buffers - , strand.wrap( - boost::bind( - &async_connection::handle_write - , async_connection::shared_from_this() - , f - , temporaries - , buffers // keep these alive until the handler is called! - , boost::asio::placeholders::error - , boost::asio::placeholders::bytes_transferred - ) - ) - ); + write_vec_impl(*buffers, callback, temporaries, buffers); } } + template + void write_vec_impl(ConstBufferSeq const & seq + ,Callback const & callback + ,shared_array_list temporaries + ,shared_buffers buffers) + { + lock_guard lock(headers_mutex); + if (error_encountered) + boost::throw_exception(boost::system::system_error(*error_encountered)); + + boost::function continuation = boost::bind( + &async_connection::write_vec_impl + ,async_connection::shared_from_this() + ,seq, callback, temporaries, buffers + ); + + if (!headers_already_sent && !headers_in_progress) { + write_headers_only(continuation); + return; + } else if (headers_in_progress && !headers_already_sent) { + pending_actions.push_back(continuation); + return; + } + + asio::async_write( + socket_ + ,seq + ,boost::bind( + &async_connection::handle_write + ,async_connection::shared_from_this() + ,callback + ,temporaries + ,buffers + ,asio::placeholders::error + ,asio::placeholders::bytes_transferred) + ); + } }; } /* http */ From ddc8bdf03eda7021f49e80fc16773ffb0bcb5595 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 30 Jan 2011 00:24:02 +0800 Subject: [PATCH 064/768] SFINAE for choosing 'write' overload Aside from adding an additional clarification in the documentation for the macro defining the size of a page, this change makes the user-facing 'write' implementation use SFINAE to choose whether to deal with the buffer provided as a buffer that doesn't need to be copied (derives from Boost.Asio's const_buffer type) or whether it's something that needs to be copied (in the case of any other range). In the future there should be other overloads which deal with explicit Boost.Range iterator ranges, and maybe specific types. --- .../network/protocol/http/server/async_connection.hpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index 6d7b929dd..9991a2f8f 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,10 @@ * This is the maximum size though and Boost.Asio's internal representation * of a streambuf would make appropriate decisions on how big a buffer * is to begin with. + * + * This kinda assumes that a page is by default 4096. Since we're using + * the default allocator with the static buffers, it's not guaranteed that + * the static buffers will be page-aligned when they are allocated. */ #define BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE 4096 #endif /* BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE */ @@ -211,14 +216,16 @@ namespace boost { namespace network { namespace http { } template - void write(Range const & range, Callback const & callback) { + typename disable_if, void>::type + write(Range const & range, Callback const & callback) { lock_guard lock(headers_mutex); if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); write_impl(boost::make_iterator_range(range), callback); } template - void write_vec(ConstBufferSeq const & seq, Callback const & callback) + typename enable_if, void>::type + write(ConstBufferSeq const & seq, Callback const & callback) { write_vec_impl(seq, callback, shared_array_list(), shared_buffers()); } From ec4689aabc4f10a516861a6d36bee50f1976cd83 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 30 Jan 2011 03:37:10 +0800 Subject: [PATCH 065/768] Test for Less Copy Connection Write This commit basically is a test for the case where the range passed to the call to connection::write is actually a Boost.Asio const_buffer derivative. This removes the requirement to make copies of the range passed into the call to connection::write. This is a backward-compatible change which means code that used to work with the range-based solution will still be supported while Boost.Asio const_buffer derivatives passed in will be supported as first-class elements that get used be the implementation directly. Note: Boost.Asio const_buffers explicitly do not own the memory that has been wrapped to it. Care should be taken when passing in Boost.Asio const_buffer sequences into the connection::write interface to make sure that the data is still accessible until at least the provided callback is provided. --- .../protocol/http/server/async_connection.hpp | 9 ++- libs/network/test/http/CMakeLists.txt | 1 + .../test/http/server_async_less_copy.cpp | 72 +++++++++++++++++++ 3 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 libs/network/test/http/server_async_less_copy.cpp diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index 9991a2f8f..d52a9b5e4 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -644,10 +644,13 @@ namespace boost { namespace network { namespace http { if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); + boost::function callback_function = + callback; + boost::function continuation = boost::bind( - &async_connection::write_vec_impl + &async_connection::write_vec_impl > ,async_connection::shared_from_this() - ,seq, callback, temporaries, buffers + ,seq, callback_function, temporaries, buffers ); if (!headers_already_sent && !headers_in_progress) { @@ -664,7 +667,7 @@ namespace boost { namespace network { namespace http { ,boost::bind( &async_connection::handle_write ,async_connection::shared_from_this() - ,callback + ,callback_function ,temporaries ,buffers ,asio::placeholders::error diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 5fa8f567d..bbf415e0f 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -69,6 +69,7 @@ if (Boost_FOUND) set ( SERVER_TESTS server_hello_world server_async + server_async_less_copy ) foreach ( test ${SERVER_TESTS} ) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) diff --git a/libs/network/test/http/server_async_less_copy.cpp b/libs/network/test/http/server_async_less_copy.cpp new file mode 100644 index 000000000..ae30be8ef --- /dev/null +++ b/libs/network/test/http/server_async_less_copy.cpp @@ -0,0 +1,72 @@ + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE HTTP Asynchronous Server Tests + +#include +#include +#include +#include + +namespace net = boost::network; +namespace http = boost::network::http; +namespace utils = boost::network::utils; + +struct async_hello_world; +typedef http::async_server server; + +struct async_hello_world { + + struct is_content_length { + template + bool operator()(Header const & header) { + return boost::iequals(name(header), "content-length"); + } + }; + + void operator()(server::request const & request, server::connection_ptr connection) { + static server::response_header headers[] = { + {"Connection", "close"} + , {"Content-Type", "text/plain"} + , {"Server", "cpp-netlib/0.9-devel"} + }; + if (request.method == "HEAD") { + connection->set_status(server::connection::ok); + connection->set_headers(boost::make_iterator_range(headers, headers+3)); + } else { + if (request.method == "PUT" || request.method == "POST") { + static std::string bad_request("Bad Request."); + server::request::headers_container_type::iterator found = + boost::find_if(request.headers, is_content_length()); + if (found == request.headers.end()) { + connection->set_status(server::connection::bad_request); + connection->set_headers(boost::make_iterator_range(headers, headers+3)); + connection->write(bad_request); + return; + } + } + static char const * hello_world = "Hello, World!"; + connection->set_status(server::connection::ok); + connection->set_headers(boost::make_iterator_range(headers, headers+3)); + connection->write( + boost::asio::const_buffers_1(hello_world, 13) + , boost::bind(&async_hello_world::error, this, _1)); + } + } + + void error(boost::system::error_code const & ec) { + // do nothing here. + } +}; + +int main(int argc, char * argv[]) { + utils::thread_pool thread_pool(2); + async_hello_world handler; + server instance("127.0.0.1", "8000", handler, thread_pool, http::_reuse_address=true); + instance.run(); + return 0; +} + From a912ab9dacf9bee02a0a9aee6f3bf48429eabbfa Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 30 Jan 2011 18:44:19 +0800 Subject: [PATCH 066/768] Supporting Custom Ports in Host Header for Requests This commit addresses mikhailberis/cpp-netlib#25 which puts the port as part of the Host header in HTTP requests. --- boost/network/protocol/http/algorithms/linearize.hpp | 7 +++++++ boost/network/protocol/http/message/wrappers/port.hpp | 6 ++++++ boost/network/protocol/http/message/wrappers/uri.hpp | 5 +++++ 3 files changed, 18 insertions(+) diff --git a/boost/network/protocol/http/algorithms/linearize.hpp b/boost/network/protocol/http/algorithms/linearize.hpp index 8010f19bd..c53305ae2 100644 --- a/boost/network/protocol/http/algorithms/linearize.hpp +++ b/boost/network/protocol/http/algorithms/linearize.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace boost { namespace network { namespace http { @@ -95,6 +96,12 @@ namespace boost { namespace network { namespace http { *oi = consts::colon_char(); *oi = consts::space_char(); boost::copy(request.host(), oi); + boost::optional port_ = port(request); + if (port_) { + string_type port_str = boost::lexical_cast(*port_); + *oi = consts::colon_char(); + boost::copy(port_str, oi); + } boost::copy(crlf, oi); boost::copy(accept, oi); *oi = consts::colon_char(); diff --git a/boost/network/protocol/http/message/wrappers/port.hpp b/boost/network/protocol/http/message/wrappers/port.hpp index 16ab50099..4da1f6eda 100644 --- a/boost/network/protocol/http/message/wrappers/port.hpp +++ b/boost/network/protocol/http/message/wrappers/port.hpp @@ -7,6 +7,8 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include + namespace boost { namespace network { namespace http { template @@ -26,6 +28,10 @@ namespace boost { namespace network { namespace http { operator port_type() { return message_.port(); } + + operator boost::optional () { + return port(message_.uri()); + } }; } // namespace impl diff --git a/boost/network/protocol/http/message/wrappers/uri.hpp b/boost/network/protocol/http/message/wrappers/uri.hpp index c7288a2e3..7d4be811a 100644 --- a/boost/network/protocol/http/message/wrappers/uri.hpp +++ b/boost/network/protocol/http/message/wrappers/uri.hpp @@ -7,6 +7,8 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include + namespace boost { namespace network { namespace http { template @@ -22,6 +24,9 @@ namespace boost { namespace network { namespace http { operator string_type() { return message_.uri().raw(); } + operator boost::network::uri::basic_uri () { + return message_.uri(); + } }; } From c0e214bc4006fcf5b90954c42759e7555e5534c9 Mon Sep 17 00:00:00 2001 From: Oleg Malashenko Date: Wed, 2 Feb 2011 10:49:00 +1000 Subject: [PATCH 067/768] Fixed async_connection::write() SFINAE-isation Overloaded function selection based on ConstBufferSeq::value_type. http_server_async_less_copy test fixed accordingly. --- boost/network/protocol/http/server/async_connection.hpp | 4 ++-- libs/network/test/http/server_async_less_copy.cpp | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index d52a9b5e4..3570657c5 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -216,7 +216,7 @@ namespace boost { namespace network { namespace http { } template - typename disable_if, void>::type + typename disable_if, void>::type write(Range const & range, Callback const & callback) { lock_guard lock(headers_mutex); if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); @@ -224,7 +224,7 @@ namespace boost { namespace network { namespace http { } template - typename enable_if, void>::type + typename enable_if, void>::type write(ConstBufferSeq const & seq, Callback const & callback) { write_vec_impl(seq, callback, shared_array_list(), shared_buffers()); diff --git a/libs/network/test/http/server_async_less_copy.cpp b/libs/network/test/http/server_async_less_copy.cpp index ae30be8ef..ae8599371 100644 --- a/libs/network/test/http/server_async_less_copy.cpp +++ b/libs/network/test/http/server_async_less_copy.cpp @@ -6,6 +6,8 @@ #define BOOST_TEST_MODULE HTTP Asynchronous Server Tests +#include + #include #include #include @@ -51,9 +53,9 @@ struct async_hello_world { static char const * hello_world = "Hello, World!"; connection->set_status(server::connection::ok); connection->set_headers(boost::make_iterator_range(headers, headers+3)); - connection->write( - boost::asio::const_buffers_1(hello_world, 13) - , boost::bind(&async_hello_world::error, this, _1)); + std::vector iovec; + iovec.push_back(boost::asio::const_buffer(hello_world, 13)); + connection->write(iovec, boost::bind(&async_hello_world::error, this, _1)); } } From ab45cedd030bf4b9d8db89f7df7206c87a013e7c Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 6 Mar 2011 18:15:47 +0800 Subject: [PATCH 068/768] Supporting BOOST_NETWORK_NO_LIB This commit actually enables support for the BOOST_NETWORK_NO_LIB macro that will allow users of the library to define this so that there will be no need to have the externally-linked components when the network library is used. This commit only adds the support for the URI parsing parts -- this means that code using the HTTP client code don't need to link the URI parser external library to use it. NOTE: I'm still thinking about whether it's better that the default implementation would remain header-only, and only have a special macro for requiring the externally-linked libraries. I'm still not convinced that the default for header-only would be productive, but I'm still thinking about how to support some sort of backward compatibility for the code that's already using the library in header only mode. --- boost/network/uri/detail/impl/parse_uri.ipp | 317 ++++++++++++++++++ boost/network/uri/detail/parse_uri.hpp | 5 + libs/network/src/parse_uri_impl.cpp | 301 +---------------- libs/network/test/http/CMakeLists.txt | 32 +- .../test/http/client_include_inlined.cpp | 17 + 5 files changed, 365 insertions(+), 307 deletions(-) create mode 100644 boost/network/uri/detail/impl/parse_uri.ipp create mode 100644 libs/network/test/http/client_include_inlined.cpp diff --git a/boost/network/uri/detail/impl/parse_uri.ipp b/boost/network/uri/detail/impl/parse_uri.ipp new file mode 100644 index 000000000..3bc4ae201 --- /dev/null +++ b/boost/network/uri/detail/impl/parse_uri.ipp @@ -0,0 +1,317 @@ + +// Copyright 2010-2011 Dean Michael Berris. +// Copyright 2009 Jeroen Habraken. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef PARSE_URI_IMPL_AQAWWXWT +#define PARSE_URI_IMPL_AQAWWXWT + +#ifdef BOOST_NETWORK_NO_LIB +#define BOOST_NETWORK_INLINE inline +#else +#define BOOST_NETWORK_INLINE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +BOOST_FUSION_ADAPT_STRUCT(boost::network::uri::detail::uri_parts_default_base, + (std::string, scheme) + (optional, user_info) + (optional, host) + (optional, port) + (optional, path) + (optional, query) + (optional, fragment) +) + +BOOST_FUSION_ADAPT_STRUCT(boost::network::uri::detail::uri_parts_wide_base, + (std::wstring, scheme) + (optional, user_info) + (optional, host) + (optional, port) + (optional, path) + (optional, query) + (optional, fragment) +) + +namespace boost { namespace spirit { namespace traits { +template <> +struct transform_attribute< + boost::network::uri::detail::uri_parts_default_base, + boost::fusion::tuple< + std::string &, + boost::fusion::tuple< + boost::optional&, + boost::optional&, + boost::optional &, + std::string & + >, + optional&, + optional& + > +#if SPIRIT_VERSION >= 0x2030 + , boost::spirit::qi::domain +#endif + > +{ + typedef + boost::fusion::tuple< + std::string &, + boost::fusion::tuple< + boost::optional&, + boost::optional&, + boost::optional &, + std::string & + >, + optional&, + optional& + > type; + + static type pre(boost::network::uri::detail::uri_parts_default_base & parts) { + boost::fusion::tuple< + boost::optional &, + boost::optional &, + boost::optional &, + std::string & + > hier_part = + boost::fusion::tie( + parts.user_info, + parts.host, + parts.port, + parts.path + ); + + return boost::fusion::tie( + parts.scheme, + hier_part, + parts.query, + parts.fragment + ); +} + +static void post(boost::network::uri::detail::uri_parts_default_base &, type const &) { } + +#if SPIRIT_VERSION >= 0x2030 +static void fail(boost::network::uri::detail::uri_parts_default_base & val) { } +#endif +}; + +#if SPIRIT_VERSION < 0x2030 +template +struct transform_attribute< + optional, + Transformed, + typename disable_if, Transformed> >::type + > +{ + typedef Transformed & type; + + static Transformed & pre(optional & val) { + if (!val) + val = Transformed(); + return boost::get(val); + } + + static void post(optional &, Transformed const &) { } +}; +#endif +} // namespace traits +} // namespace spirit +} // namespace boost + + +namespace boost { namespace network { namespace uri { namespace detail { + +namespace qi = boost::spirit::qi; + +template +struct uri_grammar_default : qi::grammar { + uri_grammar_default() : uri_grammar_default::base_type(start, "uri") { + // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" + gen_delims %= qi::char_(":/?#[]@"); + // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + sub_delims %= qi::char_("!$&'()*+,;="); + // reserved = gen-delims / sub-delims + reserved %= gen_delims | sub_delims; + // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + unreserved %= qi::alnum | qi::char_("-._~"); + // pct-encoded = "%" HEXDIG HEXDIG + pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; + + // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + pchar %= qi::raw[ + unreserved | pct_encoded | sub_delims | qi::char_(":@") + ]; + + // segment = *pchar + segment %= qi::raw[*pchar]; + // segment-nz = 1*pchar + segment_nz %= qi::raw[+pchar]; + // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) + segment_nz_nc %= qi::raw[ + +(unreserved | pct_encoded | sub_delims | qi::char_("@")) + ]; + // path-abempty = *( "/" segment ) + path_abempty %= qi::raw[*(qi::char_("/") >> segment)]; + // path-absolute = "/" [ segment-nz *( "/" segment ) ] + path_absolute %= qi::raw[ + qi::char_("/") + >> -(segment_nz >> *(qi::char_("/") >> segment)) + ]; + // path-rootless = segment-nz *( "/" segment ) + path_rootless %= qi::raw[ + segment_nz >> *(qi::char_("/") >> segment) + ]; + // path-empty = 0 + path_empty %= qi::eps; + + // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + scheme %= qi::alpha >> *(qi::alnum | qi::char_("+.-")); + + // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) + user_info %= qi::raw[ + *(unreserved | pct_encoded | sub_delims | qi::char_(":")) + ]; + + // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 + dec_octet %= + !(qi::lit('0') >> qi::digit) + >> qi::raw[ + qi::uint_parser() + ]; + // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet + ipv4address %= qi::raw[ + dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] + ]; + // reg-name = *( unreserved / pct-encoded / sub-delims ) + reg_name %= qi::raw[ + *(unreserved | pct_encoded | sub_delims) + ]; + // TODO, host = IP-literal / IPv4address / reg-name + host %= ipv4address | reg_name; + + // query = *( pchar / "/" / "?" ) + query %= qi::raw[*(pchar | qi::char_("/?"))]; + // fragment = *( pchar / "/" / "?" ) + fragment %= qi::raw[*(pchar | qi::char_("/?"))]; + + // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty + // authority = [ userinfo "@" ] host [ ":" port ] + hier_part %= + ( + "//" + >> -(user_info >> '@') + >> host + >> -(':' >> qi::ushort_) + >> path_abempty + ) + | + ( + qi::attr(optional()) + >> qi::attr(optional()) + >> qi::attr(optional()) + >> ( + path_absolute + | path_rootless + | path_empty + ) + ); + + uri %= + scheme >> ':' + >> hier_part + >> -('?' >> query) + >> -('#' >> fragment); + + start %= uri.alias(); + } + + typedef std::string string_type; + + qi::rule + gen_delims, sub_delims, reserved, unreserved; + qi::rule + pct_encoded, pchar; + + qi::rule + segment, segment_nz, segment_nz_nc; + qi::rule + path_abempty, path_absolute, path_rootless, path_empty; + + qi::rule + dec_octet, ipv4address, reg_name, host; + + qi::rule + scheme, user_info, query, fragment; + + qi::rule&, + optional&, + optional&, + string_type & + >()> hier_part; + + // start rule of grammar + qi::rule start; + + // actual uri parser + qi::rule< + Iterator, + boost::fusion::tuple< + string_type&, + boost::fusion::tuple< + optional&, + optional&, + optional&, + string_type & + >, + optional&, + optional& + >() + > uri; + +}; + +BOOST_NETWORK_INLINE bool parse_uri_impl(boost::iterator_range & range, uri_parts_default_base & parts, boost::network::tags::default_string) { + // Qualified boost::begin and boost::end because MSVC complains + // of ambiguity on call to begin(range) and end(rand). + std::string::const_iterator start_ = boost::begin(range); + std::string::const_iterator end_ = boost::end(range); + + static uri_grammar_default grammar; + + bool ok = qi::parse(start_, end_, grammar, parts); + + return ok && start_ == end_; +} + +BOOST_NETWORK_INLINE bool parse_uri_impl(boost::iterator_range & range, uri_parts_wide_base & parts, boost::network::tags::default_wstring) { + // TODO implement the grammar that supports wide strings + return false; // this always fails because it's not supported yet! +} + +} /* detail */ + +} /* uri */ + +} /* network */ + +} /* boost */ + +#endif /* PARSE_URI_IMPL_AQAWWXWT */ diff --git a/boost/network/uri/detail/parse_uri.hpp b/boost/network/uri/detail/parse_uri.hpp index 73d68bd5e..0c7cb9b70 100644 --- a/boost/network/uri/detail/parse_uri.hpp +++ b/boost/network/uri/detail/parse_uri.hpp @@ -9,6 +9,9 @@ #include #include #include +#ifdef BOOST_NETWORK_NO_LIB +#include +#endif namespace boost { namespace network { namespace uri { namespace detail { @@ -17,8 +20,10 @@ inline bool parse_specific(uri_parts & parts) { return true; } +#ifndef BOOST_NETWORK_NO_LIB extern bool parse_uri_impl(boost::iterator_range & range, uri_parts_default_base & parts, tags::default_string); extern bool parse_uri_impl(boost::iterator_range & range, uri_parts_wide_base & parts, tags::default_wstring); +#endif template struct unsupported_tag; diff --git a/libs/network/src/parse_uri_impl.cpp b/libs/network/src/parse_uri_impl.cpp index 7d6433950..7de09346b 100644 --- a/libs/network/src/parse_uri_impl.cpp +++ b/libs/network/src/parse_uri_impl.cpp @@ -1,306 +1,13 @@ -// Copyright 2010 Dean Michael Berris. +// Copyright 2010-2011 Dean Michael Berris. // Copyright 2009 Jeroen Habraken. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -BOOST_FUSION_ADAPT_STRUCT(boost::network::uri::detail::uri_parts_default_base, - (std::string, scheme) - (optional, user_info) - (optional, host) - (optional, port) - (optional, path) - (optional, query) - (optional, fragment) -) - -BOOST_FUSION_ADAPT_STRUCT(boost::network::uri::detail::uri_parts_wide_base, - (std::wstring, scheme) - (optional, user_info) - (optional, host) - (optional, port) - (optional, path) - (optional, query) - (optional, fragment) -) - -namespace boost { namespace spirit { namespace traits { -template <> -struct transform_attribute< - boost::network::uri::detail::uri_parts_default_base, - boost::fusion::tuple< - std::string &, - boost::fusion::tuple< - boost::optional&, - boost::optional&, - boost::optional &, - std::string & - >, - optional&, - optional& - > -#if SPIRIT_VERSION >= 0x2030 - , boost::spirit::qi::domain -#endif - > -{ - typedef - boost::fusion::tuple< - std::string &, - boost::fusion::tuple< - boost::optional&, - boost::optional&, - boost::optional &, - std::string & - >, - optional&, - optional& - > type; - - static type pre(boost::network::uri::detail::uri_parts_default_base & parts) { - boost::fusion::tuple< - boost::optional &, - boost::optional &, - boost::optional &, - std::string & - > hier_part = - boost::fusion::tie( - parts.user_info, - parts.host, - parts.port, - parts.path - ); - - return boost::fusion::tie( - parts.scheme, - hier_part, - parts.query, - parts.fragment - ); -} - -static void post(boost::network::uri::detail::uri_parts_default_base &, type const &) { } - -#if SPIRIT_VERSION >= 0x2030 -static void fail(boost::network::uri::detail::uri_parts_default_base & val) { } +#ifdef BOOST_NETWORK_NO_LIB +#undef BOOST_NETWORK_NO_LIB #endif -}; - -#if SPIRIT_VERSION < 0x2030 -template -struct transform_attribute< - optional, - Transformed, - typename disable_if, Transformed> >::type - > -{ - typedef Transformed & type; - - static Transformed & pre(optional & val) { - if (!val) - val = Transformed(); - return boost::get(val); - } - - static void post(optional &, Transformed const &) { } -}; -#endif -} // namespace traits -} // namespace spirit -} // namespace boost - - -namespace boost { namespace network { namespace uri { namespace detail { - -namespace qi = boost::spirit::qi; - -template -struct uri_grammar_default : qi::grammar { - uri_grammar_default() : uri_grammar_default::base_type(start, "uri") { - // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" - gen_delims %= qi::char_(":/?#[]@"); - // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" - sub_delims %= qi::char_("!$&'()*+,;="); - // reserved = gen-delims / sub-delims - reserved %= gen_delims | sub_delims; - // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - unreserved %= qi::alnum | qi::char_("-._~"); - // pct-encoded = "%" HEXDIG HEXDIG - pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; - - // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - pchar %= qi::raw[ - unreserved | pct_encoded | sub_delims | qi::char_(":@") - ]; - - // segment = *pchar - segment %= qi::raw[*pchar]; - // segment-nz = 1*pchar - segment_nz %= qi::raw[+pchar]; - // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) - segment_nz_nc %= qi::raw[ - +(unreserved | pct_encoded | sub_delims | qi::char_("@")) - ]; - // path-abempty = *( "/" segment ) - path_abempty %= qi::raw[*(qi::char_("/") >> segment)]; - // path-absolute = "/" [ segment-nz *( "/" segment ) ] - path_absolute %= qi::raw[ - qi::char_("/") - >> -(segment_nz >> *(qi::char_("/") >> segment)) - ]; - // path-rootless = segment-nz *( "/" segment ) - path_rootless %= qi::raw[ - segment_nz >> *(qi::char_("/") >> segment) - ]; - // path-empty = 0 - path_empty %= qi::eps; - - // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) - scheme %= qi::alpha >> *(qi::alnum | qi::char_("+.-")); - - // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) - user_info %= qi::raw[ - *(unreserved | pct_encoded | sub_delims | qi::char_(":")) - ]; - - // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 - dec_octet %= - !(qi::lit('0') >> qi::digit) - >> qi::raw[ - qi::uint_parser() - ]; - // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet - ipv4address %= qi::raw[ - dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] - ]; - // reg-name = *( unreserved / pct-encoded / sub-delims ) - reg_name %= qi::raw[ - *(unreserved | pct_encoded | sub_delims) - ]; - // TODO, host = IP-literal / IPv4address / reg-name - host %= ipv4address | reg_name; - - // query = *( pchar / "/" / "?" ) - query %= qi::raw[*(pchar | qi::char_("/?"))]; - // fragment = *( pchar / "/" / "?" ) - fragment %= qi::raw[*(pchar | qi::char_("/?"))]; - - // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty - // authority = [ userinfo "@" ] host [ ":" port ] - hier_part %= - ( - "//" - >> -(user_info >> '@') - >> host - >> -(':' >> qi::ushort_) - >> path_abempty - ) - | - ( - qi::attr(optional()) - >> qi::attr(optional()) - >> qi::attr(optional()) - >> ( - path_absolute - | path_rootless - | path_empty - ) - ); - - uri %= - scheme >> ':' - >> hier_part - >> -('?' >> query) - >> -('#' >> fragment); - - start %= uri.alias(); - } - - typedef std::string string_type; - - qi::rule - gen_delims, sub_delims, reserved, unreserved; - qi::rule - pct_encoded, pchar; - - qi::rule - segment, segment_nz, segment_nz_nc; - qi::rule - path_abempty, path_absolute, path_rootless, path_empty; - - qi::rule - dec_octet, ipv4address, reg_name, host; - - qi::rule - scheme, user_info, query, fragment; - - qi::rule&, - optional&, - optional&, - string_type & - >()> hier_part; - - // start rule of grammar - qi::rule start; - - // actual uri parser - qi::rule< - Iterator, - boost::fusion::tuple< - string_type&, - boost::fusion::tuple< - optional&, - optional&, - optional&, - string_type & - >, - optional&, - optional& - >() - > uri; - -}; - -bool parse_uri_impl(boost::iterator_range & range, uri_parts_default_base & parts, boost::network::tags::default_string) { - // Qualified boost::begin and boost::end because MSVC complains - // of ambiguity on call to begin(range) and end(rand). - std::string::const_iterator start_ = boost::begin(range); - std::string::const_iterator end_ = boost::end(range); - - static uri_grammar_default grammar; - - bool ok = qi::parse(start_, end_, grammar, parts); - - return ok && start_ == end_; -} -bool parse_uri_impl(boost::iterator_range & range, uri_parts_wide_base & parts, boost::network::tags::default_wstring) { - // TODO implement the grammar that supports wide strings - return false; // this always fails because it's not supported yet! -} +#include -} /* detail */ - -} /* uri */ - -} /* network */ - -} /* boost */ diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index bbf415e0f..060b0e2de 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -5,7 +5,7 @@ # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) -find_package( Boost 1.43.0 COMPONENTS unit_test_framework system regex thread filesystem ) +find_package( Boost 1.43.0 REQUIRED unit_test_framework system regex thread filesystem ) find_package( OpenSSL ) if (OPENSSL_FOUND) @@ -13,6 +13,8 @@ if (OPENSSL_FOUND) add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) endif() +add_definitions(-DBOOST_NETWORK_DEBUG) + find_package( Threads ) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) @@ -23,14 +25,6 @@ if (Boost_FOUND) client_get_test client_get_different_port_test client_get_timeout_test - client_localhost_ssl_test - client_localhost_normal_test - message_async_ready_test - message_test - request_linearize_test - request_incremental_parser_test - response_incremental_parser_test - url_test ) foreach ( test ${TESTS} ) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) @@ -69,7 +63,6 @@ if (Boost_FOUND) set ( SERVER_TESTS server_hello_world server_async - server_async_less_copy ) foreach ( test ${SERVER_TESTS} ) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) @@ -89,4 +82,23 @@ if (Boost_FOUND) ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}.passed) endforeach (test) + set ( INLINED_TESTS + client_include_inlined + ) + foreach ( test ${INLINED_TESTS} ) + if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") + endif() + add_executable(cpp-netlib-http-inlined-${test} ${test}.cpp) + target_link_libraries(cpp-netlib-http-inlined-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + if (OPENSSL_FOUND) + target_link_libraries(cpp-netlib-http-inlined-${test} ${OPENSSL_LIBRARIES}) + endif() + set_target_properties(cpp-netlib-http-inlined-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-http-inlined-${test} + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-inlined-${test}) + endforeach (test) + endif() diff --git a/libs/network/test/http/client_include_inlined.cpp b/libs/network/test/http/client_include_inlined.cpp new file mode 100644 index 000000000..918444f49 --- /dev/null +++ b/libs/network/test/http/client_include_inlined.cpp @@ -0,0 +1,17 @@ +// Copyright 2011 Dean Michael Berris <mikhailberis@gmail.com>. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_NETWORK_NO_LIB +#include + +int main(int argc, char * argv[]) { + using namespace boost; + using namespace boost::network; + http::client c; + http::client::request req("http://www.boost.org/"); + http::client::response res = c.get(req); + return 0; +} + From 1675db043f2fc4fd7f6e5a00fe118160c09aadea Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 6 Mar 2011 18:59:41 +0800 Subject: [PATCH 069/768] Making Server tests' port to run on configurable This addresses some concerns with the unit tests for servers that don't run mainly because the port they're all trying to run on (port 8000) is being used across all the executables. Even if the socket address is reused, that will only make sense for the same executable on UNIX/Linux. Now the tests run on different ports, with the help of changes in the tests and the CMake configuration. --- libs/network/test/http/CMakeLists.txt | 8 ++++++++ libs/network/test/http/server_async.cpp | 4 +++- libs/network/test/http/server_async_less_copy.cpp | 4 +++- libs/network/test/http/server_hello_world.cpp | 4 +++- libs/network/test/httplib_acceptance.py | 14 +++++++------- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 060b0e2de..9544e8a25 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -25,7 +25,11 @@ if (Boost_FOUND) client_get_test client_get_different_port_test client_get_timeout_test + client_localhost_normal_test ) + if (OPENSSL_FOUND) + set ( TESTS ${TESTS} client_localhost_ssl_test ) + endif (OPENSSL_FOUND) foreach ( test ${TESTS} ) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) set_source_files_properties(${test}.cpp @@ -63,7 +67,9 @@ if (Boost_FOUND) set ( SERVER_TESTS server_hello_world server_async + server_async_less_copy ) + set ( PORT 8000 ) foreach ( test ${SERVER_TESTS} ) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) set_source_files_properties(${test}.cpp @@ -79,7 +85,9 @@ if (Boost_FOUND) python ${CPP-NETLIB_SOURCE_DIR}/libs/network/test/httplib_acceptance.py ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test} + ${PORT} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}.passed) + math (EXPR PORT "${PORT} + 1") endforeach (test) set ( INLINED_TESTS diff --git a/libs/network/test/http/server_async.cpp b/libs/network/test/http/server_async.cpp index e9e906982..78cde5318 100644 --- a/libs/network/test/http/server_async.cpp +++ b/libs/network/test/http/server_async.cpp @@ -59,7 +59,9 @@ struct async_hello_world { int main(int argc, char * argv[]) { utils::thread_pool thread_pool(2); async_hello_world handler; - server instance("127.0.0.1", "8000", handler, thread_pool, http::_reuse_address=true); + std::string port = "8000"; + if (argc > 1) port = argv[1]; + server instance("127.0.0.1", port, handler, thread_pool, http::_reuse_address=true); instance.run(); return 0; } diff --git a/libs/network/test/http/server_async_less_copy.cpp b/libs/network/test/http/server_async_less_copy.cpp index ae8599371..2b5ceb6e8 100644 --- a/libs/network/test/http/server_async_less_copy.cpp +++ b/libs/network/test/http/server_async_less_copy.cpp @@ -67,7 +67,9 @@ struct async_hello_world { int main(int argc, char * argv[]) { utils::thread_pool thread_pool(2); async_hello_world handler; - server instance("127.0.0.1", "8000", handler, thread_pool, http::_reuse_address=true); + std::string port = "8000"; + if (argc > 1) port = argv[1]; + server instance("127.0.0.1", port, handler, thread_pool, http::_reuse_address=true); instance.run(); return 0; } diff --git a/libs/network/test/http/server_hello_world.cpp b/libs/network/test/http/server_hello_world.cpp index 823fb35e9..86857a9f2 100644 --- a/libs/network/test/http/server_hello_world.cpp +++ b/libs/network/test/http/server_hello_world.cpp @@ -43,7 +43,9 @@ struct hello_world { int main(int argc, char * argv[]) { hello_world handler; - server server_("127.0.0.1", "8000", handler, http::_reuse_address=true); + std::string port = "8000"; + if (argc > 1) port = argv[1]; + server server_("127.0.0.1", port, handler, http::_reuse_address=true); server_.run(); return EXIT_SUCCESS; } diff --git a/libs/network/test/httplib_acceptance.py b/libs/network/test/httplib_acceptance.py index 52ba176f8..787a74306 100644 --- a/libs/network/test/httplib_acceptance.py +++ b/libs/network/test/httplib_acceptance.py @@ -10,15 +10,15 @@ import httplib2 as httplib from subprocess import Popen,PIPE -if len(argv) < 3: - print('I need the executable to run.') +if len(argv) < 4: + print('I need the executable to run, the port to run it on, and the final touched file indicator.') exit(1) -print('Running {0}...'.format(argv[1])) +print('Running {0} on port {1}...'.format(argv[1], argv[2])) pipe = None try: - pipe = Popen(argv[1], executable=argv[1], stdin=PIPE, stdout=PIPE, close_fds=True) + pipe = Popen(args=[argv[1], argv[2]], executable=argv[1], stdin=PIPE, stdout=PIPE, close_fds=True) print('Done with spawning {0}.'.format(argv[1])) print('Sleeping to give the server a chance to run...') sleep(1) @@ -58,7 +58,7 @@ def test_status(url, method, expected, headers={}, body=''): print('Caught Exception: {0}'.format(e)) status = 1 -url = 'http://localhost:8000/' +url = 'http://localhost:{0}/'.format(argv[2]) test(url, 'GET', expected) test(url, 'DELETE', expected) # Good request case, there's a content-length header for POST @@ -72,10 +72,10 @@ def test_status(url, method, expected, headers={}, body=''): if status != 0: print('Failures encountered.') - pipe.kill() + pipe.terminate() exit(status) open(argv[len(argv) - 1], 'w').close() print('All tests pass.') -pipe.kill() +pipe.terminate() From 18271fe994e67353f10a85d88d773286bc6f9b3c Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 6 Mar 2011 19:26:31 +0800 Subject: [PATCH 070/768] Support for BOOST_NETWORK_NO_LIB (server) This commit adds support for BOOST_NETWORK_NO_LIB for server includes. --- .../protocol/http/server/async_connection.hpp | 5 ++ .../protocol/http/server/impl/parsers.ipp | 59 +++++++++++++++++++ .../src/server_request_parsers_impl.cpp | 43 ++------------ libs/network/test/http/CMakeLists.txt | 1 + .../test/http/server_include_inlined.cpp | 56 ++++++++++++++++++ 5 files changed, 125 insertions(+), 39 deletions(-) create mode 100644 boost/network/protocol/http/server/impl/parsers.ipp create mode 100644 libs/network/test/http/server_include_inlined.cpp diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index cb1e7d789..1f566f2ff 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -28,6 +28,9 @@ #include #include #include +#ifdef BOOST_NETWORK_NO_LIB +#include +#endif #ifndef BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE /** Here we define a page's worth of header connection buffer data. @@ -46,8 +49,10 @@ namespace boost { namespace network { namespace http { +#ifndef BOOST_NETWORK_NO_LIB extern void parse_version(std::string const & partial_parsed, fusion::tuple & version_pair); extern void parse_headers(std::string const & input, std::vector & container); +#endif template struct async_connection : boost::enable_shared_from_this > { diff --git a/boost/network/protocol/http/server/impl/parsers.ipp b/boost/network/protocol/http/server/impl/parsers.ipp new file mode 100644 index 000000000..e39c7b26d --- /dev/null +++ b/boost/network/protocol/http/server/impl/parsers.ipp @@ -0,0 +1,59 @@ +#ifndef SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 +#define SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 + +#include + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +#ifdef BOOST_NETWORK_NO_LIB +# ifndef BOOST_NETWORK_INLINE +# define BOOST_NETWORK_INLINE inline +# endif +#else +# define BOOST_NETWORK_INLINE +#endif +#include + +namespace boost { namespace network { namespace http { + + BOOST_NETWORK_INLINE void parse_version(std::string const & partial_parsed, fusion::tuple & version_pair) { + using namespace boost::spirit::qi; + parse( + partial_parsed.begin(), partial_parsed.end(), + ( + lit("HTTP/") + >> ushort_ + >> '.' + >> ushort_ + ) + , version_pair); + } + + BOOST_NETWORK_INLINE void parse_headers(std::string const & input, std::vector & container) { + using namespace boost::spirit::qi; + parse( + input.begin(), input.end(), + *( + +(alnum|(punct-':')) + >> lit(": ") + >> +((alnum|space|punct) - '\r' - '\n') + >> lit("\r\n") + ) + >> lit("\r\n") + , container + ); + } + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* SERVER_REQUEST_PARSERS_IMPL_UW3PM6V6 */ diff --git a/libs/network/src/server_request_parsers_impl.cpp b/libs/network/src/server_request_parsers_impl.cpp index 78bca4c82..91dfafb77 100644 --- a/libs/network/src/server_request_parsers_impl.cpp +++ b/libs/network/src/server_request_parsers_impl.cpp @@ -1,46 +1,11 @@ -#include - // Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include -#include -#include - -namespace boost { namespace network { namespace http { - - void parse_version(std::string const & partial_parsed, fusion::tuple & version_pair) { - using namespace boost::spirit::qi; - parse( - partial_parsed.begin(), partial_parsed.end(), - ( - lit("HTTP/") - >> ushort_ - >> '.' - >> ushort_ - ) - , version_pair); - } +#ifdef BOOST_NETWORK_NO_LIB +#undef BOOST_NETWORK_NO_LIB +#endif - void parse_headers(std::string const & input, std::vector & container) { - using namespace boost::spirit::qi; - parse( - input.begin(), input.end(), - *( - +(alnum|(punct-':')) - >> lit(": ") - >> +((alnum|space|punct) - '\r' - '\n') - >> lit("\r\n") - ) - >> lit("\r\n") - , container - ); - } +#include -} /* http */ - -} /* network */ - -} /* boost */ diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 9544e8a25..8af6f352a 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -92,6 +92,7 @@ if (Boost_FOUND) set ( INLINED_TESTS client_include_inlined + server_include_inlined ) foreach ( test ${INLINED_TESTS} ) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) diff --git a/libs/network/test/http/server_include_inlined.cpp b/libs/network/test/http/server_include_inlined.cpp new file mode 100644 index 000000000..a8cb362df --- /dev/null +++ b/libs/network/test/http/server_include_inlined.cpp @@ -0,0 +1,56 @@ +// Copyright 2009 (c) Tarro, Inc. +// Copyright 2009-2010 (c) Dean Michael Berris +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#define BOOST_NETWORK_NO_LIB +#include +#include +#include +#include +#include +#include + +namespace http = boost::network::http; +using boost::assign::list_of; +using boost::lexical_cast; +using std::string; +using std::cerr; +using std::endl; + +struct hello_world; +typedef http::server server; + +struct hello_world { + + void operator()(server::request const & request, server::response & response) { + static server::response::header_type header = {"Connection", "close"}; + response = server::response::stock_reply(server::response::ok, "Hello, World!"); + response.headers.push_back(header); + assert(response.status == server::response::ok); + assert(response.headers.size() == 3); + assert(response.content == "Hello, World!"); + } + + void log(string const & data) { + cerr << data << endl; + abort(); + } + +}; + +int main(int argc, char * argv[]) { + hello_world handler; + std::string port = "8000"; + if (argc > 1) port = argv[1]; + server server_("127.0.0.1", port, handler, http::_reuse_address=true); + boost::thread runner(boost::bind(&server::run, &server_)); + server_.stop(); + runner.join(); + return EXIT_SUCCESS; +} + From a623730270cbcefe55f3f8172eb356095c95aa12 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Tue, 8 Mar 2011 02:15:37 +0800 Subject: [PATCH 071/768] Fixes cpp-netlib/cpp-netlib#35 Making calls to client.post and client.put smarter with the provided request objects. --- boost/network/protocol/http/client/facade.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/boost/network/protocol/http/client/facade.hpp b/boost/network/protocol/http/client/facade.hpp index da484b4fa..160760e71 100644 --- a/boost/network/protocol/http/client/facade.hpp +++ b/boost/network/protocol/http/client/facade.hpp @@ -56,8 +56,9 @@ namespace boost { namespace network { namespace http { response const post (request request_, string_type const & content_type, string_type const & body_) { request_ << ::boost::network::body(body_) - << header("Content-Type", content_type) << header("Content-Length", boost::lexical_cast(body_.size())); + if (!boost::empty(headers(request_)["Content-Type"])) + request_ << header("Content-Type", content_type); return post(request_); } @@ -75,8 +76,9 @@ namespace boost { namespace network { namespace http { response const put (request request_, string_type const & content_type, string_type const & body_) { request_ << ::boost::network::body(body_) - << header("Content-Type", content_type) << header("Content-Length", boost::lexical_cast(body_.size())); + if (!boost::empty(headers(request_)["Content-Type"])) + request_ << header("Content-Type", content_type); return put(request_); } From 862f6142e7d51b350f8b05c4ad480e764b0929c2 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Tue, 8 Mar 2011 02:56:56 +0800 Subject: [PATCH 072/768] Addendum to cpp-netlib/cpp-netlib#35 This fix improves upon the earlier commit to make the implementation more predictable and semantically consistent with the interface for both the put and post methods. --- boost/network/protocol/http/client/facade.hpp | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/boost/network/protocol/http/client/facade.hpp b/boost/network/protocol/http/client/facade.hpp index 160760e71..b4bac09af 100644 --- a/boost/network/protocol/http/client/facade.hpp +++ b/boost/network/protocol/http/client/facade.hpp @@ -55,15 +55,22 @@ namespace boost { namespace network { namespace http { } response const post (request request_, string_type const & content_type, string_type const & body_) { + if (!boost::empty(headers(request_)["Content-Type"])) + request_ << remove_header("Content-Type"); + request_ << ::boost::network::body(body_) + << header("Content-Type", content_type) << header("Content-Length", boost::lexical_cast(body_.size())); - if (!boost::empty(headers(request_)["Content-Type"])) - request_ << header("Content-Type", content_type); return post(request_); } response const post (request const & request_, string_type const & body_) { - return post(request_, "x-application/octet-stream", body_); + string_type content_type = "x-application/octet-stream"; + typename headers_range::type content_type_headers = + headers(request_)["Content-Type"]; + if (!boost::empty(content_type_headers)) + content_type = boost::begin(content_type_headers)->second; + return post(request_, content_type, body_); } response const put (request const & request_) { @@ -71,14 +78,21 @@ namespace boost { namespace network { namespace http { } response const put (request const & request_, string_type const & body_) { - return put(request_, "x-application/octet-stream", body_); + string_type content_type = "x-application/octet-stream"; + typename headers_range::type content_type_headers = + headers(request_)["Content-Type"]; + if (!boost::empty(content_type_headers)) + content_type = boost::begin(content_type_headers)->second; + return put(request_, content_type, body_); } response const put (request request_, string_type const & content_type, string_type const & body_) { + if (!boost::empty(headers(request_)["Content-Type"])) + request_ << remove_header("Content-Type"); + request_ << ::boost::network::body(body_) + << header("Content-Type", content_type) << header("Content-Length", boost::lexical_cast(body_.size())); - if (!boost::empty(headers(request_)["Content-Type"])) - request_ << header("Content-Type", content_type); return put(request_); } From dd026f359795cea1f0e045f66097b35ea4f0180d Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Tue, 15 Mar 2011 16:14:08 +0800 Subject: [PATCH 073/768] Bundling and adding Breathe Breathe is the documentation bridge between Sphinx and Doxygen. --- libs/network/doc/Doxyfile | 1551 +++ libs/network/doc/conf.py | 14 +- libs/network/doc/ext/breathe/.gitignore | 1 + libs/network/doc/ext/breathe/LICENCE | 28 + libs/network/doc/ext/breathe/README.rst | 56 + .../doc/ext/breathe/breathe/__init__.py | 571 ++ .../ext/breathe/breathe/finder/__init__.py | 61 + .../breathe/finder/doxygen/__init__.py | 147 + .../breathe/breathe/finder/doxygen/base.py | 10 + .../breathe/finder/doxygen/compound.py | 42 + .../breathe/breathe/finder/doxygen/index.py | 67 + .../ext/breathe/breathe/parser/__init__.py | 51 + .../breathe/parser/doxygen/__init__.py | 0 .../breathe/parser/doxygen/compound.py | 660 ++ .../breathe/parser/doxygen/compoundsuper.py | 8342 +++++++++++++++++ .../breathe/breathe/parser/doxygen/index.py | 52 + .../breathe/parser/doxygen/indexsuper.py | 523 ++ .../ext/breathe/breathe/renderer/__init__.py | 0 .../breathe/breathe/renderer/rst/__init__.py | 2 + .../breathe/renderer/rst/doxygen/__init__.py | 292 + .../breathe/renderer/rst/doxygen/base.py | 24 + .../breathe/renderer/rst/doxygen/compound.py | 615 ++ .../breathe/renderer/rst/doxygen/domain.py | 190 + .../breathe/renderer/rst/doxygen/filter.py | 101 + .../breathe/renderer/rst/doxygen/index.py | 52 + .../breathe/renderer/rst/doxygen/target.py | 40 + .../ext/breathe/examples/doxygen/.gitignore | 27 + .../ext/breathe/examples/doxygen/afterdoc.cfg | 11 + .../ext/breathe/examples/doxygen/afterdoc.h | 18 + .../ext/breathe/examples/doxygen/author.cfg | 11 + .../ext/breathe/examples/doxygen/author.cpp | 14 + .../ext/breathe/examples/doxygen/autolink.cfg | 11 + .../ext/breathe/examples/doxygen/autolink.cpp | 99 + .../ext/breathe/examples/doxygen/class.cfg | 11 + .../doc/ext/breathe/examples/doxygen/class.h | 11 + .../ext/breathe/examples/doxygen/define.cfg | 12 + .../doc/ext/breathe/examples/doxygen/define.h | 18 + .../ext/breathe/examples/doxygen/diagrams.cfg | 15 + .../ext/breathe/examples/doxygen/diagrams_a.h | 4 + .../ext/breathe/examples/doxygen/diagrams_b.h | 5 + .../ext/breathe/examples/doxygen/diagrams_c.h | 6 + .../ext/breathe/examples/doxygen/diagrams_d.h | 7 + .../ext/breathe/examples/doxygen/diagrams_e.h | 5 + .../breathe/examples/doxygen/docstring.cfg | 12 + .../ext/breathe/examples/doxygen/docstring.py | 27 + .../doc/ext/breathe/examples/doxygen/enum.cfg | 11 + .../doc/ext/breathe/examples/doxygen/enum.h | 24 + .../ext/breathe/examples/doxygen/example.cfg | 13 + .../ext/breathe/examples/doxygen/example.cpp | 19 + .../ext/breathe/examples/doxygen/example.tag | 14 + .../breathe/examples/doxygen/example_test.cpp | 5 + .../doc/ext/breathe/examples/doxygen/file.cfg | 11 + .../doc/ext/breathe/examples/doxygen/file.h | 10 + .../doc/ext/breathe/examples/doxygen/func.cfg | 11 + .../doc/ext/breathe/examples/doxygen/func.h | 21 + .../ext/breathe/examples/doxygen/group.cfg | 11 + .../ext/breathe/examples/doxygen/group.cpp | 88 + .../ext/breathe/examples/doxygen/include.cfg | 12 + .../ext/breathe/examples/doxygen/include.cpp | 22 + .../ext/breathe/examples/doxygen/jdstyle.cfg | 11 + .../ext/breathe/examples/doxygen/jdstyle.cpp | 66 + .../doc/ext/breathe/examples/doxygen/manual.c | 87 + .../ext/breathe/examples/doxygen/manual.cfg | 17 + .../ext/breathe/examples/doxygen/memgrp.cfg | 12 + .../ext/breathe/examples/doxygen/memgrp.cpp | 41 + .../doc/ext/breathe/examples/doxygen/mux.cfg | 15 + .../doc/ext/breathe/examples/doxygen/mux.vhdl | 32 + .../ext/breathe/examples/doxygen/overload.cfg | 12 + .../ext/breathe/examples/doxygen/overload.cpp | 25 + .../doc/ext/breathe/examples/doxygen/page.cfg | 11 + .../doc/ext/breathe/examples/doxygen/page.doc | 14 + .../doc/ext/breathe/examples/doxygen/par.cfg | 11 + .../doc/ext/breathe/examples/doxygen/par.cpp | 20 + .../breathe/examples/doxygen/pyexample.cfg | 11 + .../ext/breathe/examples/doxygen/pyexample.py | 30 + .../ext/breathe/examples/doxygen/qtstyle.cfg | 11 + .../ext/breathe/examples/doxygen/qtstyle.cpp | 65 + .../ext/breathe/examples/doxygen/relates.cfg | 11 + .../ext/breathe/examples/doxygen/relates.cpp | 23 + .../breathe/examples/doxygen/restypedef.cfg | 11 + .../breathe/examples/doxygen/restypedef.cpp | 25 + .../breathe/examples/doxygen/structcmd.cfg | 11 + .../ext/breathe/examples/doxygen/structcmd.h | 59 + .../doc/ext/breathe/examples/doxygen/tag.cfg | 13 + .../doc/ext/breathe/examples/doxygen/tag.cpp | 9 + .../ext/breathe/examples/doxygen/templ.cfg | 11 + .../ext/breathe/examples/doxygen/templ.cpp | 35 + .../ext/breathe/examples/specific/.gitignore | 7 + .../ext/breathe/examples/specific/alias.cfg | 13 + .../doc/ext/breathe/examples/specific/alias.h | 7 + .../ext/breathe/examples/specific/class.cfg | 11 + .../doc/ext/breathe/examples/specific/class.h | 43 + .../ext/breathe/examples/specific/inline.cfg | 11 + .../ext/breathe/examples/specific/inline.h | 17 + .../ext/breathe/examples/specific/members.cfg | 11 + .../ext/breathe/examples/specific/members.h | 27 + .../breathe/examples/specific/nutshell.cfg | 11 + .../ext/breathe/examples/specific/nutshell.h | 43 + .../doc/ext/breathe/examples/specific/rst.cfg | 14 + .../doc/ext/breathe/examples/specific/rst.h | 31 + .../ext/breathe/examples/specific/typedef.cfg | 11 + .../ext/breathe/examples/specific/typedef.h | 15 + .../ext/breathe/examples/tinyxml/.gitignore | 1 + .../ext/breathe/examples/tinyxml/tinyxml.cfg | 11 + .../ext/breathe/examples/tinyxml/tinyxml.h | 1779 ++++ .../doc/ext/breathe/spec/specification.rst | 84 + .../doc/ext/breathe/testsuite/.gitignore | 2 + .../doc/ext/breathe/testsuite/pseudorst.py | 49 + .../testsuite/source/_static/breathe.css | 13 + .../ext/breathe/testsuite/source/class.rst | 31 + .../breathe/testsuite/source/codeguide.rst | 237 + .../doc/ext/breathe/testsuite/source/conf.py | 224 + .../breathe/testsuite/source/contributing.rst | 56 + .../ext/breathe/testsuite/source/credits.rst | 19 + .../breathe/testsuite/source/directives.rst | 158 + .../ext/breathe/testsuite/source/domains.rst | 44 + .../ext/breathe/testsuite/source/doxygen.rst | 146 + .../breathe/testsuite/source/embeddedrst.rst | 9 + .../doc/ext/breathe/testsuite/source/enum.rst | 31 + .../ext/breathe/testsuite/source/function.rst | 31 + .../ext/breathe/testsuite/source/index.rst | 80 + .../ext/breathe/testsuite/source/inline.rst | 20 + .../ext/breathe/testsuite/source/members.rst | 28 + .../ext/breathe/testsuite/source/nutshell.h | 43 + .../breathe/testsuite/source/quickstart.rst | 56 + .../ext/breathe/testsuite/source/specific.rst | 36 + .../ext/breathe/testsuite/source/struct.rst | 31 + .../breathe/testsuite/source/testpages.rst | 15 + .../ext/breathe/testsuite/source/tinyxml.rst | 8 + .../ext/breathe/testsuite/source/typedef.rst | 31 + 130 files changed, 18330 insertions(+), 2 deletions(-) create mode 100644 libs/network/doc/Doxyfile create mode 100644 libs/network/doc/ext/breathe/.gitignore create mode 100644 libs/network/doc/ext/breathe/LICENCE create mode 100644 libs/network/doc/ext/breathe/README.rst create mode 100644 libs/network/doc/ext/breathe/breathe/__init__.py create mode 100644 libs/network/doc/ext/breathe/breathe/finder/__init__.py create mode 100644 libs/network/doc/ext/breathe/breathe/finder/doxygen/__init__.py create mode 100644 libs/network/doc/ext/breathe/breathe/finder/doxygen/base.py create mode 100644 libs/network/doc/ext/breathe/breathe/finder/doxygen/compound.py create mode 100644 libs/network/doc/ext/breathe/breathe/finder/doxygen/index.py create mode 100644 libs/network/doc/ext/breathe/breathe/parser/__init__.py create mode 100644 libs/network/doc/ext/breathe/breathe/parser/doxygen/__init__.py create mode 100644 libs/network/doc/ext/breathe/breathe/parser/doxygen/compound.py create mode 100644 libs/network/doc/ext/breathe/breathe/parser/doxygen/compoundsuper.py create mode 100644 libs/network/doc/ext/breathe/breathe/parser/doxygen/index.py create mode 100644 libs/network/doc/ext/breathe/breathe/parser/doxygen/indexsuper.py create mode 100644 libs/network/doc/ext/breathe/breathe/renderer/__init__.py create mode 100644 libs/network/doc/ext/breathe/breathe/renderer/rst/__init__.py create mode 100644 libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/__init__.py create mode 100644 libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/base.py create mode 100644 libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/compound.py create mode 100644 libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/domain.py create mode 100644 libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/filter.py create mode 100644 libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/index.py create mode 100644 libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/target.py create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/.gitignore create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/afterdoc.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/afterdoc.h create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/author.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/author.cpp create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/autolink.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/autolink.cpp create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/class.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/class.h create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/define.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/define.h create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/diagrams.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/diagrams_a.h create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/diagrams_b.h create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/diagrams_c.h create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/diagrams_d.h create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/diagrams_e.h create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/docstring.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/docstring.py create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/enum.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/enum.h create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/example.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/example.cpp create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/example.tag create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/example_test.cpp create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/file.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/file.h create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/func.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/func.h create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/group.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/group.cpp create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/include.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/include.cpp create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/jdstyle.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/jdstyle.cpp create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/manual.c create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/manual.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/memgrp.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/memgrp.cpp create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/mux.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/mux.vhdl create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/overload.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/overload.cpp create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/page.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/page.doc create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/par.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/par.cpp create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/pyexample.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/pyexample.py create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/qtstyle.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/qtstyle.cpp create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/relates.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/relates.cpp create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/restypedef.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/restypedef.cpp create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/structcmd.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/structcmd.h create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/tag.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/tag.cpp create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/templ.cfg create mode 100644 libs/network/doc/ext/breathe/examples/doxygen/templ.cpp create mode 100644 libs/network/doc/ext/breathe/examples/specific/.gitignore create mode 100644 libs/network/doc/ext/breathe/examples/specific/alias.cfg create mode 100644 libs/network/doc/ext/breathe/examples/specific/alias.h create mode 100644 libs/network/doc/ext/breathe/examples/specific/class.cfg create mode 100644 libs/network/doc/ext/breathe/examples/specific/class.h create mode 100644 libs/network/doc/ext/breathe/examples/specific/inline.cfg create mode 100644 libs/network/doc/ext/breathe/examples/specific/inline.h create mode 100644 libs/network/doc/ext/breathe/examples/specific/members.cfg create mode 100644 libs/network/doc/ext/breathe/examples/specific/members.h create mode 100644 libs/network/doc/ext/breathe/examples/specific/nutshell.cfg create mode 100644 libs/network/doc/ext/breathe/examples/specific/nutshell.h create mode 100644 libs/network/doc/ext/breathe/examples/specific/rst.cfg create mode 100644 libs/network/doc/ext/breathe/examples/specific/rst.h create mode 100644 libs/network/doc/ext/breathe/examples/specific/typedef.cfg create mode 100644 libs/network/doc/ext/breathe/examples/specific/typedef.h create mode 100644 libs/network/doc/ext/breathe/examples/tinyxml/.gitignore create mode 100644 libs/network/doc/ext/breathe/examples/tinyxml/tinyxml.cfg create mode 100644 libs/network/doc/ext/breathe/examples/tinyxml/tinyxml.h create mode 100644 libs/network/doc/ext/breathe/spec/specification.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/.gitignore create mode 100755 libs/network/doc/ext/breathe/testsuite/pseudorst.py create mode 100644 libs/network/doc/ext/breathe/testsuite/source/_static/breathe.css create mode 100644 libs/network/doc/ext/breathe/testsuite/source/class.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/codeguide.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/conf.py create mode 100644 libs/network/doc/ext/breathe/testsuite/source/contributing.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/credits.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/directives.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/domains.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/doxygen.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/embeddedrst.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/enum.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/function.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/index.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/inline.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/members.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/nutshell.h create mode 100644 libs/network/doc/ext/breathe/testsuite/source/quickstart.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/specific.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/struct.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/testpages.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/tinyxml.rst create mode 100644 libs/network/doc/ext/breathe/testsuite/source/typedef.rst diff --git a/libs/network/doc/Doxyfile b/libs/network/doc/Doxyfile new file mode 100644 index 000000000..dd2bd8b0f --- /dev/null +++ b/libs/network/doc/Doxyfile @@ -0,0 +1,1551 @@ +# Doxyfile 1.6.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "cpp-netlib" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = YES + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it parses. +# With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this tag. +# The format is ext=language, where ext is a file extension, and language is one of +# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, +# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = C++ + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = YES + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = YES + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = YES + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by +# doxygen. The layout file controls the global structure of the generated output files +# in an output format independent way. The create the layout file that represents +# doxygen's defaults, run doxygen with the -l option. You can optionally specify a +# file name after the option, if omitted DoxygenLayout.xml will be used as the name +# of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = ../../../boost ../src + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = NO + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER +# are set, an additional index file will be generated that can be used as input for +# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated +# HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. +# For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's +# filter section matches. +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be implemented using a PHP enabled web server instead of at the web client using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server based approach is that it scales better to large projects and allows full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = YES + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = doxyxml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = BOOST_ENABLE_HTTPS + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = YES + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = YES + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/libs/network/doc/conf.py b/libs/network/doc/conf.py index b15c462d9..d86815fb3 100644 --- a/libs/network/doc/conf.py +++ b/libs/network/doc/conf.py @@ -18,6 +18,8 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.append(os.path.abspath('.')) +sys.path.append(os.path.abspath('ext/breathe')) + # -- General configuration ----------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be extensions @@ -26,7 +28,9 @@ extensions = ['sphinx.ext.todo', 'sphinx.ext.autodoc', 'sphinx.ext.doctest', - 'sphinx.ext.coverage',] + 'sphinx.ext.coverage', + 'breathe', + ] # Uncomment this to generate output for Github. # extensions += ['sphinxtogithub'] @@ -73,7 +77,7 @@ # List of directories, relative to source directory, that shouldn't be searched # for source files. -exclude_trees = ['build'] +exclude_trees = ['build', 'doxyxml', 'ext'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None @@ -203,3 +207,9 @@ # If false, no module index is generated. #latex_use_modindex = True + +breathe_projects = {'cpp-netlib': 'doxyxml/'} + +breathe_default_project = 'cpp-netlib' + + diff --git a/libs/network/doc/ext/breathe/.gitignore b/libs/network/doc/ext/breathe/.gitignore new file mode 100644 index 000000000..0d20b6487 --- /dev/null +++ b/libs/network/doc/ext/breathe/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/libs/network/doc/ext/breathe/LICENCE b/libs/network/doc/ext/breathe/LICENCE new file mode 100644 index 000000000..46a85058a --- /dev/null +++ b/libs/network/doc/ext/breathe/LICENCE @@ -0,0 +1,28 @@ +// BSD licence, modified to remove the organisation as there isn't one. + +Copyright (c) 2009, Michael Jones +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/libs/network/doc/ext/breathe/README.rst b/libs/network/doc/ext/breathe/README.rst new file mode 100644 index 000000000..46367ba7b --- /dev/null +++ b/libs/network/doc/ext/breathe/README.rst @@ -0,0 +1,56 @@ +Breathe +======= + +This is an extension to restructured text and Sphinx to be able to read and +render the Doxygen xml output. + +Documentation +------------- + +Documentation is available in the ``testsuite`` folder and up in full `here +`_. + +Running Testsuite +----------------- + +This process assumes the ``sphinx-build`` script is on your path. If it is not, +then either edit ``testsuite/Makefile`` to point at it or create a link to it in +the ``testsuite`` directory. + +First run ``make`` for each folder in the examples directory, then:: + + cd testsuite + make html + +Then view the resulting html with your browser of choice. + + +Requirements +------------ + +Development is currently done with: + +- Python 2.5 +- Docutils 0.7 +- Sphinx 1.0.4 +- Doxygen 1.7.2 + +Doxygen 1.5.1 seems to produce xml with repeated sections which causes Breathe +some confusion. Not sure when this was resolved but it might be best to go for +the latest possible. + +Credits +------- + +Thank you to: + +- `nijel `_ +- `sebastianschaetz `_ +- `mbolivar `_ + +For their contributions; improving the code and the documentation. And thanks to: + +- Dimitri van Heesch for `Doxygen `_. +- Georg Brandl for `Sphinx `_. +- David Goodger for `Docutils `_ and Restructured Text. + diff --git a/libs/network/doc/ext/breathe/breathe/__init__.py b/libs/network/doc/ext/breathe/breathe/__init__.py new file mode 100644 index 000000000..50c645983 --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/__init__.py @@ -0,0 +1,571 @@ + +from docutils import nodes +from docutils.parsers.rst.directives import unchanged_required, unchanged, flag + +import os +import sys +import copy +import fnmatch +import re +import textwrap + +from docutils.parsers import rst +from docutils.statemachine import ViewList +from sphinx.domains.cpp import DefinitionParser + +from breathe.finder import FinderFactory, NoMatchesError, MultipleMatchesError +from breathe.parser import DoxygenParserFactory, DoxygenIndexParser, ParserError +from breathe.renderer.rst.doxygen import DoxygenToRstRendererFactoryCreator, RstContentCreator +from breathe.renderer.rst.doxygen.domain import DomainHandlerFactoryCreator, CppDomainHelper, CDomainHelper +from breathe.renderer.rst.doxygen.filter import FilterFactory, GlobFactory +from breathe.renderer.rst.doxygen.target import TargetHandlerFactory +from breathe.finder.doxygen import DoxygenItemFinderFactoryCreator, ItemMatcherFactory + +import docutils.nodes +import sphinx.addnodes + +# Somewhat outrageously, reach in and fix a Sphinx regex +import sphinx.domains.cpp +sphinx.domains.cpp._identifier_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*)\b') + +class BaseDirective(rst.Directive): + + def __init__( + self, + renderer_factory_creator, + finder_factory, + matcher_factory, + project_info_factory, + member_filter_factory, + target_handler_factory, + *args + ): + rst.Directive.__init__(self, *args) + + self.renderer_factory_creator = renderer_factory_creator + self.finder_factory = finder_factory + self.matcher_factory = matcher_factory + self.project_info_factory = project_info_factory + self.member_filter_factory = member_filter_factory + self.target_handler_factory = target_handler_factory + + +# Directives +# ---------- + +class DoxygenIndexDirective(BaseDirective): + + required_arguments = 0 + optional_arguments = 2 + option_spec = { + "path" : unchanged_required, + "project" : unchanged_required, + } + has_content = False + + def run(self): + + project_info = self.project_info_factory.create_project_info(self.options) + + try: + finder = self.finder_factory.create_finder(project_info) + except ParserError, e: + warning = 'doxygenindex: Unable to parse file "%s"' % e + return [ docutils.nodes.warning( "", docutils.nodes.paragraph("", "", docutils.nodes.Text(warning))), + self.state.document.reporter.warning( warning, line=self.lineno) ] + + data_object = finder.root() + + target_handler = self.target_handler_factory.create(self.options, project_info, self.state.document) + member_filter = self.member_filter_factory.create_open_filter() + + renderer_factory = self.renderer_factory_creator.create_factory(project_info, self.state, self.state.document, member_filter, target_handler) + object_renderer = renderer_factory.create_renderer(data_object) + nodes = object_renderer.render() + + return nodes + + +class DoxygenFunctionDirective(BaseDirective): + + required_arguments = 1 + optional_arguments = 1 + option_spec = { + "path" : unchanged_required, + "project" : unchanged_required, + } + has_content = False + + def run(self): + + try: + (namespace, function_name) = self.arguments[0].rsplit("::", 1) + except ValueError: + (namespace, function_name) = "", self.arguments[0] + + project_info = self.project_info_factory.create_project_info(self.options) + + finder = self.finder_factory.create_finder(project_info) + + matcher_stack = self.matcher_factory.create_matcher_stack( + { + "compound" : self.matcher_factory.create_name_matcher(namespace), + "member" : self.matcher_factory.create_name_type_matcher(function_name, "function") + }, + "member" + ) + + try: + data_object = finder.find_one(matcher_stack) + except NoMatchesError, e: + warning = 'doxygenfunction: Cannot find function "%s%s" in doxygen xml output' % (namespace, function_name) + return [ docutils.nodes.warning( "", docutils.nodes.paragraph("", "", docutils.nodes.Text(warning))), + self.state.document.reporter.warning( warning, line=self.lineno) ] + + target_handler = self.target_handler_factory.create(self.options, project_info, self.state.document) + member_filter = self.member_filter_factory.create_open_filter() + + renderer_factory = self.renderer_factory_creator.create_factory(project_info, self.state, self.state.document, member_filter, target_handler) + object_renderer = renderer_factory.create_renderer(data_object) + nodes = object_renderer.render() + + return nodes + + + +class DoxygenClassDirective(BaseDirective): + + kind = "class" + + required_arguments = 1 + optional_arguments = 1 + option_spec = { + "path" : unchanged_required, + "project" : unchanged_required, + "members" : unchanged, + "no-link" : flag, + } + has_content = False + + + def run(self): + + name = self.arguments[0] + + project_info = self.project_info_factory.create_project_info(self.options) + + finder = self.finder_factory.create_finder(project_info) + + matcher_stack = self.matcher_factory.create_matcher_stack( + { + "compound" : self.matcher_factory.create_name_type_matcher(name, self.kind) + }, + "compound" + ) + + try: + data_object = finder.find_one(matcher_stack) + except NoMatchesError, e: + warning = 'doxygen%s: Cannot find %s "%s" in doxygen xml output' % (self.kind, self.kind, name) + return [ docutils.nodes.warning( "", docutils.nodes.paragraph("", "", docutils.nodes.Text(warning))), + self.state.document.reporter.warning( warning, line=self.lineno) ] + + target_handler = self.target_handler_factory.create(self.options, project_info, self.state.document) + member_filter = self.member_filter_factory.create_filter(self.options) + + renderer_factory = self.renderer_factory_creator.create_factory(project_info, self.state, self.state.document, member_filter, target_handler) + object_renderer = renderer_factory.create_renderer(data_object) + + nodes = object_renderer.render() + + return nodes + + + +class DoxygenBaseDirective(BaseDirective): + + required_arguments = 1 + optional_arguments = 1 + option_spec = { + "path" : unchanged_required, + "project" : unchanged_required, + } + has_content = False + + def run(self): + + name = self.arguments[0] + + project_info = self.project_info_factory.create_project_info(self.options) + + finder = self.finder_factory.create_finder(project_info) + + matcher_stack = self.create_matcher_stack(name) + + try: + data_object = finder.find_one(matcher_stack) + except NoMatchesError, e: + warning = 'doxygen%s: Cannot find %s "%s" in doxygen xml output' % (self.kind, self.kind, name) + return [ docutils.nodes.warning( "", docutils.nodes.paragraph("", "", docutils.nodes.Text(warning))), + self.state.document.reporter.warning( warning, line=self.lineno) ] + + target_handler = self.target_handler_factory.create(self.options, project_info, self.state.document) + member_filter = self.member_filter_factory.create_open_filter() + + renderer_factory = self.renderer_factory_creator.create_factory(project_info, self.state, self.state.document, member_filter, target_handler) + object_renderer = renderer_factory.create_renderer(data_object) + + nodes = object_renderer.render() + + return nodes + + +class DoxygenStructDirective(DoxygenBaseDirective): + + kind = "struct" + + def create_matcher_stack(self, name): + + return self.matcher_factory.create_matcher_stack( + { + "compound" : self.matcher_factory.create_name_type_matcher(name, self.kind) + }, + "compound" + ) + + + +class DoxygenEnumDirective(DoxygenBaseDirective): + + kind = "enum" + + def create_matcher_stack(self, name): + + return self.matcher_factory.create_matcher_stack( + { + "compound" : self.matcher_factory.create_name_matcher(""), + "member" : self.matcher_factory.create_name_type_matcher(name, self.kind) + }, + "member" + ) + +class DoxygenTypedefDirective(DoxygenBaseDirective): + + kind = "typedef" + + def create_matcher_stack(self, name): + + return self.matcher_factory.create_matcher_stack( + { + "compound" : self.matcher_factory.create_name_matcher(""), + "member" : self.matcher_factory.create_name_type_matcher(name, self.kind) + }, + "member" + ) + + + +# Setup Administration +# -------------------- + +class DirectiveContainer(object): + + def __init__( + self, + directive, + *args + ): + + self.directive = directive + self.args = args + + # Required for sphinx to inspect + self.required_arguments = directive.required_arguments + self.optional_arguments = directive.optional_arguments + self.option_spec = directive.option_spec + self.has_content = directive.has_content + + def __call__(self, *args): + + call_args = [] + call_args.extend(self.args) + call_args.extend(args) + + return self.directive(*call_args) + + +class ProjectInfo(object): + + def __init__(self, name, path, reference, domain_by_extension, domain_by_file_pattern, match): + + self._name = name + self._path = path + self._reference = reference + self._domain_by_extension = domain_by_extension + self._domain_by_file_pattern = domain_by_file_pattern + self._match = match + + def name(self): + return self._name + + def path(self): + return self._path + + def reference(self): + return self._reference + + def domain_for_file(self, file_): + + domain = "" + extension = file_.split(".")[-1] + + try: + domain = self._domain_by_extension[extension] + except KeyError: + pass + + for pattern, pattern_domain in self._domain_by_file_pattern.items(): + if self._match(file_, pattern): + domain = pattern_domain + + return domain + + +class ProjectInfoFactory(object): + + def __init__(self, match): + + self.match = match + + self.projects = {} + self.default_project = None + self.domain_by_extension = {} + self.domain_by_file_pattern = {} + + self.project_count = 0 + self.project_info_store = {} + + + def update( + self, + projects, + default_project, + domain_by_extension, + domain_by_file_pattern, + ): + + self.projects = projects + self.default_project = default_project + self.domain_by_extension = domain_by_extension + self.domain_by_file_pattern = domain_by_file_pattern + + def default_path(self): + + return self.projects[self.default_project] + + def create_project_info(self, options): + + name = "" + path = self.default_path() + + if options.has_key("project"): + try: + path = self.projects[ options["project"] ] + name = options["project"] + except KeyError, e: + sys.stderr.write( + "Unable to find project '%s' in breathe_projects dictionary" % options["project"] + ) + + if options.has_key("path"): + path = options["path"] + + + try: + return self.project_info_store[path] + except KeyError: + + reference = name + + if not name: + name = "project%s" % self.project_count + reference = path + self.project_count += 1 + + project_info = ProjectInfo( + name, + path, + reference, + self.domain_by_extension, + self.domain_by_file_pattern, + self.match + ) + + self.project_info_store[path] = project_info + + return project_info + + + +class DoxygenDirectiveFactory(object): + + directives = { + "doxygenindex" : DoxygenIndexDirective, + "doxygenfunction" : DoxygenFunctionDirective, + "doxygenstruct" : DoxygenStructDirective, + "doxygenclass" : DoxygenClassDirective, + "doxygenenum" : DoxygenEnumDirective, + "doxygentypedef" : DoxygenTypedefDirective, + } + + def __init__( + self, + renderer_factory_creator, + finder_factory, + matcher_factory, + project_info_factory, + member_filter_factory, + target_handler_factory + ): + self.renderer_factory_creator = renderer_factory_creator + self.finder_factory = finder_factory + self.matcher_factory = matcher_factory + self.project_info_factory = project_info_factory + self.member_filter_factory = member_filter_factory + self.target_handler_factory = target_handler_factory + + def create_index_directive_container(self): + return self.create_directive_container("doxygenindex") + + def create_function_directive_container(self): + return self.create_directive_container("doxygenfunction") + + def create_struct_directive_container(self): + return self.create_directive_container("doxygenstruct") + + def create_enum_directive_container(self): + return self.create_directive_container("doxygenenum") + + def create_typedef_directive_container(self): + return self.create_directive_container("doxygentypedef") + + def create_class_directive_container(self): + return self.create_directive_container("doxygenclass") + + def create_directive_container(self, type_): + + return DirectiveContainer( + self.directives[type_], + self.renderer_factory_creator, + self.finder_factory, + self.matcher_factory, + self.project_info_factory, + self.member_filter_factory, + self.target_handler_factory + ) + + def get_config_values(self, app): + + # All DirectiveContainers maintain references to this project info factory + # so we can update this to update them + self.project_info_factory.update( + app.config.breathe_projects, + app.config.breathe_default_project, + app.config.breathe_domain_by_extension, + app.config.breathe_domain_by_file_pattern, + ) + +class NodeFactory(object): + + def __init__(self, *args): + + self.sources = args + + def __getattr__(self, node_name): + + for source in self.sources: + try: + return getattr(source, node_name) + except AttributeError: + pass + + raise NodeNotFoundError(node_name) + + +# Setup +# ----- + +def setup(app): + + parser_factory = DoxygenParserFactory() + matcher_factory = ItemMatcherFactory() + item_finder_factory_creator = DoxygenItemFinderFactoryCreator(parser_factory, matcher_factory) + index_parser = DoxygenIndexParser() + finder_factory = FinderFactory(index_parser, item_finder_factory_creator) + + node_factory = NodeFactory(docutils.nodes, sphinx.addnodes) + + cpp_domain_helper = CppDomainHelper(DefinitionParser, re.sub) + c_domain_helper = CDomainHelper() + domain_helpers = {"c" : c_domain_helper, "cpp" : cpp_domain_helper} + domain_handler_factory_creator = DomainHandlerFactoryCreator(node_factory, domain_helpers) + + rst_content_creator = RstContentCreator( ViewList, textwrap.dedent ) + renderer_factory_creator = DoxygenToRstRendererFactoryCreator(node_factory, parser_factory, domain_handler_factory_creator, rst_content_creator) + + project_info_factory = ProjectInfoFactory(fnmatch.fnmatch) + glob_factory = GlobFactory(fnmatch.fnmatch) + member_filter_factory = FilterFactory(glob_factory) + target_handler_factory = TargetHandlerFactory(node_factory) + + directive_factory = DoxygenDirectiveFactory( + renderer_factory_creator, + finder_factory, + matcher_factory, + project_info_factory, + member_filter_factory, + target_handler_factory + ) + + app.add_directive( + "doxygenindex", + directive_factory.create_index_directive_container(), + ) + + app.add_directive( + "doxygenfunction", + directive_factory.create_function_directive_container(), + ) + + app.add_directive( + "doxygenstruct", + directive_factory.create_struct_directive_container(), + ) + + app.add_directive( + "doxygenenum", + directive_factory.create_enum_directive_container(), + ) + + app.add_directive( + "doxygentypedef", + directive_factory.create_typedef_directive_container(), + ) + + app.add_directive( + "doxygenclass", + directive_factory.create_class_directive_container(), + ) + + app.add_config_value("breathe_projects", {}, True) + app.add_config_value("breathe_default_project", "", True) + app.add_config_value("breathe_domain_by_extension", {}, True) + app.add_config_value("breathe_domain_by_file_pattern", {}, True) + + app.add_stylesheet("breathe.css") + + app.connect("builder-inited", directive_factory.get_config_values) + + + + diff --git a/libs/network/doc/ext/breathe/breathe/finder/__init__.py b/libs/network/doc/ext/breathe/breathe/finder/__init__.py new file mode 100644 index 000000000..1c8ff5744 --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/finder/__init__.py @@ -0,0 +1,61 @@ + +class FinderError(Exception): + pass + +class MultipleMatchesError(FinderError): + pass + +class NoMatchesError(FinderError): + pass + +class Finder(object): + + def __init__(self, root, item_finder_factory): + + self._root = root + self.item_finder_factory = item_finder_factory + + def find(self, matcher_stack): + + item_finder = self.item_finder_factory.create_finder(self._root) + + return item_finder.find(matcher_stack) + + + def find_one(self, matcher_stack): + + results = self.find(matcher_stack) + + count = len(results) + if count == 1: + return results[0] + elif count > 1: + # Multiple matches can easily happen as same thing + # can be present in both file and group sections + return results[0] + elif count < 1: + raise NoMatchesError(matcher_stack) + + + def root(self): + + return self._root + + +class FinderFactory(object): + + def __init__(self, parser, item_finder_factory_creator): + + self.parser = parser + self.item_finder_factory_creator = item_finder_factory_creator + + + def create_finder(self, project_info): + + root = self.parser.parse(project_info) + item_finder_factory = self.item_finder_factory_creator.create_factory(project_info) + + return Finder(root, item_finder_factory) + + + diff --git a/libs/network/doc/ext/breathe/breathe/finder/doxygen/__init__.py b/libs/network/doc/ext/breathe/breathe/finder/doxygen/__init__.py new file mode 100644 index 000000000..e2371383f --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/finder/doxygen/__init__.py @@ -0,0 +1,147 @@ + +from breathe.finder.doxygen import index as indexfinder +from breathe.finder.doxygen import compound as compoundfinder + +from breathe.parser.doxygen import index, compound + +class MissingLevelError(Exception): + pass + +class Matcher(object): + pass + +class ItemMatcher(Matcher): + + def __init__(self, name, type_): + self.name = name + self.type_ = type_ + + def match(self, data_object): + return self.name == data_object.name and self.type_ == data_object.kind + + def __repr__(self): + return "" % (self.name, self.type_) + +class NameMatcher(Matcher): + + def __init__(self, name): + self.name = name + + def match(self, data_object): + return self.name == data_object.name + + +class RefMatcher(Matcher): + + def __init__(self, refid): + + self.refid = refid + + def match(self, data_object): + return self.refid == data_object.refid + +class AnyMatcher(Matcher): + + def match(self, data_object): + return True + + +class MatcherStack(object): + + def __init__(self, matchers, lowest_level): + + self.matchers = matchers + self.lowest_level = lowest_level + + def match(self, level, data_object): + + try: + return self.matchers[level].match(data_object) + except KeyError: + return False + + def full_match(self, level, data_object): + + try: + return self.matchers[level].match(data_object) and level == self.lowest_level + except KeyError: + raise MissingLevelError(level) + + +class ItemMatcherFactory(Matcher): + + def create_name_type_matcher(self, name, type_): + + return ItemMatcher(name, type_) + + def create_name_matcher(self, name): + + return NameMatcher(name) if name else AnyMatcher() + + def create_ref_matcher(self, ref): + + return RefMatcher(ref) + + def create_matcher_stack(self, matchers, lowest_level): + + return MatcherStack(matchers, lowest_level) + + def create_ref_matcher_stack(self, class_, ref): + + matchers = { + "compound" : ItemMatcher(class_, "class") if class_ else AnyMatcher(), + "member" : RefMatcher(ref), + } + + return MatcherStack(matchers, "member") + + +class CreateCompoundTypeSubFinder(object): + + def __init__(self, parser_factory, matcher_factory): + + self.parser_factory = parser_factory + self.matcher_factory = matcher_factory + + def __call__(self, project_info, *args): + + compound_parser = self.parser_factory.create_compound_parser(project_info) + return indexfinder.CompoundTypeSubItemFinder(self.matcher_factory, compound_parser, project_info, *args) + + + +class DoxygenItemFinderFactory(object): + + def __init__(self, finders, project_info): + + self.finders = finders + self.project_info = project_info + + def create_finder(self, data_object): + + return self.finders[data_object.__class__](self.project_info, data_object, self) + + +class DoxygenItemFinderFactoryCreator(object): + + def __init__(self, parser_factory, matcher_factory): + + self.parser_factory = parser_factory + self.matcher_factory = matcher_factory + + def create_factory(self, project_info): + + finders = { + index.DoxygenTypeSub : indexfinder.DoxygenTypeSubItemFinder, + index.CompoundTypeSub : CreateCompoundTypeSubFinder(self.parser_factory, self.matcher_factory), + index.MemberTypeSub : indexfinder.MemberTypeSubItemFinder, + compound.DoxygenTypeSub : compoundfinder.DoxygenTypeSubItemFinder, + compound.compounddefTypeSub : compoundfinder.CompoundDefTypeSubItemFinder, + compound.sectiondefTypeSub : compoundfinder.SectionDefTypeSubItemFinder, + compound.memberdefTypeSub : compoundfinder.MemberDefTypeSubItemFinder, + } + + return DoxygenItemFinderFactory(finders, project_info) + + + diff --git a/libs/network/doc/ext/breathe/breathe/finder/doxygen/base.py b/libs/network/doc/ext/breathe/breathe/finder/doxygen/base.py new file mode 100644 index 000000000..7678f789b --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/finder/doxygen/base.py @@ -0,0 +1,10 @@ + +class ItemFinder(object): + + def __init__(self, project_info, data_object, item_finder_factory): + + self.data_object = data_object + self.item_finder_factory = item_finder_factory + self.project_info = project_info + + diff --git a/libs/network/doc/ext/breathe/breathe/finder/doxygen/compound.py b/libs/network/doc/ext/breathe/breathe/finder/doxygen/compound.py new file mode 100644 index 000000000..5387da472 --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/finder/doxygen/compound.py @@ -0,0 +1,42 @@ + +from breathe.finder.doxygen.base import ItemFinder + +class DoxygenTypeSubItemFinder(ItemFinder): + + def find(self, matcher_stack): + + compound_finder = self.item_finder_factory.create_finder(self.data_object.compounddef) + return compound_finder.find(matcher_stack) + +class CompoundDefTypeSubItemFinder(ItemFinder): + + def find(self, matcher_stack): + + results = [] + for sectiondef in self.data_object.sectiondef: + finder = self.item_finder_factory.create_finder(sectiondef) + results.extend(finder.find(matcher_stack)) + + return results + + +class SectionDefTypeSubItemFinder(ItemFinder): + + def find(self, matcher_stack): + + results = [] + for memberdef in self.data_object.memberdef: + finder = self.item_finder_factory.create_finder(memberdef) + results.extend(finder.find(matcher_stack)) + + return results + +class MemberDefTypeSubItemFinder(ItemFinder): + + def find(self, matcher_stack): + + if matcher_stack.match("member", self.data_object): + return [self.data_object] + else: + return [] + diff --git a/libs/network/doc/ext/breathe/breathe/finder/doxygen/index.py b/libs/network/doc/ext/breathe/breathe/finder/doxygen/index.py new file mode 100644 index 000000000..5b4d4e067 --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/finder/doxygen/index.py @@ -0,0 +1,67 @@ + +from breathe.finder.doxygen.base import ItemFinder + +class DoxygenTypeSubItemFinder(ItemFinder): + + def find(self, matcher_stack): + + compounds = self.data_object.get_compound() + + results = [] + + for compound in compounds: + + if matcher_stack.match("compound", compound): + compound_finder = self.item_finder_factory.create_finder(compound) + results.extend(compound_finder.find(matcher_stack)) + + return results + +class CompoundTypeSubItemFinder(ItemFinder): + + def __init__(self, matcher_factory, compound_parser, *args): + ItemFinder.__init__(self, *args) + + self.matcher_factory = matcher_factory + self.compound_parser = compound_parser + + def find(self, matcher_stack): + + members = self.data_object.get_member() + + member_results = [] + + for member in members: + if matcher_stack.match("member", member): + member_finder = self.item_finder_factory.create_finder(member) + member_results.extend(member_finder.find(matcher_stack)) + + results = [] + + # If there are members in this compound that match the criteria + # then load up the file for this compound and get the member data objects + if member_results: + + file_data = self.compound_parser.parse(self.data_object.refid) + finder = self.item_finder_factory.create_finder(file_data) + + for member_data in member_results: + ref_matcher_stack = self.matcher_factory.create_ref_matcher_stack("", member_data.refid) + # TODO: Fix this! Should be ref_matcher_stack! + results.extend(finder.find(matcher_stack)) + + elif matcher_stack.full_match("compound", self.data_object): + results.append(self.data_object) + + return results + +class MemberTypeSubItemFinder(ItemFinder): + + def find(self, matcher_stack): + + if matcher_stack.full_match("member", self.data_object): + return [self.data_object] + else: + return [] + + diff --git a/libs/network/doc/ext/breathe/breathe/parser/__init__.py b/libs/network/doc/ext/breathe/breathe/parser/__init__.py new file mode 100644 index 000000000..7f14ca991 --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/parser/__init__.py @@ -0,0 +1,51 @@ + +import breathe.parser.doxygen.index +import breathe.parser.doxygen.compound +import os + +class ParserError(Exception): + pass + +class Parser(object): + + pass + + +class DoxygenIndexParser(Parser): + + def parse(self, project_info): + + filename = os.path.join(project_info.path(), "index.xml") + try: + return breathe.parser.doxygen.index.parse(filename) + except breathe.parser.doxygen.index.ParseError: + raise ParserError(filename) + + +class DoxygenCompoundParser(Parser): + + def __init__(self, project_info): + + self.project_info = project_info + + def parse(self, refid): + + filename = os.path.join(self.project_info.path(), "%s.xml" % refid) + + try: + return breathe.parser.doxygen.compound.parse(filename) + except breathe.parser.doxygen.compound.ParseError: + raise ParserError(filename) + +class DoxygenParserFactory(object): + + def __init__(self): + + pass + + def create_compound_parser(self, project_info): + + return DoxygenCompoundParser(project_info) + + + diff --git a/libs/network/doc/ext/breathe/breathe/parser/doxygen/__init__.py b/libs/network/doc/ext/breathe/breathe/parser/doxygen/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/libs/network/doc/ext/breathe/breathe/parser/doxygen/compound.py b/libs/network/doc/ext/breathe/breathe/parser/doxygen/compound.py new file mode 100644 index 000000000..290f67997 --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/parser/doxygen/compound.py @@ -0,0 +1,660 @@ +#!/usr/bin/env python + +""" +Generated Mon Feb 9 19:08:05 2009 by generateDS.py. +""" + +from string import lower as str_lower +from xml.dom import minidom +from xml.dom import Node +from docutils import nodes + + +import sys + +import compoundsuper as supermod +from compoundsuper import MixedContainer + + +class DoxygenTypeSub(supermod.DoxygenType): + def __init__(self, version=None, compounddef=None): + supermod.DoxygenType.__init__(self, version, compounddef) +supermod.DoxygenType.subclass = DoxygenTypeSub +# end class DoxygenTypeSub + + +class compounddefTypeSub(supermod.compounddefType): + def __init__(self, kind=None, prot=None, id=None, compoundname='', title='', basecompoundref=None, derivedcompoundref=None, includes=None, includedby=None, incdepgraph=None, invincdepgraph=None, innerdir=None, innerfile=None, innerclass=None, innernamespace=None, innerpage=None, innergroup=None, templateparamlist=None, sectiondef=None, briefdescription=None, detaileddescription=None, inheritancegraph=None, collaborationgraph=None, programlisting=None, location=None, listofallmembers=None): + supermod.compounddefType.__init__(self, kind, prot, id, compoundname, title, basecompoundref, derivedcompoundref, includes, includedby, incdepgraph, invincdepgraph, innerdir, innerfile, innerclass, innernamespace, innerpage, innergroup, templateparamlist, sectiondef, briefdescription, detaileddescription, inheritancegraph, collaborationgraph, programlisting, location, listofallmembers) +supermod.compounddefType.subclass = compounddefTypeSub +# end class compounddefTypeSub + + +class listofallmembersTypeSub(supermod.listofallmembersType): + def __init__(self, member=None): + supermod.listofallmembersType.__init__(self, member) +supermod.listofallmembersType.subclass = listofallmembersTypeSub +# end class listofallmembersTypeSub + + +class memberRefTypeSub(supermod.memberRefType): + def __init__(self, virt=None, prot=None, refid=None, ambiguityscope=None, scope='', name=''): + supermod.memberRefType.__init__(self, virt, prot, refid, ambiguityscope, scope, name) +supermod.memberRefType.subclass = memberRefTypeSub +# end class memberRefTypeSub + + +class compoundRefTypeSub(supermod.compoundRefType): + def __init__(self, virt=None, prot=None, refid=None, valueOf_='', mixedclass_=None, content_=None): + supermod.compoundRefType.__init__(self, mixedclass_, content_) +supermod.compoundRefType.subclass = compoundRefTypeSub +# end class compoundRefTypeSub + + +class reimplementTypeSub(supermod.reimplementType): + def __init__(self, refid=None, valueOf_='', mixedclass_=None, content_=None): + supermod.reimplementType.__init__(self, mixedclass_, content_) +supermod.reimplementType.subclass = reimplementTypeSub +# end class reimplementTypeSub + + +class incTypeSub(supermod.incType): + def __init__(self, local=None, refid=None, valueOf_='', mixedclass_=None, content_=None): + supermod.incType.__init__(self, mixedclass_, content_) +supermod.incType.subclass = incTypeSub +# end class incTypeSub + + +class refTypeSub(supermod.refType): + def __init__(self, prot=None, refid=None, valueOf_='', mixedclass_=None, content_=None): + supermod.refType.__init__(self, mixedclass_, content_) +supermod.refType.subclass = refTypeSub +# end class refTypeSub + + + +class refTextTypeSub(supermod.refTextType): + def __init__(self, refid=None, kindref=None, external=None, valueOf_='', mixedclass_=None, content_=None): + supermod.refTextType.__init__(self, mixedclass_, content_) + +supermod.refTextType.subclass = refTextTypeSub +# end class refTextTypeSub + +class sectiondefTypeSub(supermod.sectiondefType): + def __init__(self, kind=None, header='', description=None, memberdef=None): + supermod.sectiondefType.__init__(self, kind, header, description, memberdef) +supermod.sectiondefType.subclass = sectiondefTypeSub +# end class sectiondefTypeSub + + +class memberdefTypeSub(supermod.memberdefType): + def __init__(self, initonly=None, kind=None, volatile=None, const=None, raise_=None, virt=None, readable=None, prot=None, explicit=None, new=None, final=None, writable=None, add=None, static=None, remove=None, sealed=None, mutable=None, gettable=None, inline=None, settable=None, id=None, templateparamlist=None, type_=None, definition='', argsstring='', name='', read='', write='', bitfield='', reimplements=None, reimplementedby=None, param=None, enumvalue=None, initializer=None, exceptions=None, briefdescription=None, detaileddescription=None, inbodydescription=None, location=None, references=None, referencedby=None): + supermod.memberdefType.__init__(self, initonly, kind, volatile, const, raise_, virt, readable, prot, explicit, new, final, writable, add, static, remove, sealed, mutable, gettable, inline, settable, id, templateparamlist, type_, definition, argsstring, name, read, write, bitfield, reimplements, reimplementedby, param, enumvalue, initializer, exceptions, briefdescription, detaileddescription, inbodydescription, location, references, referencedby) + + self.parameterlist = supermod.docParamListType.factory() + self.parameterlist.kind = "param" + + + def buildChildren(self, child_, nodeName_): + supermod.memberdefType.buildChildren(self, child_, nodeName_) + + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'param': + + # Get latest param + param = self.param[-1] + + # If it doesn't have a description we're done + if not param.briefdescription: + return + + # Construct our own param list from the descriptions stored inline + # with the parameters + paramdescription = param.briefdescription + paramname = supermod.docParamName.factory() + + # Add parameter name + obj_ = paramname.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', param.declname) + paramname.content_.append(obj_) + + paramnamelist = supermod.docParamNameList.factory() + paramnamelist.parametername.append(paramname) + + paramlistitem = supermod.docParamListItem.factory() + paramlistitem.parameternamelist.append(paramnamelist) + + # Add parameter description + paramlistitem.parameterdescription = paramdescription + + self.parameterlist.parameteritem.append(paramlistitem) + + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'detaileddescription': + + if not self.parameterlist.parameteritem: + # No items in our list + return + + + # Assume supermod.memberdefType.buildChildren has already built the + # description object, we just want to slot our parameterlist in at + # a reasonable point + + if not self.detaileddescription: + # Create one if it doesn't exist + self.detaileddescription = supermod.descriptionType.factory() + + detaileddescription = self.detaileddescription + + para = supermod.docParaType.factory() + para.parameterlist.append(self.parameterlist) + + obj_ = detaileddescription.mixedclass_(MixedContainer.CategoryComplex, MixedContainer.TypeNone, 'para', para) + + index = 0 + detaileddescription.content_.insert( index, obj_ ) + + + +supermod.memberdefType.subclass = memberdefTypeSub +# end class memberdefTypeSub + +class descriptionTypeSub(supermod.descriptionType): + def __init__(self, title='', para=None, sect1=None, internal=None, mixedclass_=None, content_=None): + supermod.descriptionType.__init__(self, mixedclass_, content_) +supermod.descriptionType.subclass = descriptionTypeSub +# end class descriptionTypeSub + + +class enumvalueTypeSub(supermod.enumvalueType): + def __init__(self, prot=None, id=None, name='', initializer=None, briefdescription=None, detaileddescription=None, mixedclass_=None, content_=None): + supermod.enumvalueType.__init__(self, mixedclass_, content_) + + self.initializer = None + + def buildChildren(self, child_, nodeName_): + # Get text from child and put it in self.name + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'name': + value_ = [] + for text_ in child_.childNodes: + value_.append(text_.nodeValue) + valuestr_ = ''.join(value_) + self.name = valuestr_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'briefdescription': + obj_ = supermod.descriptionType.factory() + obj_.build(child_) + self.set_briefdescription(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'detaileddescription': + obj_ = supermod.descriptionType.factory() + obj_.build(child_) + self.set_detaileddescription(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'initializer': + childobj_ = supermod.linkedTextType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'initializer', childobj_) + self.set_initializer(obj_) + self.content_.append(obj_) + +supermod.enumvalueType.subclass = enumvalueTypeSub +# end class enumvalueTypeSub + + +class templateparamlistTypeSub(supermod.templateparamlistType): + def __init__(self, param=None): + supermod.templateparamlistType.__init__(self, param) +supermod.templateparamlistType.subclass = templateparamlistTypeSub +# end class templateparamlistTypeSub + + +class paramTypeSub(supermod.paramType): + def __init__(self, type_=None, declname='', defname='', array='', defval=None, briefdescription=None): + supermod.paramType.__init__(self, type_, declname, defname, array, defval, briefdescription) +supermod.paramType.subclass = paramTypeSub +# end class paramTypeSub + + +class linkedTextTypeSub(supermod.linkedTextType): + def __init__(self, ref=None, mixedclass_=None, content_=None): + supermod.linkedTextType.__init__(self, mixedclass_, content_) +supermod.linkedTextType.subclass = linkedTextTypeSub +# end class linkedTextTypeSub + + +class graphTypeSub(supermod.graphType): + def __init__(self, node=None): + supermod.graphType.__init__(self, node) +supermod.graphType.subclass = graphTypeSub +# end class graphTypeSub + + +class nodeTypeSub(supermod.nodeType): + def __init__(self, id=None, label='', link=None, childnode=None): + supermod.nodeType.__init__(self, id, label, link, childnode) +supermod.nodeType.subclass = nodeTypeSub +# end class nodeTypeSub + + +class childnodeTypeSub(supermod.childnodeType): + def __init__(self, relation=None, refid=None, edgelabel=None): + supermod.childnodeType.__init__(self, relation, refid, edgelabel) +supermod.childnodeType.subclass = childnodeTypeSub +# end class childnodeTypeSub + + +class linkTypeSub(supermod.linkType): + def __init__(self, refid=None, external=None, valueOf_=''): + supermod.linkType.__init__(self, refid, external) +supermod.linkType.subclass = linkTypeSub +# end class linkTypeSub + + +class listingTypeSub(supermod.listingType): + def __init__(self, codeline=None): + supermod.listingType.__init__(self, codeline) +supermod.listingType.subclass = listingTypeSub +# end class listingTypeSub + + +class codelineTypeSub(supermod.codelineType): + def __init__(self, external=None, lineno=None, refkind=None, refid=None, highlight=None): + supermod.codelineType.__init__(self, external, lineno, refkind, refid, highlight) +supermod.codelineType.subclass = codelineTypeSub +# end class codelineTypeSub + + +class highlightTypeSub(supermod.highlightType): + def __init__(self, class_=None, sp=None, ref=None, mixedclass_=None, content_=None): + supermod.highlightType.__init__(self, mixedclass_, content_) +supermod.highlightType.subclass = highlightTypeSub +# end class highlightTypeSub + + +class referenceTypeSub(supermod.referenceType): + def __init__(self, endline=None, startline=None, refid=None, compoundref=None, valueOf_='', mixedclass_=None, content_=None): + supermod.referenceType.__init__(self, mixedclass_, content_) +supermod.referenceType.subclass = referenceTypeSub +# end class referenceTypeSub + + +class locationTypeSub(supermod.locationType): + def __init__(self, bodystart=None, line=None, bodyend=None, bodyfile=None, file=None, valueOf_=''): + supermod.locationType.__init__(self, bodystart, line, bodyend, bodyfile, file) +supermod.locationType.subclass = locationTypeSub +# end class locationTypeSub + + +class docSect1TypeSub(supermod.docSect1Type): + def __init__(self, id=None, title='', para=None, sect2=None, internal=None, mixedclass_=None, content_=None): + supermod.docSect1Type.__init__(self, mixedclass_, content_) +supermod.docSect1Type.subclass = docSect1TypeSub +# end class docSect1TypeSub + + +class docSect2TypeSub(supermod.docSect2Type): + def __init__(self, id=None, title='', para=None, sect3=None, internal=None, mixedclass_=None, content_=None): + supermod.docSect2Type.__init__(self, mixedclass_, content_) +supermod.docSect2Type.subclass = docSect2TypeSub +# end class docSect2TypeSub + + +class docSect3TypeSub(supermod.docSect3Type): + def __init__(self, id=None, title='', para=None, sect4=None, internal=None, mixedclass_=None, content_=None): + supermod.docSect3Type.__init__(self, mixedclass_, content_) +supermod.docSect3Type.subclass = docSect3TypeSub +# end class docSect3TypeSub + + +class docSect4TypeSub(supermod.docSect4Type): + def __init__(self, id=None, title='', para=None, internal=None, mixedclass_=None, content_=None): + supermod.docSect4Type.__init__(self, mixedclass_, content_) +supermod.docSect4Type.subclass = docSect4TypeSub +# end class docSect4TypeSub + + +class docInternalTypeSub(supermod.docInternalType): + def __init__(self, para=None, sect1=None, mixedclass_=None, content_=None): + supermod.docInternalType.__init__(self, mixedclass_, content_) +supermod.docInternalType.subclass = docInternalTypeSub +# end class docInternalTypeSub + + +class docInternalS1TypeSub(supermod.docInternalS1Type): + def __init__(self, para=None, sect2=None, mixedclass_=None, content_=None): + supermod.docInternalS1Type.__init__(self, mixedclass_, content_) +supermod.docInternalS1Type.subclass = docInternalS1TypeSub +# end class docInternalS1TypeSub + + +class docInternalS2TypeSub(supermod.docInternalS2Type): + def __init__(self, para=None, sect3=None, mixedclass_=None, content_=None): + supermod.docInternalS2Type.__init__(self, mixedclass_, content_) +supermod.docInternalS2Type.subclass = docInternalS2TypeSub +# end class docInternalS2TypeSub + + +class docInternalS3TypeSub(supermod.docInternalS3Type): + def __init__(self, para=None, sect3=None, mixedclass_=None, content_=None): + supermod.docInternalS3Type.__init__(self, mixedclass_, content_) +supermod.docInternalS3Type.subclass = docInternalS3TypeSub +# end class docInternalS3TypeSub + + +class docInternalS4TypeSub(supermod.docInternalS4Type): + def __init__(self, para=None, mixedclass_=None, content_=None): + supermod.docInternalS4Type.__init__(self, mixedclass_, content_) +supermod.docInternalS4Type.subclass = docInternalS4TypeSub +# end class docInternalS4TypeSub + + +class docURLLinkSub(supermod.docURLLink): + def __init__(self, url=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docURLLink.__init__(self, mixedclass_, content_) +supermod.docURLLink.subclass = docURLLinkSub +# end class docURLLinkSub + + +class docAnchorTypeSub(supermod.docAnchorType): + def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docAnchorType.__init__(self, mixedclass_, content_) +supermod.docAnchorType.subclass = docAnchorTypeSub +# end class docAnchorTypeSub + + +class docFormulaTypeSub(supermod.docFormulaType): + def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docFormulaType.__init__(self, mixedclass_, content_) +supermod.docFormulaType.subclass = docFormulaTypeSub +# end class docFormulaTypeSub + + +class docIndexEntryTypeSub(supermod.docIndexEntryType): + def __init__(self, primaryie='', secondaryie=''): + supermod.docIndexEntryType.__init__(self, primaryie, secondaryie) +supermod.docIndexEntryType.subclass = docIndexEntryTypeSub +# end class docIndexEntryTypeSub + + +class docListTypeSub(supermod.docListType): + def __init__(self, listitem=None): + supermod.docListType.__init__(self, listitem) +supermod.docListType.subclass = docListTypeSub +# end class docListTypeSub + + +class docListItemTypeSub(supermod.docListItemType): + def __init__(self, para=None): + supermod.docListItemType.__init__(self, para) +supermod.docListItemType.subclass = docListItemTypeSub +# end class docListItemTypeSub + + +class docSimpleSectTypeSub(supermod.docSimpleSectType): + def __init__(self, kind=None, title=None, para=None): + supermod.docSimpleSectType.__init__(self, kind, title, para) +supermod.docSimpleSectType.subclass = docSimpleSectTypeSub +# end class docSimpleSectTypeSub + + +class docVarListEntryTypeSub(supermod.docVarListEntryType): + def __init__(self, term=None): + supermod.docVarListEntryType.__init__(self, term) +supermod.docVarListEntryType.subclass = docVarListEntryTypeSub +# end class docVarListEntryTypeSub + + +class docRefTextTypeSub(supermod.docRefTextType): + def __init__(self, refid=None, kindref=None, external=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docRefTextType.__init__(self, mixedclass_, content_) + + self.para = [] + + def buildChildren(self, child_, nodeName_): + supermod.docRefTextType.buildChildren(self, child_, nodeName_) + + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + obj_ = supermod.docParaType.factory() + obj_.build(child_) + self.para.append(obj_) + +supermod.docRefTextType.subclass = docRefTextTypeSub +# end class docRefTextTypeSub + + +class docTableTypeSub(supermod.docTableType): + def __init__(self, rows=None, cols=None, row=None, caption=None): + supermod.docTableType.__init__(self, rows, cols, row, caption) +supermod.docTableType.subclass = docTableTypeSub +# end class docTableTypeSub + + +class docRowTypeSub(supermod.docRowType): + def __init__(self, entry=None): + supermod.docRowType.__init__(self, entry) +supermod.docRowType.subclass = docRowTypeSub +# end class docRowTypeSub + + +class docEntryTypeSub(supermod.docEntryType): + def __init__(self, thead=None, para=None): + supermod.docEntryType.__init__(self, thead, para) +supermod.docEntryType.subclass = docEntryTypeSub +# end class docEntryTypeSub + + +class docHeadingTypeSub(supermod.docHeadingType): + def __init__(self, level=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docHeadingType.__init__(self, mixedclass_, content_) +supermod.docHeadingType.subclass = docHeadingTypeSub +# end class docHeadingTypeSub + + +class docImageTypeSub(supermod.docImageType): + def __init__(self, width=None, type_=None, name=None, height=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docImageType.__init__(self, mixedclass_, content_) +supermod.docImageType.subclass = docImageTypeSub +# end class docImageTypeSub + + +class docDotFileTypeSub(supermod.docDotFileType): + def __init__(self, name=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docDotFileType.__init__(self, mixedclass_, content_) +supermod.docDotFileType.subclass = docDotFileTypeSub +# end class docDotFileTypeSub + + +class docTocItemTypeSub(supermod.docTocItemType): + def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): + supermod.docTocItemType.__init__(self, mixedclass_, content_) +supermod.docTocItemType.subclass = docTocItemTypeSub +# end class docTocItemTypeSub + + +class docTocListTypeSub(supermod.docTocListType): + def __init__(self, tocitem=None): + supermod.docTocListType.__init__(self, tocitem) +supermod.docTocListType.subclass = docTocListTypeSub +# end class docTocListTypeSub + + +class docLanguageTypeSub(supermod.docLanguageType): + def __init__(self, langid=None, para=None): + supermod.docLanguageType.__init__(self, langid, para) +supermod.docLanguageType.subclass = docLanguageTypeSub +# end class docLanguageTypeSub + + +class docParamListTypeSub(supermod.docParamListType): + def __init__(self, kind=None, parameteritem=None): + supermod.docParamListType.__init__(self, kind, parameteritem) +supermod.docParamListType.subclass = docParamListTypeSub +# end class docParamListTypeSub + + +class docParamListItemSub(supermod.docParamListItem): + def __init__(self, parameternamelist=None, parameterdescription=None): + supermod.docParamListItem.__init__(self, parameternamelist, parameterdescription) +supermod.docParamListItem.subclass = docParamListItemSub +# end class docParamListItemSub + + +class docParamNameListSub(supermod.docParamNameList): + def __init__(self, parametername=None): + supermod.docParamNameList.__init__(self, parametername) +supermod.docParamNameList.subclass = docParamNameListSub +# end class docParamNameListSub + + +class docParamNameSub(supermod.docParamName): + def __init__(self, direction=None, ref=None, mixedclass_=None, content_=None): + supermod.docParamName.__init__(self, mixedclass_, content_) +supermod.docParamName.subclass = docParamNameSub +# end class docParamNameSub + + +class docXRefSectTypeSub(supermod.docXRefSectType): + def __init__(self, id=None, xreftitle=None, xrefdescription=None): + supermod.docXRefSectType.__init__(self, id, xreftitle, xrefdescription) +supermod.docXRefSectType.subclass = docXRefSectTypeSub +# end class docXRefSectTypeSub + + +class docCopyTypeSub(supermod.docCopyType): + def __init__(self, link=None, para=None, sect1=None, internal=None): + supermod.docCopyType.__init__(self, link, para, sect1, internal) +supermod.docCopyType.subclass = docCopyTypeSub +# end class docCopyTypeSub + + +class docCharTypeSub(supermod.docCharType): + def __init__(self, char=None, valueOf_=''): + supermod.docCharType.__init__(self, char) +supermod.docCharType.subclass = docCharTypeSub +# end class docCharTypeSub + + +class verbatimTypeSub(object): + """ + New node type. Structure is largely pillaged from other nodes in order to + match the set. + """ + + def __init__(self, valueOf_='', mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + self.text = "" + def factory(*args, **kwargs): + return verbatimTypeSub(*args, **kwargs) + factory = staticmethod(factory) + def buildAttributes(self, attrs): + pass + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.text += child_.nodeValue + +class docParaTypeSub(supermod.docParaType): + def __init__(self, char=None, valueOf_=''): + supermod.docParaType.__init__(self, char) + + self.parameterlist = [] + self.simplesects = [] + self.content = [] + + def buildChildren(self, child_, nodeName_): + supermod.docParaType.buildChildren(self, child_, nodeName_) + + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == "ref": + obj_ = supermod.docRefTextType.factory() + obj_.build(child_) + self.content.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'parameterlist': + obj_ = supermod.docParamListType.factory() + obj_.build(child_) + self.parameterlist.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'simplesect': + obj_ = supermod.docSimpleSectType.factory() + obj_.build(child_) + self.simplesects.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and ( + nodeName_ == 'bold' or + nodeName_ == 'emphasis' or + nodeName_ == 'computeroutput' or + nodeName_ == 'subscript' or + nodeName_ == 'superscript' or + nodeName_ == 'center' or + nodeName_ == 'small'): + obj_ = supermod.docMarkupType.factory() + obj_.build(child_) + obj_.type_ = nodeName_ + self.content.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'verbatim': + childobj_ = verbatimTypeSub.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'verbatim', childobj_) + self.content.append(obj_) + +supermod.docParaType.subclass = docParaTypeSub +# end class docParaTypeSub + + +class docMarkupTypeSub(supermod.docMarkupType): + def __init__(self, valueOf_='', mixedclass_=None, content_=None): + supermod.docMarkupType.__init__(self, valueOf_, mixedclass_, content_) + self.type_ = None +supermod.docMarkupType.subclass = docMarkupTypeSub +# end class docMarkupTypeSub + + +class docTitleTypeSub(supermod.docTitleType): + def __init__(self, valueOf_='', mixedclass_=None, content_=None): + supermod.docTitleType.__init__(self, valueOf_, mixedclass_, content_) + self.type_ = None +supermod.docTitleType.subclass = docTitleTypeSub +# end class docTitleTypeSub + + +class ParseError(Exception): + pass + +def parse(inFilename): + + try: + doc = minidom.parse(inFilename) + except IOError, e: + print e + raise ParseError(inFilename) + + rootNode = doc.documentElement + rootObj = supermod.DoxygenType.factory() + rootObj.build(rootNode) + return rootObj + + diff --git a/libs/network/doc/ext/breathe/breathe/parser/doxygen/compoundsuper.py b/libs/network/doc/ext/breathe/breathe/parser/doxygen/compoundsuper.py new file mode 100644 index 000000000..6255dda16 --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/parser/doxygen/compoundsuper.py @@ -0,0 +1,8342 @@ +#!/usr/bin/env python + +# +# Generated Thu Jun 11 18:44:25 2009 by generateDS.py. +# + +import sys +import getopt +from string import lower as str_lower +from xml.dom import minidom +from xml.dom import Node + +# +# User methods +# +# Calls to the methods in these classes are generated by generateDS.py. +# You can replace these methods by re-implementing the following class +# in a module named generatedssuper.py. + +try: + from generatedssuper import GeneratedsSuper +except ImportError, exp: + + class GeneratedsSuper: + def format_string(self, input_data, input_name=''): + return input_data + def format_integer(self, input_data, input_name=''): + return '%d' % input_data + def format_float(self, input_data, input_name=''): + return '%f' % input_data + def format_double(self, input_data, input_name=''): + return '%e' % input_data + def format_boolean(self, input_data, input_name=''): + return '%s' % input_data + + +# +# If you have installed IPython you can uncomment and use the following. +# IPython is available from http://ipython.scipy.org/. +# + +## from IPython.Shell import IPShellEmbed +## args = '' +## ipshell = IPShellEmbed(args, +## banner = 'Dropping into IPython', +## exit_msg = 'Leaving Interpreter, back to program.') + +# Then use the following line where and when you want to drop into the +# IPython shell: +# ipshell(' -- Entering ipshell.\nHit Ctrl-D to exit') + +# +# Globals +# + +ExternalEncoding = 'ascii' + +# +# Support/utility functions. +# + +def showIndent(outfile, level): + for idx in range(level): + outfile.write(' ') + +def quote_xml(inStr): + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s1 = s1.replace('&', '&') + s1 = s1.replace('<', '<') + s1 = s1.replace('>', '>') + return s1 + +def quote_attrib(inStr): + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s1 = s1.replace('&', '&') + s1 = s1.replace('<', '<') + s1 = s1.replace('>', '>') + if '"' in s1: + if "'" in s1: + s1 = '"%s"' % s1.replace('"', """) + else: + s1 = "'%s'" % s1 + else: + s1 = '"%s"' % s1 + return s1 + +def quote_python(inStr): + s1 = inStr + if s1.find("'") == -1: + if s1.find('\n') == -1: + return "'%s'" % s1 + else: + return "'''%s'''" % s1 + else: + if s1.find('"') != -1: + s1 = s1.replace('"', '\\"') + if s1.find('\n') == -1: + return '"%s"' % s1 + else: + return '"""%s"""' % s1 + + +class MixedContainer: + # Constants for category: + CategoryNone = 0 + CategoryText = 1 + CategorySimple = 2 + CategoryComplex = 3 + # Constants for content_type: + TypeNone = 0 + TypeText = 1 + TypeString = 2 + TypeInteger = 3 + TypeFloat = 4 + TypeDecimal = 5 + TypeDouble = 6 + TypeBoolean = 7 + def __init__(self, category, content_type, name, value): + self.category = category + self.content_type = content_type + self.name = name + self.value = value + def getCategory(self): + return self.category + def getContenttype(self, content_type): + return self.content_type + def getValue(self): + return self.value + def getName(self): + return self.name + def export(self, outfile, level, name, namespace): + if self.category == MixedContainer.CategoryText: + outfile.write(self.value) + elif self.category == MixedContainer.CategorySimple: + self.exportSimple(outfile, level, name) + else: # category == MixedContainer.CategoryComplex + self.value.export(outfile, level, namespace,name) + def exportSimple(self, outfile, level, name): + if self.content_type == MixedContainer.TypeString: + outfile.write('<%s>%s' % (self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeInteger or \ + self.content_type == MixedContainer.TypeBoolean: + outfile.write('<%s>%d' % (self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeFloat or \ + self.content_type == MixedContainer.TypeDecimal: + outfile.write('<%s>%f' % (self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeDouble: + outfile.write('<%s>%g' % (self.name, self.value, self.name)) + def exportLiteral(self, outfile, level, name): + if self.category == MixedContainer.CategoryText: + showIndent(outfile, level) + outfile.write('MixedContainer(%d, %d, "%s", "%s"),\n' % \ + (self.category, self.content_type, self.name, self.value)) + elif self.category == MixedContainer.CategorySimple: + showIndent(outfile, level) + outfile.write('MixedContainer(%d, %d, "%s", "%s"),\n' % \ + (self.category, self.content_type, self.name, self.value)) + else: # category == MixedContainer.CategoryComplex + showIndent(outfile, level) + outfile.write('MixedContainer(%d, %d, "%s",\n' % \ + (self.category, self.content_type, self.name,)) + self.value.exportLiteral(outfile, level + 1) + showIndent(outfile, level) + outfile.write(')\n') + + +class _MemberSpec(object): + def __init__(self, name='', data_type='', container=0): + self.name = name + self.data_type = data_type + self.container = container + def set_name(self, name): self.name = name + def get_name(self): return self.name + def set_data_type(self, data_type): self.data_type = data_type + def get_data_type(self): return self.data_type + def set_container(self, container): self.container = container + def get_container(self): return self.container + + +# +# Data representation classes. +# + +class DoxygenType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, version=None, compounddef=None): + self.version = version + self.compounddef = compounddef + def factory(*args_, **kwargs_): + if DoxygenType.subclass: + return DoxygenType.subclass(*args_, **kwargs_) + else: + return DoxygenType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_compounddef(self): return self.compounddef + def set_compounddef(self, compounddef): self.compounddef = compounddef + def get_version(self): return self.version + def set_version(self, version): self.version = version + def export(self, outfile, level, namespace_='', name_='DoxygenType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='DoxygenType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='DoxygenType'): + outfile.write(' version=%s' % (quote_attrib(self.version), )) + def exportChildren(self, outfile, level, namespace_='', name_='DoxygenType'): + if self.compounddef: + self.compounddef.export(outfile, level, namespace_, name_='compounddef') + def hasContent_(self): + if ( + self.compounddef is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='DoxygenType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.version is not None: + showIndent(outfile, level) + outfile.write('version = "%s",\n' % (self.version,)) + def exportLiteralChildren(self, outfile, level, name_): + if self.compounddef: + showIndent(outfile, level) + outfile.write('compounddef=model_.compounddefType(\n') + self.compounddef.exportLiteral(outfile, level, name_='compounddef') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('version'): + self.version = attrs.get('version').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'compounddef': + obj_ = compounddefType.factory() + obj_.build(child_) + self.set_compounddef(obj_) +# end class DoxygenType + + +class compounddefType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, kind=None, prot=None, id=None, compoundname=None, title=None, basecompoundref=None, derivedcompoundref=None, includes=None, includedby=None, incdepgraph=None, invincdepgraph=None, innerdir=None, innerfile=None, innerclass=None, innernamespace=None, innerpage=None, innergroup=None, templateparamlist=None, sectiondef=None, briefdescription=None, detaileddescription=None, inheritancegraph=None, collaborationgraph=None, programlisting=None, location=None, listofallmembers=None): + self.kind = kind + self.prot = prot + self.id = id + self.compoundname = compoundname + self.title = title + if basecompoundref is None: + self.basecompoundref = [] + else: + self.basecompoundref = basecompoundref + if derivedcompoundref is None: + self.derivedcompoundref = [] + else: + self.derivedcompoundref = derivedcompoundref + if includes is None: + self.includes = [] + else: + self.includes = includes + if includedby is None: + self.includedby = [] + else: + self.includedby = includedby + self.incdepgraph = incdepgraph + self.invincdepgraph = invincdepgraph + if innerdir is None: + self.innerdir = [] + else: + self.innerdir = innerdir + if innerfile is None: + self.innerfile = [] + else: + self.innerfile = innerfile + if innerclass is None: + self.innerclass = [] + else: + self.innerclass = innerclass + if innernamespace is None: + self.innernamespace = [] + else: + self.innernamespace = innernamespace + if innerpage is None: + self.innerpage = [] + else: + self.innerpage = innerpage + if innergroup is None: + self.innergroup = [] + else: + self.innergroup = innergroup + self.templateparamlist = templateparamlist + if sectiondef is None: + self.sectiondef = [] + else: + self.sectiondef = sectiondef + self.briefdescription = briefdescription + self.detaileddescription = detaileddescription + self.inheritancegraph = inheritancegraph + self.collaborationgraph = collaborationgraph + self.programlisting = programlisting + self.location = location + self.listofallmembers = listofallmembers + def factory(*args_, **kwargs_): + if compounddefType.subclass: + return compounddefType.subclass(*args_, **kwargs_) + else: + return compounddefType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_compoundname(self): return self.compoundname + def set_compoundname(self, compoundname): self.compoundname = compoundname + def get_title(self): return self.title + def set_title(self, title): self.title = title + def get_basecompoundref(self): return self.basecompoundref + def set_basecompoundref(self, basecompoundref): self.basecompoundref = basecompoundref + def add_basecompoundref(self, value): self.basecompoundref.append(value) + def insert_basecompoundref(self, index, value): self.basecompoundref[index] = value + def get_derivedcompoundref(self): return self.derivedcompoundref + def set_derivedcompoundref(self, derivedcompoundref): self.derivedcompoundref = derivedcompoundref + def add_derivedcompoundref(self, value): self.derivedcompoundref.append(value) + def insert_derivedcompoundref(self, index, value): self.derivedcompoundref[index] = value + def get_includes(self): return self.includes + def set_includes(self, includes): self.includes = includes + def add_includes(self, value): self.includes.append(value) + def insert_includes(self, index, value): self.includes[index] = value + def get_includedby(self): return self.includedby + def set_includedby(self, includedby): self.includedby = includedby + def add_includedby(self, value): self.includedby.append(value) + def insert_includedby(self, index, value): self.includedby[index] = value + def get_incdepgraph(self): return self.incdepgraph + def set_incdepgraph(self, incdepgraph): self.incdepgraph = incdepgraph + def get_invincdepgraph(self): return self.invincdepgraph + def set_invincdepgraph(self, invincdepgraph): self.invincdepgraph = invincdepgraph + def get_innerdir(self): return self.innerdir + def set_innerdir(self, innerdir): self.innerdir = innerdir + def add_innerdir(self, value): self.innerdir.append(value) + def insert_innerdir(self, index, value): self.innerdir[index] = value + def get_innerfile(self): return self.innerfile + def set_innerfile(self, innerfile): self.innerfile = innerfile + def add_innerfile(self, value): self.innerfile.append(value) + def insert_innerfile(self, index, value): self.innerfile[index] = value + def get_innerclass(self): return self.innerclass + def set_innerclass(self, innerclass): self.innerclass = innerclass + def add_innerclass(self, value): self.innerclass.append(value) + def insert_innerclass(self, index, value): self.innerclass[index] = value + def get_innernamespace(self): return self.innernamespace + def set_innernamespace(self, innernamespace): self.innernamespace = innernamespace + def add_innernamespace(self, value): self.innernamespace.append(value) + def insert_innernamespace(self, index, value): self.innernamespace[index] = value + def get_innerpage(self): return self.innerpage + def set_innerpage(self, innerpage): self.innerpage = innerpage + def add_innerpage(self, value): self.innerpage.append(value) + def insert_innerpage(self, index, value): self.innerpage[index] = value + def get_innergroup(self): return self.innergroup + def set_innergroup(self, innergroup): self.innergroup = innergroup + def add_innergroup(self, value): self.innergroup.append(value) + def insert_innergroup(self, index, value): self.innergroup[index] = value + def get_templateparamlist(self): return self.templateparamlist + def set_templateparamlist(self, templateparamlist): self.templateparamlist = templateparamlist + def get_sectiondef(self): return self.sectiondef + def set_sectiondef(self, sectiondef): self.sectiondef = sectiondef + def add_sectiondef(self, value): self.sectiondef.append(value) + def insert_sectiondef(self, index, value): self.sectiondef[index] = value + def get_briefdescription(self): return self.briefdescription + def set_briefdescription(self, briefdescription): self.briefdescription = briefdescription + def get_detaileddescription(self): return self.detaileddescription + def set_detaileddescription(self, detaileddescription): self.detaileddescription = detaileddescription + def get_inheritancegraph(self): return self.inheritancegraph + def set_inheritancegraph(self, inheritancegraph): self.inheritancegraph = inheritancegraph + def get_collaborationgraph(self): return self.collaborationgraph + def set_collaborationgraph(self, collaborationgraph): self.collaborationgraph = collaborationgraph + def get_programlisting(self): return self.programlisting + def set_programlisting(self, programlisting): self.programlisting = programlisting + def get_location(self): return self.location + def set_location(self, location): self.location = location + def get_listofallmembers(self): return self.listofallmembers + def set_listofallmembers(self, listofallmembers): self.listofallmembers = listofallmembers + def get_kind(self): return self.kind + def set_kind(self, kind): self.kind = kind + def get_prot(self): return self.prot + def set_prot(self, prot): self.prot = prot + def get_id(self): return self.id + def set_id(self, id): self.id = id + def export(self, outfile, level, namespace_='', name_='compounddefType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='compounddefType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='compounddefType'): + if self.kind is not None: + outfile.write(' kind=%s' % (quote_attrib(self.kind), )) + if self.prot is not None: + outfile.write(' prot=%s' % (quote_attrib(self.prot), )) + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='compounddefType'): + if self.compoundname is not None: + showIndent(outfile, level) + outfile.write('<%scompoundname>%s\n' % (namespace_, self.format_string(quote_xml(self.compoundname).encode(ExternalEncoding), input_name='compoundname'), namespace_)) + if self.title is not None: + showIndent(outfile, level) + outfile.write('<%stitle>%s\n' % (namespace_, self.format_string(quote_xml(self.title).encode(ExternalEncoding), input_name='title'), namespace_)) + for basecompoundref_ in self.basecompoundref: + basecompoundref_.export(outfile, level, namespace_, name_='basecompoundref') + for derivedcompoundref_ in self.derivedcompoundref: + derivedcompoundref_.export(outfile, level, namespace_, name_='derivedcompoundref') + for includes_ in self.includes: + includes_.export(outfile, level, namespace_, name_='includes') + for includedby_ in self.includedby: + includedby_.export(outfile, level, namespace_, name_='includedby') + if self.incdepgraph: + self.incdepgraph.export(outfile, level, namespace_, name_='incdepgraph') + if self.invincdepgraph: + self.invincdepgraph.export(outfile, level, namespace_, name_='invincdepgraph') + for innerdir_ in self.innerdir: + innerdir_.export(outfile, level, namespace_, name_='innerdir') + for innerfile_ in self.innerfile: + innerfile_.export(outfile, level, namespace_, name_='innerfile') + for innerclass_ in self.innerclass: + innerclass_.export(outfile, level, namespace_, name_='innerclass') + for innernamespace_ in self.innernamespace: + innernamespace_.export(outfile, level, namespace_, name_='innernamespace') + for innerpage_ in self.innerpage: + innerpage_.export(outfile, level, namespace_, name_='innerpage') + for innergroup_ in self.innergroup: + innergroup_.export(outfile, level, namespace_, name_='innergroup') + if self.templateparamlist: + self.templateparamlist.export(outfile, level, namespace_, name_='templateparamlist') + for sectiondef_ in self.sectiondef: + sectiondef_.export(outfile, level, namespace_, name_='sectiondef') + if self.briefdescription: + self.briefdescription.export(outfile, level, namespace_, name_='briefdescription') + if self.detaileddescription: + self.detaileddescription.export(outfile, level, namespace_, name_='detaileddescription') + if self.inheritancegraph: + self.inheritancegraph.export(outfile, level, namespace_, name_='inheritancegraph') + if self.collaborationgraph: + self.collaborationgraph.export(outfile, level, namespace_, name_='collaborationgraph') + if self.programlisting: + self.programlisting.export(outfile, level, namespace_, name_='programlisting') + if self.location: + self.location.export(outfile, level, namespace_, name_='location') + if self.listofallmembers: + self.listofallmembers.export(outfile, level, namespace_, name_='listofallmembers') + def hasContent_(self): + if ( + self.compoundname is not None or + self.title is not None or + self.basecompoundref is not None or + self.derivedcompoundref is not None or + self.includes is not None or + self.includedby is not None or + self.incdepgraph is not None or + self.invincdepgraph is not None or + self.innerdir is not None or + self.innerfile is not None or + self.innerclass is not None or + self.innernamespace is not None or + self.innerpage is not None or + self.innergroup is not None or + self.templateparamlist is not None or + self.sectiondef is not None or + self.briefdescription is not None or + self.detaileddescription is not None or + self.inheritancegraph is not None or + self.collaborationgraph is not None or + self.programlisting is not None or + self.location is not None or + self.listofallmembers is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='compounddefType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.kind is not None: + showIndent(outfile, level) + outfile.write('kind = "%s",\n' % (self.kind,)) + if self.prot is not None: + showIndent(outfile, level) + outfile.write('prot = "%s",\n' % (self.prot,)) + if self.id is not None: + showIndent(outfile, level) + outfile.write('id = %s,\n' % (self.id,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('compoundname=%s,\n' % quote_python(self.compoundname).encode(ExternalEncoding)) + if self.title: + showIndent(outfile, level) + outfile.write('title=model_.xsd_string(\n') + self.title.exportLiteral(outfile, level, name_='title') + showIndent(outfile, level) + outfile.write('),\n') + showIndent(outfile, level) + outfile.write('basecompoundref=[\n') + level += 1 + for basecompoundref in self.basecompoundref: + showIndent(outfile, level) + outfile.write('model_.basecompoundref(\n') + basecompoundref.exportLiteral(outfile, level, name_='basecompoundref') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('derivedcompoundref=[\n') + level += 1 + for derivedcompoundref in self.derivedcompoundref: + showIndent(outfile, level) + outfile.write('model_.derivedcompoundref(\n') + derivedcompoundref.exportLiteral(outfile, level, name_='derivedcompoundref') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('includes=[\n') + level += 1 + for includes in self.includes: + showIndent(outfile, level) + outfile.write('model_.includes(\n') + includes.exportLiteral(outfile, level, name_='includes') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('includedby=[\n') + level += 1 + for includedby in self.includedby: + showIndent(outfile, level) + outfile.write('model_.includedby(\n') + includedby.exportLiteral(outfile, level, name_='includedby') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + if self.incdepgraph: + showIndent(outfile, level) + outfile.write('incdepgraph=model_.graphType(\n') + self.incdepgraph.exportLiteral(outfile, level, name_='incdepgraph') + showIndent(outfile, level) + outfile.write('),\n') + if self.invincdepgraph: + showIndent(outfile, level) + outfile.write('invincdepgraph=model_.graphType(\n') + self.invincdepgraph.exportLiteral(outfile, level, name_='invincdepgraph') + showIndent(outfile, level) + outfile.write('),\n') + showIndent(outfile, level) + outfile.write('innerdir=[\n') + level += 1 + for innerdir in self.innerdir: + showIndent(outfile, level) + outfile.write('model_.innerdir(\n') + innerdir.exportLiteral(outfile, level, name_='innerdir') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('innerfile=[\n') + level += 1 + for innerfile in self.innerfile: + showIndent(outfile, level) + outfile.write('model_.innerfile(\n') + innerfile.exportLiteral(outfile, level, name_='innerfile') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('innerclass=[\n') + level += 1 + for innerclass in self.innerclass: + showIndent(outfile, level) + outfile.write('model_.innerclass(\n') + innerclass.exportLiteral(outfile, level, name_='innerclass') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('innernamespace=[\n') + level += 1 + for innernamespace in self.innernamespace: + showIndent(outfile, level) + outfile.write('model_.innernamespace(\n') + innernamespace.exportLiteral(outfile, level, name_='innernamespace') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('innerpage=[\n') + level += 1 + for innerpage in self.innerpage: + showIndent(outfile, level) + outfile.write('model_.innerpage(\n') + innerpage.exportLiteral(outfile, level, name_='innerpage') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('innergroup=[\n') + level += 1 + for innergroup in self.innergroup: + showIndent(outfile, level) + outfile.write('model_.innergroup(\n') + innergroup.exportLiteral(outfile, level, name_='innergroup') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + if self.templateparamlist: + showIndent(outfile, level) + outfile.write('templateparamlist=model_.templateparamlistType(\n') + self.templateparamlist.exportLiteral(outfile, level, name_='templateparamlist') + showIndent(outfile, level) + outfile.write('),\n') + showIndent(outfile, level) + outfile.write('sectiondef=[\n') + level += 1 + for sectiondef in self.sectiondef: + showIndent(outfile, level) + outfile.write('model_.sectiondef(\n') + sectiondef.exportLiteral(outfile, level, name_='sectiondef') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + if self.briefdescription: + showIndent(outfile, level) + outfile.write('briefdescription=model_.descriptionType(\n') + self.briefdescription.exportLiteral(outfile, level, name_='briefdescription') + showIndent(outfile, level) + outfile.write('),\n') + if self.detaileddescription: + showIndent(outfile, level) + outfile.write('detaileddescription=model_.descriptionType(\n') + self.detaileddescription.exportLiteral(outfile, level, name_='detaileddescription') + showIndent(outfile, level) + outfile.write('),\n') + if self.inheritancegraph: + showIndent(outfile, level) + outfile.write('inheritancegraph=model_.graphType(\n') + self.inheritancegraph.exportLiteral(outfile, level, name_='inheritancegraph') + showIndent(outfile, level) + outfile.write('),\n') + if self.collaborationgraph: + showIndent(outfile, level) + outfile.write('collaborationgraph=model_.graphType(\n') + self.collaborationgraph.exportLiteral(outfile, level, name_='collaborationgraph') + showIndent(outfile, level) + outfile.write('),\n') + if self.programlisting: + showIndent(outfile, level) + outfile.write('programlisting=model_.listingType(\n') + self.programlisting.exportLiteral(outfile, level, name_='programlisting') + showIndent(outfile, level) + outfile.write('),\n') + if self.location: + showIndent(outfile, level) + outfile.write('location=model_.locationType(\n') + self.location.exportLiteral(outfile, level, name_='location') + showIndent(outfile, level) + outfile.write('),\n') + if self.listofallmembers: + showIndent(outfile, level) + outfile.write('listofallmembers=model_.listofallmembersType(\n') + self.listofallmembers.exportLiteral(outfile, level, name_='listofallmembers') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('kind'): + self.kind = attrs.get('kind').value + if attrs.get('prot'): + self.prot = attrs.get('prot').value + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'compoundname': + compoundname_ = '' + for text__content_ in child_.childNodes: + compoundname_ += text__content_.nodeValue + self.compoundname = compoundname_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'title': + obj_ = docTitleType.factory() + obj_.build(child_) + self.set_title(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'basecompoundref': + obj_ = compoundRefType.factory() + obj_.build(child_) + self.basecompoundref.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'derivedcompoundref': + obj_ = compoundRefType.factory() + obj_.build(child_) + self.derivedcompoundref.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'includes': + obj_ = incType.factory() + obj_.build(child_) + self.includes.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'includedby': + obj_ = incType.factory() + obj_.build(child_) + self.includedby.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'incdepgraph': + obj_ = graphType.factory() + obj_.build(child_) + self.set_incdepgraph(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'invincdepgraph': + obj_ = graphType.factory() + obj_.build(child_) + self.set_invincdepgraph(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'innerdir': + obj_ = refType.factory() + obj_.build(child_) + self.innerdir.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'innerfile': + obj_ = refType.factory() + obj_.build(child_) + self.innerfile.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'innerclass': + obj_ = refType.factory() + obj_.build(child_) + self.innerclass.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'innernamespace': + obj_ = refType.factory() + obj_.build(child_) + self.innernamespace.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'innerpage': + obj_ = refType.factory() + obj_.build(child_) + self.innerpage.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'innergroup': + obj_ = refType.factory() + obj_.build(child_) + self.innergroup.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'templateparamlist': + obj_ = templateparamlistType.factory() + obj_.build(child_) + self.set_templateparamlist(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sectiondef': + obj_ = sectiondefType.factory() + obj_.build(child_) + self.sectiondef.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'briefdescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_briefdescription(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'detaileddescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_detaileddescription(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'inheritancegraph': + obj_ = graphType.factory() + obj_.build(child_) + self.set_inheritancegraph(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'collaborationgraph': + obj_ = graphType.factory() + obj_.build(child_) + self.set_collaborationgraph(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'programlisting': + obj_ = listingType.factory() + obj_.build(child_) + self.set_programlisting(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'location': + obj_ = locationType.factory() + obj_.build(child_) + self.set_location(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'listofallmembers': + obj_ = listofallmembersType.factory() + obj_.build(child_) + self.set_listofallmembers(obj_) +# end class compounddefType + + +class listofallmembersType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, member=None): + if member is None: + self.member = [] + else: + self.member = member + def factory(*args_, **kwargs_): + if listofallmembersType.subclass: + return listofallmembersType.subclass(*args_, **kwargs_) + else: + return listofallmembersType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_member(self): return self.member + def set_member(self, member): self.member = member + def add_member(self, value): self.member.append(value) + def insert_member(self, index, value): self.member[index] = value + def export(self, outfile, level, namespace_='', name_='listofallmembersType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='listofallmembersType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='listofallmembersType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='listofallmembersType'): + for member_ in self.member: + member_.export(outfile, level, namespace_, name_='member') + def hasContent_(self): + if ( + self.member is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='listofallmembersType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('member=[\n') + level += 1 + for member in self.member: + showIndent(outfile, level) + outfile.write('model_.member(\n') + member.exportLiteral(outfile, level, name_='member') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'member': + obj_ = memberRefType.factory() + obj_.build(child_) + self.member.append(obj_) +# end class listofallmembersType + + +class memberRefType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, virt=None, prot=None, refid=None, ambiguityscope=None, scope=None, name=None): + self.virt = virt + self.prot = prot + self.refid = refid + self.ambiguityscope = ambiguityscope + self.scope = scope + self.name = name + def factory(*args_, **kwargs_): + if memberRefType.subclass: + return memberRefType.subclass(*args_, **kwargs_) + else: + return memberRefType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_scope(self): return self.scope + def set_scope(self, scope): self.scope = scope + def get_name(self): return self.name + def set_name(self, name): self.name = name + def get_virt(self): return self.virt + def set_virt(self, virt): self.virt = virt + def get_prot(self): return self.prot + def set_prot(self, prot): self.prot = prot + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def get_ambiguityscope(self): return self.ambiguityscope + def set_ambiguityscope(self, ambiguityscope): self.ambiguityscope = ambiguityscope + def export(self, outfile, level, namespace_='', name_='memberRefType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='memberRefType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='memberRefType'): + if self.virt is not None: + outfile.write(' virt=%s' % (quote_attrib(self.virt), )) + if self.prot is not None: + outfile.write(' prot=%s' % (quote_attrib(self.prot), )) + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + if self.ambiguityscope is not None: + outfile.write(' ambiguityscope=%s' % (self.format_string(quote_attrib(self.ambiguityscope).encode(ExternalEncoding), input_name='ambiguityscope'), )) + def exportChildren(self, outfile, level, namespace_='', name_='memberRefType'): + if self.scope is not None: + showIndent(outfile, level) + outfile.write('<%sscope>%s\n' % (namespace_, self.format_string(quote_xml(self.scope).encode(ExternalEncoding), input_name='scope'), namespace_)) + if self.name is not None: + showIndent(outfile, level) + outfile.write('<%sname>%s\n' % (namespace_, self.format_string(quote_xml(self.name).encode(ExternalEncoding), input_name='name'), namespace_)) + def hasContent_(self): + if ( + self.scope is not None or + self.name is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='memberRefType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.virt is not None: + showIndent(outfile, level) + outfile.write('virt = "%s",\n' % (self.virt,)) + if self.prot is not None: + showIndent(outfile, level) + outfile.write('prot = "%s",\n' % (self.prot,)) + if self.refid is not None: + showIndent(outfile, level) + outfile.write('refid = %s,\n' % (self.refid,)) + if self.ambiguityscope is not None: + showIndent(outfile, level) + outfile.write('ambiguityscope = %s,\n' % (self.ambiguityscope,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('scope=%s,\n' % quote_python(self.scope).encode(ExternalEncoding)) + showIndent(outfile, level) + outfile.write('name=%s,\n' % quote_python(self.name).encode(ExternalEncoding)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('virt'): + self.virt = attrs.get('virt').value + if attrs.get('prot'): + self.prot = attrs.get('prot').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + if attrs.get('ambiguityscope'): + self.ambiguityscope = attrs.get('ambiguityscope').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'scope': + scope_ = '' + for text__content_ in child_.childNodes: + scope_ += text__content_.nodeValue + self.scope = scope_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'name': + name_ = '' + for text__content_ in child_.childNodes: + name_ += text__content_.nodeValue + self.name = name_ +# end class memberRefType + + +class scope(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if scope.subclass: + return scope.subclass(*args_, **kwargs_) + else: + return scope(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='scope', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='scope') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='scope'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='scope'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='scope'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class scope + + +class name(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if name.subclass: + return name.subclass(*args_, **kwargs_) + else: + return name(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='name', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='name') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='name'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='name'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='name'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class name + + +class compoundRefType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, virt=None, prot=None, refid=None, valueOf_='', mixedclass_=None, content_=None): + self.virt = virt + self.prot = prot + self.refid = refid + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if compoundRefType.subclass: + return compoundRefType.subclass(*args_, **kwargs_) + else: + return compoundRefType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_virt(self): return self.virt + def set_virt(self, virt): self.virt = virt + def get_prot(self): return self.prot + def set_prot(self, prot): self.prot = prot + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='compoundRefType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='compoundRefType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='compoundRefType'): + if self.virt is not None: + outfile.write(' virt=%s' % (quote_attrib(self.virt), )) + if self.prot is not None: + outfile.write(' prot=%s' % (quote_attrib(self.prot), )) + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + def exportChildren(self, outfile, level, namespace_='', name_='compoundRefType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='compoundRefType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.virt is not None: + showIndent(outfile, level) + outfile.write('virt = "%s",\n' % (self.virt,)) + if self.prot is not None: + showIndent(outfile, level) + outfile.write('prot = "%s",\n' % (self.prot,)) + if self.refid is not None: + showIndent(outfile, level) + outfile.write('refid = %s,\n' % (self.refid,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('virt'): + self.virt = attrs.get('virt').value + if attrs.get('prot'): + self.prot = attrs.get('prot').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class compoundRefType + + +class reimplementType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, refid=None, valueOf_='', mixedclass_=None, content_=None): + self.refid = refid + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if reimplementType.subclass: + return reimplementType.subclass(*args_, **kwargs_) + else: + return reimplementType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='reimplementType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='reimplementType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='reimplementType'): + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + def exportChildren(self, outfile, level, namespace_='', name_='reimplementType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='reimplementType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.refid is not None: + showIndent(outfile, level) + outfile.write('refid = %s,\n' % (self.refid,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class reimplementType + + +class incType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, local=None, refid=None, valueOf_='', mixedclass_=None, content_=None): + self.local = local + self.refid = refid + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if incType.subclass: + return incType.subclass(*args_, **kwargs_) + else: + return incType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_local(self): return self.local + def set_local(self, local): self.local = local + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='incType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='incType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='incType'): + if self.local is not None: + outfile.write(' local=%s' % (quote_attrib(self.local), )) + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + def exportChildren(self, outfile, level, namespace_='', name_='incType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='incType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.local is not None: + showIndent(outfile, level) + outfile.write('local = "%s",\n' % (self.local,)) + if self.refid is not None: + showIndent(outfile, level) + outfile.write('refid = %s,\n' % (self.refid,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('local'): + self.local = attrs.get('local').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class incType + + +class refType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, prot=None, refid=None, valueOf_='', mixedclass_=None, content_=None): + self.prot = prot + self.refid = refid + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if refType.subclass: + return refType.subclass(*args_, **kwargs_) + else: + return refType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_prot(self): return self.prot + def set_prot(self, prot): self.prot = prot + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='refType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='refType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='refType'): + if self.prot is not None: + outfile.write(' prot=%s' % (quote_attrib(self.prot), )) + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + def exportChildren(self, outfile, level, namespace_='', name_='refType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='refType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.prot is not None: + showIndent(outfile, level) + outfile.write('prot = "%s",\n' % (self.prot,)) + if self.refid is not None: + showIndent(outfile, level) + outfile.write('refid = %s,\n' % (self.refid,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('prot'): + self.prot = attrs.get('prot').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class refType + + +class refTextType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, refid=None, kindref=None, external=None, valueOf_='', mixedclass_=None, content_=None): + self.refid = refid + self.kindref = kindref + self.external = external + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if refTextType.subclass: + return refTextType.subclass(*args_, **kwargs_) + else: + return refTextType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def get_kindref(self): return self.kindref + def set_kindref(self, kindref): self.kindref = kindref + def get_external(self): return self.external + def set_external(self, external): self.external = external + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='refTextType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='refTextType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='refTextType'): + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + if self.kindref is not None: + outfile.write(' kindref=%s' % (quote_attrib(self.kindref), )) + if self.external is not None: + outfile.write(' external=%s' % (self.format_string(quote_attrib(self.external).encode(ExternalEncoding), input_name='external'), )) + def exportChildren(self, outfile, level, namespace_='', name_='refTextType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='refTextType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.refid is not None: + showIndent(outfile, level) + outfile.write('refid = %s,\n' % (self.refid,)) + if self.kindref is not None: + showIndent(outfile, level) + outfile.write('kindref = "%s",\n' % (self.kindref,)) + if self.external is not None: + showIndent(outfile, level) + outfile.write('external = %s,\n' % (self.external,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('refid'): + self.refid = attrs.get('refid').value + if attrs.get('kindref'): + self.kindref = attrs.get('kindref').value + if attrs.get('external'): + self.external = attrs.get('external').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class refTextType + + +class sectiondefType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, kind=None, header=None, description=None, memberdef=None): + self.kind = kind + self.header = header + self.description = description + if memberdef is None: + self.memberdef = [] + else: + self.memberdef = memberdef + def factory(*args_, **kwargs_): + if sectiondefType.subclass: + return sectiondefType.subclass(*args_, **kwargs_) + else: + return sectiondefType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_header(self): return self.header + def set_header(self, header): self.header = header + def get_description(self): return self.description + def set_description(self, description): self.description = description + def get_memberdef(self): return self.memberdef + def set_memberdef(self, memberdef): self.memberdef = memberdef + def add_memberdef(self, value): self.memberdef.append(value) + def insert_memberdef(self, index, value): self.memberdef[index] = value + def get_kind(self): return self.kind + def set_kind(self, kind): self.kind = kind + def export(self, outfile, level, namespace_='', name_='sectiondefType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='sectiondefType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='sectiondefType'): + if self.kind is not None: + outfile.write(' kind=%s' % (quote_attrib(self.kind), )) + def exportChildren(self, outfile, level, namespace_='', name_='sectiondefType'): + if self.header is not None: + showIndent(outfile, level) + outfile.write('<%sheader>%s\n' % (namespace_, self.format_string(quote_xml(self.header).encode(ExternalEncoding), input_name='header'), namespace_)) + if self.description: + self.description.export(outfile, level, namespace_, name_='description') + for memberdef_ in self.memberdef: + memberdef_.export(outfile, level, namespace_, name_='memberdef') + def hasContent_(self): + if ( + self.header is not None or + self.description is not None or + self.memberdef is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='sectiondefType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.kind is not None: + showIndent(outfile, level) + outfile.write('kind = "%s",\n' % (self.kind,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('header=%s,\n' % quote_python(self.header).encode(ExternalEncoding)) + if self.description: + showIndent(outfile, level) + outfile.write('description=model_.descriptionType(\n') + self.description.exportLiteral(outfile, level, name_='description') + showIndent(outfile, level) + outfile.write('),\n') + showIndent(outfile, level) + outfile.write('memberdef=[\n') + level += 1 + for memberdef in self.memberdef: + showIndent(outfile, level) + outfile.write('model_.memberdef(\n') + memberdef.exportLiteral(outfile, level, name_='memberdef') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('kind'): + self.kind = attrs.get('kind').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'header': + header_ = '' + for text__content_ in child_.childNodes: + header_ += text__content_.nodeValue + self.header = header_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'description': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_description(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'memberdef': + obj_ = memberdefType.factory() + obj_.build(child_) + self.memberdef.append(obj_) +# end class sectiondefType + + +class memberdefType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, initonly=None, kind=None, volatile=None, const=None, raisexx=None, virt=None, readable=None, prot=None, explicit=None, new=None, final=None, writable=None, add=None, static=None, remove=None, sealed=None, mutable=None, gettable=None, inline=None, settable=None, id=None, templateparamlist=None, type_=None, definition=None, argsstring=None, name=None, read=None, write=None, bitfield=None, reimplements=None, reimplementedby=None, param=None, enumvalue=None, initializer=None, exceptions=None, briefdescription=None, detaileddescription=None, inbodydescription=None, location=None, references=None, referencedby=None): + self.initonly = initonly + self.kind = kind + self.volatile = volatile + self.const = const + self.raisexx = raisexx + self.virt = virt + self.readable = readable + self.prot = prot + self.explicit = explicit + self.new = new + self.final = final + self.writable = writable + self.add = add + self.static = static + self.remove = remove + self.sealed = sealed + self.mutable = mutable + self.gettable = gettable + self.inline = inline + self.settable = settable + self.id = id + self.templateparamlist = templateparamlist + self.type_ = type_ + self.definition = definition + self.argsstring = argsstring + self.name = name + self.read = read + self.write = write + self.bitfield = bitfield + if reimplements is None: + self.reimplements = [] + else: + self.reimplements = reimplements + if reimplementedby is None: + self.reimplementedby = [] + else: + self.reimplementedby = reimplementedby + if param is None: + self.param = [] + else: + self.param = param + if enumvalue is None: + self.enumvalue = [] + else: + self.enumvalue = enumvalue + self.initializer = initializer + self.exceptions = exceptions + self.briefdescription = briefdescription + self.detaileddescription = detaileddescription + self.inbodydescription = inbodydescription + self.location = location + if references is None: + self.references = [] + else: + self.references = references + if referencedby is None: + self.referencedby = [] + else: + self.referencedby = referencedby + def factory(*args_, **kwargs_): + if memberdefType.subclass: + return memberdefType.subclass(*args_, **kwargs_) + else: + return memberdefType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_templateparamlist(self): return self.templateparamlist + def set_templateparamlist(self, templateparamlist): self.templateparamlist = templateparamlist + def get_type(self): return self.type_ + def set_type(self, type_): self.type_ = type_ + def get_definition(self): return self.definition + def set_definition(self, definition): self.definition = definition + def get_argsstring(self): return self.argsstring + def set_argsstring(self, argsstring): self.argsstring = argsstring + def get_name(self): return self.name + def set_name(self, name): self.name = name + def get_read(self): return self.read + def set_read(self, read): self.read = read + def get_write(self): return self.write + def set_write(self, write): self.write = write + def get_bitfield(self): return self.bitfield + def set_bitfield(self, bitfield): self.bitfield = bitfield + def get_reimplements(self): return self.reimplements + def set_reimplements(self, reimplements): self.reimplements = reimplements + def add_reimplements(self, value): self.reimplements.append(value) + def insert_reimplements(self, index, value): self.reimplements[index] = value + def get_reimplementedby(self): return self.reimplementedby + def set_reimplementedby(self, reimplementedby): self.reimplementedby = reimplementedby + def add_reimplementedby(self, value): self.reimplementedby.append(value) + def insert_reimplementedby(self, index, value): self.reimplementedby[index] = value + def get_param(self): return self.param + def set_param(self, param): self.param = param + def add_param(self, value): self.param.append(value) + def insert_param(self, index, value): self.param[index] = value + def get_enumvalue(self): return self.enumvalue + def set_enumvalue(self, enumvalue): self.enumvalue = enumvalue + def add_enumvalue(self, value): self.enumvalue.append(value) + def insert_enumvalue(self, index, value): self.enumvalue[index] = value + def get_initializer(self): return self.initializer + def set_initializer(self, initializer): self.initializer = initializer + def get_exceptions(self): return self.exceptions + def set_exceptions(self, exceptions): self.exceptions = exceptions + def get_briefdescription(self): return self.briefdescription + def set_briefdescription(self, briefdescription): self.briefdescription = briefdescription + def get_detaileddescription(self): return self.detaileddescription + def set_detaileddescription(self, detaileddescription): self.detaileddescription = detaileddescription + def get_inbodydescription(self): return self.inbodydescription + def set_inbodydescription(self, inbodydescription): self.inbodydescription = inbodydescription + def get_location(self): return self.location + def set_location(self, location): self.location = location + def get_references(self): return self.references + def set_references(self, references): self.references = references + def add_references(self, value): self.references.append(value) + def insert_references(self, index, value): self.references[index] = value + def get_referencedby(self): return self.referencedby + def set_referencedby(self, referencedby): self.referencedby = referencedby + def add_referencedby(self, value): self.referencedby.append(value) + def insert_referencedby(self, index, value): self.referencedby[index] = value + def get_initonly(self): return self.initonly + def set_initonly(self, initonly): self.initonly = initonly + def get_kind(self): return self.kind + def set_kind(self, kind): self.kind = kind + def get_volatile(self): return self.volatile + def set_volatile(self, volatile): self.volatile = volatile + def get_const(self): return self.const + def set_const(self, const): self.const = const + def get_raise(self): return self.raisexx + def set_raise(self, raisexx): self.raisexx = raisexx + def get_virt(self): return self.virt + def set_virt(self, virt): self.virt = virt + def get_readable(self): return self.readable + def set_readable(self, readable): self.readable = readable + def get_prot(self): return self.prot + def set_prot(self, prot): self.prot = prot + def get_explicit(self): return self.explicit + def set_explicit(self, explicit): self.explicit = explicit + def get_new(self): return self.new + def set_new(self, new): self.new = new + def get_final(self): return self.final + def set_final(self, final): self.final = final + def get_writable(self): return self.writable + def set_writable(self, writable): self.writable = writable + def get_add(self): return self.add + def set_add(self, add): self.add = add + def get_static(self): return self.static + def set_static(self, static): self.static = static + def get_remove(self): return self.remove + def set_remove(self, remove): self.remove = remove + def get_sealed(self): return self.sealed + def set_sealed(self, sealed): self.sealed = sealed + def get_mutable(self): return self.mutable + def set_mutable(self, mutable): self.mutable = mutable + def get_gettable(self): return self.gettable + def set_gettable(self, gettable): self.gettable = gettable + def get_inline(self): return self.inline + def set_inline(self, inline): self.inline = inline + def get_settable(self): return self.settable + def set_settable(self, settable): self.settable = settable + def get_id(self): return self.id + def set_id(self, id): self.id = id + def export(self, outfile, level, namespace_='', name_='memberdefType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='memberdefType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='memberdefType'): + if self.initonly is not None: + outfile.write(' initonly=%s' % (quote_attrib(self.initonly), )) + if self.kind is not None: + outfile.write(' kind=%s' % (quote_attrib(self.kind), )) + if self.volatile is not None: + outfile.write(' volatile=%s' % (quote_attrib(self.volatile), )) + if self.const is not None: + outfile.write(' const=%s' % (quote_attrib(self.const), )) + if self.raisexx is not None: + outfile.write(' raise=%s' % (quote_attrib(self.raisexx), )) + if self.virt is not None: + outfile.write(' virt=%s' % (quote_attrib(self.virt), )) + if self.readable is not None: + outfile.write(' readable=%s' % (quote_attrib(self.readable), )) + if self.prot is not None: + outfile.write(' prot=%s' % (quote_attrib(self.prot), )) + if self.explicit is not None: + outfile.write(' explicit=%s' % (quote_attrib(self.explicit), )) + if self.new is not None: + outfile.write(' new=%s' % (quote_attrib(self.new), )) + if self.final is not None: + outfile.write(' final=%s' % (quote_attrib(self.final), )) + if self.writable is not None: + outfile.write(' writable=%s' % (quote_attrib(self.writable), )) + if self.add is not None: + outfile.write(' add=%s' % (quote_attrib(self.add), )) + if self.static is not None: + outfile.write(' static=%s' % (quote_attrib(self.static), )) + if self.remove is not None: + outfile.write(' remove=%s' % (quote_attrib(self.remove), )) + if self.sealed is not None: + outfile.write(' sealed=%s' % (quote_attrib(self.sealed), )) + if self.mutable is not None: + outfile.write(' mutable=%s' % (quote_attrib(self.mutable), )) + if self.gettable is not None: + outfile.write(' gettable=%s' % (quote_attrib(self.gettable), )) + if self.inline is not None: + outfile.write(' inline=%s' % (quote_attrib(self.inline), )) + if self.settable is not None: + outfile.write(' settable=%s' % (quote_attrib(self.settable), )) + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='memberdefType'): + if self.templateparamlist: + self.templateparamlist.export(outfile, level, namespace_, name_='templateparamlist') + if self.type_: + self.type_.export(outfile, level, namespace_, name_='type') + if self.definition is not None: + showIndent(outfile, level) + outfile.write('<%sdefinition>%s\n' % (namespace_, self.format_string(quote_xml(self.definition).encode(ExternalEncoding), input_name='definition'), namespace_)) + if self.argsstring is not None: + showIndent(outfile, level) + outfile.write('<%sargsstring>%s\n' % (namespace_, self.format_string(quote_xml(self.argsstring).encode(ExternalEncoding), input_name='argsstring'), namespace_)) + if self.name is not None: + showIndent(outfile, level) + outfile.write('<%sname>%s\n' % (namespace_, self.format_string(quote_xml(self.name).encode(ExternalEncoding), input_name='name'), namespace_)) + if self.read is not None: + showIndent(outfile, level) + outfile.write('<%sread>%s\n' % (namespace_, self.format_string(quote_xml(self.read).encode(ExternalEncoding), input_name='read'), namespace_)) + if self.write is not None: + showIndent(outfile, level) + outfile.write('<%swrite>%s\n' % (namespace_, self.format_string(quote_xml(self.write).encode(ExternalEncoding), input_name='write'), namespace_)) + if self.bitfield is not None: + showIndent(outfile, level) + outfile.write('<%sbitfield>%s\n' % (namespace_, self.format_string(quote_xml(self.bitfield).encode(ExternalEncoding), input_name='bitfield'), namespace_)) + for reimplements_ in self.reimplements: + reimplements_.export(outfile, level, namespace_, name_='reimplements') + for reimplementedby_ in self.reimplementedby: + reimplementedby_.export(outfile, level, namespace_, name_='reimplementedby') + for param_ in self.param: + param_.export(outfile, level, namespace_, name_='param') + for enumvalue_ in self.enumvalue: + enumvalue_.export(outfile, level, namespace_, name_='enumvalue') + if self.initializer: + self.initializer.export(outfile, level, namespace_, name_='initializer') + if self.exceptions: + self.exceptions.export(outfile, level, namespace_, name_='exceptions') + if self.briefdescription: + self.briefdescription.export(outfile, level, namespace_, name_='briefdescription') + if self.detaileddescription: + self.detaileddescription.export(outfile, level, namespace_, name_='detaileddescription') + if self.inbodydescription: + self.inbodydescription.export(outfile, level, namespace_, name_='inbodydescription') + if self.location: + self.location.export(outfile, level, namespace_, name_='location', ) + for references_ in self.references: + references_.export(outfile, level, namespace_, name_='references') + for referencedby_ in self.referencedby: + referencedby_.export(outfile, level, namespace_, name_='referencedby') + def hasContent_(self): + if ( + self.templateparamlist is not None or + self.type_ is not None or + self.definition is not None or + self.argsstring is not None or + self.name is not None or + self.read is not None or + self.write is not None or + self.bitfield is not None or + self.reimplements is not None or + self.reimplementedby is not None or + self.param is not None or + self.enumvalue is not None or + self.initializer is not None or + self.exceptions is not None or + self.briefdescription is not None or + self.detaileddescription is not None or + self.inbodydescription is not None or + self.location is not None or + self.references is not None or + self.referencedby is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='memberdefType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.initonly is not None: + showIndent(outfile, level) + outfile.write('initonly = "%s",\n' % (self.initonly,)) + if self.kind is not None: + showIndent(outfile, level) + outfile.write('kind = "%s",\n' % (self.kind,)) + if self.volatile is not None: + showIndent(outfile, level) + outfile.write('volatile = "%s",\n' % (self.volatile,)) + if self.const is not None: + showIndent(outfile, level) + outfile.write('const = "%s",\n' % (self.const,)) + if self.raisexx is not None: + showIndent(outfile, level) + outfile.write('raisexx = "%s",\n' % (self.raisexx,)) + if self.virt is not None: + showIndent(outfile, level) + outfile.write('virt = "%s",\n' % (self.virt,)) + if self.readable is not None: + showIndent(outfile, level) + outfile.write('readable = "%s",\n' % (self.readable,)) + if self.prot is not None: + showIndent(outfile, level) + outfile.write('prot = "%s",\n' % (self.prot,)) + if self.explicit is not None: + showIndent(outfile, level) + outfile.write('explicit = "%s",\n' % (self.explicit,)) + if self.new is not None: + showIndent(outfile, level) + outfile.write('new = "%s",\n' % (self.new,)) + if self.final is not None: + showIndent(outfile, level) + outfile.write('final = "%s",\n' % (self.final,)) + if self.writable is not None: + showIndent(outfile, level) + outfile.write('writable = "%s",\n' % (self.writable,)) + if self.add is not None: + showIndent(outfile, level) + outfile.write('add = "%s",\n' % (self.add,)) + if self.static is not None: + showIndent(outfile, level) + outfile.write('static = "%s",\n' % (self.static,)) + if self.remove is not None: + showIndent(outfile, level) + outfile.write('remove = "%s",\n' % (self.remove,)) + if self.sealed is not None: + showIndent(outfile, level) + outfile.write('sealed = "%s",\n' % (self.sealed,)) + if self.mutable is not None: + showIndent(outfile, level) + outfile.write('mutable = "%s",\n' % (self.mutable,)) + if self.gettable is not None: + showIndent(outfile, level) + outfile.write('gettable = "%s",\n' % (self.gettable,)) + if self.inline is not None: + showIndent(outfile, level) + outfile.write('inline = "%s",\n' % (self.inline,)) + if self.settable is not None: + showIndent(outfile, level) + outfile.write('settable = "%s",\n' % (self.settable,)) + if self.id is not None: + showIndent(outfile, level) + outfile.write('id = %s,\n' % (self.id,)) + def exportLiteralChildren(self, outfile, level, name_): + if self.templateparamlist: + showIndent(outfile, level) + outfile.write('templateparamlist=model_.templateparamlistType(\n') + self.templateparamlist.exportLiteral(outfile, level, name_='templateparamlist') + showIndent(outfile, level) + outfile.write('),\n') + if self.type_: + showIndent(outfile, level) + outfile.write('type_=model_.linkedTextType(\n') + self.type_.exportLiteral(outfile, level, name_='type') + showIndent(outfile, level) + outfile.write('),\n') + showIndent(outfile, level) + outfile.write('definition=%s,\n' % quote_python(self.definition).encode(ExternalEncoding)) + showIndent(outfile, level) + outfile.write('argsstring=%s,\n' % quote_python(self.argsstring).encode(ExternalEncoding)) + showIndent(outfile, level) + outfile.write('name=%s,\n' % quote_python(self.name).encode(ExternalEncoding)) + showIndent(outfile, level) + outfile.write('read=%s,\n' % quote_python(self.read).encode(ExternalEncoding)) + showIndent(outfile, level) + outfile.write('write=%s,\n' % quote_python(self.write).encode(ExternalEncoding)) + showIndent(outfile, level) + outfile.write('bitfield=%s,\n' % quote_python(self.bitfield).encode(ExternalEncoding)) + showIndent(outfile, level) + outfile.write('reimplements=[\n') + level += 1 + for reimplements in self.reimplements: + showIndent(outfile, level) + outfile.write('model_.reimplements(\n') + reimplements.exportLiteral(outfile, level, name_='reimplements') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('reimplementedby=[\n') + level += 1 + for reimplementedby in self.reimplementedby: + showIndent(outfile, level) + outfile.write('model_.reimplementedby(\n') + reimplementedby.exportLiteral(outfile, level, name_='reimplementedby') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('param=[\n') + level += 1 + for param in self.param: + showIndent(outfile, level) + outfile.write('model_.param(\n') + param.exportLiteral(outfile, level, name_='param') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('enumvalue=[\n') + level += 1 + for enumvalue in self.enumvalue: + showIndent(outfile, level) + outfile.write('model_.enumvalue(\n') + enumvalue.exportLiteral(outfile, level, name_='enumvalue') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + if self.initializer: + showIndent(outfile, level) + outfile.write('initializer=model_.linkedTextType(\n') + self.initializer.exportLiteral(outfile, level, name_='initializer') + showIndent(outfile, level) + outfile.write('),\n') + if self.exceptions: + showIndent(outfile, level) + outfile.write('exceptions=model_.linkedTextType(\n') + self.exceptions.exportLiteral(outfile, level, name_='exceptions') + showIndent(outfile, level) + outfile.write('),\n') + if self.briefdescription: + showIndent(outfile, level) + outfile.write('briefdescription=model_.descriptionType(\n') + self.briefdescription.exportLiteral(outfile, level, name_='briefdescription') + showIndent(outfile, level) + outfile.write('),\n') + if self.detaileddescription: + showIndent(outfile, level) + outfile.write('detaileddescription=model_.descriptionType(\n') + self.detaileddescription.exportLiteral(outfile, level, name_='detaileddescription') + showIndent(outfile, level) + outfile.write('),\n') + if self.inbodydescription: + showIndent(outfile, level) + outfile.write('inbodydescription=model_.descriptionType(\n') + self.inbodydescription.exportLiteral(outfile, level, name_='inbodydescription') + showIndent(outfile, level) + outfile.write('),\n') + if self.location: + showIndent(outfile, level) + outfile.write('location=model_.locationType(\n') + self.location.exportLiteral(outfile, level, name_='location') + showIndent(outfile, level) + outfile.write('),\n') + showIndent(outfile, level) + outfile.write('references=[\n') + level += 1 + for references in self.references: + showIndent(outfile, level) + outfile.write('model_.references(\n') + references.exportLiteral(outfile, level, name_='references') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('referencedby=[\n') + level += 1 + for referencedby in self.referencedby: + showIndent(outfile, level) + outfile.write('model_.referencedby(\n') + referencedby.exportLiteral(outfile, level, name_='referencedby') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('initonly'): + self.initonly = attrs.get('initonly').value + if attrs.get('kind'): + self.kind = attrs.get('kind').value + if attrs.get('volatile'): + self.volatile = attrs.get('volatile').value + if attrs.get('const'): + self.const = attrs.get('const').value + if attrs.get('raise'): + self.raisexx = attrs.get('raise').value + if attrs.get('virt'): + self.virt = attrs.get('virt').value + if attrs.get('readable'): + self.readable = attrs.get('readable').value + if attrs.get('prot'): + self.prot = attrs.get('prot').value + if attrs.get('explicit'): + self.explicit = attrs.get('explicit').value + if attrs.get('new'): + self.new = attrs.get('new').value + if attrs.get('final'): + self.final = attrs.get('final').value + if attrs.get('writable'): + self.writable = attrs.get('writable').value + if attrs.get('add'): + self.add = attrs.get('add').value + if attrs.get('static'): + self.static = attrs.get('static').value + if attrs.get('remove'): + self.remove = attrs.get('remove').value + if attrs.get('sealed'): + self.sealed = attrs.get('sealed').value + if attrs.get('mutable'): + self.mutable = attrs.get('mutable').value + if attrs.get('gettable'): + self.gettable = attrs.get('gettable').value + if attrs.get('inline'): + self.inline = attrs.get('inline').value + if attrs.get('settable'): + self.settable = attrs.get('settable').value + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'templateparamlist': + obj_ = templateparamlistType.factory() + obj_.build(child_) + self.set_templateparamlist(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'type': + obj_ = linkedTextType.factory() + obj_.build(child_) + self.set_type(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'definition': + definition_ = '' + for text__content_ in child_.childNodes: + definition_ += text__content_.nodeValue + self.definition = definition_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'argsstring': + argsstring_ = '' + for text__content_ in child_.childNodes: + argsstring_ += text__content_.nodeValue + self.argsstring = argsstring_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'name': + name_ = '' + for text__content_ in child_.childNodes: + name_ += text__content_.nodeValue + self.name = name_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'read': + read_ = '' + for text__content_ in child_.childNodes: + read_ += text__content_.nodeValue + self.read = read_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'write': + write_ = '' + for text__content_ in child_.childNodes: + write_ += text__content_.nodeValue + self.write = write_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'bitfield': + bitfield_ = '' + for text__content_ in child_.childNodes: + bitfield_ += text__content_.nodeValue + self.bitfield = bitfield_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'reimplements': + obj_ = reimplementType.factory() + obj_.build(child_) + self.reimplements.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'reimplementedby': + obj_ = reimplementType.factory() + obj_.build(child_) + self.reimplementedby.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'param': + obj_ = paramType.factory() + obj_.build(child_) + self.param.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'enumvalue': + obj_ = enumvalueType.factory() + obj_.build(child_) + self.enumvalue.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'initializer': + obj_ = linkedTextType.factory() + obj_.build(child_) + self.set_initializer(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'exceptions': + obj_ = linkedTextType.factory() + obj_.build(child_) + self.set_exceptions(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'briefdescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_briefdescription(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'detaileddescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_detaileddescription(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'inbodydescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_inbodydescription(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'location': + obj_ = locationType.factory() + obj_.build(child_) + self.set_location(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'references': + obj_ = referenceType.factory() + obj_.build(child_) + self.references.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'referencedby': + obj_ = referenceType.factory() + obj_.build(child_) + self.referencedby.append(obj_) +# end class memberdefType + + +class definition(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if definition.subclass: + return definition.subclass(*args_, **kwargs_) + else: + return definition(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='definition', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='definition') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='definition'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='definition'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='definition'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class definition + + +class argsstring(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if argsstring.subclass: + return argsstring.subclass(*args_, **kwargs_) + else: + return argsstring(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='argsstring', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='argsstring') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='argsstring'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='argsstring'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='argsstring'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class argsstring + + +class read(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if read.subclass: + return read.subclass(*args_, **kwargs_) + else: + return read(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='read', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='read') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='read'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='read'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='read'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class read + + +class write(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if write.subclass: + return write.subclass(*args_, **kwargs_) + else: + return write(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='write', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='write') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='write'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='write'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='write'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class write + + +class bitfield(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if bitfield.subclass: + return bitfield.subclass(*args_, **kwargs_) + else: + return bitfield(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='bitfield', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='bitfield') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='bitfield'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='bitfield'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='bitfield'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class bitfield + + +class descriptionType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, title=None, para=None, sect1=None, internal=None, mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if descriptionType.subclass: + return descriptionType.subclass(*args_, **kwargs_) + else: + return descriptionType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_title(self): return self.title + def set_title(self, title): self.title = title + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect1(self): return self.sect1 + def set_sect1(self, sect1): self.sect1 = sect1 + def add_sect1(self, value): self.sect1.append(value) + def insert_sect1(self, index, value): self.sect1[index] = value + def get_internal(self): return self.internal + def set_internal(self, internal): self.internal = internal + def export(self, outfile, level, namespace_='', name_='descriptionType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='descriptionType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='descriptionType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='descriptionType'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.title is not None or + self.para is not None or + self.sect1 is not None or + self.internal is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='descriptionType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'title': + childobj_ = docTitleType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'title', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect1': + childobj_ = docSect1Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect1', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'internal': + childobj_ = docInternalType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'internal', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class descriptionType + + +class enumvalueType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, prot=None, id=None, name=None, initializer=None, briefdescription=None, detaileddescription=None, mixedclass_=None, content_=None): + self.prot = prot + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if enumvalueType.subclass: + return enumvalueType.subclass(*args_, **kwargs_) + else: + return enumvalueType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_name(self): return self.name + def set_name(self, name): self.name = name + def get_initializer(self): return self.initializer + def set_initializer(self, initializer): self.initializer = initializer + def get_briefdescription(self): return self.briefdescription + def set_briefdescription(self, briefdescription): self.briefdescription = briefdescription + def get_detaileddescription(self): return self.detaileddescription + def set_detaileddescription(self, detaileddescription): self.detaileddescription = detaileddescription + def get_prot(self): return self.prot + def set_prot(self, prot): self.prot = prot + def get_id(self): return self.id + def set_id(self, id): self.id = id + def export(self, outfile, level, namespace_='', name_='enumvalueType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='enumvalueType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='enumvalueType'): + if self.prot is not None: + outfile.write(' prot=%s' % (quote_attrib(self.prot), )) + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='enumvalueType'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.name is not None or + self.initializer is not None or + self.briefdescription is not None or + self.detaileddescription is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='enumvalueType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.prot is not None: + showIndent(outfile, level) + outfile.write('prot = "%s",\n' % (self.prot,)) + if self.id is not None: + showIndent(outfile, level) + outfile.write('id = %s,\n' % (self.id,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('prot'): + self.prot = attrs.get('prot').value + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'name': + value_ = [] + for text_ in child_.childNodes: + value_.append(text_.nodeValue) + valuestr_ = ''.join(value_) + obj_ = self.mixedclass_(MixedContainer.CategorySimple, + MixedContainer.TypeString, 'name', valuestr_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'initializer': + childobj_ = linkedTextType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'initializer', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'briefdescription': + childobj_ = descriptionType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'briefdescription', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'detaileddescription': + childobj_ = descriptionType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'detaileddescription', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class enumvalueType + + +class templateparamlistType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, param=None): + if param is None: + self.param = [] + else: + self.param = param + def factory(*args_, **kwargs_): + if templateparamlistType.subclass: + return templateparamlistType.subclass(*args_, **kwargs_) + else: + return templateparamlistType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_param(self): return self.param + def set_param(self, param): self.param = param + def add_param(self, value): self.param.append(value) + def insert_param(self, index, value): self.param[index] = value + def export(self, outfile, level, namespace_='', name_='templateparamlistType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='templateparamlistType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='templateparamlistType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='templateparamlistType'): + for param_ in self.param: + param_.export(outfile, level, namespace_, name_='param') + def hasContent_(self): + if ( + self.param is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='templateparamlistType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('param=[\n') + level += 1 + for param in self.param: + showIndent(outfile, level) + outfile.write('model_.param(\n') + param.exportLiteral(outfile, level, name_='param') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'param': + obj_ = paramType.factory() + obj_.build(child_) + self.param.append(obj_) +# end class templateparamlistType + + +class paramType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, type_=None, declname=None, defname=None, array=None, defval=None, briefdescription=None): + self.type_ = type_ + self.declname = declname + self.defname = defname + self.array = array + self.defval = defval + self.briefdescription = briefdescription + def factory(*args_, **kwargs_): + if paramType.subclass: + return paramType.subclass(*args_, **kwargs_) + else: + return paramType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_type(self): return self.type_ + def set_type(self, type_): self.type_ = type_ + def get_declname(self): return self.declname + def set_declname(self, declname): self.declname = declname + def get_defname(self): return self.defname + def set_defname(self, defname): self.defname = defname + def get_array(self): return self.array + def set_array(self, array): self.array = array + def get_defval(self): return self.defval + def set_defval(self, defval): self.defval = defval + def get_briefdescription(self): return self.briefdescription + def set_briefdescription(self, briefdescription): self.briefdescription = briefdescription + def export(self, outfile, level, namespace_='', name_='paramType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='paramType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='paramType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='paramType'): + if self.type_: + self.type_.export(outfile, level, namespace_, name_='type') + if self.declname is not None: + showIndent(outfile, level) + outfile.write('<%sdeclname>%s\n' % (namespace_, self.format_string(quote_xml(self.declname).encode(ExternalEncoding), input_name='declname'), namespace_)) + if self.defname is not None: + showIndent(outfile, level) + outfile.write('<%sdefname>%s\n' % (namespace_, self.format_string(quote_xml(self.defname).encode(ExternalEncoding), input_name='defname'), namespace_)) + if self.array is not None: + showIndent(outfile, level) + outfile.write('<%sarray>%s\n' % (namespace_, self.format_string(quote_xml(self.array).encode(ExternalEncoding), input_name='array'), namespace_)) + if self.defval: + self.defval.export(outfile, level, namespace_, name_='defval') + if self.briefdescription: + self.briefdescription.export(outfile, level, namespace_, name_='briefdescription') + def hasContent_(self): + if ( + self.type_ is not None or + self.declname is not None or + self.defname is not None or + self.array is not None or + self.defval is not None or + self.briefdescription is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='paramType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.type_: + showIndent(outfile, level) + outfile.write('type_=model_.linkedTextType(\n') + self.type_.exportLiteral(outfile, level, name_='type') + showIndent(outfile, level) + outfile.write('),\n') + showIndent(outfile, level) + outfile.write('declname=%s,\n' % quote_python(self.declname).encode(ExternalEncoding)) + showIndent(outfile, level) + outfile.write('defname=%s,\n' % quote_python(self.defname).encode(ExternalEncoding)) + showIndent(outfile, level) + outfile.write('array=%s,\n' % quote_python(self.array).encode(ExternalEncoding)) + if self.defval: + showIndent(outfile, level) + outfile.write('defval=model_.linkedTextType(\n') + self.defval.exportLiteral(outfile, level, name_='defval') + showIndent(outfile, level) + outfile.write('),\n') + if self.briefdescription: + showIndent(outfile, level) + outfile.write('briefdescription=model_.descriptionType(\n') + self.briefdescription.exportLiteral(outfile, level, name_='briefdescription') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'type': + obj_ = linkedTextType.factory() + obj_.build(child_) + self.set_type(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'declname': + declname_ = '' + for text__content_ in child_.childNodes: + declname_ += text__content_.nodeValue + self.declname = declname_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'defname': + defname_ = '' + for text__content_ in child_.childNodes: + defname_ += text__content_.nodeValue + self.defname = defname_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'array': + array_ = '' + for text__content_ in child_.childNodes: + array_ += text__content_.nodeValue + self.array = array_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'defval': + obj_ = linkedTextType.factory() + obj_.build(child_) + self.set_defval(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'briefdescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_briefdescription(obj_) +# end class paramType + + +class declname(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if declname.subclass: + return declname.subclass(*args_, **kwargs_) + else: + return declname(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='declname', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='declname') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='declname'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='declname'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='declname'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class declname + + +class defname(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if defname.subclass: + return defname.subclass(*args_, **kwargs_) + else: + return defname(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='defname', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='defname') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='defname'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='defname'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='defname'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class defname + + +class array(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if array.subclass: + return array.subclass(*args_, **kwargs_) + else: + return array(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='array', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='array') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='array'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='array'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='array'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class array + + +class linkedTextType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, ref=None, mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if linkedTextType.subclass: + return linkedTextType.subclass(*args_, **kwargs_) + else: + return linkedTextType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_ref(self): return self.ref + def set_ref(self, ref): self.ref = ref + def add_ref(self, value): self.ref.append(value) + def insert_ref(self, index, value): self.ref[index] = value + def export(self, outfile, level, namespace_='', name_='linkedTextType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='linkedTextType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='linkedTextType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='linkedTextType'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.ref is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='linkedTextType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'ref': + childobj_ = docRefTextType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'ref', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class linkedTextType + + +class graphType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, node=None): + if node is None: + self.node = [] + else: + self.node = node + def factory(*args_, **kwargs_): + if graphType.subclass: + return graphType.subclass(*args_, **kwargs_) + else: + return graphType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_node(self): return self.node + def set_node(self, node): self.node = node + def add_node(self, value): self.node.append(value) + def insert_node(self, index, value): self.node[index] = value + def export(self, outfile, level, namespace_='', name_='graphType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='graphType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='graphType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='graphType'): + for node_ in self.node: + node_.export(outfile, level, namespace_, name_='node') + def hasContent_(self): + if ( + self.node is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='graphType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('node=[\n') + level += 1 + for node in self.node: + showIndent(outfile, level) + outfile.write('model_.node(\n') + node.exportLiteral(outfile, level, name_='node') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'node': + obj_ = nodeType.factory() + obj_.build(child_) + self.node.append(obj_) +# end class graphType + + +class nodeType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, label=None, link=None, childnode=None): + self.id = id + self.label = label + self.link = link + if childnode is None: + self.childnode = [] + else: + self.childnode = childnode + def factory(*args_, **kwargs_): + if nodeType.subclass: + return nodeType.subclass(*args_, **kwargs_) + else: + return nodeType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_label(self): return self.label + def set_label(self, label): self.label = label + def get_link(self): return self.link + def set_link(self, link): self.link = link + def get_childnode(self): return self.childnode + def set_childnode(self, childnode): self.childnode = childnode + def add_childnode(self, value): self.childnode.append(value) + def insert_childnode(self, index, value): self.childnode[index] = value + def get_id(self): return self.id + def set_id(self, id): self.id = id + def export(self, outfile, level, namespace_='', name_='nodeType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='nodeType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='nodeType'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='nodeType'): + if self.label is not None: + showIndent(outfile, level) + outfile.write('<%slabel>%s\n' % (namespace_, self.format_string(quote_xml(self.label).encode(ExternalEncoding), input_name='label'), namespace_)) + if self.link: + self.link.export(outfile, level, namespace_, name_='link') + for childnode_ in self.childnode: + childnode_.export(outfile, level, namespace_, name_='childnode') + def hasContent_(self): + if ( + self.label is not None or + self.link is not None or + self.childnode is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='nodeType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.id is not None: + showIndent(outfile, level) + outfile.write('id = %s,\n' % (self.id,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('label=%s,\n' % quote_python(self.label).encode(ExternalEncoding)) + if self.link: + showIndent(outfile, level) + outfile.write('link=model_.linkType(\n') + self.link.exportLiteral(outfile, level, name_='link') + showIndent(outfile, level) + outfile.write('),\n') + showIndent(outfile, level) + outfile.write('childnode=[\n') + level += 1 + for childnode in self.childnode: + showIndent(outfile, level) + outfile.write('model_.childnode(\n') + childnode.exportLiteral(outfile, level, name_='childnode') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'label': + label_ = '' + for text__content_ in child_.childNodes: + label_ += text__content_.nodeValue + self.label = label_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'link': + obj_ = linkType.factory() + obj_.build(child_) + self.set_link(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'childnode': + obj_ = childnodeType.factory() + obj_.build(child_) + self.childnode.append(obj_) +# end class nodeType + + +class label(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if label.subclass: + return label.subclass(*args_, **kwargs_) + else: + return label(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='label', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='label') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='label'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='label'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='label'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class label + + +class childnodeType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, relation=None, refid=None, edgelabel=None): + self.relation = relation + self.refid = refid + if edgelabel is None: + self.edgelabel = [] + else: + self.edgelabel = edgelabel + def factory(*args_, **kwargs_): + if childnodeType.subclass: + return childnodeType.subclass(*args_, **kwargs_) + else: + return childnodeType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_edgelabel(self): return self.edgelabel + def set_edgelabel(self, edgelabel): self.edgelabel = edgelabel + def add_edgelabel(self, value): self.edgelabel.append(value) + def insert_edgelabel(self, index, value): self.edgelabel[index] = value + def get_relation(self): return self.relation + def set_relation(self, relation): self.relation = relation + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def export(self, outfile, level, namespace_='', name_='childnodeType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='childnodeType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='childnodeType'): + if self.relation is not None: + outfile.write(' relation=%s' % (quote_attrib(self.relation), )) + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + def exportChildren(self, outfile, level, namespace_='', name_='childnodeType'): + for edgelabel_ in self.edgelabel: + showIndent(outfile, level) + outfile.write('<%sedgelabel>%s\n' % (namespace_, self.format_string(quote_xml(edgelabel_).encode(ExternalEncoding), input_name='edgelabel'), namespace_)) + def hasContent_(self): + if ( + self.edgelabel is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='childnodeType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.relation is not None: + showIndent(outfile, level) + outfile.write('relation = "%s",\n' % (self.relation,)) + if self.refid is not None: + showIndent(outfile, level) + outfile.write('refid = %s,\n' % (self.refid,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('edgelabel=[\n') + level += 1 + for edgelabel in self.edgelabel: + showIndent(outfile, level) + outfile.write('%s,\n' % quote_python(edgelabel).encode(ExternalEncoding)) + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('relation'): + self.relation = attrs.get('relation').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'edgelabel': + edgelabel_ = '' + for text__content_ in child_.childNodes: + edgelabel_ += text__content_.nodeValue + self.edgelabel.append(edgelabel_) +# end class childnodeType + + +class edgelabel(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if edgelabel.subclass: + return edgelabel.subclass(*args_, **kwargs_) + else: + return edgelabel(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='edgelabel', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='edgelabel') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='edgelabel'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='edgelabel'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='edgelabel'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class edgelabel + + +class linkType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, refid=None, external=None, valueOf_=''): + self.refid = refid + self.external = external + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if linkType.subclass: + return linkType.subclass(*args_, **kwargs_) + else: + return linkType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def get_external(self): return self.external + def set_external(self, external): self.external = external + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='linkType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='linkType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='linkType'): + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + if self.external is not None: + outfile.write(' external=%s' % (self.format_string(quote_attrib(self.external).encode(ExternalEncoding), input_name='external'), )) + def exportChildren(self, outfile, level, namespace_='', name_='linkType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='linkType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.refid is not None: + showIndent(outfile, level) + outfile.write('refid = %s,\n' % (self.refid,)) + if self.external is not None: + showIndent(outfile, level) + outfile.write('external = %s,\n' % (self.external,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('refid'): + self.refid = attrs.get('refid').value + if attrs.get('external'): + self.external = attrs.get('external').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class linkType + + +class listingType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, codeline=None): + if codeline is None: + self.codeline = [] + else: + self.codeline = codeline + def factory(*args_, **kwargs_): + if listingType.subclass: + return listingType.subclass(*args_, **kwargs_) + else: + return listingType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_codeline(self): return self.codeline + def set_codeline(self, codeline): self.codeline = codeline + def add_codeline(self, value): self.codeline.append(value) + def insert_codeline(self, index, value): self.codeline[index] = value + def export(self, outfile, level, namespace_='', name_='listingType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='listingType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='listingType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='listingType'): + for codeline_ in self.codeline: + codeline_.export(outfile, level, namespace_, name_='codeline') + def hasContent_(self): + if ( + self.codeline is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='listingType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('codeline=[\n') + level += 1 + for codeline in self.codeline: + showIndent(outfile, level) + outfile.write('model_.codeline(\n') + codeline.exportLiteral(outfile, level, name_='codeline') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'codeline': + obj_ = codelineType.factory() + obj_.build(child_) + self.codeline.append(obj_) +# end class listingType + + +class codelineType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, external=None, lineno=None, refkind=None, refid=None, highlight=None): + self.external = external + self.lineno = lineno + self.refkind = refkind + self.refid = refid + if highlight is None: + self.highlight = [] + else: + self.highlight = highlight + def factory(*args_, **kwargs_): + if codelineType.subclass: + return codelineType.subclass(*args_, **kwargs_) + else: + return codelineType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_highlight(self): return self.highlight + def set_highlight(self, highlight): self.highlight = highlight + def add_highlight(self, value): self.highlight.append(value) + def insert_highlight(self, index, value): self.highlight[index] = value + def get_external(self): return self.external + def set_external(self, external): self.external = external + def get_lineno(self): return self.lineno + def set_lineno(self, lineno): self.lineno = lineno + def get_refkind(self): return self.refkind + def set_refkind(self, refkind): self.refkind = refkind + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def export(self, outfile, level, namespace_='', name_='codelineType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='codelineType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='codelineType'): + if self.external is not None: + outfile.write(' external=%s' % (quote_attrib(self.external), )) + if self.lineno is not None: + outfile.write(' lineno="%s"' % self.format_integer(self.lineno, input_name='lineno')) + if self.refkind is not None: + outfile.write(' refkind=%s' % (quote_attrib(self.refkind), )) + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + def exportChildren(self, outfile, level, namespace_='', name_='codelineType'): + for highlight_ in self.highlight: + highlight_.export(outfile, level, namespace_, name_='highlight') + def hasContent_(self): + if ( + self.highlight is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='codelineType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.external is not None: + showIndent(outfile, level) + outfile.write('external = "%s",\n' % (self.external,)) + if self.lineno is not None: + showIndent(outfile, level) + outfile.write('lineno = %s,\n' % (self.lineno,)) + if self.refkind is not None: + showIndent(outfile, level) + outfile.write('refkind = "%s",\n' % (self.refkind,)) + if self.refid is not None: + showIndent(outfile, level) + outfile.write('refid = %s,\n' % (self.refid,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('highlight=[\n') + level += 1 + for highlight in self.highlight: + showIndent(outfile, level) + outfile.write('model_.highlight(\n') + highlight.exportLiteral(outfile, level, name_='highlight') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('external'): + self.external = attrs.get('external').value + if attrs.get('lineno'): + try: + self.lineno = int(attrs.get('lineno').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (lineno): %s' % exp) + if attrs.get('refkind'): + self.refkind = attrs.get('refkind').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'highlight': + obj_ = highlightType.factory() + obj_.build(child_) + self.highlight.append(obj_) +# end class codelineType + + +class highlightType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, classxx=None, sp=None, ref=None, mixedclass_=None, content_=None): + self.classxx = classxx + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if highlightType.subclass: + return highlightType.subclass(*args_, **kwargs_) + else: + return highlightType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_sp(self): return self.sp + def set_sp(self, sp): self.sp = sp + def add_sp(self, value): self.sp.append(value) + def insert_sp(self, index, value): self.sp[index] = value + def get_ref(self): return self.ref + def set_ref(self, ref): self.ref = ref + def add_ref(self, value): self.ref.append(value) + def insert_ref(self, index, value): self.ref[index] = value + def get_class(self): return self.classxx + def set_class(self, classxx): self.classxx = classxx + def export(self, outfile, level, namespace_='', name_='highlightType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='highlightType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='highlightType'): + if self.classxx is not None: + outfile.write(' class=%s' % (quote_attrib(self.classxx), )) + def exportChildren(self, outfile, level, namespace_='', name_='highlightType'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.sp is not None or + self.ref is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='highlightType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.classxx is not None: + showIndent(outfile, level) + outfile.write('classxx = "%s",\n' % (self.classxx,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('class'): + self.classxx = attrs.get('class').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sp': + value_ = [] + for text_ in child_.childNodes: + value_.append(text_.nodeValue) + valuestr_ = ''.join(value_) + obj_ = self.mixedclass_(MixedContainer.CategorySimple, + MixedContainer.TypeString, 'sp', valuestr_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'ref': + childobj_ = docRefTextType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'ref', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class highlightType + + +class sp(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if sp.subclass: + return sp.subclass(*args_, **kwargs_) + else: + return sp(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='sp', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='sp') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='sp'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='sp'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='sp'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class sp + + +class referenceType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, endline=None, startline=None, refid=None, compoundref=None, valueOf_='', mixedclass_=None, content_=None): + self.endline = endline + self.startline = startline + self.refid = refid + self.compoundref = compoundref + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if referenceType.subclass: + return referenceType.subclass(*args_, **kwargs_) + else: + return referenceType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_endline(self): return self.endline + def set_endline(self, endline): self.endline = endline + def get_startline(self): return self.startline + def set_startline(self, startline): self.startline = startline + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def get_compoundref(self): return self.compoundref + def set_compoundref(self, compoundref): self.compoundref = compoundref + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='referenceType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='referenceType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='referenceType'): + if self.endline is not None: + outfile.write(' endline="%s"' % self.format_integer(self.endline, input_name='endline')) + if self.startline is not None: + outfile.write(' startline="%s"' % self.format_integer(self.startline, input_name='startline')) + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + if self.compoundref is not None: + outfile.write(' compoundref=%s' % (self.format_string(quote_attrib(self.compoundref).encode(ExternalEncoding), input_name='compoundref'), )) + def exportChildren(self, outfile, level, namespace_='', name_='referenceType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='referenceType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.endline is not None: + showIndent(outfile, level) + outfile.write('endline = %s,\n' % (self.endline,)) + if self.startline is not None: + showIndent(outfile, level) + outfile.write('startline = %s,\n' % (self.startline,)) + if self.refid is not None: + showIndent(outfile, level) + outfile.write('refid = %s,\n' % (self.refid,)) + if self.compoundref is not None: + showIndent(outfile, level) + outfile.write('compoundref = %s,\n' % (self.compoundref,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('endline'): + try: + self.endline = int(attrs.get('endline').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (endline): %s' % exp) + if attrs.get('startline'): + try: + self.startline = int(attrs.get('startline').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (startline): %s' % exp) + if attrs.get('refid'): + self.refid = attrs.get('refid').value + if attrs.get('compoundref'): + self.compoundref = attrs.get('compoundref').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class referenceType + + +class locationType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, bodystart=None, line=None, bodyend=None, bodyfile=None, file=None, valueOf_=''): + self.bodystart = bodystart + self.line = line + self.bodyend = bodyend + self.bodyfile = bodyfile + self.file = file + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if locationType.subclass: + return locationType.subclass(*args_, **kwargs_) + else: + return locationType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_bodystart(self): return self.bodystart + def set_bodystart(self, bodystart): self.bodystart = bodystart + def get_line(self): return self.line + def set_line(self, line): self.line = line + def get_bodyend(self): return self.bodyend + def set_bodyend(self, bodyend): self.bodyend = bodyend + def get_bodyfile(self): return self.bodyfile + def set_bodyfile(self, bodyfile): self.bodyfile = bodyfile + def get_file(self): return self.file + def set_file(self, file): self.file = file + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='locationType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='locationType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='locationType'): + if self.bodystart is not None: + outfile.write(' bodystart="%s"' % self.format_integer(self.bodystart, input_name='bodystart')) + if self.line is not None: + outfile.write(' line="%s"' % self.format_integer(self.line, input_name='line')) + if self.bodyend is not None: + outfile.write(' bodyend="%s"' % self.format_integer(self.bodyend, input_name='bodyend')) + if self.bodyfile is not None: + outfile.write(' bodyfile=%s' % (self.format_string(quote_attrib(self.bodyfile).encode(ExternalEncoding), input_name='bodyfile'), )) + if self.file is not None: + outfile.write(' file=%s' % (self.format_string(quote_attrib(self.file).encode(ExternalEncoding), input_name='file'), )) + def exportChildren(self, outfile, level, namespace_='', name_='locationType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='locationType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.bodystart is not None: + showIndent(outfile, level) + outfile.write('bodystart = %s,\n' % (self.bodystart,)) + if self.line is not None: + showIndent(outfile, level) + outfile.write('line = %s,\n' % (self.line,)) + if self.bodyend is not None: + showIndent(outfile, level) + outfile.write('bodyend = %s,\n' % (self.bodyend,)) + if self.bodyfile is not None: + showIndent(outfile, level) + outfile.write('bodyfile = %s,\n' % (self.bodyfile,)) + if self.file is not None: + showIndent(outfile, level) + outfile.write('file = %s,\n' % (self.file,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('bodystart'): + try: + self.bodystart = int(attrs.get('bodystart').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (bodystart): %s' % exp) + if attrs.get('line'): + try: + self.line = int(attrs.get('line').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (line): %s' % exp) + if attrs.get('bodyend'): + try: + self.bodyend = int(attrs.get('bodyend').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (bodyend): %s' % exp) + if attrs.get('bodyfile'): + self.bodyfile = attrs.get('bodyfile').value + if attrs.get('file'): + self.file = attrs.get('file').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class locationType + + +class docSect1Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, title=None, para=None, sect2=None, internal=None, mixedclass_=None, content_=None): + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docSect1Type.subclass: + return docSect1Type.subclass(*args_, **kwargs_) + else: + return docSect1Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_title(self): return self.title + def set_title(self, title): self.title = title + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect2(self): return self.sect2 + def set_sect2(self, sect2): self.sect2 = sect2 + def add_sect2(self, value): self.sect2.append(value) + def insert_sect2(self, index, value): self.sect2[index] = value + def get_internal(self): return self.internal + def set_internal(self, internal): self.internal = internal + def get_id(self): return self.id + def set_id(self, id): self.id = id + def export(self, outfile, level, namespace_='', name_='docSect1Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docSect1Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docSect1Type'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docSect1Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.title is not None or + self.para is not None or + self.sect2 is not None or + self.internal is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docSect1Type'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.id is not None: + showIndent(outfile, level) + outfile.write('id = %s,\n' % (self.id,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'title': + childobj_ = docTitleType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'title', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect2': + childobj_ = docSect2Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect2', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'internal': + childobj_ = docInternalS1Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'internal', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docSect1Type + + +class docSect2Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, title=None, para=None, sect3=None, internal=None, mixedclass_=None, content_=None): + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docSect2Type.subclass: + return docSect2Type.subclass(*args_, **kwargs_) + else: + return docSect2Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_title(self): return self.title + def set_title(self, title): self.title = title + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect3(self): return self.sect3 + def set_sect3(self, sect3): self.sect3 = sect3 + def add_sect3(self, value): self.sect3.append(value) + def insert_sect3(self, index, value): self.sect3[index] = value + def get_internal(self): return self.internal + def set_internal(self, internal): self.internal = internal + def get_id(self): return self.id + def set_id(self, id): self.id = id + def export(self, outfile, level, namespace_='', name_='docSect2Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docSect2Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docSect2Type'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docSect2Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.title is not None or + self.para is not None or + self.sect3 is not None or + self.internal is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docSect2Type'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.id is not None: + showIndent(outfile, level) + outfile.write('id = %s,\n' % (self.id,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'title': + childobj_ = docTitleType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'title', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect3': + childobj_ = docSect3Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect3', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'internal': + childobj_ = docInternalS2Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'internal', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docSect2Type + + +class docSect3Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, title=None, para=None, sect4=None, internal=None, mixedclass_=None, content_=None): + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docSect3Type.subclass: + return docSect3Type.subclass(*args_, **kwargs_) + else: + return docSect3Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_title(self): return self.title + def set_title(self, title): self.title = title + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect4(self): return self.sect4 + def set_sect4(self, sect4): self.sect4 = sect4 + def add_sect4(self, value): self.sect4.append(value) + def insert_sect4(self, index, value): self.sect4[index] = value + def get_internal(self): return self.internal + def set_internal(self, internal): self.internal = internal + def get_id(self): return self.id + def set_id(self, id): self.id = id + def export(self, outfile, level, namespace_='', name_='docSect3Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docSect3Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docSect3Type'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docSect3Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.title is not None or + self.para is not None or + self.sect4 is not None or + self.internal is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docSect3Type'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.id is not None: + showIndent(outfile, level) + outfile.write('id = %s,\n' % (self.id,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'title': + childobj_ = docTitleType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'title', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect4': + childobj_ = docSect4Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect4', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'internal': + childobj_ = docInternalS3Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'internal', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docSect3Type + + +class docSect4Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, title=None, para=None, internal=None, mixedclass_=None, content_=None): + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docSect4Type.subclass: + return docSect4Type.subclass(*args_, **kwargs_) + else: + return docSect4Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_title(self): return self.title + def set_title(self, title): self.title = title + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_internal(self): return self.internal + def set_internal(self, internal): self.internal = internal + def get_id(self): return self.id + def set_id(self, id): self.id = id + def export(self, outfile, level, namespace_='', name_='docSect4Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docSect4Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docSect4Type'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docSect4Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.title is not None or + self.para is not None or + self.internal is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docSect4Type'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.id is not None: + showIndent(outfile, level) + outfile.write('id = %s,\n' % (self.id,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'title': + childobj_ = docTitleType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'title', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'internal': + childobj_ = docInternalS4Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'internal', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docSect4Type + + +class docInternalType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, para=None, sect1=None, mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docInternalType.subclass: + return docInternalType.subclass(*args_, **kwargs_) + else: + return docInternalType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect1(self): return self.sect1 + def set_sect1(self, sect1): self.sect1 = sect1 + def add_sect1(self, value): self.sect1.append(value) + def insert_sect1(self, index, value): self.sect1[index] = value + def export(self, outfile, level, namespace_='', name_='docInternalType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docInternalType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docInternalType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docInternalType'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.para is not None or + self.sect1 is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docInternalType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect1': + childobj_ = docSect1Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect1', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docInternalType + + +class docInternalS1Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, para=None, sect2=None, mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docInternalS1Type.subclass: + return docInternalS1Type.subclass(*args_, **kwargs_) + else: + return docInternalS1Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect2(self): return self.sect2 + def set_sect2(self, sect2): self.sect2 = sect2 + def add_sect2(self, value): self.sect2.append(value) + def insert_sect2(self, index, value): self.sect2[index] = value + def export(self, outfile, level, namespace_='', name_='docInternalS1Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docInternalS1Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docInternalS1Type'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docInternalS1Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.para is not None or + self.sect2 is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docInternalS1Type'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect2': + childobj_ = docSect2Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect2', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docInternalS1Type + + +class docInternalS2Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, para=None, sect3=None, mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docInternalS2Type.subclass: + return docInternalS2Type.subclass(*args_, **kwargs_) + else: + return docInternalS2Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect3(self): return self.sect3 + def set_sect3(self, sect3): self.sect3 = sect3 + def add_sect3(self, value): self.sect3.append(value) + def insert_sect3(self, index, value): self.sect3[index] = value + def export(self, outfile, level, namespace_='', name_='docInternalS2Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docInternalS2Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docInternalS2Type'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docInternalS2Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.para is not None or + self.sect3 is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docInternalS2Type'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect3': + childobj_ = docSect3Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect3', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docInternalS2Type + + +class docInternalS3Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, para=None, sect3=None, mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docInternalS3Type.subclass: + return docInternalS3Type.subclass(*args_, **kwargs_) + else: + return docInternalS3Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect3(self): return self.sect3 + def set_sect3(self, sect3): self.sect3 = sect3 + def add_sect3(self, value): self.sect3.append(value) + def insert_sect3(self, index, value): self.sect3[index] = value + def export(self, outfile, level, namespace_='', name_='docInternalS3Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docInternalS3Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docInternalS3Type'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docInternalS3Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.para is not None or + self.sect3 is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docInternalS3Type'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect3': + childobj_ = docSect4Type.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'sect3', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docInternalS3Type + + +class docInternalS4Type(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, para=None, mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docInternalS4Type.subclass: + return docInternalS4Type.subclass(*args_, **kwargs_) + else: + return docInternalS4Type(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def export(self, outfile, level, namespace_='', name_='docInternalS4Type', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docInternalS4Type') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docInternalS4Type'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docInternalS4Type'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.para is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docInternalS4Type'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + childobj_ = docParaType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'para', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docInternalS4Type + + +class docTitleType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_='', mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docTitleType.subclass: + return docTitleType.subclass(*args_, **kwargs_) + else: + return docTitleType(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docTitleType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docTitleType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docTitleType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docTitleType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docTitleType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docTitleType + + +class docParaType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_='', mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docParaType.subclass: + return docParaType.subclass(*args_, **kwargs_) + else: + return docParaType(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docParaType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docParaType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docParaType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docParaType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docParaType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docParaType + + +class docMarkupType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_='', mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docMarkupType.subclass: + return docMarkupType.subclass(*args_, **kwargs_) + else: + return docMarkupType(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docMarkupType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docMarkupType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docMarkupType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docMarkupType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docMarkupType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docMarkupType + + +class docURLLink(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, url=None, valueOf_='', mixedclass_=None, content_=None): + self.url = url + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docURLLink.subclass: + return docURLLink.subclass(*args_, **kwargs_) + else: + return docURLLink(*args_, **kwargs_) + factory = staticmethod(factory) + def get_url(https://github.com/self): return self.url + def set_url(https://github.com/self,%20url): self.url = url + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docURLLink', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docURLLink') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docURLLink'): + if self.url is not None: + outfile.write(' url=%s' % (self.format_string(quote_attrib(self.url).encode(ExternalEncoding), input_name='url'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docURLLink'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docURLLink'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.url is not None: + showIndent(outfile, level) + outfile.write('url = %s,\n' % (self.url,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('url'): + self.url = attrs.get('url').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docURLLink + + +class docAnchorType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docAnchorType.subclass: + return docAnchorType.subclass(*args_, **kwargs_) + else: + return docAnchorType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_id(self): return self.id + def set_id(self, id): self.id = id + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docAnchorType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docAnchorType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docAnchorType'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docAnchorType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docAnchorType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.id is not None: + showIndent(outfile, level) + outfile.write('id = %s,\n' % (self.id,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docAnchorType + + +class docFormulaType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docFormulaType.subclass: + return docFormulaType.subclass(*args_, **kwargs_) + else: + return docFormulaType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_id(self): return self.id + def set_id(self, id): self.id = id + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docFormulaType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docFormulaType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docFormulaType'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docFormulaType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docFormulaType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.id is not None: + showIndent(outfile, level) + outfile.write('id = %s,\n' % (self.id,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docFormulaType + + +class docIndexEntryType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, primaryie=None, secondaryie=None): + self.primaryie = primaryie + self.secondaryie = secondaryie + def factory(*args_, **kwargs_): + if docIndexEntryType.subclass: + return docIndexEntryType.subclass(*args_, **kwargs_) + else: + return docIndexEntryType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_primaryie(self): return self.primaryie + def set_primaryie(self, primaryie): self.primaryie = primaryie + def get_secondaryie(self): return self.secondaryie + def set_secondaryie(self, secondaryie): self.secondaryie = secondaryie + def export(self, outfile, level, namespace_='', name_='docIndexEntryType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docIndexEntryType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docIndexEntryType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docIndexEntryType'): + if self.primaryie is not None: + showIndent(outfile, level) + outfile.write('<%sprimaryie>%s\n' % (namespace_, self.format_string(quote_xml(self.primaryie).encode(ExternalEncoding), input_name='primaryie'), namespace_)) + if self.secondaryie is not None: + showIndent(outfile, level) + outfile.write('<%ssecondaryie>%s\n' % (namespace_, self.format_string(quote_xml(self.secondaryie).encode(ExternalEncoding), input_name='secondaryie'), namespace_)) + def hasContent_(self): + if ( + self.primaryie is not None or + self.secondaryie is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docIndexEntryType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('primaryie=%s,\n' % quote_python(self.primaryie).encode(ExternalEncoding)) + showIndent(outfile, level) + outfile.write('secondaryie=%s,\n' % quote_python(self.secondaryie).encode(ExternalEncoding)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'primaryie': + primaryie_ = '' + for text__content_ in child_.childNodes: + primaryie_ += text__content_.nodeValue + self.primaryie = primaryie_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'secondaryie': + secondaryie_ = '' + for text__content_ in child_.childNodes: + secondaryie_ += text__content_.nodeValue + self.secondaryie = secondaryie_ +# end class docIndexEntryType + + +class docListType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, listitem=None): + if listitem is None: + self.listitem = [] + else: + self.listitem = listitem + def factory(*args_, **kwargs_): + if docListType.subclass: + return docListType.subclass(*args_, **kwargs_) + else: + return docListType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_listitem(self): return self.listitem + def set_listitem(self, listitem): self.listitem = listitem + def add_listitem(self, value): self.listitem.append(value) + def insert_listitem(self, index, value): self.listitem[index] = value + def export(self, outfile, level, namespace_='', name_='docListType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docListType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docListType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docListType'): + for listitem_ in self.listitem: + listitem_.export(outfile, level, namespace_, name_='listitem') + def hasContent_(self): + if ( + self.listitem is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docListType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('listitem=[\n') + level += 1 + for listitem in self.listitem: + showIndent(outfile, level) + outfile.write('model_.listitem(\n') + listitem.exportLiteral(outfile, level, name_='listitem') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'listitem': + obj_ = docListItemType.factory() + obj_.build(child_) + self.listitem.append(obj_) +# end class docListType + + +class docListItemType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, para=None): + if para is None: + self.para = [] + else: + self.para = para + def factory(*args_, **kwargs_): + if docListItemType.subclass: + return docListItemType.subclass(*args_, **kwargs_) + else: + return docListItemType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def export(self, outfile, level, namespace_='', name_='docListItemType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docListItemType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docListItemType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docListItemType'): + for para_ in self.para: + para_.export(outfile, level, namespace_, name_='para') + def hasContent_(self): + if ( + self.para is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docListItemType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('para=[\n') + level += 1 + for para in self.para: + showIndent(outfile, level) + outfile.write('model_.para(\n') + para.exportLiteral(outfile, level, name_='para') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + obj_ = docParaType.factory() + obj_.build(child_) + self.para.append(obj_) +# end class docListItemType + + +class docSimpleSectType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, kind=None, title=None, para=None): + self.kind = kind + self.title = title + if para is None: + self.para = [] + else: + self.para = para + def factory(*args_, **kwargs_): + if docSimpleSectType.subclass: + return docSimpleSectType.subclass(*args_, **kwargs_) + else: + return docSimpleSectType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_title(self): return self.title + def set_title(self, title): self.title = title + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_kind(self): return self.kind + def set_kind(self, kind): self.kind = kind + def export(self, outfile, level, namespace_='', name_='docSimpleSectType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docSimpleSectType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docSimpleSectType'): + if self.kind is not None: + outfile.write(' kind=%s' % (quote_attrib(self.kind), )) + def exportChildren(self, outfile, level, namespace_='', name_='docSimpleSectType'): + if self.title: + self.title.export(outfile, level, namespace_, name_='title') + for para_ in self.para: + para_.export(outfile, level, namespace_, name_='para') + def hasContent_(self): + if ( + self.title is not None or + self.para is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docSimpleSectType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.kind is not None: + showIndent(outfile, level) + outfile.write('kind = "%s",\n' % (self.kind,)) + def exportLiteralChildren(self, outfile, level, name_): + if self.title: + showIndent(outfile, level) + outfile.write('title=model_.docTitleType(\n') + self.title.exportLiteral(outfile, level, name_='title') + showIndent(outfile, level) + outfile.write('),\n') + showIndent(outfile, level) + outfile.write('para=[\n') + level += 1 + for para in self.para: + showIndent(outfile, level) + outfile.write('model_.para(\n') + para.exportLiteral(outfile, level, name_='para') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('kind'): + self.kind = attrs.get('kind').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'title': + obj_ = docTitleType.factory() + obj_.build(child_) + self.set_title(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + obj_ = docParaType.factory() + obj_.build(child_) + self.para.append(obj_) +# end class docSimpleSectType + + +class docVarListEntryType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, term=None): + self.term = term + def factory(*args_, **kwargs_): + if docVarListEntryType.subclass: + return docVarListEntryType.subclass(*args_, **kwargs_) + else: + return docVarListEntryType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_term(self): return self.term + def set_term(self, term): self.term = term + def export(self, outfile, level, namespace_='', name_='docVarListEntryType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docVarListEntryType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docVarListEntryType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docVarListEntryType'): + if self.term: + self.term.export(outfile, level, namespace_, name_='term', ) + def hasContent_(self): + if ( + self.term is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docVarListEntryType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + if self.term: + showIndent(outfile, level) + outfile.write('term=model_.docTitleType(\n') + self.term.exportLiteral(outfile, level, name_='term') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'term': + obj_ = docTitleType.factory() + obj_.build(child_) + self.set_term(obj_) +# end class docVarListEntryType + + +class docVariableListType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if docVariableListType.subclass: + return docVariableListType.subclass(*args_, **kwargs_) + else: + return docVariableListType(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docVariableListType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docVariableListType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docVariableListType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docVariableListType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docVariableListType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docVariableListType + + +class docRefTextType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, refid=None, kindref=None, external=None, valueOf_='', mixedclass_=None, content_=None): + self.refid = refid + self.kindref = kindref + self.external = external + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docRefTextType.subclass: + return docRefTextType.subclass(*args_, **kwargs_) + else: + return docRefTextType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def get_kindref(self): return self.kindref + def set_kindref(self, kindref): self.kindref = kindref + def get_external(self): return self.external + def set_external(self, external): self.external = external + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docRefTextType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docRefTextType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docRefTextType'): + if self.refid is not None: + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + if self.kindref is not None: + outfile.write(' kindref=%s' % (quote_attrib(self.kindref), )) + if self.external is not None: + outfile.write(' external=%s' % (self.format_string(quote_attrib(self.external).encode(ExternalEncoding), input_name='external'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docRefTextType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docRefTextType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.refid is not None: + showIndent(outfile, level) + outfile.write('refid = %s,\n' % (self.refid,)) + if self.kindref is not None: + showIndent(outfile, level) + outfile.write('kindref = "%s",\n' % (self.kindref,)) + if self.external is not None: + showIndent(outfile, level) + outfile.write('external = %s,\n' % (self.external,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('refid'): + self.refid = attrs.get('refid').value + if attrs.get('kindref'): + self.kindref = attrs.get('kindref').value + if attrs.get('external'): + self.external = attrs.get('external').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docRefTextType + + +class docTableType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, rows=None, cols=None, row=None, caption=None): + self.rows = rows + self.cols = cols + if row is None: + self.row = [] + else: + self.row = row + self.caption = caption + def factory(*args_, **kwargs_): + if docTableType.subclass: + return docTableType.subclass(*args_, **kwargs_) + else: + return docTableType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_row(self): return self.row + def set_row(self, row): self.row = row + def add_row(self, value): self.row.append(value) + def insert_row(self, index, value): self.row[index] = value + def get_caption(self): return self.caption + def set_caption(self, caption): self.caption = caption + def get_rows(self): return self.rows + def set_rows(self, rows): self.rows = rows + def get_cols(self): return self.cols + def set_cols(self, cols): self.cols = cols + def export(self, outfile, level, namespace_='', name_='docTableType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docTableType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docTableType'): + if self.rows is not None: + outfile.write(' rows="%s"' % self.format_integer(self.rows, input_name='rows')) + if self.cols is not None: + outfile.write(' cols="%s"' % self.format_integer(self.cols, input_name='cols')) + def exportChildren(self, outfile, level, namespace_='', name_='docTableType'): + for row_ in self.row: + row_.export(outfile, level, namespace_, name_='row') + if self.caption: + self.caption.export(outfile, level, namespace_, name_='caption') + def hasContent_(self): + if ( + self.row is not None or + self.caption is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docTableType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.rows is not None: + showIndent(outfile, level) + outfile.write('rows = %s,\n' % (self.rows,)) + if self.cols is not None: + showIndent(outfile, level) + outfile.write('cols = %s,\n' % (self.cols,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('row=[\n') + level += 1 + for row in self.row: + showIndent(outfile, level) + outfile.write('model_.row(\n') + row.exportLiteral(outfile, level, name_='row') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + if self.caption: + showIndent(outfile, level) + outfile.write('caption=model_.docCaptionType(\n') + self.caption.exportLiteral(outfile, level, name_='caption') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('rows'): + try: + self.rows = int(attrs.get('rows').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (rows): %s' % exp) + if attrs.get('cols'): + try: + self.cols = int(attrs.get('cols').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (cols): %s' % exp) + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'row': + obj_ = docRowType.factory() + obj_.build(child_) + self.row.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'caption': + obj_ = docCaptionType.factory() + obj_.build(child_) + self.set_caption(obj_) +# end class docTableType + + +class docRowType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, entry=None): + if entry is None: + self.entry = [] + else: + self.entry = entry + def factory(*args_, **kwargs_): + if docRowType.subclass: + return docRowType.subclass(*args_, **kwargs_) + else: + return docRowType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_entry(self): return self.entry + def set_entry(self, entry): self.entry = entry + def add_entry(self, value): self.entry.append(value) + def insert_entry(self, index, value): self.entry[index] = value + def export(self, outfile, level, namespace_='', name_='docRowType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docRowType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docRowType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docRowType'): + for entry_ in self.entry: + entry_.export(outfile, level, namespace_, name_='entry') + def hasContent_(self): + if ( + self.entry is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docRowType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('entry=[\n') + level += 1 + for entry in self.entry: + showIndent(outfile, level) + outfile.write('model_.entry(\n') + entry.exportLiteral(outfile, level, name_='entry') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'entry': + obj_ = docEntryType.factory() + obj_.build(child_) + self.entry.append(obj_) +# end class docRowType + + +class docEntryType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, thead=None, para=None): + self.thead = thead + if para is None: + self.para = [] + else: + self.para = para + def factory(*args_, **kwargs_): + if docEntryType.subclass: + return docEntryType.subclass(*args_, **kwargs_) + else: + return docEntryType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_thead(self): return self.thead + def set_thead(self, thead): self.thead = thead + def export(self, outfile, level, namespace_='', name_='docEntryType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docEntryType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docEntryType'): + if self.thead is not None: + outfile.write(' thead=%s' % (quote_attrib(self.thead), )) + def exportChildren(self, outfile, level, namespace_='', name_='docEntryType'): + for para_ in self.para: + para_.export(outfile, level, namespace_, name_='para') + def hasContent_(self): + if ( + self.para is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docEntryType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.thead is not None: + showIndent(outfile, level) + outfile.write('thead = "%s",\n' % (self.thead,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('para=[\n') + level += 1 + for para in self.para: + showIndent(outfile, level) + outfile.write('model_.para(\n') + para.exportLiteral(outfile, level, name_='para') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('thead'): + self.thead = attrs.get('thead').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + obj_ = docParaType.factory() + obj_.build(child_) + self.para.append(obj_) +# end class docEntryType + + +class docCaptionType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_='', mixedclass_=None, content_=None): + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docCaptionType.subclass: + return docCaptionType.subclass(*args_, **kwargs_) + else: + return docCaptionType(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docCaptionType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docCaptionType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docCaptionType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docCaptionType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docCaptionType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docCaptionType + + +class docHeadingType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, level=None, valueOf_='', mixedclass_=None, content_=None): + self.level = level + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docHeadingType.subclass: + return docHeadingType.subclass(*args_, **kwargs_) + else: + return docHeadingType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_level(self): return self.level + def set_level(self, level): self.level = level + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docHeadingType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docHeadingType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docHeadingType'): + if self.level is not None: + outfile.write(' level="%s"' % self.format_integer(self.level, input_name='level')) + def exportChildren(self, outfile, level, namespace_='', name_='docHeadingType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docHeadingType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.level is not None: + showIndent(outfile, level) + outfile.write('level = %s,\n' % (self.level,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('level'): + try: + self.level = int(attrs.get('level').value) + except ValueError, exp: + raise ValueError('Bad integer attribute (level): %s' % exp) + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docHeadingType + + +class docImageType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, width=None, type_=None, name=None, height=None, valueOf_='', mixedclass_=None, content_=None): + self.width = width + self.type_ = type_ + self.name = name + self.height = height + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docImageType.subclass: + return docImageType.subclass(*args_, **kwargs_) + else: + return docImageType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_width(self): return self.width + def set_width(self, width): self.width = width + def get_type(self): return self.type_ + def set_type(self, type_): self.type_ = type_ + def get_name(self): return self.name + def set_name(self, name): self.name = name + def get_height(self): return self.height + def set_height(self, height): self.height = height + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docImageType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docImageType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docImageType'): + if self.width is not None: + outfile.write(' width=%s' % (self.format_string(quote_attrib(self.width).encode(ExternalEncoding), input_name='width'), )) + if self.type_ is not None: + outfile.write(' type=%s' % (quote_attrib(self.type_), )) + if self.name is not None: + outfile.write(' name=%s' % (self.format_string(quote_attrib(self.name).encode(ExternalEncoding), input_name='name'), )) + if self.height is not None: + outfile.write(' height=%s' % (self.format_string(quote_attrib(self.height).encode(ExternalEncoding), input_name='height'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docImageType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docImageType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.width is not None: + showIndent(outfile, level) + outfile.write('width = %s,\n' % (self.width,)) + if self.type_ is not None: + showIndent(outfile, level) + outfile.write('type_ = "%s",\n' % (self.type_,)) + if self.name is not None: + showIndent(outfile, level) + outfile.write('name = %s,\n' % (self.name,)) + if self.height is not None: + showIndent(outfile, level) + outfile.write('height = %s,\n' % (self.height,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('width'): + self.width = attrs.get('width').value + if attrs.get('type'): + self.type_ = attrs.get('type').value + if attrs.get('name'): + self.name = attrs.get('name').value + if attrs.get('height'): + self.height = attrs.get('height').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docImageType + + +class docDotFileType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, name=None, valueOf_='', mixedclass_=None, content_=None): + self.name = name + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docDotFileType.subclass: + return docDotFileType.subclass(*args_, **kwargs_) + else: + return docDotFileType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_name(self): return self.name + def set_name(self, name): self.name = name + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docDotFileType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docDotFileType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docDotFileType'): + if self.name is not None: + outfile.write(' name=%s' % (self.format_string(quote_attrib(self.name).encode(ExternalEncoding), input_name='name'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docDotFileType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docDotFileType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.name is not None: + showIndent(outfile, level) + outfile.write('name = %s,\n' % (self.name,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('name'): + self.name = attrs.get('name').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docDotFileType + + +class docTocItemType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, valueOf_='', mixedclass_=None, content_=None): + self.id = id + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docTocItemType.subclass: + return docTocItemType.subclass(*args_, **kwargs_) + else: + return docTocItemType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_id(self): return self.id + def set_id(self, id): self.id = id + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docTocItemType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docTocItemType') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docTocItemType'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docTocItemType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docTocItemType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.id is not None: + showIndent(outfile, level) + outfile.write('id = %s,\n' % (self.id,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docTocItemType + + +class docTocListType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, tocitem=None): + if tocitem is None: + self.tocitem = [] + else: + self.tocitem = tocitem + def factory(*args_, **kwargs_): + if docTocListType.subclass: + return docTocListType.subclass(*args_, **kwargs_) + else: + return docTocListType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_tocitem(self): return self.tocitem + def set_tocitem(self, tocitem): self.tocitem = tocitem + def add_tocitem(self, value): self.tocitem.append(value) + def insert_tocitem(self, index, value): self.tocitem[index] = value + def export(self, outfile, level, namespace_='', name_='docTocListType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docTocListType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docTocListType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docTocListType'): + for tocitem_ in self.tocitem: + tocitem_.export(outfile, level, namespace_, name_='tocitem') + def hasContent_(self): + if ( + self.tocitem is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docTocListType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('tocitem=[\n') + level += 1 + for tocitem in self.tocitem: + showIndent(outfile, level) + outfile.write('model_.tocitem(\n') + tocitem.exportLiteral(outfile, level, name_='tocitem') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'tocitem': + obj_ = docTocItemType.factory() + obj_.build(child_) + self.tocitem.append(obj_) +# end class docTocListType + + +class docLanguageType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, langid=None, para=None): + self.langid = langid + if para is None: + self.para = [] + else: + self.para = para + def factory(*args_, **kwargs_): + if docLanguageType.subclass: + return docLanguageType.subclass(*args_, **kwargs_) + else: + return docLanguageType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_langid(self): return self.langid + def set_langid(self, langid): self.langid = langid + def export(self, outfile, level, namespace_='', name_='docLanguageType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docLanguageType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docLanguageType'): + if self.langid is not None: + outfile.write(' langid=%s' % (self.format_string(quote_attrib(self.langid).encode(ExternalEncoding), input_name='langid'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docLanguageType'): + for para_ in self.para: + para_.export(outfile, level, namespace_, name_='para') + def hasContent_(self): + if ( + self.para is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docLanguageType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.langid is not None: + showIndent(outfile, level) + outfile.write('langid = %s,\n' % (self.langid,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('para=[\n') + level += 1 + for para in self.para: + showIndent(outfile, level) + outfile.write('model_.para(\n') + para.exportLiteral(outfile, level, name_='para') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('langid'): + self.langid = attrs.get('langid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + obj_ = docParaType.factory() + obj_.build(child_) + self.para.append(obj_) +# end class docLanguageType + + +class docParamListType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, kind=None, parameteritem=None): + self.kind = kind + if parameteritem is None: + self.parameteritem = [] + else: + self.parameteritem = parameteritem + def factory(*args_, **kwargs_): + if docParamListType.subclass: + return docParamListType.subclass(*args_, **kwargs_) + else: + return docParamListType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_parameteritem(self): return self.parameteritem + def set_parameteritem(self, parameteritem): self.parameteritem = parameteritem + def add_parameteritem(self, value): self.parameteritem.append(value) + def insert_parameteritem(self, index, value): self.parameteritem[index] = value + def get_kind(self): return self.kind + def set_kind(self, kind): self.kind = kind + def export(self, outfile, level, namespace_='', name_='docParamListType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docParamListType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docParamListType'): + if self.kind is not None: + outfile.write(' kind=%s' % (quote_attrib(self.kind), )) + def exportChildren(self, outfile, level, namespace_='', name_='docParamListType'): + for parameteritem_ in self.parameteritem: + parameteritem_.export(outfile, level, namespace_, name_='parameteritem') + def hasContent_(self): + if ( + self.parameteritem is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docParamListType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.kind is not None: + showIndent(outfile, level) + outfile.write('kind = "%s",\n' % (self.kind,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('parameteritem=[\n') + level += 1 + for parameteritem in self.parameteritem: + showIndent(outfile, level) + outfile.write('model_.parameteritem(\n') + parameteritem.exportLiteral(outfile, level, name_='parameteritem') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('kind'): + self.kind = attrs.get('kind').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'parameteritem': + obj_ = docParamListItem.factory() + obj_.build(child_) + self.parameteritem.append(obj_) +# end class docParamListType + + +class docParamListItem(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, parameternamelist=None, parameterdescription=None): + if parameternamelist is None: + self.parameternamelist = [] + else: + self.parameternamelist = parameternamelist + self.parameterdescription = parameterdescription + def factory(*args_, **kwargs_): + if docParamListItem.subclass: + return docParamListItem.subclass(*args_, **kwargs_) + else: + return docParamListItem(*args_, **kwargs_) + factory = staticmethod(factory) + def get_parameternamelist(self): return self.parameternamelist + def set_parameternamelist(self, parameternamelist): self.parameternamelist = parameternamelist + def add_parameternamelist(self, value): self.parameternamelist.append(value) + def insert_parameternamelist(self, index, value): self.parameternamelist[index] = value + def get_parameterdescription(self): return self.parameterdescription + def set_parameterdescription(self, parameterdescription): self.parameterdescription = parameterdescription + def export(self, outfile, level, namespace_='', name_='docParamListItem', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docParamListItem') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docParamListItem'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docParamListItem'): + for parameternamelist_ in self.parameternamelist: + parameternamelist_.export(outfile, level, namespace_, name_='parameternamelist') + if self.parameterdescription: + self.parameterdescription.export(outfile, level, namespace_, name_='parameterdescription', ) + def hasContent_(self): + if ( + self.parameternamelist is not None or + self.parameterdescription is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docParamListItem'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('parameternamelist=[\n') + level += 1 + for parameternamelist in self.parameternamelist: + showIndent(outfile, level) + outfile.write('model_.parameternamelist(\n') + parameternamelist.exportLiteral(outfile, level, name_='parameternamelist') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + if self.parameterdescription: + showIndent(outfile, level) + outfile.write('parameterdescription=model_.descriptionType(\n') + self.parameterdescription.exportLiteral(outfile, level, name_='parameterdescription') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'parameternamelist': + obj_ = docParamNameList.factory() + obj_.build(child_) + self.parameternamelist.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'parameterdescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_parameterdescription(obj_) +# end class docParamListItem + + +class docParamNameList(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, parametername=None): + if parametername is None: + self.parametername = [] + else: + self.parametername = parametername + def factory(*args_, **kwargs_): + if docParamNameList.subclass: + return docParamNameList.subclass(*args_, **kwargs_) + else: + return docParamNameList(*args_, **kwargs_) + factory = staticmethod(factory) + def get_parametername(self): return self.parametername + def set_parametername(self, parametername): self.parametername = parametername + def add_parametername(self, value): self.parametername.append(value) + def insert_parametername(self, index, value): self.parametername[index] = value + def export(self, outfile, level, namespace_='', name_='docParamNameList', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docParamNameList') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docParamNameList'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docParamNameList'): + for parametername_ in self.parametername: + parametername_.export(outfile, level, namespace_, name_='parametername') + def hasContent_(self): + if ( + self.parametername is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docParamNameList'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('parametername=[\n') + level += 1 + for parametername in self.parametername: + showIndent(outfile, level) + outfile.write('model_.parametername(\n') + parametername.exportLiteral(outfile, level, name_='parametername') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'parametername': + obj_ = docParamName.factory() + obj_.build(child_) + self.parametername.append(obj_) +# end class docParamNameList + + +class docParamName(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, direction=None, ref=None, mixedclass_=None, content_=None): + self.direction = direction + if mixedclass_ is None: + self.mixedclass_ = MixedContainer + else: + self.mixedclass_ = mixedclass_ + if content_ is None: + self.content_ = [] + else: + self.content_ = content_ + def factory(*args_, **kwargs_): + if docParamName.subclass: + return docParamName.subclass(*args_, **kwargs_) + else: + return docParamName(*args_, **kwargs_) + factory = staticmethod(factory) + def get_ref(self): return self.ref + def set_ref(self, ref): self.ref = ref + def get_direction(self): return self.direction + def set_direction(self, direction): self.direction = direction + def export(self, outfile, level, namespace_='', name_='docParamName', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docParamName') + outfile.write('>') + self.exportChildren(outfile, level + 1, namespace_, name_) + outfile.write('\n' % (namespace_, name_)) + def exportAttributes(self, outfile, level, namespace_='', name_='docParamName'): + if self.direction is not None: + outfile.write(' direction=%s' % (quote_attrib(self.direction), )) + def exportChildren(self, outfile, level, namespace_='', name_='docParamName'): + for item_ in self.content_: + item_.export(outfile, level, item_.name, namespace_) + def hasContent_(self): + if ( + self.ref is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docParamName'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.direction is not None: + showIndent(outfile, level) + outfile.write('direction = "%s",\n' % (self.direction,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('content_ = [\n') + for item_ in self.content_: + item_.exportLiteral(outfile, level, name_) + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('direction'): + self.direction = attrs.get('direction').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'ref': + childobj_ = docRefTextType.factory() + childobj_.build(child_) + obj_ = self.mixedclass_(MixedContainer.CategoryComplex, + MixedContainer.TypeNone, 'ref', childobj_) + self.content_.append(obj_) + elif child_.nodeType == Node.TEXT_NODE: + obj_ = self.mixedclass_(MixedContainer.CategoryText, + MixedContainer.TypeNone, '', child_.nodeValue) + self.content_.append(obj_) +# end class docParamName + + +class docXRefSectType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, id=None, xreftitle=None, xrefdescription=None): + self.id = id + if xreftitle is None: + self.xreftitle = [] + else: + self.xreftitle = xreftitle + self.xrefdescription = xrefdescription + def factory(*args_, **kwargs_): + if docXRefSectType.subclass: + return docXRefSectType.subclass(*args_, **kwargs_) + else: + return docXRefSectType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_xreftitle(self): return self.xreftitle + def set_xreftitle(self, xreftitle): self.xreftitle = xreftitle + def add_xreftitle(self, value): self.xreftitle.append(value) + def insert_xreftitle(self, index, value): self.xreftitle[index] = value + def get_xrefdescription(self): return self.xrefdescription + def set_xrefdescription(self, xrefdescription): self.xrefdescription = xrefdescription + def get_id(self): return self.id + def set_id(self, id): self.id = id + def export(self, outfile, level, namespace_='', name_='docXRefSectType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docXRefSectType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docXRefSectType'): + if self.id is not None: + outfile.write(' id=%s' % (self.format_string(quote_attrib(self.id).encode(ExternalEncoding), input_name='id'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docXRefSectType'): + for xreftitle_ in self.xreftitle: + showIndent(outfile, level) + outfile.write('<%sxreftitle>%s\n' % (namespace_, self.format_string(quote_xml(xreftitle_).encode(ExternalEncoding), input_name='xreftitle'), namespace_)) + if self.xrefdescription: + self.xrefdescription.export(outfile, level, namespace_, name_='xrefdescription', ) + def hasContent_(self): + if ( + self.xreftitle is not None or + self.xrefdescription is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docXRefSectType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.id is not None: + showIndent(outfile, level) + outfile.write('id = %s,\n' % (self.id,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('xreftitle=[\n') + level += 1 + for xreftitle in self.xreftitle: + showIndent(outfile, level) + outfile.write('%s,\n' % quote_python(xreftitle).encode(ExternalEncoding)) + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + if self.xrefdescription: + showIndent(outfile, level) + outfile.write('xrefdescription=model_.descriptionType(\n') + self.xrefdescription.exportLiteral(outfile, level, name_='xrefdescription') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('id'): + self.id = attrs.get('id').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'xreftitle': + xreftitle_ = '' + for text__content_ in child_.childNodes: + xreftitle_ += text__content_.nodeValue + self.xreftitle.append(xreftitle_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'xrefdescription': + obj_ = descriptionType.factory() + obj_.build(child_) + self.set_xrefdescription(obj_) +# end class docXRefSectType + + +class docCopyType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, link=None, para=None, sect1=None, internal=None): + self.link = link + if para is None: + self.para = [] + else: + self.para = para + if sect1 is None: + self.sect1 = [] + else: + self.sect1 = sect1 + self.internal = internal + def factory(*args_, **kwargs_): + if docCopyType.subclass: + return docCopyType.subclass(*args_, **kwargs_) + else: + return docCopyType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_para(self): return self.para + def set_para(self, para): self.para = para + def add_para(self, value): self.para.append(value) + def insert_para(self, index, value): self.para[index] = value + def get_sect1(self): return self.sect1 + def set_sect1(self, sect1): self.sect1 = sect1 + def add_sect1(self, value): self.sect1.append(value) + def insert_sect1(self, index, value): self.sect1[index] = value + def get_internal(self): return self.internal + def set_internal(self, internal): self.internal = internal + def get_link(self): return self.link + def set_link(self, link): self.link = link + def export(self, outfile, level, namespace_='', name_='docCopyType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docCopyType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docCopyType'): + if self.link is not None: + outfile.write(' link=%s' % (self.format_string(quote_attrib(self.link).encode(ExternalEncoding), input_name='link'), )) + def exportChildren(self, outfile, level, namespace_='', name_='docCopyType'): + for para_ in self.para: + para_.export(outfile, level, namespace_, name_='para') + for sect1_ in self.sect1: + sect1_.export(outfile, level, namespace_, name_='sect1') + if self.internal: + self.internal.export(outfile, level, namespace_, name_='internal') + def hasContent_(self): + if ( + self.para is not None or + self.sect1 is not None or + self.internal is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docCopyType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.link is not None: + showIndent(outfile, level) + outfile.write('link = %s,\n' % (self.link,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('para=[\n') + level += 1 + for para in self.para: + showIndent(outfile, level) + outfile.write('model_.para(\n') + para.exportLiteral(outfile, level, name_='para') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + showIndent(outfile, level) + outfile.write('sect1=[\n') + level += 1 + for sect1 in self.sect1: + showIndent(outfile, level) + outfile.write('model_.sect1(\n') + sect1.exportLiteral(outfile, level, name_='sect1') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + if self.internal: + showIndent(outfile, level) + outfile.write('internal=model_.docInternalType(\n') + self.internal.exportLiteral(outfile, level, name_='internal') + showIndent(outfile, level) + outfile.write('),\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('link'): + self.link = attrs.get('link').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'para': + obj_ = docParaType.factory() + obj_.build(child_) + self.para.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'sect1': + obj_ = docSect1Type.factory() + obj_.build(child_) + self.sect1.append(obj_) + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'internal': + obj_ = docInternalType.factory() + obj_.build(child_) + self.set_internal(obj_) +# end class docCopyType + + +class docCharType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, char=None, valueOf_=''): + self.char = char + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if docCharType.subclass: + return docCharType.subclass(*args_, **kwargs_) + else: + return docCharType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_char(self): return self.char + def set_char(self, char): self.char = char + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docCharType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docCharType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docCharType'): + if self.char is not None: + outfile.write(' char=%s' % (quote_attrib(self.char), )) + def exportChildren(self, outfile, level, namespace_='', name_='docCharType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docCharType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.char is not None: + showIndent(outfile, level) + outfile.write('char = "%s",\n' % (self.char,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('char'): + self.char = attrs.get('char').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docCharType + + +class docEmptyType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, valueOf_=''): + self.valueOf_ = valueOf_ + def factory(*args_, **kwargs_): + if docEmptyType.subclass: + return docEmptyType.subclass(*args_, **kwargs_) + else: + return docEmptyType(*args_, **kwargs_) + factory = staticmethod(factory) + def getValueOf_(self): return self.valueOf_ + def setValueOf_(self, valueOf_): self.valueOf_ = valueOf_ + def export(self, outfile, level, namespace_='', name_='docEmptyType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='docEmptyType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='docEmptyType'): + pass + def exportChildren(self, outfile, level, namespace_='', name_='docEmptyType'): + if self.valueOf_.find('![CDATA')>-1: + value=quote_xml('%s' % self.valueOf_) + value=value.replace('![CDATA','') + outfile.write(value) + else: + outfile.write(quote_xml('%s' % self.valueOf_)) + def hasContent_(self): + if ( + self.valueOf_ is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='docEmptyType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + pass + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('valueOf_ = "%s",\n' % (self.valueOf_,)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + self.valueOf_ = '' + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + pass + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.TEXT_NODE: + self.valueOf_ += child_.nodeValue + elif child_.nodeType == Node.CDATA_SECTION_NODE: + self.valueOf_ += '![CDATA['+child_.nodeValue+']]' +# end class docEmptyType + + +USAGE_TEXT = """ +Usage: python .py [ -s ] +Options: + -s Use the SAX parser, not the minidom parser. +""" + +def usage(): + print USAGE_TEXT + sys.exit(1) + + +def parse(inFileName): + doc = minidom.parse(inFileName) + rootNode = doc.documentElement + rootObj = DoxygenType.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + sys.stdout.write('\n') + rootObj.export(sys.stdout, 0, name_="doxygen", + namespacedef_='') + return rootObj + + +def parseString(inString): + doc = minidom.parseString(inString) + rootNode = doc.documentElement + rootObj = DoxygenType.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + sys.stdout.write('\n') + rootObj.export(sys.stdout, 0, name_="doxygen", + namespacedef_='') + return rootObj + + +def parseLiteral(inFileName): + doc = minidom.parse(inFileName) + rootNode = doc.documentElement + rootObj = DoxygenType.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + sys.stdout.write('from compound import *\n\n') + sys.stdout.write('rootObj = doxygen(\n') + rootObj.exportLiteral(sys.stdout, 0, name_="doxygen") + sys.stdout.write(')\n') + return rootObj + + +def main(): + args = sys.argv[1:] + if len(args) == 1: + parse(args[0]) + else: + usage() + + +if __name__ == '__main__': + main() + #import pdb + #pdb.run('main()') + diff --git a/libs/network/doc/ext/breathe/breathe/parser/doxygen/index.py b/libs/network/doc/ext/breathe/breathe/parser/doxygen/index.py new file mode 100644 index 000000000..c8621d497 --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/parser/doxygen/index.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +""" +Generated Mon Feb 9 19:08:05 2009 by generateDS.py. +""" + +from xml.dom import minidom +from docutils import nodes + +import os +import sys +import breathe.parser.doxygen.compound + +import indexsuper as supermod + +class DoxygenTypeSub(supermod.DoxygenType): + def __init__(self, version=None, compound=None): + supermod.DoxygenType.__init__(self, version, compound) +supermod.DoxygenType.subclass = DoxygenTypeSub +# end class DoxygenTypeSub + + +class CompoundTypeSub(supermod.CompoundType): + def __init__(self, kind=None, refid=None, name='', member=None): + supermod.CompoundType.__init__(self, kind, refid, name, member) +supermod.CompoundType.subclass = CompoundTypeSub +# end class CompoundTypeSub + + +class MemberTypeSub(supermod.MemberType): + def __init__(self, kind=None, refid=None, name=''): + supermod.MemberType.__init__(self, kind, refid, name) +supermod.MemberType.subclass = MemberTypeSub +# end class MemberTypeSub + + +class ParseError(Exception): + pass + +def parse(inFilename): + + try: + doc = minidom.parse(inFilename) + except IOError, e: + raise ParseError(inFilename) + + rootNode = doc.documentElement + rootObj = supermod.DoxygenType.factory() + rootObj.build(rootNode) + + return rootObj + diff --git a/libs/network/doc/ext/breathe/breathe/parser/doxygen/indexsuper.py b/libs/network/doc/ext/breathe/breathe/parser/doxygen/indexsuper.py new file mode 100644 index 000000000..a99153019 --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/parser/doxygen/indexsuper.py @@ -0,0 +1,523 @@ +#!/usr/bin/env python + +# +# Generated Thu Jun 11 18:43:54 2009 by generateDS.py. +# + +import sys +import getopt +from string import lower as str_lower +from xml.dom import minidom +from xml.dom import Node + +# +# User methods +# +# Calls to the methods in these classes are generated by generateDS.py. +# You can replace these methods by re-implementing the following class +# in a module named generatedssuper.py. + +try: + from generatedssuper import GeneratedsSuper +except ImportError, exp: + + class GeneratedsSuper: + def format_string(self, input_data, input_name=''): + return input_data + def format_integer(self, input_data, input_name=''): + return '%d' % input_data + def format_float(self, input_data, input_name=''): + return '%f' % input_data + def format_double(self, input_data, input_name=''): + return '%e' % input_data + def format_boolean(self, input_data, input_name=''): + return '%s' % input_data + + +# +# If you have installed IPython you can uncomment and use the following. +# IPython is available from http://ipython.scipy.org/. +# + +## from IPython.Shell import IPShellEmbed +## args = '' +## ipshell = IPShellEmbed(args, +## banner = 'Dropping into IPython', +## exit_msg = 'Leaving Interpreter, back to program.') + +# Then use the following line where and when you want to drop into the +# IPython shell: +# ipshell(' -- Entering ipshell.\nHit Ctrl-D to exit') + +# +# Globals +# + +ExternalEncoding = 'ascii' + +# +# Support/utility functions. +# + +def showIndent(outfile, level): + for idx in range(level): + outfile.write(' ') + +def quote_xml(inStr): + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s1 = s1.replace('&', '&') + s1 = s1.replace('<', '<') + s1 = s1.replace('>', '>') + return s1 + +def quote_attrib(inStr): + s1 = (isinstance(inStr, basestring) and inStr or + '%s' % inStr) + s1 = s1.replace('&', '&') + s1 = s1.replace('<', '<') + s1 = s1.replace('>', '>') + if '"' in s1: + if "'" in s1: + s1 = '"%s"' % s1.replace('"', """) + else: + s1 = "'%s'" % s1 + else: + s1 = '"%s"' % s1 + return s1 + +def quote_python(inStr): + s1 = inStr + if s1.find("'") == -1: + if s1.find('\n') == -1: + return "'%s'" % s1 + else: + return "'''%s'''" % s1 + else: + if s1.find('"') != -1: + s1 = s1.replace('"', '\\"') + if s1.find('\n') == -1: + return '"%s"' % s1 + else: + return '"""%s"""' % s1 + + +class MixedContainer: + # Constants for category: + CategoryNone = 0 + CategoryText = 1 + CategorySimple = 2 + CategoryComplex = 3 + # Constants for content_type: + TypeNone = 0 + TypeText = 1 + TypeString = 2 + TypeInteger = 3 + TypeFloat = 4 + TypeDecimal = 5 + TypeDouble = 6 + TypeBoolean = 7 + def __init__(self, category, content_type, name, value): + self.category = category + self.content_type = content_type + self.name = name + self.value = value + def getCategory(self): + return self.category + def getContenttype(self, content_type): + return self.content_type + def getValue(self): + return self.value + def getName(self): + return self.name + def export(self, outfile, level, name, namespace): + if self.category == MixedContainer.CategoryText: + outfile.write(self.value) + elif self.category == MixedContainer.CategorySimple: + self.exportSimple(outfile, level, name) + else: # category == MixedContainer.CategoryComplex + self.value.export(outfile, level, namespace,name) + def exportSimple(self, outfile, level, name): + if self.content_type == MixedContainer.TypeString: + outfile.write('<%s>%s' % (self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeInteger or \ + self.content_type == MixedContainer.TypeBoolean: + outfile.write('<%s>%d' % (self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeFloat or \ + self.content_type == MixedContainer.TypeDecimal: + outfile.write('<%s>%f' % (self.name, self.value, self.name)) + elif self.content_type == MixedContainer.TypeDouble: + outfile.write('<%s>%g' % (self.name, self.value, self.name)) + def exportLiteral(self, outfile, level, name): + if self.category == MixedContainer.CategoryText: + showIndent(outfile, level) + outfile.write('MixedContainer(%d, %d, "%s", "%s"),\n' % \ + (self.category, self.content_type, self.name, self.value)) + elif self.category == MixedContainer.CategorySimple: + showIndent(outfile, level) + outfile.write('MixedContainer(%d, %d, "%s", "%s"),\n' % \ + (self.category, self.content_type, self.name, self.value)) + else: # category == MixedContainer.CategoryComplex + showIndent(outfile, level) + outfile.write('MixedContainer(%d, %d, "%s",\n' % \ + (self.category, self.content_type, self.name,)) + self.value.exportLiteral(outfile, level + 1) + showIndent(outfile, level) + outfile.write(')\n') + + +class _MemberSpec(object): + def __init__(self, name='', data_type='', container=0): + self.name = name + self.data_type = data_type + self.container = container + def set_name(self, name): self.name = name + def get_name(self): return self.name + def set_data_type(self, data_type): self.data_type = data_type + def get_data_type(self): return self.data_type + def set_container(self, container): self.container = container + def get_container(self): return self.container + + +# +# Data representation classes. +# + +class DoxygenType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, version=None, compound=None): + self.version = version + if compound is None: + self.compound = [] + else: + self.compound = compound + def factory(*args_, **kwargs_): + if DoxygenType.subclass: + return DoxygenType.subclass(*args_, **kwargs_) + else: + return DoxygenType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_compound(self): return self.compound + def set_compound(self, compound): self.compound = compound + def add_compound(self, value): self.compound.append(value) + def insert_compound(self, index, value): self.compound[index] = value + def get_version(self): return self.version + def set_version(self, version): self.version = version + def export(self, outfile, level, namespace_='', name_='DoxygenType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='DoxygenType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='DoxygenType'): + outfile.write(' version=%s' % (self.format_string(quote_attrib(self.version).encode(ExternalEncoding), input_name='version'), )) + def exportChildren(self, outfile, level, namespace_='', name_='DoxygenType'): + for compound_ in self.compound: + compound_.export(outfile, level, namespace_, name_='compound') + def hasContent_(self): + if ( + self.compound is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='DoxygenType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.version is not None: + showIndent(outfile, level) + outfile.write('version = %s,\n' % (self.version,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('compound=[\n') + level += 1 + for compound in self.compound: + showIndent(outfile, level) + outfile.write('model_.compound(\n') + compound.exportLiteral(outfile, level, name_='compound') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('version'): + self.version = attrs.get('version').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'compound': + obj_ = CompoundType.factory() + obj_.build(child_) + self.compound.append(obj_) +# end class DoxygenType + + +class CompoundType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, kind=None, refid=None, name=None, member=None): + self.kind = kind + self.refid = refid + self.name = name + if member is None: + self.member = [] + else: + self.member = member + def factory(*args_, **kwargs_): + if CompoundType.subclass: + return CompoundType.subclass(*args_, **kwargs_) + else: + return CompoundType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_name(self): return self.name + def set_name(self, name): self.name = name + def get_member(self): return self.member + def set_member(self, member): self.member = member + def add_member(self, value): self.member.append(value) + def insert_member(self, index, value): self.member[index] = value + def get_kind(self): return self.kind + def set_kind(self, kind): self.kind = kind + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def export(self, outfile, level, namespace_='', name_='CompoundType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='CompoundType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='CompoundType'): + outfile.write(' kind=%s' % (quote_attrib(self.kind), )) + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + def exportChildren(self, outfile, level, namespace_='', name_='CompoundType'): + if self.name is not None: + showIndent(outfile, level) + outfile.write('<%sname>%s\n' % (namespace_, self.format_string(quote_xml(self.name).encode(ExternalEncoding), input_name='name'), namespace_)) + for member_ in self.member: + member_.export(outfile, level, namespace_, name_='member') + def hasContent_(self): + if ( + self.name is not None or + self.member is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='CompoundType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.kind is not None: + showIndent(outfile, level) + outfile.write('kind = "%s",\n' % (self.kind,)) + if self.refid is not None: + showIndent(outfile, level) + outfile.write('refid = %s,\n' % (self.refid,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('name=%s,\n' % quote_python(self.name).encode(ExternalEncoding)) + showIndent(outfile, level) + outfile.write('member=[\n') + level += 1 + for member in self.member: + showIndent(outfile, level) + outfile.write('model_.member(\n') + member.exportLiteral(outfile, level, name_='member') + showIndent(outfile, level) + outfile.write('),\n') + level -= 1 + showIndent(outfile, level) + outfile.write('],\n') + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('kind'): + self.kind = attrs.get('kind').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'name': + name_ = '' + for text__content_ in child_.childNodes: + name_ += text__content_.nodeValue + self.name = name_ + elif child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'member': + obj_ = MemberType.factory() + obj_.build(child_) + self.member.append(obj_) +# end class CompoundType + + +class MemberType(GeneratedsSuper): + subclass = None + superclass = None + def __init__(self, kind=None, refid=None, name=None): + self.kind = kind + self.refid = refid + self.name = name + def factory(*args_, **kwargs_): + if MemberType.subclass: + return MemberType.subclass(*args_, **kwargs_) + else: + return MemberType(*args_, **kwargs_) + factory = staticmethod(factory) + def get_name(self): return self.name + def set_name(self, name): self.name = name + def get_kind(self): return self.kind + def set_kind(self, kind): self.kind = kind + def get_refid(self): return self.refid + def set_refid(self, refid): self.refid = refid + def export(self, outfile, level, namespace_='', name_='MemberType', namespacedef_=''): + showIndent(outfile, level) + outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) + self.exportAttributes(outfile, level, namespace_, name_='MemberType') + if self.hasContent_(): + outfile.write('>\n') + self.exportChildren(outfile, level + 1, namespace_, name_) + showIndent(outfile, level) + outfile.write('\n' % (namespace_, name_)) + else: + outfile.write(' />\n') + def exportAttributes(self, outfile, level, namespace_='', name_='MemberType'): + outfile.write(' kind=%s' % (quote_attrib(self.kind), )) + outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) + def exportChildren(self, outfile, level, namespace_='', name_='MemberType'): + if self.name is not None: + showIndent(outfile, level) + outfile.write('<%sname>%s\n' % (namespace_, self.format_string(quote_xml(self.name).encode(ExternalEncoding), input_name='name'), namespace_)) + def hasContent_(self): + if ( + self.name is not None + ): + return True + else: + return False + def exportLiteral(self, outfile, level, name_='MemberType'): + level += 1 + self.exportLiteralAttributes(outfile, level, name_) + if self.hasContent_(): + self.exportLiteralChildren(outfile, level, name_) + def exportLiteralAttributes(self, outfile, level, name_): + if self.kind is not None: + showIndent(outfile, level) + outfile.write('kind = "%s",\n' % (self.kind,)) + if self.refid is not None: + showIndent(outfile, level) + outfile.write('refid = %s,\n' % (self.refid,)) + def exportLiteralChildren(self, outfile, level, name_): + showIndent(outfile, level) + outfile.write('name=%s,\n' % quote_python(self.name).encode(ExternalEncoding)) + def build(self, node_): + attrs = node_.attributes + self.buildAttributes(attrs) + for child_ in node_.childNodes: + nodeName_ = child_.nodeName.split(':')[-1] + self.buildChildren(child_, nodeName_) + def buildAttributes(self, attrs): + if attrs.get('kind'): + self.kind = attrs.get('kind').value + if attrs.get('refid'): + self.refid = attrs.get('refid').value + def buildChildren(self, child_, nodeName_): + if child_.nodeType == Node.ELEMENT_NODE and \ + nodeName_ == 'name': + name_ = '' + for text__content_ in child_.childNodes: + name_ += text__content_.nodeValue + self.name = name_ +# end class MemberType + + +USAGE_TEXT = """ +Usage: python .py [ -s ] +Options: + -s Use the SAX parser, not the minidom parser. +""" + +def usage(): + print USAGE_TEXT + sys.exit(1) + + +def parse(inFileName): + doc = minidom.parse(inFileName) + rootNode = doc.documentElement + rootObj = DoxygenType.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + sys.stdout.write('\n') + rootObj.export(sys.stdout, 0, name_="doxygenindex", + namespacedef_='') + return rootObj + + +def parseString(inString): + doc = minidom.parseString(inString) + rootNode = doc.documentElement + rootObj = DoxygenType.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + sys.stdout.write('\n') + rootObj.export(sys.stdout, 0, name_="doxygenindex", + namespacedef_='') + return rootObj + + +def parseLiteral(inFileName): + doc = minidom.parse(inFileName) + rootNode = doc.documentElement + rootObj = DoxygenType.factory() + rootObj.build(rootNode) + # Enable Python to collect the space used by the DOM. + doc = None + sys.stdout.write('from index import *\n\n') + sys.stdout.write('rootObj = doxygenindex(\n') + rootObj.exportLiteral(sys.stdout, 0, name_="doxygenindex") + sys.stdout.write(')\n') + return rootObj + + +def main(): + args = sys.argv[1:] + if len(args) == 1: + parse(args[0]) + else: + usage() + + + + +if __name__ == '__main__': + main() + #import pdb + #pdb.run('main()') + diff --git a/libs/network/doc/ext/breathe/breathe/renderer/__init__.py b/libs/network/doc/ext/breathe/breathe/renderer/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/libs/network/doc/ext/breathe/breathe/renderer/rst/__init__.py b/libs/network/doc/ext/breathe/breathe/renderer/rst/__init__.py new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/renderer/rst/__init__.py @@ -0,0 +1,2 @@ + + diff --git a/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/__init__.py b/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/__init__.py new file mode 100644 index 000000000..cf205411d --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/__init__.py @@ -0,0 +1,292 @@ + +from breathe.renderer.rst.doxygen.base import Renderer +from breathe.renderer.rst.doxygen import index as indexrenderer +from breathe.renderer.rst.doxygen import compound as compoundrenderer + +from breathe.parser.doxygen import index, compound, compoundsuper + +class RstContentCreator(object): + + def __init__(self, list_type, dedent): + + self.list_type = list_type + self.dedent = dedent + + def __call__(self, text): + + # Remove the first line + text = "\n".join(text.split(u"\n")[1:]) + + # Remove starting whitespace + text = self.dedent(text) + + # Inspired by autodoc.py in Sphinx + result = self.list_type() + for line in text.split("\n"): + result.append(line, "") + + return result + +class UnicodeRenderer(Renderer): + + def render(self): + + return [self.node_factory.Text(self.data_object)] + +class NullRenderer(Renderer): + + def __init__(self): + pass + + def render(self): + return [] + +class DoxygenToRstRendererFactory(object): + + def __init__( + self, + renderers, + node_factory, + project_info, + state, + document, + domain_handler_factory, + domain_handler, + rst_content_creator, + member_filter, + target_handler + ): + + self.node_factory = node_factory + self.project_info = project_info + self.renderers = renderers + self.state = state + self.document = document + self.domain_handler_factory = domain_handler_factory + self.domain_handler = domain_handler + self.rst_content_creator = rst_content_creator + self.member_filter = member_filter + self.target_handler = target_handler + + def create_renderer(self, data_object): + + renderer_factory = self + + location = "" + + try: + location = data_object.location.file + except AttributeError: + # No location attribute + pass + + renderer_factory = self.create_domain_renderer_factory(location) + + return self.create_renderer_with_factory( + data_object, + renderer_factory, + renderer_factory.domain_handler + ) + + def create_renderer_with_factory( + self, + data_object, + renderer_factory, + domain_handler + ): + + Renderer = self.renderers[data_object.__class__] + + if data_object.__class__ == compound.docMarkupTypeSub: + + creator = self.node_factory.inline + if data_object.type_ == "emphasis": + creator = self.node_factory.emphasis + elif data_object.type_ == "computeroutput": + creator = self.node_factory.literal + elif data_object.type_ == "bold": + creator = self.node_factory.strong + elif data_object.type_ == "superscript": + creator = self.node_factory.superscript + elif data_object.type_ == "subscript": + creator = self.node_factory.subscript + elif data_object.type_ == "center": + print "Warning: does not currently handle 'center' text display" + elif data_object.type_ == "small": + print "Warning: does not currently handle 'small' text display" + + return Renderer( + creator, + self.project_info, + data_object, + renderer_factory, + self.node_factory, + self.state, + self.document, + domain_handler, + self.target_handler + ) + + if data_object.__class__ == compound.verbatimTypeSub: + + return Renderer( + self.rst_content_creator, + self.project_info, + data_object, + renderer_factory, + self.node_factory, + self.state, + self.document, + domain_handler, + self.target_handler + ) + + if data_object.__class__ == compound.memberdefTypeSub: + + if data_object.kind == "function": + Renderer = compoundrenderer.FuncMemberDefTypeSubRenderer + elif data_object.kind == "enum": + Renderer = compoundrenderer.EnumMemberDefTypeSubRenderer + elif data_object.kind == "typedef": + Renderer = compoundrenderer.TypedefMemberDefTypeSubRenderer + elif data_object.kind == "variable": + Renderer = compoundrenderer.VariableMemberDefTypeSubRenderer + + if data_object.__class__ == compound.docSimpleSectTypeSub: + if data_object.kind == "par": + Renderer = compoundrenderer.ParDocSimpleSectTypeSubRenderer + + return Renderer( + self.project_info, + data_object, + renderer_factory, + self.node_factory, + self.state, + self.document, + domain_handler, + self.target_handler + ) + + def create_domain_renderer_factory(self, location): + + if not location: + return self + + domain_handler = self.domain_handler_factory.create_domain_handler(location) + + return DomainRendererFactory( + self.renderers, + self.node_factory, + self.project_info, + self.state, + self.document, + self.domain_handler_factory, + domain_handler, + self.rst_content_creator, + self.member_filter, + self.target_handler + ) + + def create_member_renderer(self, data_object): + + name = data_object.name + + if self.member_filter.allow_member(name): + return self.create_renderer(data_object) + + return NullRenderer() + + def create_section_renderer(self, data_object): + + name = data_object.kind + + if self.member_filter.allow_section(name): + return self.create_renderer(data_object) + + return NullRenderer() + + +class DomainRendererFactory(DoxygenToRstRendererFactory): + + def create_renderer(self, data_object): + + return self.create_renderer_with_factory(data_object, self, self.domain_handler) + + +class CreateCompoundTypeSubRenderer(object): + + def __init__(self, parser_factory): + + self.parser_factory = parser_factory + + def __call__(self, project_info, *args): + + compound_parser = self.parser_factory.create_compound_parser(project_info) + return indexrenderer.CompoundTypeSubRenderer(compound_parser, project_info, *args) + + +class DoxygenToRstRendererFactoryCreator(object): + + def __init__( + self, + node_factory, + parser_factory, + domain_handler_factory_creator, + rst_content_creator + ): + + self.node_factory = node_factory + self.parser_factory = parser_factory + self.domain_handler_factory_creator = domain_handler_factory_creator + self.rst_content_creator = rst_content_creator + + def create_factory(self, project_info, state, document, member_filter, target_handler): + + renderers = { + index.DoxygenTypeSub : indexrenderer.DoxygenTypeSubRenderer, + index.CompoundTypeSub : CreateCompoundTypeSubRenderer(self.parser_factory), + compound.DoxygenTypeSub : compoundrenderer.DoxygenTypeSubRenderer, + compound.compounddefTypeSub : compoundrenderer.CompoundDefTypeSubRenderer, + compound.sectiondefTypeSub : compoundrenderer.SectionDefTypeSubRenderer, + compound.memberdefTypeSub : compoundrenderer.MemberDefTypeSubRenderer, + compound.enumvalueTypeSub : compoundrenderer.EnumvalueTypeSubRenderer, + compound.linkedTextTypeSub : compoundrenderer.LinkedTextTypeSubRenderer, + compound.descriptionTypeSub : compoundrenderer.DescriptionTypeSubRenderer, + compound.paramTypeSub : compoundrenderer.ParamTypeSubRenderer, + compound.docRefTextTypeSub : compoundrenderer.DocRefTextTypeSubRenderer, + compound.docParaTypeSub : compoundrenderer.DocParaTypeSubRenderer, + compound.docMarkupTypeSub : compoundrenderer.DocMarkupTypeSubRenderer, + compound.docParamListTypeSub : compoundrenderer.DocParamListTypeSubRenderer, + compound.docParamListItemSub : compoundrenderer.DocParamListItemSubRenderer, + compound.docParamNameListSub : compoundrenderer.DocParamNameListSubRenderer, + compound.docParamNameSub : compoundrenderer.DocParamNameSubRenderer, + compound.docSect1TypeSub : compoundrenderer.DocSect1TypeSubRenderer, + compound.docSimpleSectTypeSub : compoundrenderer.DocSimpleSectTypeSubRenderer, + compound.docTitleTypeSub : compoundrenderer.DocTitleTypeSubRenderer, + compound.verbatimTypeSub : compoundrenderer.VerbatimTypeSubRenderer, + compoundsuper.MixedContainer : compoundrenderer.MixedContainerRenderer, + unicode : UnicodeRenderer, + } + + domain_handler_factory = self.domain_handler_factory_creator.create( + project_info, + document, + document.settings.env + ) + + domain_handler = domain_handler_factory.create_null_domain_handler() + + return DoxygenToRstRendererFactory( + renderers, + self.node_factory, + project_info, + state, + document, + domain_handler_factory, + domain_handler, + self.rst_content_creator, + member_filter, + target_handler + ) + + diff --git a/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/base.py b/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/base.py new file mode 100644 index 000000000..6858d0830 --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/base.py @@ -0,0 +1,24 @@ + +class Renderer(object): + + def __init__(self, + project_info, + data_object, + renderer_factory, + node_factory, + state, + document, + domain_handler, + target_handler + ): + + self.project_info = project_info + self.data_object = data_object + self.renderer_factory = renderer_factory + self.node_factory = node_factory + self.state = state + self.document = document + self.domain_handler = domain_handler + self.target_handler = target_handler + + diff --git a/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/compound.py b/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/compound.py new file mode 100644 index 000000000..9db62d182 --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/compound.py @@ -0,0 +1,615 @@ + +from breathe.renderer.rst.doxygen.base import Renderer + +class DoxygenTypeSubRenderer(Renderer): + + def render(self): + + compound_renderer = self.renderer_factory.create_renderer(self.data_object.compounddef) + return compound_renderer.render() + + +class CompoundDefTypeSubRenderer(Renderer): + + section_titles = [ + "user-defined", + "public-type", + "public-func", + "public-attrib", + "public-slot", + "signal", + "dcop-func", + "property", + "event", + "public-static-func", + "public-static-attrib", + "protected-type", + "protected-func", + "protected-attrib", + "protected-slot", + "protected-static-func", + "protected-static-attrib", + "package-type", + "package-attrib", + "package-static-func", + "package-static-attrib", + "private-type", + "private-func", + "private-attrib", + "private-slot", + "private-static-func", + "private-static-attrib", + "friend", + "related", + "define", + "prototype", + "typedef", + "enum", + "func", + "var" + ] + + + def extend_nodelist(self, nodelist, section, title, section_nodelists): + + # Add title and contents if found + if section_nodelists.has_key(section): + nodes = section_nodelists[section] + + if nodes: + + nodelist.append(self.node_factory.emphasis(text=title)) + nodelist.append(self.node_factory.block_quote("", *nodes)) + + def render(self): + + nodelist = [] + + if self.data_object.briefdescription: + renderer = self.renderer_factory.create_renderer(self.data_object.briefdescription) + nodelist.append(self.node_factory.paragraph("", "", *renderer.render())) + + if self.data_object.detaileddescription: + renderer = self.renderer_factory.create_renderer(self.data_object.detaileddescription) + nodelist.append(self.node_factory.paragraph("", "", *renderer.render())) + + section_nodelists = {} + + # Get all sub sections + for sectiondef in self.data_object.sectiondef: + kind = sectiondef.kind + renderer = self.renderer_factory.create_section_renderer(sectiondef) + subnodes = renderer.render() + section_nodelists[kind] = subnodes + + # Order the results in an appropriate manner + for kind in self.section_titles: + nodelist.extend(section_nodelists.get(kind, [])) + + return [self.node_factory.block_quote("", *nodelist)] + + +class SectionDefTypeSubRenderer(Renderer): + + section_titles = { + "user-defined": "User Defined", + "public-type": "Public Type", + "public-func": "Public Functions", + "public-attrib": "Public Members", + "public-slot": "Public Slot", + "signal": "Signal", + "dcop-func": "DCOP Function", + "property": "Property", + "event": "Event", + "public-static-func": "Public Static Functons", + "public-static-attrib": "Public Static Attributes", + "protected-type": "Protected Types", + "protected-func": "Protected Functions", + "protected-attrib": "Protected Attributes", + "protected-slot": "Protected Slots", + "protected-static-func": "Protected Static Functions", + "protected-static-attrib": "Protected Static Attributes", + "package-type": "Package Types", + "package-attrib": "Package Attributes", + "package-static-func": "Package Static Functions", + "package-static-attrib": "Package Static Attributes", + "private-type": "Private Types", + "private-func": "Private Functions", + "private-attrib": "Private Members", + "private-slot": "Private Slots", + "private-static-func": "Private Static Functions", + "private-static-attrib": "Private Static Attributes", + "friend": "Friends", + "related": "Related", + "define": "Defines", + "prototype": "Prototypes", + "typedef": "Typedefs", + "enum": "Enums", + "func": "Functions", + "var": "Variables", + } + + def render(self): + + defs = [] + + # Get all the memberdef info + for memberdef in self.data_object.memberdef: + renderer = self.renderer_factory.create_member_renderer(memberdef) + defs.extend(renderer.render()) + + if defs: + text = self.section_titles[self.data_object.kind] + title = self.node_factory.emphasis(text=text) + def_list = self.node_factory.definition_list("", *defs) + return [title, self.node_factory.block_quote("", def_list)] + + return [] + + +class MemberDefTypeSubRenderer(Renderer): + + def create_target(self, refid): + + return self.target_handler.create_target(refid) + + def create_domain_id(self): + + return "" + + def title(self): + + kind = [] + + # Variable type or function return type + if self.data_object.type_: + renderer = self.renderer_factory.create_renderer(self.data_object.type_) + kind = renderer.render() + + name = self.node_factory.strong(text=self.data_object.name) + + args = [] + args.extend(kind) + args.extend([self.node_factory.Text(" "), name]) + + return args + + + def description(self): + + description_nodes = [] + + if self.data_object.briefdescription: + renderer = self.renderer_factory.create_renderer(self.data_object.briefdescription) + description_nodes.append(self.node_factory.paragraph("", "", *renderer.render())) + + if self.data_object.detaileddescription: + renderer = self.renderer_factory.create_renderer(self.data_object.detaileddescription) + description_nodes.append(self.node_factory.paragraph( "", "", *renderer.render())) + + return description_nodes + + + def render(self): + + refid = "%s%s" % (self.project_info.name(), self.data_object.id) + + domain_id = self.create_domain_id() + + title = self.title() + target = self.create_target(refid) + target.extend(title) + term = self.node_factory.term("","", ids=[domain_id,refid], *target ) + definition = self.node_factory.definition("", *self.description()) + entry = self.node_factory.definition_list_item("",term, definition) + + return [entry] + + +class FuncMemberDefTypeSubRenderer(MemberDefTypeSubRenderer): + + def create_target(self, refid): + + self.domain_handler.create_function_target(self.data_object) + + return MemberDefTypeSubRenderer.create_target(self, refid) + + + def create_domain_id(self): + + return self.domain_handler.create_function_id(self.data_object) + + + def title(self): + + args = MemberDefTypeSubRenderer.title(self) + + # Get the function arguments + args.append(self.node_factory.Text("(")) + for i, parameter in enumerate(self.data_object.param): + if i: args.append(self.node_factory.Text(", ")) + renderer = self.renderer_factory.create_renderer(parameter) + args.extend(renderer.render()) + args.append(self.node_factory.Text(")")) + + return args + + +class EnumMemberDefTypeSubRenderer(MemberDefTypeSubRenderer): + + def title(self): + + if self.data_object.name.startswith("@"): + # Assume anonymous enum + return [self.node_factory.strong(text="Anonymous enum")] + + name = self.node_factory.strong(text="%s enum" % self.data_object.name) + return [name] + + def description(self): + + description_nodes = MemberDefTypeSubRenderer.description(self) + + name = self.node_factory.emphasis("", self.node_factory.Text("Values:")) + title = self.node_factory.paragraph("", "", name) + description_nodes.append(title) + + enums = [] + for item in self.data_object.enumvalue: + renderer = self.renderer_factory.create_renderer(item) + enums.extend(renderer.render()) + + description_nodes.append(self.node_factory.bullet_list("", classes=["breatheenumvalues"], *enums)) + + return description_nodes + + +class TypedefMemberDefTypeSubRenderer(MemberDefTypeSubRenderer): + + def title(self): + + args = [self.node_factory.Text("typedef ")] + args.extend(MemberDefTypeSubRenderer.title(self)) + + if self.data_object.argsstring: + renderer = self.renderer_factory.create_renderer(self.data_object.argsstring) + args.extend(renderer.render()) + + return args + + +class VariableMemberDefTypeSubRenderer(MemberDefTypeSubRenderer): + + def title(self): + + args = MemberDefTypeSubRenderer.title(self) + + if self.data_object.argsstring: + renderer = self.renderer_factory.create_renderer(self.data_object.argsstring) + args.extend(renderer.render()) + + return args + + +class EnumvalueTypeSubRenderer(Renderer): + + def render(self): + + name = self.node_factory.literal(text=self.data_object.name) + description_nodes = [name] + + if self.data_object.initializer: + renderer = self.renderer_factory.create_renderer(self.data_object.initializer) + nodelist = [self.node_factory.Text(" = ")] + nodelist.extend(renderer.render()) + description_nodes.append(self.node_factory.literal("", "", *nodelist)) + + separator = self.node_factory.Text(" - ") + description_nodes.append(separator) + + if self.data_object.briefdescription: + renderer = self.renderer_factory.create_renderer(self.data_object.briefdescription) + description_nodes.extend(renderer.render()) + + if self.data_object.detaileddescription: + renderer = self.renderer_factory.create_renderer(self.data_object.detaileddescription) + description_nodes.extend(renderer.render()) + + # Build the list item + return [self.node_factory.list_item("", *description_nodes)] + +class DescriptionTypeSubRenderer(Renderer): + + def render(self): + + nodelist = [] + + # Get description in rst_nodes if possible + for item in self.data_object.content_: + renderer = self.renderer_factory.create_renderer(item) + nodelist.extend(renderer.render()) + + return nodelist + + +class LinkedTextTypeSubRenderer(Renderer): + + def render(self): + + nodelist = [] + + # Recursively process where possible + for i in self.data_object.content_: + renderer = self.renderer_factory.create_renderer(i) + nodelist.extend(renderer.render()) + nodelist.append(self.node_factory.Text(" ")) + + + return nodelist + + +class ParamTypeSubRenderer(Renderer): + + def render(self): + + nodelist = [] + + # Parameter type + if self.data_object.type_: + renderer = self.renderer_factory.create_renderer(self.data_object.type_) + nodelist.extend(renderer.render()) + + # Parameter name + if self.data_object.declname: + nodelist.append(self.node_factory.Text(self.data_object.declname)) + + if self.data_object.defname: + nodelist.append(self.node_factory.Text(self.data_object.defname)) + + # Default value + if self.data_object.defval: + nodelist.append(self.node_factory.Text(" = ")) + renderer = self.renderer_factory.create_renderer(self.data_object.defval) + nodelist.extend(renderer.render()) + + return nodelist + + + +class DocRefTextTypeSubRenderer(Renderer): + + def render(self): + + nodelist = [] + + for item in self.data_object.content_: + renderer = self.renderer_factory.create_renderer(item) + nodelist.extend(renderer.render()) + + for item in self.data_object.para: + renderer = self.renderer_factory.create_renderer(item) + nodelist.extend(renderer.render()) + + refid = "%s%s" % (self.project_info.name(), self.data_object.refid) + nodelist = [ + self.node_factory.pending_xref( + "", + reftype="ref", + refdomain="std", + refexplicit=True, + refid=refid, + reftarget=refid, + *nodelist + ) + ] + + return nodelist + + +class DocParaTypeSubRenderer(Renderer): + + def render(self): + + nodelist = [] + for entry in self.data_object.parameterlist: + renderer = self.renderer_factory.create_renderer(entry) + nodelist.extend(renderer.render()) + + for item in self.data_object.content: + renderer = self.renderer_factory.create_renderer(item) + nodelist.extend(renderer.render()) + + def_list_items = [] + for item in self.data_object.simplesects: + renderer = self.renderer_factory.create_renderer(item) + def_list_items.extend(renderer.render()) + + if def_list_items: + nodelist.append(self.node_factory.definition_list("", *def_list_items)) + + return [self.node_factory.paragraph("", "", *nodelist)] + +class DocMarkupTypeSubRenderer(Renderer): + + def __init__( + self, + creator, + *args + ): + + Renderer.__init__( self, *args ) + + self.creator = creator + + def render(self): + + nodelist = [] + + for item in self.data_object.content_: + renderer = self.renderer_factory.create_renderer(item) + nodelist.extend(renderer.render()) + + return [self.creator("", *nodelist)] + + +class DocParamListTypeSubRenderer(Renderer): + + lookup = { + "param" : "Parameters", + "exception" : "Exceptions", + "templateparam" : "Templates", + "retval" : "Return Value", + } + + def render(self): + + nodelist = [] + for entry in self.data_object.parameteritem: + renderer = self.renderer_factory.create_renderer(entry) + nodelist.extend(renderer.render()) + + name = self.lookup[self.data_object.kind] + name = self.node_factory.emphasis("", self.node_factory.Text(name)) + title = self.node_factory.paragraph("", "", name) + + return [title,self.node_factory.bullet_list("", classes=["breatheparameterlist"], *nodelist)] + + + +class DocParamListItemSubRenderer(Renderer): + + def render(self): + + nodelist = [] + for entry in self.data_object.parameternamelist: + renderer = self.renderer_factory.create_renderer(entry) + nodelist.extend(renderer.render()) + + term = self.node_factory.literal("","", *nodelist) + + separator = self.node_factory.Text(" - ") + + nodelist = [] + + if self.data_object.parameterdescription: + renderer = self.renderer_factory.create_renderer(self.data_object.parameterdescription) + nodelist.extend(renderer.render()) + + return [self.node_factory.list_item("", term, separator, *nodelist)] + +class DocParamNameListSubRenderer(Renderer): + + def render(self): + + nodelist = [] + for entry in self.data_object.parametername: + renderer = self.renderer_factory.create_renderer(entry) + nodelist.extend(renderer.render()) + + return nodelist + +class DocParamNameSubRenderer(Renderer): + + def render(self): + + nodelist = [] + for item in self.data_object.content_: + renderer = self.renderer_factory.create_renderer(item) + nodelist.extend(renderer.render()) + + return nodelist + +class DocSect1TypeSubRenderer(Renderer): + + def render(self): + + return [] + + +class DocSimpleSectTypeSubRenderer(Renderer): + + def title(self): + + text = self.node_factory.Text(self.data_object.kind.capitalize()) + emphasis = self.node_factory.emphasis("", text) + + return [emphasis] + + def render(self): + + term = self.node_factory.term("","", *self.title()) + + nodelist = [] + for item in self.data_object.para: + renderer = self.renderer_factory.create_renderer(item) + nodelist.append(self.node_factory.paragraph("", "", *renderer.render())) + + definition = self.node_factory.definition("", *nodelist) + + return [self.node_factory.definition_list_item("", term, definition)] + + +class ParDocSimpleSectTypeSubRenderer(DocSimpleSectTypeSubRenderer): + + def title(self): + + renderer = self.renderer_factory.create_renderer(self.data_object.title) + emphasis = self.node_factory.emphasis("", *renderer.render()) + + return [emphasis] + + +class DocTitleTypeSubRenderer(Renderer): + + def render(self): + + nodelist = [] + + for item in self.data_object.content_: + renderer = self.renderer_factory.create_renderer(item) + nodelist.extend(renderer.render()) + + return nodelist + + +class VerbatimTypeSubRenderer(Renderer): + + def __init__(self, content_creator, *args): + Renderer.__init__(self, *args) + + self.content_creator = content_creator + + def render(self): + + if not self.data_object.text.strip().startswith("embed:rst"): + + # Remove trailing new lines. Purely subjective call from viewing results + text = self.data_object.text.rstrip() + + # Handle has a preformatted text + return [self.node_factory.literal_block(text, text)] + + rst = self.content_creator(self.data_object.text) + + # Parent node for the generated node subtree + node = self.node_factory.paragraph() + node.document = self.state.document + + # Generate node subtree + self.state.nested_parse(rst, 0, node) + + return node + + +class MixedContainerRenderer(Renderer): + + def render(self): + + renderer = self.renderer_factory.create_renderer(self.data_object.getValue()) + return renderer.render() + + + + + + diff --git a/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/domain.py b/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/domain.py new file mode 100644 index 000000000..2dba46f79 --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/domain.py @@ -0,0 +1,190 @@ + + +class DomainHelper(object): + pass + +class NullDomainHelper(DomainHelper): + pass + +class CppDomainHelper(DomainHelper): + + def __init__(self, definition_parser, substitute): + + self.definition_parser = definition_parser + self.substitute = substitute + + self.duplicates = {} + + def check_cache(self, _id): + try: + return True, self.duplicates[_id] + except KeyError: + return False, "" + + def cache(self, _id, project_info): + self.duplicates[_id] = project_info + + def remove_word(self, word, definition): + return self.substitute(r"(\s*\b|^)%s\b\s*" % word, "", definition) + + +class CDomainHelper(DomainHelper): + + def __init__(self): + + self.duplicates = set() + + def is_duplicate(self, name): + return name in self.duplicates + + def remember(self, name): + self.duplicates.add(name) + + + +class DomainHandler(object): + + def __init__(self, node_factory, document, env, helper, project_info): + + self.node_factory = node_factory + self.document = document + self.env = env + self.helper = helper + self.project_info = project_info + +class NullDomainHandler(DomainHandler): + + def __init__(self): + pass + + def create_function_id(self, data_object): + return "" + + def create_function_target(self, data_object): + pass + +class CDomainHandler(DomainHandler): + + def create_function_id(self, data_object): + + name = data_object.definition.split()[-1] + + return name + + def create_function_target(self, data_object): + + name = data_object.definition.split()[-1] + + if self.helper.is_duplicate(name): + print "Warning: Ignoring duplicate '%s'. As C does not support overloaded functions. Perhaps you should be using the cpp domain?" % name + return + + self.helper.remember(name) + + signode = self.node_factory.desc_signature() + + signode["names"].append(name) + signode["ids"].append(name) + + self.document.note_explicit_target(signode) + + inv = self.env.domaindata['c']['objects'] + if name in inv: + self.env.warn( + self.env.docname, + 'duplicate C object description of %s, ' % name + + 'other instance in ' + self.env.doc2path(inv[name][0]), + self.lineno) + inv[name] = (self.env.docname, "function") + + +class CppDomainHandler(DomainHandler): + + def create_function_id(self, data_object): + + definition = self.helper.remove_word("virtual", data_object.definition) + argstring = data_object.argsstring + + explicit = "explicit " if data_object.explicit == "yes" else "" + + def_ = "%(explicit)s%(definition)s%(argstring)s" % { + "explicit" : explicit, + "definition" : definition, + "argstring" : argstring, + } + + parser = self.helper.definition_parser(def_) + sigobj = parser.parse_function() + + return sigobj.get_id() + + def create_function_target(self, data_object): + + _id = self.create_function_id(data_object) + + in_cache, project = self.helper.check_cache(_id) + if in_cache: + print "Warning: Ignoring duplicate domain reference '%s'. " \ + "First found in project '%s'" % (_id, project.reference()) + return + + self.helper.cache(_id, self.project_info) + + signode = self.node_factory.desc_signature() + + signode["names"].append(_id) + signode["ids"].append(_id) + + name = data_object.definition.split()[-1] + self.document.settings.env.domaindata['cpp']['objects'].setdefault(name, + (self.document.settings.env.docname, "function", _id)) + + self.document.note_explicit_target(signode) + + +class DomainHandlerFactory(object): + + def __init__(self, project_info, node_factory, document, env, helpers): + + self.project_info = project_info + self.node_factory = node_factory + self.document = document + self.env = env + self.domain_helpers = helpers + + def create_null_domain_handler(self): + + return NullDomainHandler() + + def create_domain_handler(self, file_): + + domains_handlers = { + "c" : CDomainHandler, + "cpp" : CppDomainHandler, + } + + domain = self.project_info.domain_for_file(file_) + + try: + helper = self.domain_helpers[domain] + except KeyError: + helper = NullDomainHelper() + + try: + return domains_handlers[domain](self.node_factory, self.document, self.env, helper, self.project_info) + except KeyError: + return NullDomainHandler() + + +class DomainHandlerFactoryCreator(object): + + def __init__(self, node_factory, helpers): + + self.node_factory = node_factory + self.helpers = helpers + + def create(self, project_info, document, env): + + return DomainHandlerFactory(project_info, self.node_factory, document, env, self.helpers) + + diff --git a/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/filter.py b/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/filter.py new file mode 100644 index 000000000..fed3b64f0 --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/filter.py @@ -0,0 +1,101 @@ + +class NamedFilter(object): + + def __init__(self, members): + + self.members = members + + def allow(self, name): + + return name in self.members + +class GlobFilter(object): + + def __init__(self, glob): + + self.glob = glob + + def allow(self, name): + + return self.glob.match(name) + + +class OpenFilter(object): + + def allow(self, name): + + return True + +class ClosedFilter(object): + + def allow(self, name): + + return False + +class CombinedFilter(object): + + def __init__(self, section_filter, member_filter): + + self.section_filter = section_filter + self.member_filter = member_filter + + def allow_section(self, name): + + return self.section_filter.allow(name) + + def allow_member(self, name): + + return self.member_filter.allow(name) + + +class Glob(object): + + def __init__(self, method, pattern): + + self.method = method + self.pattern = pattern + + def match(self, name): + + return self.method(name, self.pattern) + + +class GlobFactory(object): + + def __init__(self, method): + + self.method = method + + def create(self, pattern): + + return Glob(self.method, pattern) + + +class FilterFactory(object): + + def __init__(self, globber_factory): + + self.globber_factory = globber_factory + + def create_filter(self, options): + + try: + text = options["members"] + except KeyError: + return CombinedFilter(ClosedFilter(), ClosedFilter()) + + if not text.strip(): + return CombinedFilter( + GlobFilter(self.globber_factory.create("public*")), + OpenFilter() + ) + + # Matches sphinx-autodoc behaviour + members = set([x.strip() for x in text.split(",")]) + + return CombinedFilter(OpenFilter(), NamedFilter(members)) + + def create_open_filter(self): + + return CombinedFilter(OpenFilter(), OpenFilter()) + diff --git a/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/index.py b/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/index.py new file mode 100644 index 000000000..0d3c86902 --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/index.py @@ -0,0 +1,52 @@ + +from breathe.renderer.rst.doxygen.base import Renderer + +class DoxygenTypeSubRenderer(Renderer): + + def render(self): + + nodelist = [] + + # Process all the compound children + for compound in self.data_object.get_compound(): + compound_renderer = self.renderer_factory.create_renderer(compound) + nodelist.extend(compound_renderer.render()) + + return nodelist + + +class CompoundTypeSubRenderer(Renderer): + + def __init__(self, compound_parser, *args): + Renderer.__init__(self, *args) + + self.compound_parser = compound_parser + + def render(self): + + refid = "%s%s" % (self.project_info.name(), self.data_object.refid) + nodelist = self.target_handler.create_target(refid) + + # Set up the title and a reference for it (refid) + kind = self.node_factory.emphasis(text=self.data_object.kind) + name = self.node_factory.strong(text=self.data_object.name) + nodelist.append( + self.node_factory.paragraph( + "", + "", + kind, + self.node_factory.Text(" "), + name, + ids=[refid] + ) + ) + + # Read in the corresponding xml file and process + file_data = self.compound_parser.parse(self.data_object.refid) + data_renderer = self.renderer_factory.create_renderer(file_data) + + nodelist.extend(data_renderer.render()) + + return nodelist + + diff --git a/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/target.py b/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/target.py new file mode 100644 index 000000000..2ddb43a6a --- /dev/null +++ b/libs/network/doc/ext/breathe/breathe/renderer/rst/doxygen/target.py @@ -0,0 +1,40 @@ + +class TargetHandler(object): + + def __init__(self, project_info, node_factory, document): + + self.project_info = project_info + self.node_factory = node_factory + self.document = document + + def create_target(self, refid): + + target = self.node_factory.target(refid=refid, ids=[refid], names=[refid]) + + # Tell the document about our target + try: + self.document.note_explicit_target(target) + except Exception, e: + print "Failed to register id: %s. This is a seemingly harmless bug." % refid + + return [target] + +class NullTargetHandler(object): + + def create_target(self, refid): + return [] + + +class TargetHandlerFactory(object): + + def __init__(self, node_factory): + + self.node_factory = node_factory + + def create(self, options, project_info, document): + + if options.has_key("no-link"): + return NullTargetHandler() + + return TargetHandler(project_info, self.node_factory, document) + diff --git a/libs/network/doc/ext/breathe/examples/doxygen/.gitignore b/libs/network/doc/ext/breathe/examples/doxygen/.gitignore new file mode 100644 index 000000000..19d84e83c --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/.gitignore @@ -0,0 +1,27 @@ +afterdoc +author +autolink +class +define +diagrams +docstring +enum +example +file +func +group +include +jdstyle +manual +memgrp +mux +overload +page +par +pyexample +qtstyle +relates +restypedef +structcmd +tag +template diff --git a/libs/network/doc/ext/breathe/examples/doxygen/afterdoc.cfg b/libs/network/doc/ext/breathe/examples/doxygen/afterdoc.cfg new file mode 100644 index 000000000..184558326 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/afterdoc.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "AfterDocs" +OUTPUT_DIRECTORY = afterdoc +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = afterdoc.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/afterdoc.h b/libs/network/doc/ext/breathe/examples/doxygen/afterdoc.h new file mode 100644 index 000000000..907dabea3 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/afterdoc.h @@ -0,0 +1,18 @@ +/*! A test class */ + +class Test +{ + public: + /** An enum type. + * The documentation block cannot be put after the enum! + */ + enum EnumType + { + int EVal1, /**< enum value 1 */ + int EVal2 /**< enum value 2 */ + }; + void member(); //!< a member function. + + protected: + int value; /*!< an integer value */ +}; diff --git a/libs/network/doc/ext/breathe/examples/doxygen/author.cfg b/libs/network/doc/ext/breathe/examples/doxygen/author.cfg new file mode 100644 index 000000000..510c3d195 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/author.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Author Command" +OUTPUT_DIRECTORY = author +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = author.cpp +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/author.cpp b/libs/network/doc/ext/breathe/examples/doxygen/author.cpp new file mode 100644 index 000000000..59cc7abf4 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/author.cpp @@ -0,0 +1,14 @@ +/*! \class WindowsNT + * \brief Windows Nice Try. + * \author Bill Gates + * \author Several species of small furry animals gathered together + * in a cave and grooving with a pict. + * \version 4.0 + * \date 1996-1998 + * \bug It crashes a lot and requires huge amounts of memory. + * \bug The class introduces the more bugs, the longer it is used. + * \warning This class may explode in your face. + * \warning If you inherit anything from this class, you're doomed. + */ + +class WindowsNT {}; diff --git a/libs/network/doc/ext/breathe/examples/doxygen/autolink.cfg b/libs/network/doc/ext/breathe/examples/doxygen/autolink.cfg new file mode 100644 index 000000000..7a5dde284 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/autolink.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Automatic link generation" +OUTPUT_DIRECTORY = autolink +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = autolink.cpp +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/autolink.cpp b/libs/network/doc/ext/breathe/examples/doxygen/autolink.cpp new file mode 100644 index 000000000..e028f22f0 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/autolink.cpp @@ -0,0 +1,99 @@ +/*! \file autolink.cpp + Testing automatic link generation. + + A link to a member of the Test class: Test::member, + + More specific links to the each of the overloaded members: + Test::member(int) and Test#member(int,int) + + A link to a protected member variable of Test: Test#var, + + A link to the global enumeration type #GlobEnum. + + A link to the define #ABS(x). + + A link to the destructor of the Test class: Test::~Test, + + A link to the typedef ::B. + + A link to the enumeration type Test::EType + + A link to some enumeration values Test::Val1 and ::GVal2 +*/ + +/*! + Since this documentation block belongs to the class Test no link to + Test is generated. + + Two ways to link to a constructor are: #Test and Test(). + + Links to the destructor are: #~Test and ~Test(). + + A link to a member in this class: member(). + + More specific links to the each of the overloaded members: + member(int) and member(int,int). + + A link to the variable #var. + + A link to the global typedef ::B. + + A link to the global enumeration type #GlobEnum. + + A link to the define ABS(x). + + A link to a variable \link #var using another text\endlink as a link. + + A link to the enumeration type #EType. + + A link to some enumeration values: \link Test::Val1 Val1 \endlink and ::GVal1. + + And last but not least a link to a file: autolink.cpp. + + \sa Inside a see also section any word is checked, so EType, + Val1, GVal1, ~Test and member will be replaced by links in HTML. +*/ + +class Test +{ + public: + Test(); //!< constructor + ~Test(); //!< destructor + void member(int); /**< A member function. Details. */ + void member(int,int); /**< An overloaded member function. Details */ + + /** An enum type. More details */ + enum EType { + Val1, /**< enum value 1 */ + Val2 /**< enum value 2 */ + }; + + protected: + int var; /**< A member variable */ +}; + +/*! details. */ +Test::Test() { } + +/*! details. */ +Test::~Test() { } + +/*! A global variable. */ +int globVar; + +/*! A global enum. */ +enum GlobEnum { + GVal1, /*!< global enum value 1 */ + GVal2 /*!< global enum value 2 */ + }; + +/*! + * A macro definition. + */ +#define ABS(x) (((x)>0)?(x):-(x)) + +typedef Test B; + +/*! \fn typedef Test B + * A type definition. + */ diff --git a/libs/network/doc/ext/breathe/examples/doxygen/class.cfg b/libs/network/doc/ext/breathe/examples/doxygen/class.cfg new file mode 100644 index 000000000..6386a70d3 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/class.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Class Command" +OUTPUT_DIRECTORY = class +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = class.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/class.h b/libs/network/doc/ext/breathe/examples/doxygen/class.h new file mode 100644 index 000000000..e5a9121b6 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/class.h @@ -0,0 +1,11 @@ +/* A dummy class */ + +class Test +{ +}; + +/*! \class Test class.h "inc/class.h" + * \brief This is a test class. + * + * Some details about the Test class + */ diff --git a/libs/network/doc/ext/breathe/examples/doxygen/define.cfg b/libs/network/doc/ext/breathe/examples/doxygen/define.cfg new file mode 100644 index 000000000..3375249b8 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/define.cfg @@ -0,0 +1,12 @@ +PROJECT_NAME = "Define Command" +OUTPUT_DIRECTORY = define +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = define.h +ENABLE_PREPROCESSING = YES +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/define.h b/libs/network/doc/ext/breathe/examples/doxygen/define.h new file mode 100644 index 000000000..c330447a4 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/define.h @@ -0,0 +1,18 @@ +/*! \file define.h + \brief testing defines + + This is to test the documentation of defines. +*/ + +/*! + \def MAX(x,y) + Computes the maximum of \a x and \a y. +*/ + +/*! + Computes the absolute value of its argument \a x. +*/ +#define ABS(x) (((x)>0)?(x):-(x)) +#define MAX(x,y) ((x)>(y)?(x):(y)) +#define MIN(x,y) ((x)>(y)?(y):(x)) + /*!< Computes the minimum of \a x and \a y. */ diff --git a/libs/network/doc/ext/breathe/examples/doxygen/diagrams.cfg b/libs/network/doc/ext/breathe/examples/doxygen/diagrams.cfg new file mode 100644 index 000000000..ab3bcb493 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/diagrams.cfg @@ -0,0 +1,15 @@ +PROJECT_NAME = "Diagrams" +OUTPUT_DIRECTORY = diagrams +HAVE_DOT = YES +EXTRACT_ALL = YES +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +ENABLE_PREPROCESSING = YES +INPUT = . +FILE_PATTERNS = diagrams_*.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/diagrams_a.h b/libs/network/doc/ext/breathe/examples/doxygen/diagrams_a.h new file mode 100644 index 000000000..047a8ab5c --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/diagrams_a.h @@ -0,0 +1,4 @@ +#ifndef _DIAGRAMS_A_H +#define _DIAGRAMS_A_H +class A { public: A *m_self; }; +#endif diff --git a/libs/network/doc/ext/breathe/examples/doxygen/diagrams_b.h b/libs/network/doc/ext/breathe/examples/doxygen/diagrams_b.h new file mode 100644 index 000000000..5fcd2476f --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/diagrams_b.h @@ -0,0 +1,5 @@ +#ifndef _DIAGRAMS_B_H +#define _DIAGRAMS_B_H +class A; +class B { public: A *m_a; }; +#endif diff --git a/libs/network/doc/ext/breathe/examples/doxygen/diagrams_c.h b/libs/network/doc/ext/breathe/examples/doxygen/diagrams_c.h new file mode 100644 index 000000000..e4ec11d04 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/diagrams_c.h @@ -0,0 +1,6 @@ +#ifndef _DIAGRAMS_C_H +#define _DIAGRAMS_C_H +#include "diagrams_c.h" +class D; +class C : public A { public: D *m_d; }; +#endif diff --git a/libs/network/doc/ext/breathe/examples/doxygen/diagrams_d.h b/libs/network/doc/ext/breathe/examples/doxygen/diagrams_d.h new file mode 100644 index 000000000..3e635cecb --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/diagrams_d.h @@ -0,0 +1,7 @@ +#ifndef _DIAGRAM_D_H +#define _DIAGRAM_D_H +#include "diagrams_a.h" +#include "diagrams_b.h" +class C; +class D : virtual protected A, private B { public: C m_c; }; +#endif diff --git a/libs/network/doc/ext/breathe/examples/doxygen/diagrams_e.h b/libs/network/doc/ext/breathe/examples/doxygen/diagrams_e.h new file mode 100644 index 000000000..52823881b --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/diagrams_e.h @@ -0,0 +1,5 @@ +#ifndef _DIAGRAM_E_H +#define _DIAGRAM_E_H +#include "diagrams_d.h" +class E : public D {}; +#endif diff --git a/libs/network/doc/ext/breathe/examples/doxygen/docstring.cfg b/libs/network/doc/ext/breathe/examples/doxygen/docstring.cfg new file mode 100644 index 000000000..bda296beb --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/docstring.cfg @@ -0,0 +1,12 @@ +PROJECT_NAME = "Python" +OUTPUT_DIRECTORY = docstring +EXTRACT_ALL = YES +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +OPTIMIZE_OUTPUT_JAVA = YES +INPUT = docstring.py +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/docstring.py b/libs/network/doc/ext/breathe/examples/doxygen/docstring.py new file mode 100644 index 000000000..07b13e01b --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/docstring.py @@ -0,0 +1,27 @@ +"""@package docstring +Documentation for this module. + +More details. +""" + +def func(): + """Documentation for a function. + + More details. + """ + pass + +class PyClass: + """Documentation for a class. + + More details. + """ + + def __init__(self): + """The constructor.""" + self._memVar = 0; + + def PyMethod(self): + """Documentation for a method.""" + pass + diff --git a/libs/network/doc/ext/breathe/examples/doxygen/enum.cfg b/libs/network/doc/ext/breathe/examples/doxygen/enum.cfg new file mode 100644 index 000000000..0b0502c9c --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/enum.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Enum Command" +OUTPUT_DIRECTORY = enum +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = enum.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/enum.h b/libs/network/doc/ext/breathe/examples/doxygen/enum.h new file mode 100644 index 000000000..4c54fab25 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/enum.h @@ -0,0 +1,24 @@ +class Test +{ + public: + enum TEnum { Val1, Val2 }; + + /*! Another enum, with inline docs */ + enum AnotherEnum + { + V1, /*!< value 1 */ + V2 /*!< value 2 */ + }; +}; + +/*! \class Test + * The class description. + */ + +/*! \enum Test::TEnum + * A description of the enum type. + */ + +/*! \var Test::TEnum Test::Val1 + * The description of the first enum value. + */ diff --git a/libs/network/doc/ext/breathe/examples/doxygen/example.cfg b/libs/network/doc/ext/breathe/examples/doxygen/example.cfg new file mode 100644 index 000000000..6d677755a --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/example.cfg @@ -0,0 +1,13 @@ +PROJECT_NAME = "Example Command" +OUTPUT_DIRECTORY = example +GENERATE_TAGFILE = example.tag +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = example.cpp +EXAMPLE_PATH = example_test.cpp +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/example.cpp b/libs/network/doc/ext/breathe/examples/doxygen/example.cpp new file mode 100644 index 000000000..230d6ec9e --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/example.cpp @@ -0,0 +1,19 @@ +/** A Test class. + * More details about this class. + */ + +class Test +{ + public: + /** An example member function. + * More details about this function. + */ + void example(); +}; + +void Test::example() {} + +/** \example example_test.cpp + * This is an example of how to use the Test class. + * More details about this example. + */ diff --git a/libs/network/doc/ext/breathe/examples/doxygen/example.tag b/libs/network/doc/ext/breathe/examples/doxygen/example.tag new file mode 100644 index 000000000..a38ab5cae --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/example.tag @@ -0,0 +1,14 @@ + + + + Test + class_test.html + + void + example + class_test.html + a47b775f65718978f1ffcd96376f8ecfa + () + + + diff --git a/libs/network/doc/ext/breathe/examples/doxygen/example_test.cpp b/libs/network/doc/ext/breathe/examples/doxygen/example_test.cpp new file mode 100644 index 000000000..a7e164322 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/example_test.cpp @@ -0,0 +1,5 @@ +void main() +{ + Test t; + t.example(); +} diff --git a/libs/network/doc/ext/breathe/examples/doxygen/file.cfg b/libs/network/doc/ext/breathe/examples/doxygen/file.cfg new file mode 100644 index 000000000..9de320a20 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/file.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "File Command" +OUTPUT_DIRECTORY = file +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = file.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/file.h b/libs/network/doc/ext/breathe/examples/doxygen/file.h new file mode 100644 index 000000000..8dff6cb50 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/file.h @@ -0,0 +1,10 @@ +/** \file file.h + * A brief file description. + * A more elaborated file description. + */ + +/** + * A global integer value. + * More details about this value. + */ +extern int globalValue; diff --git a/libs/network/doc/ext/breathe/examples/doxygen/func.cfg b/libs/network/doc/ext/breathe/examples/doxygen/func.cfg new file mode 100644 index 000000000..961e5e79d --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/func.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Fn Command" +OUTPUT_DIRECTORY = func +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = func.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/func.h b/libs/network/doc/ext/breathe/examples/doxygen/func.h new file mode 100644 index 000000000..b33544806 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/func.h @@ -0,0 +1,21 @@ +class Test +{ + public: + const char *member(char,int) throw(std::out_of_range); +}; + +const char *Test::member(char c,int n) throw(std::out_of_range) {} + +/*! \class Test + * \brief Test class. + * + * Details about Test. + */ + +/*! \fn const char *Test::member(char c,int n) + * \brief A member function. + * \param c a character. + * \param n an integer. + * \exception std::out_of_range parameter is out of range. + * \return a character pointer. + */ diff --git a/libs/network/doc/ext/breathe/examples/doxygen/group.cfg b/libs/network/doc/ext/breathe/examples/doxygen/group.cfg new file mode 100644 index 000000000..f50aad51b --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/group.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Grouping" +OUTPUT_DIRECTORY = group +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = group.cpp +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/group.cpp b/libs/network/doc/ext/breathe/examples/doxygen/group.cpp new file mode 100644 index 000000000..b120b9023 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/group.cpp @@ -0,0 +1,88 @@ +/** @defgroup group1 The First Group + * This is the first group + * @{ + */ + +/** @brief class C1 in group 1 */ +class C1 {}; + +/** @brief class C2 in group 1 */ +class C2 {}; + +/** function in group 1 */ +void func() {} + +/** @} */ // end of group1 + +/** + * @defgroup group2 The Second Group + * This is the second group + */ + +/** @defgroup group3 The Third Group + * This is the third group + */ + +/** @defgroup group4 The Fourth Group + * @ingroup group3 + * Group 4 is a subgroup of group 3 + */ + +/** + * @ingroup group2 + * @brief class C3 in group 2 + */ +class C3 {}; + +/** @ingroup group2 + * @brief class C4 in group 2 + */ +class C4 {}; + +/** @ingroup group3 + * @brief class C5 in @link group3 the third group@endlink. + */ +class C5 {}; + +/** @ingroup group1 group2 group3 group4 + * namespace N1 is in four groups + * @sa @link group1 The first group@endlink, group2, group3, group4 + * + * Also see @ref mypage2 + */ +namespace N1 {}; + +/** @file + * @ingroup group3 + * @brief this file in group 3 + */ + +/** @defgroup group5 The Fifth Group + * This is the fifth group + * @{ + */ + +/** @page mypage1 This is a section in group 5 + * Text of the first section + */ + +/** @page mypage2 This is another section in group 5 + * Text of the second section + */ + +/** @} */ // end of group5 + +/** @addtogroup group1 + * + * More documentation for the first group. + * @{ + */ + +/** another function in group 1 */ +void func2() {} + +/** yet another function in group 1 */ +void func3() {} + +/** @} */ // end of group1 + diff --git a/libs/network/doc/ext/breathe/examples/doxygen/include.cfg b/libs/network/doc/ext/breathe/examples/doxygen/include.cfg new file mode 100644 index 000000000..46c9aebc1 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/include.cfg @@ -0,0 +1,12 @@ +PROJECT_NAME = "Include Command" +OUTPUT_DIRECTORY = include +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = include.cpp +EXAMPLE_PATH = example_test.cpp +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/include.cpp b/libs/network/doc/ext/breathe/examples/doxygen/include.cpp new file mode 100644 index 000000000..c50ab9650 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/include.cpp @@ -0,0 +1,22 @@ + +/*! A test class. */ + +class Test +{ + public: + /// a member function + void example(); +}; + +/*! \page example + * \dontinclude example_test.cpp + * Our main function starts like this: + * \skip main + * \until { + * First we create a object \c t of the Test class. + * \skipline Test + * Then we call the example member function + * \line example + * After that our little test routine ends. + * \line } + */ diff --git a/libs/network/doc/ext/breathe/examples/doxygen/jdstyle.cfg b/libs/network/doc/ext/breathe/examples/doxygen/jdstyle.cfg new file mode 100644 index 000000000..becde0b7e --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/jdstyle.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "JavaDoc Style" +OUTPUT_DIRECTORY = jdstyle +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = jdstyle.cpp +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/jdstyle.cpp b/libs/network/doc/ext/breathe/examples/doxygen/jdstyle.cpp new file mode 100644 index 000000000..bd8b9a7d2 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/jdstyle.cpp @@ -0,0 +1,66 @@ +/** + * A test class. A more elaborate class description. + */ + +class Test +{ + public: + + /** + * An enum. + * More detailed enum description. + */ + + enum TEnum { + TVal1, /**< enum value TVal1. */ + TVal2, /**< enum value TVal2. */ + TVal3 /**< enum value TVal3. */ + } + *enumPtr, /**< enum pointer. Details. */ + enumVar; /**< enum variable. Details. */ + + /** + * A constructor. + * A more elaborate description of the constructor. + */ + Test(); + + /** + * A destructor. + * A more elaborate description of the destructor. + */ + ~Test(); + + /** + * a normal member taking two arguments and returning an integer value. + * @param a an integer argument. + * @param s a constant character pointer. + * @see Test() + * @see ~Test() + * @see testMeToo() + * @see publicVar() + * @return The test results + */ + int testMe(int a,const char *s); + + /** + * A pure virtual member. + * @see testMe() + * @param c1 the first argument. + * @param c2 the second argument. + */ + virtual void testMeToo(char c1,char c2) = 0; + + /** + * a public variable. + * Details. + */ + int publicVar; + + /** + * a function variable. + * Details. + */ + int (*handler)(int a,int b); +}; + diff --git a/libs/network/doc/ext/breathe/examples/doxygen/manual.c b/libs/network/doc/ext/breathe/examples/doxygen/manual.c new file mode 100644 index 000000000..fac683277 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/manual.c @@ -0,0 +1,87 @@ +/** + * \file manual.c + */ + +typedef struct Object Object; //!< Object type +typedef struct Vehicle Vehicle; //!< Vehicle type +typedef struct Car Car; //!< Car type +typedef struct Truck Truck; //!< Truck type + +/*! + * Base object class. + */ +struct Object +{ + int ref; //!< \private Reference count. +}; + + +/*! + * Increments object reference count by one. + * \public \memberof Object + */ +static Object * objRef(Object *obj); + + +/*! + * Decrements object reference count by one. + * \public \memberof Object + */ +static Object * objUnref(Object *obj); + + +/*! + * Vehicle class. + * \extends Object + */ +struct Vehicle +{ + Object base; //!< \protected Base class. +}; + + +/*! + * Starts the vehicle. + * \public \memberof Vehicle + */ +void vehicleStart(Vehicle *obj); + + +/*! + * Stops the vehicle. + * \public \memberof Vehicle + */ +void vehicleStop(Vehicle *obj); + + +/*! + * Car class. + * \extends Vehicle + */ +struct Car +{ + Vehicle base; //!< \protected Base class. +}; + + +/*! + * Truck class. + * \extends Vehicle + */ +struct Truck +{ + Vehicle base; //!< \protected Base class. +}; + + +/*! + * Main function. + * + * Ref vehicleStart(), objRef(), objUnref(). + */ +int main(void) +{ + Car c; + vehicleStart((Vehicle*) &c); +} + diff --git a/libs/network/doc/ext/breathe/examples/doxygen/manual.cfg b/libs/network/doc/ext/breathe/examples/doxygen/manual.cfg new file mode 100644 index 000000000..837490e81 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/manual.cfg @@ -0,0 +1,17 @@ +PROJECT_NAME = "Manual inheritance and membership" +OUTPUT_DIRECTORY = manual +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = manual.c +QUIET = YES +JAVADOC_AUTOBRIEF = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +TYPEDEF_HIDES_STRUCT = YES +INLINE_SOURCES = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/memgrp.cfg b/libs/network/doc/ext/breathe/examples/doxygen/memgrp.cfg new file mode 100644 index 000000000..e920ca490 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/memgrp.cfg @@ -0,0 +1,12 @@ +PROJECT_NAME = "Member Grouping" +OUTPUT_DIRECTORY = memgrp +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = memgrp.cpp +QUIET = YES +DISTRIBUTE_GROUP_DOC = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/memgrp.cpp b/libs/network/doc/ext/breathe/examples/doxygen/memgrp.cpp new file mode 100644 index 000000000..394cdbc85 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/memgrp.cpp @@ -0,0 +1,41 @@ +/** A class. Details */ +class Test +{ + public: + //@{ + /** Same documentation for both members. Details */ + void func1InGroup1(); + void func2InGroup1(); + //@} + + /** Function without group. Details. */ + void ungroupedFunction(); + void func1InGroup2(); + protected: + void func2InGroup2(); +}; + +void Test::func1InGroup1() {} +void Test::func2InGroup1() {} + +/** @name Group2 + * Description of group 2. + */ +//@{ +/** Function 2 in group 2. Details. */ +void Test::func2InGroup2() {} +/** Function 1 in group 2. Details. */ +void Test::func1InGroup2() {} +//@} + +/*! \file + * docs for this file + */ + +//@{ +//! one description for all members of this group +//! (because DISTRIBUTE_GROUP_DOC is YES in the config file) +#define A 1 +#define B 2 +void glob_func(); +//@} diff --git a/libs/network/doc/ext/breathe/examples/doxygen/mux.cfg b/libs/network/doc/ext/breathe/examples/doxygen/mux.cfg new file mode 100644 index 000000000..999215090 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/mux.cfg @@ -0,0 +1,15 @@ +PROJECT_NAME = Mux +OUTPUT_DIRECTORY = mux +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = mux.vhdl +OPTIMIZE_OUTPUT_VHDL = YES +QUIET = YES +INHERIT_DOCS = YES +EXTRACT_PRIVATE = YES +HIDE_SCOPE_NAMES = YES +INHERIT_DOCS = NO +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/mux.vhdl b/libs/network/doc/ext/breathe/examples/doxygen/mux.vhdl new file mode 100644 index 000000000..211e56e59 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/mux.vhdl @@ -0,0 +1,32 @@ +------------------------------------------------------- +--! @file +--! @brief 2:1 Mux using with-select +------------------------------------------------------- + +--! Use standard library +library ieee; +--! Use logic elements + use ieee.std_logic_1164.all; + +--! Mux entity brief description + +--! Detailed description of this +--! mux design element. +entity mux_using_with is + port ( + din_0 : in std_logic; --! Mux first input + din_1 : in std_logic; --! Mux Second input + sel : in std_logic; --! Select input + mux_out : out std_logic --! Mux output + ); +end entity; + +--! @brief Architure definition of the MUX +--! @details More details about this mux element. +architecture behavior of mux_using_with is +begin + with (sel) select + mux_out <= din_0 when '0', + din_1 when others; +end architecture; + diff --git a/libs/network/doc/ext/breathe/examples/doxygen/overload.cfg b/libs/network/doc/ext/breathe/examples/doxygen/overload.cfg new file mode 100644 index 000000000..683a2eb25 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/overload.cfg @@ -0,0 +1,12 @@ +PROJECT_NAME = "Overloaded Command" +OUTPUT_DIRECTORY = overload +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +SORT_MEMBER_DOCS = NO +INPUT = overload.cpp +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/overload.cpp b/libs/network/doc/ext/breathe/examples/doxygen/overload.cpp new file mode 100644 index 000000000..02bccedad --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/overload.cpp @@ -0,0 +1,25 @@ +class Test +{ + public: + void drawRect(int,int,int,int); + void drawRect(const Rect &r); +}; + +void Test::drawRect(int x,int y,int w,int h) {} +void Test::drawRect(const Rect &r) {} + +/*! \class Test + * \brief A short description. + * + * More text. + */ + +/*! \fn void Test::drawRect(int x,int y,int w,int h) + * This command draws a rectangle with a left upper corner at ( \a x , \a y ), + * width \a w and height \a h. + */ + +/*! + * \overload void Test::drawRect(const Rect &r) + */ + diff --git a/libs/network/doc/ext/breathe/examples/doxygen/page.cfg b/libs/network/doc/ext/breathe/examples/doxygen/page.cfg new file mode 100644 index 000000000..1f19151f9 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/page.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Page Command" +OUTPUT_DIRECTORY = page +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = page.doc +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/page.doc b/libs/network/doc/ext/breathe/examples/doxygen/page.doc new file mode 100644 index 000000000..747a4b871 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/page.doc @@ -0,0 +1,14 @@ +/*! \page page1 A documentation page + Leading text. + \section sec An example section + This page contains the subsections \ref subsection1 and \ref subsection2. + For more info see page \ref page2. + \subsection subsection1 The first subsection + Text. + \subsection subsection2 The second subsection + More text. +*/ + +/*! \page page2 Another page + Even more info. +*/ diff --git a/libs/network/doc/ext/breathe/examples/doxygen/par.cfg b/libs/network/doc/ext/breathe/examples/doxygen/par.cfg new file mode 100644 index 000000000..e8888c232 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/par.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Par Command" +OUTPUT_DIRECTORY = par +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = par.cpp +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/par.cpp b/libs/network/doc/ext/breathe/examples/doxygen/par.cpp new file mode 100644 index 000000000..6fd2c4e24 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/par.cpp @@ -0,0 +1,20 @@ +/*! \class Test + * Normal text. + * + * \par User defined paragraph: + * Contents of the paragraph. + * + * \par + * New paragraph under the same heading. + * + * \note + * This note consists of two paragraphs. + * This is the first paragraph. + * + * \par + * And this is the second paragraph. + * + * More normal text. + */ + +class Test {}; diff --git a/libs/network/doc/ext/breathe/examples/doxygen/pyexample.cfg b/libs/network/doc/ext/breathe/examples/doxygen/pyexample.cfg new file mode 100644 index 000000000..96a2c0620 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/pyexample.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Python" +OUTPUT_DIRECTORY = pyexample +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +OPTIMIZE_OUTPUT_JAVA = YES +INPUT = pyexample.py +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/pyexample.py b/libs/network/doc/ext/breathe/examples/doxygen/pyexample.py new file mode 100644 index 000000000..666c25b51 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/pyexample.py @@ -0,0 +1,30 @@ +## @package pyexample +# Documentation for this module. +# +# More details. + +## Documentation for a function. +# +# More details. +def func(): + pass + +## Documentation for a class. +# +# More details. +class PyClass: + + ## The constructor. + def __init__(self): + self._memVar = 0; + + ## Documentation for a method. + # @param self The object pointer. + def PyMethod(self): + pass + + ## A class variable. + classVar = 0; + + ## @var _memVar + # a member variable diff --git a/libs/network/doc/ext/breathe/examples/doxygen/qtstyle.cfg b/libs/network/doc/ext/breathe/examples/doxygen/qtstyle.cfg new file mode 100644 index 000000000..f2684d770 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/qtstyle.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Qt Style" +OUTPUT_DIRECTORY = qtstyle +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = qtstyle.cpp +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/qtstyle.cpp b/libs/network/doc/ext/breathe/examples/doxygen/qtstyle.cpp new file mode 100644 index 000000000..e24d54108 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/qtstyle.cpp @@ -0,0 +1,65 @@ +//! A test class. +/*! + A more elaborate class description. +*/ + +class Test +{ + public: + + //! An enum. + /*! More detailed enum description. */ + enum TEnum { + TVal1, /*!< Enum value TVal1. */ + TVal2, /*!< Enum value TVal2. */ + TVal3 /*!< Enum value TVal3. */ + } + //! Enum pointer. + /*! Details. */ + *enumPtr, + //! Enum variable. + /*! Details. */ + enumVar; + + //! A constructor. + /*! + A more elaborate description of the constructor. + */ + Test(); + + //! A destructor. + /*! + A more elaborate description of the destructor. + */ + ~Test(); + + //! A normal member taking two arguments and returning an integer value. + /*! + \param a an integer argument. + \param s a constant character pointer. + \return The test results + \sa Test(), ~Test(), testMeToo() and publicVar() + */ + int testMe(int a,const char *s); + + //! A pure virtual member. + /*! + \sa testMe() + \param c1 the first argument. + \param c2 the second argument. + */ + virtual void testMeToo(char c1,char c2) = 0; + + //! A public variable. + /*! + Details. + */ + int publicVar; + + //! A function variable. + /*! + Details. + */ + int (*handler)(int a,int b); +}; + diff --git a/libs/network/doc/ext/breathe/examples/doxygen/relates.cfg b/libs/network/doc/ext/breathe/examples/doxygen/relates.cfg new file mode 100644 index 000000000..385d12515 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/relates.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Relates Command" +OUTPUT_DIRECTORY = relates +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = relates.cpp +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/relates.cpp b/libs/network/doc/ext/breathe/examples/doxygen/relates.cpp new file mode 100644 index 000000000..c6f7dc979 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/relates.cpp @@ -0,0 +1,23 @@ +/*! + * A String class. + */ + +class String +{ + friend int strcmp(const String &,const String &); +}; + +/*! + * Compares two strings. + */ + +int strcmp(const String &s1,const String &s2) +{ +} + +/*! \relates String + * A string debug function. + */ +void stringDebug() +{ +} diff --git a/libs/network/doc/ext/breathe/examples/doxygen/restypedef.cfg b/libs/network/doc/ext/breathe/examples/doxygen/restypedef.cfg new file mode 100644 index 000000000..7e639987d --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/restypedef.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Resolving Typedefs" +OUTPUT_DIRECTORY = restypedef +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = restypedef.cpp +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/restypedef.cpp b/libs/network/doc/ext/breathe/examples/doxygen/restypedef.cpp new file mode 100644 index 000000000..923cf70b8 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/restypedef.cpp @@ -0,0 +1,25 @@ +/*! \file restypedef.cpp + * An example of resolving typedefs. + */ + +/*! \struct CoordStruct + * A coordinate pair. + */ +struct CoordStruct +{ + /*! The x coordinate */ + float x; + /*! The y coordinate */ + float y; +}; + +/*! Creates a type name for CoordStruct */ +typedef CoordStruct Coord; + +/*! + * This function returns the addition of \a c1 and \a c2, i.e: + * (c1.x+c2.x,c1.y+c2.y) + */ +Coord add(Coord c1,Coord c2) +{ +} diff --git a/libs/network/doc/ext/breathe/examples/doxygen/structcmd.cfg b/libs/network/doc/ext/breathe/examples/doxygen/structcmd.cfg new file mode 100644 index 000000000..1142b3219 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/structcmd.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Structural commands" +OUTPUT_DIRECTORY = structcmd +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = structcmd.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/structcmd.h b/libs/network/doc/ext/breathe/examples/doxygen/structcmd.h new file mode 100644 index 000000000..b0d56432b --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/structcmd.h @@ -0,0 +1,59 @@ +/*! \file structcmd.h + \brief A Documented file. + + Details. +*/ + +/*! \def MAX(a,b) + \brief A macro that returns the maximum of \a a and \a b. + + Details. +*/ + +/*! \var typedef unsigned int UINT32 + \brief A type definition for a . + + Details. +*/ + +/*! \var int errno + \brief Contains the last error code. + + \warning Not thread safe! +*/ + +/*! \fn int open(const char *pathname,int flags) + \brief Opens a file descriptor. + + Detailed description. + + \param pathname The name of the descriptor. + \param flags Opening flags. +*/ + +/*! \fn int close(int fd) + \brief Closes the file descriptor \a fd. + \param fd The descriptor to close. +*/ + +/*! \fn size_t write(int fd,const char *buf, size_t count) + \brief Writes \a count bytes from \a buf to the filedescriptor \a fd. + \param fd The descriptor to write to. + \param buf The data buffer to write. + \param count The number of bytes to write. +*/ + +/*! \fn int read(int fd,char *buf,size_t count) + \brief Read bytes from a file descriptor. + \param fd The descriptor to read from. + \param buf The buffer to read into. + \param count The number of bytes to read. +*/ + +#define MAX(a,b) (((a)>(b))?(a):(b)) +typedef unsigned int UINT32; +int errno; +int open(const char *,int); +int close(int); +size_t write(int,const char *, size_t); +int read(int,char *,size_t); diff --git a/libs/network/doc/ext/breathe/examples/doxygen/tag.cfg b/libs/network/doc/ext/breathe/examples/doxygen/tag.cfg new file mode 100644 index 000000000..478701ef3 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/tag.cfg @@ -0,0 +1,13 @@ +PROJECT_NAME = "Tag Files" +OUTPUT_DIRECTORY = tag +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = tag.cpp +TAGFILES = example.tag=../../example/html +PERL_PATH = perl +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/tag.cpp b/libs/network/doc/ext/breathe/examples/doxygen/tag.cpp new file mode 100644 index 000000000..6497dd420 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/tag.cpp @@ -0,0 +1,9 @@ +/*! A class that is inherited from the external class Test. +*/ + +class Tag : public Test +{ + public: + /*! an overloaded member. */ + void example(); +}; diff --git a/libs/network/doc/ext/breathe/examples/doxygen/templ.cfg b/libs/network/doc/ext/breathe/examples/doxygen/templ.cfg new file mode 100644 index 000000000..d5b70dd8c --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/templ.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Template Test" +OUTPUT_DIRECTORY = template +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = templ.cpp +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/doxygen/templ.cpp b/libs/network/doc/ext/breathe/examples/doxygen/templ.cpp new file mode 100644 index 000000000..9ed48fbc1 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/doxygen/templ.cpp @@ -0,0 +1,35 @@ + +/*! A template class */ +template class Test +{ + public: + Test(); + Test(const Test &); +}; + +/*! complete specialization */ +template<> class Test +{ + public: + Test(); +}; + +/*! A partial template specialization */ +template class Test : public Test +{ + public: + Test(); +}; + +/*! The constructor of the template class*/ +template Test::Test() {} + +/*! The copy constructor */ +template Test::Test(const Test &t) {} + +/*! The constructor of the partial specilization */ +template Test::Test() {} + +/*! The constructor of the specilization */ +template<> Test::Test() {} + diff --git a/libs/network/doc/ext/breathe/examples/specific/.gitignore b/libs/network/doc/ext/breathe/examples/specific/.gitignore new file mode 100644 index 000000000..71c87500e --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/.gitignore @@ -0,0 +1,7 @@ +functypedef +alias +class +inline +nutshell +rst +typedef diff --git a/libs/network/doc/ext/breathe/examples/specific/alias.cfg b/libs/network/doc/ext/breathe/examples/specific/alias.cfg new file mode 100644 index 000000000..30b9339cd --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/alias.cfg @@ -0,0 +1,13 @@ +PROJECT_NAME = "ALIAS Example" +OUTPUT_DIRECTORY = alias +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = alias.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES +ALIASES = "sideeffect=\par Side Effects:\n" + diff --git a/libs/network/doc/ext/breathe/examples/specific/alias.h b/libs/network/doc/ext/breathe/examples/specific/alias.h new file mode 100644 index 000000000..b9277a23a --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/alias.h @@ -0,0 +1,7 @@ + +/** + * Foo frob routine. + * @sideeffect Frobs any foos. + */ +void frob_foos(void); + diff --git a/libs/network/doc/ext/breathe/examples/specific/class.cfg b/libs/network/doc/ext/breathe/examples/specific/class.cfg new file mode 100644 index 000000000..6386a70d3 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/class.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Class Command" +OUTPUT_DIRECTORY = class +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = class.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/specific/class.h b/libs/network/doc/ext/breathe/examples/specific/class.h new file mode 100644 index 000000000..75fe3f114 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/class.h @@ -0,0 +1,43 @@ + +namespace testnamespace { + +//! \brief first class inside of namespace +class NamespacedClassTest { + + //! \brief namespaced class function + virtual void function() const = 0; + + static void functionS(); + + explicit NamespacedClassTest() {}; + + //! \brief namespaced class other function + void anotherFunction() {}; +}; + + +//! \brief second class inside of namespace +class ClassTest { + + //! \brief second namespaced class function + void function() {}; + + //! \brief second namespaced class other function + void anotherFunction() {}; +}; + + +};; + + +//! \brief class outside of namespace +class ClassTest { + + //! \brief non-namespaced class function + void function() {}; + + //! \brief non-namespaced class other function + void anotherFunction() {}; +}; + + diff --git a/libs/network/doc/ext/breathe/examples/specific/inline.cfg b/libs/network/doc/ext/breathe/examples/specific/inline.cfg new file mode 100644 index 000000000..e356c240e --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/inline.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Inline Parameter Doc Test" +OUTPUT_DIRECTORY = inline +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = inline.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = YES +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/specific/inline.h b/libs/network/doc/ext/breathe/examples/specific/inline.h new file mode 100644 index 000000000..7aeea8c97 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/inline.h @@ -0,0 +1,17 @@ + +class Test +{ + public: + /** A member function. + * + * Details about member function + * + * \exception std::out_of_range parameter is out of range. + * @return a character pointer. + */ + const char *member(char c, ///< c a character. + int n) ///< n an integer. + + throw(std::out_of_range); +}; + diff --git a/libs/network/doc/ext/breathe/examples/specific/members.cfg b/libs/network/doc/ext/breathe/examples/specific/members.cfg new file mode 100644 index 000000000..dc020e401 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/members.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Members Option" +OUTPUT_DIRECTORY = members +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = members.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/specific/members.h b/libs/network/doc/ext/breathe/examples/specific/members.h new file mode 100644 index 000000000..bf8439243 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/members.h @@ -0,0 +1,27 @@ + + +namespace testnamespace { + +//! \brief first class inside of namespace +class NamespacedClassTest { + +public: + + //! \brief namespaced class function + virtual void function() const = 0; + + explicit NamespacedClassTest() {}; + +protected: + + //! Some kind of function + static void functionS(); + +private: + + + //! \brief namespaced class other function + void anotherFunction() {}; +}; + +} diff --git a/libs/network/doc/ext/breathe/examples/specific/nutshell.cfg b/libs/network/doc/ext/breathe/examples/specific/nutshell.cfg new file mode 100644 index 000000000..312feb3b9 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/nutshell.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Breathe in a nutshell example" +OUTPUT_DIRECTORY = nutshell +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = nutshell.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/specific/nutshell.h b/libs/network/doc/ext/breathe/examples/specific/nutshell.h new file mode 100644 index 000000000..8e6b66edc --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/nutshell.h @@ -0,0 +1,43 @@ + +//! An overly extended example of how to use breathe +/*! + With a little bit of a elaboration, should you feel it necessary. +*/ +class Nutshell +{ +public: + + //! Our toolset + /*! The various tools we can opt to use to crack this particular nut */ + enum Tool + { + kHammer = 0, //!< What? It does the job + kNutCrackers, //!< Boring + kNinjaThrowingStars //!< Stealthy + }; + + //! Nutshell constructor + Nutshell(); + + //! Nutshell destructor + ~Nutshell(); + + /*! Crack that shell with specified tool + + \param tool - the tool with which to crack the nut + */ + void crack( Tool tool ); + + /*! + \return Whether or not the nut is cracked + */ + bool isCracked(); + +private: + + //! Our cracked state + bool m_isCracked; + +}; + + diff --git a/libs/network/doc/ext/breathe/examples/specific/rst.cfg b/libs/network/doc/ext/breathe/examples/specific/rst.cfg new file mode 100644 index 000000000..296f3755b --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/rst.cfg @@ -0,0 +1,14 @@ +PROJECT_NAME = "Rst Test" +OUTPUT_DIRECTORY = rst +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = rst.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES + +ALIASES = "rst=\verbatim embed:rst" +ALIASES += "endrst=\endverbatim" diff --git a/libs/network/doc/ext/breathe/examples/specific/rst.h b/libs/network/doc/ext/breathe/examples/specific/rst.h new file mode 100644 index 000000000..a5068f627 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/rst.h @@ -0,0 +1,31 @@ + +//! \brief first class inside of namespace +class TestClass +{ +public: + + /*! + Inserting additional restructured text information. + + \rst + + This is some funky non-xml compliant text: <& !>< + + .. note:: + + This restructured text has been handled correctly. + \endrst + + \verbatim + This is just a standard verbatim block with code: + + child = 0; + while( child = parent->IterateChildren( child ) ) + \endverbatim + + */ + virtual void function() const = 0; + + //! Brief desc + virtual void testFunction() const {}; +}; diff --git a/libs/network/doc/ext/breathe/examples/specific/typedef.cfg b/libs/network/doc/ext/breathe/examples/specific/typedef.cfg new file mode 100644 index 000000000..a070035b3 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/typedef.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "Function Type Def Command" +OUTPUT_DIRECTORY = typedef +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = typedef.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/specific/typedef.h b/libs/network/doc/ext/breathe/examples/specific/typedef.h new file mode 100644 index 000000000..a278b94f9 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/specific/typedef.h @@ -0,0 +1,15 @@ + +class TypeDefTest { +}; + +/* A dummy typedef */ +typedef TypeDefTest (*TypeDefTestFuncPtr)(void); + +typedef void* (*voidFuncPtr)(float, int); + +typedef void* voidPointer; + +typedef float* floatPointer; + +typedef float floatingPointNumber; + diff --git a/libs/network/doc/ext/breathe/examples/tinyxml/.gitignore b/libs/network/doc/ext/breathe/examples/tinyxml/.gitignore new file mode 100644 index 000000000..17ec59417 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/tinyxml/.gitignore @@ -0,0 +1 @@ +tinyxml/ diff --git a/libs/network/doc/ext/breathe/examples/tinyxml/tinyxml.cfg b/libs/network/doc/ext/breathe/examples/tinyxml/tinyxml.cfg new file mode 100644 index 000000000..db06329ed --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/tinyxml/tinyxml.cfg @@ -0,0 +1,11 @@ +PROJECT_NAME = "TinyXML classes" +OUTPUT_DIRECTORY = tinyxml +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = tinyxml.h +QUIET = YES +JAVADOC_AUTOBRIEF = YES +GENERATE_HTML = NO +GENERATE_XML = YES diff --git a/libs/network/doc/ext/breathe/examples/tinyxml/tinyxml.h b/libs/network/doc/ext/breathe/examples/tinyxml/tinyxml.h new file mode 100644 index 000000000..c91ee1da9 --- /dev/null +++ b/libs/network/doc/ext/breathe/examples/tinyxml/tinyxml.h @@ -0,0 +1,1779 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + + +#ifndef TINYXML_INCLUDED +#define TINYXML_INCLUDED + +// DNEG: jons - Defined for the library build +#define TIXML_USE_STL + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4530 ) +#pragma warning( disable : 4786 ) +#endif + +#include +#include +#include +#include +#include + +// Help out windows: +#if defined( _DEBUG ) && !defined( DEBUG ) +#define DEBUG +#endif + +#ifdef TIXML_USE_STL + #include + #include + #include + #define TIXML_STRING std::string +#else + #include "tinystr.h" + #define TIXML_STRING TiXmlString +#endif + +// Deprecated library function hell. Compilers want to use the +// new safe versions. This probably doesn't fully address the problem, +// but it gets closer. There are too many compilers for me to fully +// test. If you get compilation troubles, undefine TIXML_SAFE +#define TIXML_SAFE + +#ifdef TIXML_SAFE + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + // Microsoft visual studio, version 2005 and higher. + #define TIXML_SNPRINTF _snprintf_s + #define TIXML_SNSCANF _snscanf_s + #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + //#pragma message( "Using _sn* functions." ) + #define TIXML_SNPRINTF _snprintf + #define TIXML_SNSCANF _snscanf + #elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_SNSCANF snscanf + #endif +#endif + +class TiXmlDocument; +class TiXmlElement; +class TiXmlComment; +class TiXmlUnknown; +class TiXmlAttribute; +class TiXmlText; +class TiXmlDeclaration; +class TiXmlParsingData; + +const int TIXML_MAJOR_VERSION = 2; +const int TIXML_MINOR_VERSION = 5; +const int TIXML_PATCH_VERSION = 2; + +/* Internal structure for tracking location of items + in the XML file. +*/ +struct TiXmlCursor +{ + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } + + int row; // 0 based. + int col; // 0 based. +}; + + +/** + If you call the Accept() method, it requires being passed a TiXmlVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves + are simple called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its sibilings will be Visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. + + You should never change the document from a callback. + + @sa TiXmlNode::Accept() +*/ +class TiXmlVisitor +{ +public: + virtual ~TiXmlVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const TiXmlDocument& ) { return true; } + /// Visit a document. + virtual bool VisitExit( const TiXmlDocument& ) { return true; } + + /// Visit an element. + virtual bool VisitEnter( const TiXmlElement& , const TiXmlAttribute* ) { return true; } + /// Visit an element. + virtual bool VisitExit( const TiXmlElement& ) { return true; } + + /// Visit a declaration + virtual bool Visit( const TiXmlDeclaration& ) { return true; } + /// Visit a text node + virtual bool Visit( const TiXmlText& ) { return true; } + /// Visit a comment node + virtual bool Visit( const TiXmlComment& ) { return true; } + /// Visit an unknow node + virtual bool Visit( const TiXmlUnknown& ) { return true; } +}; + +// Only used by Attribute::Query functions +enum +{ + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE +}; + + +// Used by the parsing routines. +enum TiXmlEncoding +{ + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY +}; + +const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; + +/** TiXmlBase is a base class for every class in TinyXml. + It does little except to establish that TinyXml classes + can be printed and provide some utility functions. + + In XML, the document and elements can contain + other elements and other types of nodes. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + A Decleration contains: Attributes (not on tree) + @endverbatim +*/ +class TiXmlBase +{ + friend class TiXmlNode; + friend class TiXmlElement; + friend class TiXmlDocument; + +public: + TiXmlBase() : userData(0) {} + virtual ~TiXmlBase() {} + + /** All TinyXml classes can print themselves to a filestream + or the string class (TiXmlString in non-STL mode, std::string + in STL mode.) Either or both cfile and str can be null. + + This is a formatted print, and will insert + tabs and newlines. + + (For an unformatted stream, use the << operator.) + */ + virtual void Print( FILE* cfile, int depth ) const = 0; + + /** The world does not agree on whether white space should be kept or + not. In order to make everyone happy, these global, static functions + are provided to set whether or not TinyXml will condense all white space + into a single space or not. The default is to condense. Note changing this + value is not thread safe. + */ + static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } + + /// Return the current white space setting. + static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } + + /** Return the position, in the original source file, of this node or attribute. + The row and column are 1-based. (That is the first row and first column is + 1,1). If the returns values are 0 or less, then the parser does not have + a row and column value. + + Generally, the row and column value will be set when the TiXmlDocument::Load(), + TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set + when the DOM was created from operator>>. + + The values reflect the initial load. Once the DOM is modified programmatically + (by adding or changing nodes and attributes) the new values will NOT update to + reflect changes in the document. + + There is a minor performance cost to computing the row and column. Computation + can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. + + @sa TiXmlDocument::SetTabSize() + */ + int Row() const { return location.row + 1; } + int Column() const { return location.col + 1; } ///< See Row() + + void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. + void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. + const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. + + // Table that returs, for a given lead byte, the total number of bytes + // in the UTF-8 sequence. + static const int utf8ByteTable[256]; + + virtual const char* Parse( const char* p, + TiXmlParsingData* data, + TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; + + enum + { + TIXML_NO_ERROR = 0, + TIXML_ERROR, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_OUT_OF_MEMORY, + TIXML_ERROR_PARSING_ELEMENT, + TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, + TIXML_ERROR_READING_ELEMENT_VALUE, + TIXML_ERROR_READING_ATTRIBUTES, + TIXML_ERROR_PARSING_EMPTY, + TIXML_ERROR_READING_END_TAG, + TIXML_ERROR_PARSING_UNKNOWN, + TIXML_ERROR_PARSING_COMMENT, + TIXML_ERROR_PARSING_DECLARATION, + TIXML_ERROR_DOCUMENT_EMPTY, + TIXML_ERROR_EMBEDDED_NULL, + TIXML_ERROR_PARSING_CDATA, + TIXML_ERROR_DOCUMENT_TOP_ONLY, + + TIXML_ERROR_STRING_COUNT + }; + +protected: + + static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); + inline static bool IsWhiteSpace( char c ) + { + return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); + } + inline static bool IsWhiteSpace( int c ) + { + if ( c < 256 ) + return IsWhiteSpace( (char) c ); + return false; // Again, only truly correct for English/Latin...but usually works. + } + + #ifdef TIXML_USE_STL + static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); + static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); + #endif + + /* Reads an XML name into the string provided. Returns + a pointer just past the last character of the name, + or 0 if the function has an error. + */ + static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); + + /* Reads text. Returns a pointer past the given end tag. + Wickedly complex options, but it keeps the (sensitive) code in one place. + */ + static const char* ReadText( const char* in, // where to start + TIXML_STRING* text, // the string read + bool ignoreWhiteSpace, // whether to keep the white space + const char* endTag, // what ends this text + bool ignoreCase, // whether to ignore case in the end tag + TiXmlEncoding encoding ); // the current encoding + + // If an entity has been found, transform it into a character. + static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); + + // Get a character, while interpreting entities. + // The length can be from 0 to 4 bytes. + inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) + { + assert( p ); + if ( encoding == TIXML_ENCODING_UTF8 ) + { + *length = utf8ByteTable[ *((const unsigned char*)p) ]; + assert( *length >= 0 && *length < 5 ); + } + else + { + *length = 1; + } + + if ( *length == 1 ) + { + if ( *p == '&' ) + return GetEntity( p, _value, length, encoding ); + *_value = *p; + return p+1; + } + else if ( *length ) + { + //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), + // and the null terminator isn't needed + for( int i=0; p[i] && i<*length; ++i ) { + _value[i] = p[i]; + } + return p + (*length); + } + else + { + // Not valid text. + return 0; + } + } + + // Puts a string to a stream, expanding entities as it goes. + // Note this should not contian the '<', '>', etc, or they will be transformed into entities! + static void PutString( const TIXML_STRING& str, TIXML_STRING* out ); + + // Return true if the next characters in the stream are any of the endTag sequences. + // Ignore case only works for english, and should only be relied on when comparing + // to English words: StringEqual( p, "version", true ) is fine. + static bool StringEqual( const char* p, + const char* endTag, + bool ignoreCase, + TiXmlEncoding encoding ); + + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; + + TiXmlCursor location; + + /// Field containing a generic user pointer + void* userData; + + // None of these methods are reliable for any language except English. + // Good for approximation, not great for accuracy. + static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); + static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); + inline static int ToLower( int v, TiXmlEncoding encoding ) + { + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( v < 128 ) return tolower( v ); + return v; + } + else + { + return tolower( v ); + } + } + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + +private: + TiXmlBase( const TiXmlBase& ); // not implemented. + void operator=( const TiXmlBase& base ); // not allowed. + + struct Entity + { + const char* str; + unsigned int strLength; + char chr; + }; + enum + { + NUM_ENTITY = 5, + MAX_ENTITY_LENGTH = 6 + + }; + static Entity entity[ NUM_ENTITY ]; + static bool condenseWhiteSpace; +}; + + +/** The parent class for everything in the Document Object Model. + (Except for attributes). + Nodes have siblings, a parent, and children. A node can be + in a document, or stand on its own. The type of a TiXmlNode + can be queried, and it can be cast to its more defined type. +*/ +class TiXmlNode : public TiXmlBase +{ + friend class TiXmlDocument; + friend class TiXmlElement; + +public: + #ifdef TIXML_USE_STL + + /** An input stream operator, for every class. Tolerant of newlines and + formatting, but doesn't expect them. + */ + friend std::istream& operator >> (std::istream& in, TiXmlNode& base); + + /** An output stream operator, for every class. Note that this outputs + without any newlines or formatting, as opposed to Print(), which + includes tabs and new lines. + + The operator<< and operator>> are not completely symmetric. Writing + a node to a stream is very well defined. You'll get a nice stream + of output, without any extra whitespace or newlines. + + But reading is not as well defined. (As it always is.) If you create + a TiXmlElement (for example) and read that from an input stream, + the text needs to define an element or junk will result. This is + true of all input streams, but it's worth keeping in mind. + + A TiXmlDocument will read nodes until it reads a root element, and + all the children of that root element. + */ + friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); + + /// Appends the XML node or attribute to a std::string. + friend std::string& operator<< (std::string& out, const TiXmlNode& base ); + + #endif + + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType + { + DOCUMENT, + ELEMENT, + COMMENT, + UNKNOWN, + TEXT, + DECLARATION, + TYPECOUNT + }; + + virtual ~TiXmlNode(); + + /** The meaning of 'value' changes for the specific type of + TiXmlNode. + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + + The subclasses will wrap this function. + */ + const char *Value() const { return value.c_str (); } + + #ifdef TIXML_USE_STL + /** Return Value() as a std::string. If you only use STL, + this is more efficient than calling Value(). + Only available in STL mode. + */ + const std::string& ValueStr() const { return value; } + #endif + + /** Changes the value of the node. Defined as: + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + void SetValue(const char * _value) { value = _value;} + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() { return parent; } + const TiXmlNode* Parent() const { return parent; } + + const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. + TiXmlNode* FirstChild() { return firstChild; } + const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + /// The first child of this node with the matching 'value'. Will be null if none found. + TiXmlNode* FirstChild( const char * _value ) { + // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) + // call the method, cast the return back to non-const. + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); + } + const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. + TiXmlNode* LastChild() { return lastChild; } + + const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + TiXmlNode* LastChild( const char * _value ) { + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. + #endif + + /** An alternate way to walk the children of a node. + One way to iterate over nodes is: + @verbatim + for( child = parent->FirstChild(); child; child = child->NextSibling() ) + @endverbatim + + IterateChildren does the same thing with the syntax: + @verbatim + child = 0; + while( child = parent->IterateChildren( child ) ) + @endverbatim + + IterateChildren takes the previous child as input and finds + the next one. If the previous child is null, it returns the + first. IterateChildren will return null when done. + */ + const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); + } + + /// This flavor of IterateChildren searches for children with a particular 'value' + const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + #endif + + /** Add a new node related to this. Adds a child past the LastChild. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); + + + /** Add a new node related to this. Adds a child past the LastChild. + + NOTE: the node to be added is passed by pointer, and will be + henceforth owned (and deleted) by tinyXml. This method is efficient + and avoids an extra copy, but should be used with care as it + uses a different memory model than the other insert functions. + + @sa InsertEndChild + */ + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + + /** Add a new node related to this. Adds a child before the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); + + /** Add a new node related to this. Adds a child after the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); + + /** Replace a child of this node. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); + + /// Delete a child of this node. + bool RemoveChild( TiXmlNode* removeThis ); + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling() const { return prev; } + TiXmlNode* PreviousSibling() { return prev; } + + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling( const char * ) const; + TiXmlNode* PreviousSibling( const char *_prev ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Navigate to a sibling node. + const TiXmlNode* NextSibling() const { return next; } + TiXmlNode* NextSibling() { return next; } + + /// Navigate to a sibling node with the given 'value'. + const TiXmlNode* NextSibling( const char * ) const; + TiXmlNode* NextSibling( const char* _next ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement() const; + TiXmlElement* NextSiblingElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement( const char * ) const; + TiXmlElement* NextSiblingElement( const char *_next ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement() const; + TiXmlElement* FirstChildElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); + } + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement( const char * _value ) const; + TiXmlElement* FirstChildElement( const char * _value ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); + } + + #ifdef TIXML_USE_STL + const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /** Query the type (as an enumerated value, above) of this node. + The possible types are: DOCUMENT, ELEMENT, COMMENT, + UNKNOWN, TEXT, and DECLARATION. + */ + int Type() const { return type; } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + const TiXmlDocument* GetDocument() const; + TiXmlDocument* GetDocument() { + return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); + } + + /// Returns true if this node has no children. + bool NoChildren() const { return !firstChild; } + + virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + /** Create an exact duplicate of this node and return it. The memory must be deleted + by the caller. + */ + virtual TiXmlNode* Clone() const = 0; + + /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the TiXmlVisitor interface. + + This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + TiXmlPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( TiXmlVisitor* visitor ) const = 0; + +protected: + TiXmlNode( NodeType _type ); + + // Copy to the allocated object. Shared functionality between Clone, Copy constructor, + // and the assignment operator. + void CopyTo( TiXmlNode* target ) const; + + #ifdef TIXML_USE_STL + // The real work of the input operator. + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; + #endif + + // Figure out what is at *p, and parse it. Returns null if it is not an xml node. + TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); + + TiXmlNode* parent; + NodeType type; + + TiXmlNode* firstChild; + TiXmlNode* lastChild; + + TIXML_STRING value; + + TiXmlNode* prev; + TiXmlNode* next; + +private: + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. +}; + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not TiXmlNodes, since they are not + part of the tinyXML document object model. There are other + suggested ways to look at this problem. +*/ +class TiXmlAttribute : public TiXmlBase +{ + friend class TiXmlAttributeSet; + +public: + /// Construct an empty attribute. + TiXmlAttribute() : TiXmlBase() + { + document = 0; + prev = next = 0; + } + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlAttribute( const std::string& _name, const std::string& _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + #endif + + /// Construct an attribute with a name and value. + TiXmlAttribute( const char * _name, const char * _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + + const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. + const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. + #ifdef TIXML_USE_STL + const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. + #endif + int IntValue() const; ///< Return the value of this attribute, converted to an integer. + double DoubleValue() const; ///< Return the value of this attribute, converted to a double. + + // Get the tinyxml string representation + const TIXML_STRING& NameTStr() const { return name; } + + /** QueryIntValue examines the value string. It is an alternative to the + IntValue() method with richer error checking. + If the value is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. + + A specialized but useful call. Note that for success it returns 0, + which is the opposite of almost all other TinyXml calls. + */ + int QueryIntValue( int* _value ) const; + /// QueryDoubleValue examines the value string. See QueryIntValue(). + int QueryDoubleValue( double* _value ) const; + + void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. + void SetValue( const char* _value ) { value = _value; } ///< Set the value. + + void SetIntValue( int _value ); ///< Set the value from an integer. + void SetDoubleValue( double _value ); ///< Set the value from a double. + + #ifdef TIXML_USE_STL + /// STL std::string form. + void SetName( const std::string& _name ) { name = _name; } + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Get the next sibling attribute in the DOM. Returns null at end. + const TiXmlAttribute* Next() const; + TiXmlAttribute* Next() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); + } + + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + const TiXmlAttribute* Previous() const; + TiXmlAttribute* Previous() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); + } + + bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } + bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } + bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } + + /* Attribute parsing starts: first letter of the name + returns: the next char after the value end quote + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + // Prints this Attribute to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { document = doc; } + +private: + TiXmlAttribute( const TiXmlAttribute& ); // not implemented. + void operator=( const TiXmlAttribute& base ); // not allowed. + + TiXmlDocument* document; // A pointer back to a document, for error reporting. + TIXML_STRING name; + TIXML_STRING value; + TiXmlAttribute* prev; + TiXmlAttribute* next; +}; + + +/* A class used to manage a group of attributes. + It is only used internally, both by the ELEMENT and the DECLARATION. + + The set can be changed transparent to the Element and Declaration + classes that use it, but NOT transparent to the Attribute + which has to implement a next() and previous() method. Which makes + it a bit problematic and prevents the use of STL. + + This version is implemented with circular lists because: + - I like circular lists + - it demonstrates some independence from the (typical) doubly linked list. +*/ +class TiXmlAttributeSet +{ +public: + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); + + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); + + const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + + const TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* Find( const char* _name ) { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); + } + #ifdef TIXML_USE_STL + const TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* Find( const std::string& _name ) { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); + } + + #endif + +private: + //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), + //*ME: this class must be also use a hidden/disabled copy-constructor !!! + TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed + void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) + + TiXmlAttribute sentinel; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TiXmlElement : public TiXmlNode +{ +public: + /// Construct an element. + TiXmlElement (const char * in_value); + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlElement( const std::string& _value ); + #endif + + TiXmlElement( const TiXmlElement& ); + + void operator=( const TiXmlElement& base ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + */ + const char* Attribute( const char* name ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an integer, + the integer value will be put in the return 'i', if 'i' + is non-null. + */ + const char* Attribute( const char* name, int* i ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an double, + the double value will be put in the return 'd', if 'd' + is non-null. + */ + const char* Attribute( const char* name, double* d ) const; + + /** QueryIntAttribute examines the attribute - it is an alternative to the + Attribute() method with richer error checking. + If the attribute is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. If the attribute + does not exist, then TIXML_NO_ATTRIBUTE is returned. + */ + int QueryIntAttribute( const char* name, int* _value ) const; + /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, double* _value ) const; + /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). + int QueryFloatAttribute( const char* name, float* _value ) const { + double d; + int result = QueryDoubleAttribute( name, &d ); + if ( result == TIXML_SUCCESS ) { + *_value = (float)d; + } + return result; + } + #ifdef TIXML_USE_STL + /** Template form of the attribute query which will try to read the + attribute into the specified type. Very easy, very powerful, but + be careful to make sure to call this with the correct type. + + @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE + */ + template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + std::stringstream sstream( node->ValueStr() ); + sstream >> *outValue; + if ( !sstream.fail() ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; + } + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, const char * _value ); + + #ifdef TIXML_USE_STL + const std::string* Attribute( const std::string& name ) const; + const std::string* Attribute( const std::string& name, int* i ) const; + const std::string* Attribute( const std::string& name, double* d ) const; + int QueryIntAttribute( const std::string& name, int* _value ) const; + int QueryDoubleAttribute( const std::string& name, double* _value ) const; + + /// STL std::string form. + void SetAttribute( const std::string& name, const std::string& _value ); + ///< STL std::string form. + void SetAttribute( const std::string& name, int _value ); + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char * name, int value ); + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetDoubleAttribute( const char * name, double value ); + + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const char * name ); + #ifdef TIXML_USE_STL + void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. + #endif + + const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. + TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } + const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. + TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the TiXmlText child + and accessing it directly. + + If the first child of 'this' is a TiXmlText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + + WARNING: GetText() accesses a child node - don't become confused with the + similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are + safe type casts on the referenced node. + */ + const char* GetText() const; + + /// Creates a new Element and returns it - the returned element is a copy. + virtual TiXmlNode* Clone() const; + // Print the Element to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + + void CopyTo( TiXmlElement* target ) const; + void ClearThis(); // like clear, but initializes 'this' object as well + + // Used to be public [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + /* [internal use] + Reads the "value" of the element -- another element, or text. + This should terminate with the current end tag. + */ + const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + +private: + + TiXmlAttributeSet attributeSet; +}; + + +/** An XML comment. +*/ +class TiXmlComment : public TiXmlNode +{ +public: + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} + /// Construct a comment from text. + TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) { + SetValue( _value ); + } + TiXmlComment( const TiXmlComment& ); + void operator=( const TiXmlComment& base ); + + virtual ~TiXmlComment() {} + + /// Returns a copy of this Comment. + virtual TiXmlNode* Clone() const; + // Write this Comment to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlComment* target ) const; + + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif +// virtual void StreamOut( TIXML_OSTREAM * out ) const; + +private: + +}; + + +/** XML text. A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCDATA() and query it with CDATA(). +*/ +class TiXmlText : public TiXmlNode +{ + friend class TiXmlElement; +public: + /** Constructor for text element. By default, it is treated as + normal, encoded text. If you want it be output as a CDATA text + element, set the parameter _cdata to 'true' + */ + TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT) + { + SetValue( initValue ); + cdata = false; + } + virtual ~TiXmlText() {} + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) + { + SetValue( initValue ); + cdata = false; + } + #endif + + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } + void operator=( const TiXmlText& base ) { base.CopyTo( this ); } + + // Write this text object to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /// Queries whether this represents text using a CDATA section. + bool CDATA() const { return cdata; } + /// Turns on or off a CDATA representation of text. + void SetCDATA( bool _cdata ) { cdata = _cdata; } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + /// [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const; + void CopyTo( TiXmlText* target ) const; + + bool Blank() const; // returns true if all white space and new lines + // [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + bool cdata; // true if this should be input and output as a CDATA style text element +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXml will happily read or write files without a declaration, + however. There are 3 possible attributes to the declaration: + version, encoding, and standalone. + + Note: In this version of the code, the attributes are + handled as special cases, not generic attributes, simply + because there can only be at most 3 and they are always the same. +*/ +class TiXmlDeclaration : public TiXmlNode +{ +public: + /// Construct an empty declaration. + TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} + +#ifdef TIXML_USE_STL + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); +#endif + + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); + + TiXmlDeclaration( const TiXmlDeclaration& copy ); + void operator=( const TiXmlDeclaration& copy ); + + virtual ~TiXmlDeclaration() {} + + /// Version. Will return an empty string if none was found. + const char *Version() const { return version.c_str (); } + /// Encoding. Will return an empty string if none was found. + const char *Encoding() const { return encoding.c_str (); } + /// Is this a standalone document? + const char *Standalone() const { return standalone.c_str (); } + + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const; + // Print this declaration to a FILE stream. + virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + + TIXML_STRING version; + TIXML_STRING encoding; + TIXML_STRING standalone; +}; + + +/** Any tag that tinyXml doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into TiXmlUnknowns. +*/ +class TiXmlUnknown : public TiXmlNode +{ +public: + TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} + virtual ~TiXmlUnknown() {} + + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } + void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } + + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const; + // Print this Unknown to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected: + void CopyTo( TiXmlUnknown* target ) const; + + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + +}; + + +/** Always the top level node. A document binds together all the + XML pieces. It can be saved, loaded, and printed to the screen. + The 'value' of a document node is the xml file name. +*/ +class TiXmlDocument : public TiXmlNode +{ +public: + /// Create an empty document, that has no name. + TiXmlDocument(); + /// Create a document with a name. The name of the document is also the filename of the xml. + TiXmlDocument( const char * documentName ); + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlDocument( const std::string& documentName ); + #endif + + TiXmlDocument( const TiXmlDocument& copy ); + void operator=( const TiXmlDocument& copy ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile() const; + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const char * filename ) const; + /** Load a file using the given FILE*. Returns true if successful. Note that this method + doesn't stream - the entire object pointed at by the FILE* + will be interpreted as an XML file. TinyXML doesn't stream in XML from the current + file location. Streaming may be added in the future. + */ + bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given FILE*. Returns true if successful. + bool SaveFile( FILE* ) const; + + #ifdef TIXML_USE_STL + bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. + { +// StringToBuffer f( filename ); +// return ( f.buffer && LoadFile( f.buffer, encoding )); + return LoadFile( filename.c_str(), encoding ); + } + bool SaveFile( const std::string& filename ) const ///< STL std::string version. + { +// StringToBuffer f( filename ); +// return ( f.buffer && SaveFile( f.buffer )); + return SaveFile( filename.c_str() ); + } + #endif + + /** Parse the given null terminated block of xml data. Passing in an encoding to this + method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml + to use that encoding, regardless of what TinyXml might otherwise try to detect. + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + + /** Get the root element -- the only top level element -- of the document. + In well formed XML, there should only be one. TinyXml is tolerant of + multiple elements at the document level. + */ + const TiXmlElement* RootElement() const { return FirstChildElement(); } + TiXmlElement* RootElement() { return FirstChildElement(); } + + /** If an error occurs, Error will be set to true. Also, + - The ErrorId() will contain the integer identifier of the error (not generally useful) + - The ErrorDesc() method will return the name of the error. (very useful) + - The ErrorRow() and ErrorCol() will return the location of the error (if known) + */ + bool Error() const { return error; } + + /// Contains a textual (english) description of the error if one occurs. + const char * ErrorDesc() const { return errorDesc.c_str (); } + + /** Generally, you probably want the error string ( ErrorDesc() ). But if you + prefer the ErrorId, this function will fetch it. + */ + int ErrorId() const { return errorId; } + + /** Returns the location (if known) of the error. The first column is column 1, + and the first row is row 1. A value of 0 means the row and column wasn't applicable + (memory errors, for example, have no row/column) or the parser lost the error. (An + error in the error reporting, in that case.) + + @sa SetTabSize, Row, Column + */ + int ErrorRow() const { return errorLocation.row+1; } + int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() + + /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) + to report the correct values for row and column. It does not change the output + or input in any way. + + By calling this method, with a tab size + greater than 0, the row and column of each node and attribute is stored + when the file is loaded. Very useful for tracking the DOM back in to + the source file. + + The tab size is required for calculating the location of nodes. If not + set, the default of 4 is used. The tabsize is set per document. Setting + the tabsize to 0 disables row/column tracking. + + Note that row and column tracking is not supported when using operator>>. + + The tab size needs to be enabled before the parse or load. Correct usage: + @verbatim + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Load( "myfile.xml" ); + @endverbatim + + @sa Row, Column + */ + void SetTabSize( int _tabsize ) { tabsize = _tabsize; } + + int TabSize() const { return tabsize; } + + /** If you have handled the error, it can be reset with this call. The error + state is automatically cleared if you Parse a new XML block. + */ + void ClearError() { error = false; + errorId = 0; + errorDesc = ""; + errorLocation.row = errorLocation.col = 0; + //errorLocation.last = 0; + } + + /** Write the document to standard out using formatted printing ("pretty print"). */ + void Print() const { Print( stdout, 0 ); } + + /* Write the document to a string using formatted printing ("pretty print"). This + will allocate a character array (new char[]) and return it as a pointer. The + calling code pust call delete[] on the return char* to avoid a memory leak. + */ + //char* PrintToMemory() const; + + /// Print this Document to a FILE stream. + virtual void Print( FILE* cfile, int depth = 0 ) const; + // [internal use] + void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + + virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + // [internal use] + virtual TiXmlNode* Clone() const; + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + void CopyTo( TiXmlDocument* target ) const; + + bool error; + int errorId; + TIXML_STRING errorDesc; + int tabsize; + TiXmlCursor errorLocation; + bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. +}; + + +/** + A TiXmlHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + TiXmlElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + TiXmlElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + TiXmlElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + TiXmlElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity + of such code. A TiXmlHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + TiXmlHandle docHandle( &document ); + TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + TiXmlHandle handleCopy = handle; + @endverbatim + + What they should not be used for is iteration: + + @verbatim + int i=0; + while ( true ) + { + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); + if ( !child ) + break; + // do something + ++i; + } + @endverbatim + + It seems reasonable, but it is in fact two embedded while loops. The Child method is + a linear walk to find the element, so this code would iterate much more than it needs + to. Instead, prefer: + + @verbatim + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); + + for( child; child; child=child->NextSiblingElement() ) + { + // do something + } + @endverbatim +*/ +class TiXmlHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } + /// Copy constructor + TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } + TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } + + /// Return a handle to the first child node. + TiXmlHandle FirstChild() const; + /// Return a handle to the first child node with the given name. + TiXmlHandle FirstChild( const char * value ) const; + /// Return a handle to the first child element. + TiXmlHandle FirstChildElement() const; + /// Return a handle to the first child element with the given name. + TiXmlHandle FirstChildElement( const char * value ) const; + + /** Return a handle to the "index" child with the given name. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( const char* value, int index ) const; + /** Return a handle to the "index" child. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( int index ) const; + /** Return a handle to the "index" child element with the given name. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( const char* value, int index ) const; + /** Return a handle to the "index" child element. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( int index ) const; + + #ifdef TIXML_USE_STL + TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } + TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } + + TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } + TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } + #endif + + /** Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* ToNode() const { return node; } + /** Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + /** Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + /** Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + + /** @deprecated use ToNode. + Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* Node() const { return ToNode(); } + /** @deprecated use ToElement. + Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* Element() const { return ToElement(); } + /** @deprecated use ToText() + Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* Text() const { return ToText(); } + /** @deprecated use ToUnknown() + Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* Unknown() const { return ToUnknown(); } + +private: + TiXmlNode* node; +}; + + +/** Print to memory functionality. The TiXmlPrinter is useful when you need to: + + -# Print to memory (especially in non-STL mode) + -# Control formatting (line endings, etc.) + + When constructed, the TiXmlPrinter is in its default "pretty printing" mode. + Before calling Accept() you can call methods to control the printing + of the XML document. After TiXmlNode::Accept() is called, the printed document can + be accessed via the CStr(), Str(), and Size() methods. + + TiXmlPrinter uses the Visitor API. + @verbatim + TiXmlPrinter printer; + printer.SetIndent( "\t" ); + + doc.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + @endverbatim +*/ +class TiXmlPrinter : public TiXmlVisitor +{ +public: + TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), + buffer(), indent( " " ), lineBreak( "\n" ) {} + + virtual bool VisitEnter( const TiXmlDocument& doc ); + virtual bool VisitExit( const TiXmlDocument& doc ); + + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); + virtual bool VisitExit( const TiXmlElement& element ); + + virtual bool Visit( const TiXmlDeclaration& declaration ); + virtual bool Visit( const TiXmlText& text ); + virtual bool Visit( const TiXmlComment& comment ); + virtual bool Visit( const TiXmlUnknown& unknown ); + + /** Set the indent characters for printing. By default 4 spaces + but tab (\t) is also useful, or null/empty string for no indentation. + */ + void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } + /// Query the indention string. + const char* Indent() { return indent.c_str(); } + /** Set the line breaking string. By default set to newline (\n). + Some operating systems prefer other characters, or can be + set to the null/empty string for no indenation. + */ + void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } + /// Query the current line breaking string. + const char* LineBreak() { return lineBreak.c_str(); } + + /** Switch over to "stream printing" which is the most dense formatting without + linebreaks. Common when the XML is needed for network transmission. + */ + void SetStreamPrinting() { indent = ""; + lineBreak = ""; + } + /// Return the result. + const char* CStr() { return buffer.c_str(); } + /// Return the length of the result string. + size_t Size() { return buffer.size(); } + + #ifdef TIXML_USE_STL + /// Return the result. + const std::string& Str() { return buffer; } + #endif + +private: + void DoIndent() { + for( int i=0; i + :project: ... + :path: ... + + +doxygenfunction +~~~~~~~~~~~~~~~ + +This will generate output for a single function. The syntax is:: + + .. doxygenfunction:: + :project: ... + :path: ... + + +Config Variables +~~~~~~~~~~~~~~~~ + +**breathe_projects** + This should be a dictionary in which the keys are project names and the values are + paths to the folder containing the doxygen output for that project. + +**breathe_default_project** + This should match one of the keys in the **breathe_projects** dictionary and + indicates which project should be used when the project is not specified on + the directive. + + +Roles +----- + +No restructured text roles are planned. + +Nodes +----- + +No additional nodes are planned. + +References +---------- + +All interesting atoms of data should output references by which they can be +linked to from other parts of the documentation. + diff --git a/libs/network/doc/ext/breathe/testsuite/.gitignore b/libs/network/doc/ext/breathe/testsuite/.gitignore new file mode 100644 index 000000000..e6c4a69d4 --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/.gitignore @@ -0,0 +1,2 @@ +build +view diff --git a/libs/network/doc/ext/breathe/testsuite/pseudorst.py b/libs/network/doc/ext/breathe/testsuite/pseudorst.py new file mode 100755 index 000000000..65f2c4046 --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/pseudorst.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + + +import sys + +sys.path.insert(0, "../") +sys.path.insert(0, "source") + +from docutils.parsers import rst +from breathe.builder import RstBuilder, BuilderFactory +from breathe.finder import FinderFactory, NoMatchesError, MultipleMatchesError +from breathe.parser import DoxygenParserFactory, DoxygenIndexParser +from breathe.renderer.rst.doxygen import DoxygenToRstRendererFactoryCreator +from breathe.finder.doxygen import DoxygenItemFinderFactoryCreator, ItemMatcherFactory + +from breathe import NodeFactory, ProjectInfoFactory, DoxygenDirectiveFactory + +import docutils.nodes +import sphinx.addnodes + + +# Sphinx source/conf.py file +import conf + +parser_factory = DoxygenParserFactory() +matcher_factory = ItemMatcherFactory() +item_finder_factory_creator = DoxygenItemFinderFactoryCreator(parser_factory, matcher_factory) +index_parser = DoxygenIndexParser() +finder_factory = FinderFactory(index_parser, item_finder_factory_creator) + +node_factory = NodeFactory(docutils.nodes, sphinx.addnodes) +renderer_factory_creator = DoxygenToRstRendererFactoryCreator(node_factory, parser_factory) +builder_factory = BuilderFactory(RstBuilder, renderer_factory_creator) + +project_info_factory = ProjectInfoFactory() +project_info_factory.update(conf.breathe_projects, conf.breathe_default_project) + +directive_factory = DoxygenDirectiveFactory(builder_factory, finder_factory, matcher_factory, project_info_factory) + +from docutils.core import publish_cmdline, default_description + +from docutils.parsers.rst import directives +directives.register_directive("doxygenindex", directive_factory.create_index_directive_container()) + +description = ('Generates pseudo-XML from standalone reStructuredText ' + 'sources (for testing purposes). ' + default_description) + +publish_cmdline(description=description) + diff --git a/libs/network/doc/ext/breathe/testsuite/source/_static/breathe.css b/libs/network/doc/ext/breathe/testsuite/source/_static/breathe.css new file mode 100644 index 000000000..292bc7f7d --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/_static/breathe.css @@ -0,0 +1,13 @@ + +/* -- breathe specific styles ----------------------------------------------- */ + +/* So enum value descriptions are displayed inline to the item */ +.breatheenumvalues li tt + p { + display: inline; +} + +/* So parameter descriptions are displayed inline to the item */ +.breatheparameterlist li tt + p { + display: inline; +} + diff --git a/libs/network/doc/ext/breathe/testsuite/source/class.rst b/libs/network/doc/ext/breathe/testsuite/source/class.rst new file mode 100644 index 000000000..63d9efee4 --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/class.rst @@ -0,0 +1,31 @@ + +.. _class-example: + +doxygenclass Directive Example +============================== + +Working Example +--------------- + +This should work:: + + .. doxygenclass:: Test + :project: class + +It produces this output: + +.. doxygenclass:: Test + :project: class + +Failing Example +--------------- + +This intentionally fails:: + + .. doxygenclass:: made_up_class + :project: class + +It produces the following warning message: + +.. warning:: doxygenclass: Cannot find class "made_up_class" in doxygen xml output + diff --git a/libs/network/doc/ext/breathe/testsuite/source/codeguide.rst b/libs/network/doc/ext/breathe/testsuite/source/codeguide.rst new file mode 100644 index 000000000..2196050fc --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/codeguide.rst @@ -0,0 +1,237 @@ + +.. _codeguide: + +How It Works +============ + +There are three main sections to Breathe: parser, finders and renderers. +Briefly: + + **parser** + Responsible for reading the doxygen xml output and creating objects + representing the data. Found in ``breathe.parser``. + + **finders** + Responsible for finding reference objects within the output from the + parser. Found in ``breathe.finder``. + + **renderers** + Responsible for producing restructured text nodes to represent the objects + that the finders have found. The renderers generally descend through the + object hierarchies rendering the objects, their children, their children's + children and so on. Found in ``breathe.renderer``. + + +Parser +------ + +The parsers job is to parse the doxygen xml output and create a hierarchy of +Python objects to represent the xml data. + +Doxygen Xml Output +~~~~~~~~~~~~~~~~~~ + +The xml output from doxygen comes in multiple files. There is always an +``index.xml`` file which is a central reference point and contains a list of all +the other files that have been generated by doxygen and an indication of what +they contain. + +For example, in ``examples/doxygen/func/xml`` directory, the ``index.xml`` file +contains:: + + + + Test + member + + func.h + + + +This suggests there is additional information about a class called **Test** +which has a function called **member**. Additionally there is some more +information about a file called **func.h**. + +Now, the ``refid`` attribute on the ``compound`` xml nodes gives an indication +of where the additional information can be found. So for the **Test** class, we +should look in ``class_test.xml``, which we get by simply appending ``.xml`` to +the ``refid`` value, and for the **func.h** file we should look in +``func_8h.xml``. + +So the ``index.xml`` file is unique in its role and has its own structure which +is defined in the ``index.xsd`` file which you will also find in the same +directory. All the other files, the ones referenced by the ``index.xml`` file, follow +another structure. This is described in ``compound.xsd`` file so we call these +other files **compound** files. These are generally longer than the +``index.xml`` file and contain all the specific information you might expect +from doxygen, including any documentation you added to your code as doxygen +markup. + +Have a look at ``examples/doxygen/func/xml/class_test.xml`` for a fairly short +example. + + +Doing the Parsing +~~~~~~~~~~~~~~~~~ + +To get things up and running quickly, I have used the `generateDS +`_ project to help create +classes to parse the doxygen xml output. The script automatically creates the +``compound.py``, ``compoundsuper.py``, ``index.py`` and ``indexsuper.py`` files +that you can see inside ``breathe/parser/doxygen``. + +So what is the difference between ``index.py`` and ``indexsuper.py``, and +``compound.py`` and ``compoundsuper.py``? These files allow us to separate the +bulk of the automatically generated code from the code changes we might want to +make. There are a large number of classes in the ``...super.py`` files and each +one has a basic derived class in the corresponding non-super files. + +It is designed so that all the hard work done by the generated code is +done in the ``...super.py`` files and if we need to make changes we can do them +in the derived classes in the non-super files and if we ever need to regenerate +the code, we only regenerate the ``...super.py`` files and so we don't lose our +changes in the process. + +The end result is that for the parsing, we have written relatively little code, +but have a large amount automatically generated for us. This has only been done +once and it seems relatively unlikely that we'll do it again. The entry points to +the parsing code is the ``parse`` functions at the bottom of the +``breathe.parser.doxygen.compound`` and ``breathe.parser.doxygen.index``. + +I have never really examined the details of the parsing but you can see that +there is a class for each node type you are likely to find in the xml files. I +say "node type" instead of just "node" because different nodes can share the +same type and there is one class per type. For example, there are +**detaileddescription** nodes and **briefdescription** nodes which are both of +type **descriptionType**. If we look in ``breathe.parser.doxygen.compoundsuper`` +we see a **descriptionType** class and in +``breathe.parser.doxygen.compound`` we see a **descriptionTypeSub** class which +is derived from **descriptionType**. + + +Our Changes +~~~~~~~~~~~ + +You'll notice there are some classes in the non-super files that have some +additional code in them. This tends to be adjusting the ``buildChildren`` member +function in the derived class to extend or override the one in the +automatically generated base class. + +We have to do this sometimes as it seems the original code we generated with +``generateDS`` fails to construct the children of some classes. The +``generateDS`` scripts uses the descriptions in the ``.xsd`` files to determine +what classes to generate and what nodes can be the children of other nodes. It +is possible that the doxygen ``.xsd`` files contain levels of abstraction that +the ``generateDS`` project did not cope with at the time I used it. It is +possible that newer versions would handle it better but for the moment I'm +content updating the derived classes to handle the cases I see missing. + + + +Finders +------- + +The finder classes have a relatively small but important job of finding objects +in the hierarchy generated by the parsers. For example, when a user specifies a +particular class for the :ref:`doxygenclass directive `, we use +the finder classes to go and find the object corresponding to that class. + +In fact, if you look closely, it is the finders that use the parser entry points +to parse the xml and then find the objects. The finders also use ``Matcher`` +objects to actually figure out if they have found what they are looking for. + +In the simplest case, the finder only has to find the root of the hierarchy for +the :ref:`doxygenindex directive `. In the other cases, the +finder is given a ``MatcherStack`` and the level of the hierarchy it should be +aiming for. The ``MatcherStack`` is what is sounds like, a stack of ``Matcher`` +objects which are designed to match at different levels of the hierarchy, + +More Details, Please +~~~~~~~~~~~~~~~~~~~~ + +So initially, we create a finder to look at the root of the hierarchy: the +**doxygenTypeSub** node. That finder, handily called +**DoxygenTypeSubItemFinder** (you'll notice a lot of that) looks through all the +child compound nodes of the **doxygenTypeSub** node and tries a compound-level +match against each of them and if something matches it creates a +**CompoundTypeSubItemFinder** to look further. + +In turn, that checks each of its member child nodes with a member-level match +and if it finds one it creates a **MemberTypeSubItemFinder** (see the pattern?) +and that does another check. The interesting part is, if that is successful, the +**CompoundTypeSubItemFinder** finds the corresponding xml file that has more +information in it (remember ``refid + .xml``?) and parses that and creates +another finder to start looking in there. This time it is a +**DoxygenTypeSubItemFinder** from the ``breathe.finder.doxygen.compound`` +module. And the search goes on until we find an object to return for rendering. + +If the **CompoundTypeSubItemFinder** fails to find any deeper levels to match +against then it returns itself as it must be the target we're interested in. + +As stated, the job of the finder is to find a single node for the renderers to +starting rendering to restructured text. That is all the finder does. + + +Renderers +--------- + +Finally, the bit that really does something we care about. Rendering is the art +of turning whatever object we've found in the hierarchy into restructured text +nodes. This almost invariably means most of its children as well. + +Much like with the finder classes, we start off creating a renderer for a +particular parser object and then it looks at its children and uses the renderer +factory to create appropriate renderers for those objects and tells them to +render and they look at their object's children and create appropriate renderers +for those and so on and so forth. + +The node we start at is determined by the finder and ultimately by the user. The +whole process is kicked off by the ``Builder`` class, though it doesn't really +do much. The aim of the renderers is to return a list of restructured text nodes +which is passed back to Sphinx to render into whatever you're final output +format is. + +There are two complicated bits here. All the different renderers and all the +different restructured text nodes. + +Different Renderers +~~~~~~~~~~~~~~~~~~~ + +Just like with the parsers, there is one renderer per node type. In fact there +is one renderer class per parser class and they are named almost the same and +are designed to match up. The renderers look at the data on the instance +of the corresponding parser class that they have been given and grab the +interesting bits and return restructured text nodes. + +For reference on what there is to render, you can look at the parser class +definitions or at the raw xml to see what attributes there are to render. +Sometimes if something isn't appearing in the final output, it is because the +renderer isn't returning an restructured text representation of it so the +rendering code needs to be updated, and sometimes it is because the parser +classes are not picking it up properly so both the parser and the renderer code +needs to be updated. + +Given a little bit of time, you get used to chasing through the xml nodes, +the parser classes and the corresponding renderers to figure out where all the +information is ending up. + + +Restructured Text Nodes +~~~~~~~~~~~~~~~~~~~~~~~ + +We use the restructured text API as provided by the fabulous docutils project +and extended by Sphinx itself. For the most part, they are fairly straight +forward and they are certainly well named. + +Unfortunately there are a lot of nodes and only certain ways of combining them. +It is also not always clear what arguments their constructs take. Whilst I'm +sure it would be possible to figure it out with time and the appropriate source +code, the use of them is not something I've found very well documented and my +code largely operates on a basis of trial and error. + +One day I'm sure I'll be enlightened, until then expect fairly naive code. + + + + + diff --git a/libs/network/doc/ext/breathe/testsuite/source/conf.py b/libs/network/doc/ext/breathe/testsuite/source/conf.py new file mode 100644 index 000000000..ae66d462c --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/conf.py @@ -0,0 +1,224 @@ +# -*- coding: utf-8 -*- +# +# BreatheExample documentation build configuration file, created by +# sphinx-quickstart on Tue Feb 3 18:20:48 2009. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# The contents of this file are pickled, so don't put values in the namespace +# that aren't pickleable (module imports are okay, they're removed automatically). +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If your extensions are in another directory, add it here. If the directory +# is relative to the documentation root, use os.path.abspath to make it +# absolute, like shown here. +#sys.path.append(os.path.abspath('.')) + +# General configuration +# --------------------- + +sys.path.append( "../" ) + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = [ "breathe" ] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Breathe' +copyright = u'2009-2010, Michael Jones' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.9.0' +# The full version, including alpha/beta/rc tags. +release = '0.9.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# Options for breathe extension +# ----------------------------- + +breathe_projects = { + "class":"../examples/doxygen/class/xml/", + "structcmd":"../examples/doxygen/structcmd/xml/", + "tinyxml":"../examples/tinyxml/tinyxml/xml/", + "restypedef":"../examples/doxygen/restypedef/xml/", + "nutshell":"../examples/specific/nutshell/xml/", + } + +breathe_default_project = "tinyxml" + +breathe_domain_by_extension = { + "h" : "cpp", + } + +breathe_domain_by_file_pattern = { + "*/class.h" : "cpp", + "*/alias.h" : "c", + } + + +# Options for HTML output +# ----------------------- + +# The style sheet to use for HTML and HTML Help pages. A file of that name +# must exist either in Sphinx' static/ path, or in one of the custom paths +# given in html_static_path. +# html_style = 'default.css' + +html_theme = "haiku" + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, the reST sources are included in the HTML build as _sources/. +#html_copy_source = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'BreatheExampledoc' + + +# Options for LaTeX output +# ------------------------ + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, document class [howto/manual]). +latex_documents = [ + ('index', 'BreatheExample.tex', ur'BreatheExample Documentation', + ur'Michael Jones', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True + +# *Cough*, ahem, borrowed from the Sphinx docs +def setup(app): + app.add_object_type('confval', 'confval', + objname='configuration value', + indextemplate='pair: %s; configuration value') + + diff --git a/libs/network/doc/ext/breathe/testsuite/source/contributing.rst b/libs/network/doc/ext/breathe/testsuite/source/contributing.rst new file mode 100644 index 000000000..b278556da --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/contributing.rst @@ -0,0 +1,56 @@ + +Contributing to Breathe +======================= + +There are four main ways you might consider contributing to Breathe. + + +Give It A Go +------------ + +**...and let me know!** Firstly, the more people using it the better, but more +than that, hearing about the project being put to use is a great motivator for +the developer, namely me. + + +Report Bugs & Suggest Features +------------------------------ + +Embarrassingly I don't get to use Breathe that much in my general work, so it +doesn't really get pushed beyond the test code we have here in the repository. + +If you use it and find issues with it, minor or major, please let me know and if +possible provide some detail so I can reproduce it. + +With the help of those who have posted issues on the github issue tracker we've +managed to track down and improve some of the less obvious (and some more +obvious!) parts of Breathe that weren't working properly. + + +Improve the Documentation +------------------------- + +I've made an effort to document Breathe so it is usable, but I have a twisted +perspective on the whole thing as I made it. + +I've already had some help with the documentation, which was greatly +appreciated, but if you managed to get it working and find that the +documentation could have been clearer in parts, let me know or write up a +paragraph or two that would have helped you when you were trying it. + + +Fork It! And Improve the Code +----------------------------- + +If you find a bug, quite like Python and have some time, then grab a copy of the +code and have a go at fixing it. Nothing motivates me quite like other people +caring enough to put a bit of time into working on it. The contributions we've +had this way have been great and much appreciated. + +If you want to help out, take a look at the :ref:`code guide` to see how +it is all structured and works. + + + + + diff --git a/libs/network/doc/ext/breathe/testsuite/source/credits.rst b/libs/network/doc/ext/breathe/testsuite/source/credits.rst new file mode 100644 index 000000000..e11a0237e --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/credits.rst @@ -0,0 +1,19 @@ + +Credits +======= + +Thank you to: + +- `nijel `_ +- `sebastianschaetz `_ +- `mbolivar `_ + +For their contributions; reporting bugs, suggesting features, improving the code +and working on the documentation. And thanks to: + +- Dimitri van Heesch for `Doxygen `_. +- Georg Brandl for `Sphinx `_. +- David Goodger for `Docutils `_ and Restructured Text. + +And thank you to whoever made the ``haiku`` theme for Sphinx. + diff --git a/libs/network/doc/ext/breathe/testsuite/source/directives.rst b/libs/network/doc/ext/breathe/testsuite/source/directives.rst new file mode 100644 index 000000000..d19696ba9 --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/directives.rst @@ -0,0 +1,158 @@ + +Directives & Config Variables +============================= + +.. toctree:: + :hidden: + + function + struct + class + enum + typedef + +The available directives are shown below. In each case the ``project`` and +``path`` options have the following meaning: + +``project`` + Specifies which project, as defined in the breathe_projects config value, + should be used for this directive. This overrides the default project if one + has been specified. + +``path`` + Directly specifies the path to the folder with the doxygen output. This + overrides the project and default project if they have been specified. + +.. _doxygenindex: + +doxygenindex Directive +~~~~~~~~~~~~~~~~~~~~~~ + +This directive processes and produces output for everything described by the +Doxygen xml output. It reads the ``index.xml`` file and process everything +referenced by it. + +:: + + .. doxygenindex:: + :project: ... + :path: ... + + + +doxygenfunction Directive +~~~~~~~~~~~~~~~~~~~~~~~~~ + +This directive generates the appropriate output for a single function. The +function name is required to be unique in the project. + +:: + + .. doxygenfunction:: + :project: ... + :path: ... + +Checkout the :ref:`example ` to see it in action. + +doxygenstruct Directive +~~~~~~~~~~~~~~~~~~~~~~~ + +This directive generates the appropriate output for a single struct. The struct +name is required to be unique in the project. + +:: + + .. doxygenstruct:: + :project: ... + :path: ... + +Checkout the :ref:`example ` to see it in action. + +doxygenenum Directive +~~~~~~~~~~~~~~~~~~~~~~~ + +This directive generates the appropriate output for a single enum. It behaves +the same as the doxygenstruct directive. + +:: + + .. doxygenenum:: + :project: ... + :path: ... + +Checkout the :ref:`example ` to see it in action. + +doxygentypedef Directive +~~~~~~~~~~~~~~~~~~~~~~~~ + +This directive generates the appropriate output for a single typedef. It behaves +the same as the doxygenstruct directive. + +:: + + .. doxygentypedef:: + :project: ... + :path: ... + +Checkout the :ref:`example ` to see it in action. + +.. _doxygenclass: + +doxygenclass Directive +~~~~~~~~~~~~~~~~~~~~~~ + +This directive generates the appropriate output for a single class. It behaves +the same as the doxygenstruct directive. + +:: + + .. doxygenclass:: + :project: ... + :path: ... + +Checkout the :ref:`example ` to see it in action. + + +Config Values +------------- + +.. confval:: breathe_projects + + This should be a dictionary in which the keys are project names and the values are + paths to the folder containing the doxygen output for that project. + +.. confval:: breathe_default_project + + This should match one of the keys in the :confval:`breathe_projects` dictionary and + indicates which project should be used when the project is not specified on + the directive. + +.. confval:: breathe_domain_by_extension + + Allows you to specify domains for particular files according to their + extension. + + For example:: + + breathe_domain_by_extension = { + "h" : "cpp", + } + +.. confval:: breathe_domain_by_file_pattern + + Allows you to specify domains for particular files by wildcard syntax. This + is checked after :confval:`breathe_domain_by_extension` and so will override + it when necessary. + + For example:: + + breathe_domain_by_file_pattern = { + "\*/alias.h" : "c", + } + + If you wanted all ``.h`` header files to be treated as being in the **cpp** + domain you might use the :confval:`breathe_domain_by_extension` example + above. But if you had one ``.h`` file that should be treated as being in the + **c** domain then you can override as above. + + diff --git a/libs/network/doc/ext/breathe/testsuite/source/domains.rst b/libs/network/doc/ext/breathe/testsuite/source/domains.rst new file mode 100644 index 000000000..67f004f1b --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/domains.rst @@ -0,0 +1,44 @@ + +Domain Tests +============ + +.. doxygenfunction:: testnamespace::NamespacedClassTest::function + :path: ../examples/specific/class/xml + +.. doxygenfunction:: frob_foos + :path: ../examples/specific/alias/xml + +Domain Reference +---------------- + +Through Breathe +~~~~~~~~~~~~~~~ + +Sphinx domains linking to Breathe output. + +This is a reference to a c func: :c:func:`frob_foos()`. + +This is :c:func:`another reference ` to a c func. + +This is a reference to a c++ func: :cpp:func:`testnamespace::NamespacedClassTest::function()`. + +This is :cpp:func:`another reference ` to a cpp func. + + +Through Sphinx +~~~~~~~~~~~~~~ + +Pure Sphinx functionality. + +.. c:function:: void* c_function(int) + +This is :c:func:`c_function()` to a c func. + +This is :c:func:`another reference ` to a c func. + +.. cpp:function:: void* mynamespace::MyClass::cppFunction(int param) + +This is a reference to a c++ func: :cpp:func:`mynamespace::MyClass::cppFunction()`. + +This is :cpp:func:`another reference ` to a cpp func. + diff --git a/libs/network/doc/ext/breathe/testsuite/source/doxygen.rst b/libs/network/doc/ext/breathe/testsuite/source/doxygen.rst new file mode 100644 index 000000000..fecd76034 --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/doxygen.rst @@ -0,0 +1,146 @@ + +Doxygen Test Suite +================== + +Class +----- + +.. doxygenindex:: + :project: class + +Define +------ + +.. doxygenindex:: + :path: ../examples/doxygen/define/xml + +Enum +---- +.. doxygenindex:: + :path: ../examples/doxygen/enum/xml + +File +----- +.. doxygenindex:: + :path: ../examples/doxygen/file/xml + +Func +---- +.. doxygenindex:: + :path: ../examples/doxygen/func/xml + +Page +---- +.. doxygenindex:: + :path: ../examples/doxygen/page/xml + +Relates +------- +.. doxygenindex:: + :path: ../examples/doxygen/relates/xml + +Author +------ +.. doxygenindex:: + :path: ../examples/doxygen/author/xml + +Par +--- +.. doxygenindex:: + :path: ../examples/doxygen/par/xml + +Overload +-------- +.. doxygenindex:: + :path: ../examples/doxygen/overload/xml + +Example +------- +.. doxygenindex:: + :path: ../examples/doxygen/example/xml + +Include +------- +.. doxygenindex:: + :path: ../examples/doxygen/include/xml + +QtStyle +------- +.. doxygenindex:: + :path: ../examples/doxygen/qtstyle/xml + +JdStyle +------- +.. doxygenindex:: + :path: ../examples/doxygen/jdstyle/xml + +StructCmd +--------- +.. doxygenindex:: + :path: ../examples/doxygen/structcmd/xml + +Autolink +-------- +.. doxygenindex:: + :path: ../examples/doxygen/autolink/xml + +ResTypeDef +---------- +.. doxygenindex:: + :path: ../examples/doxygen/restypedef/xml + +AfterDoc +-------- +.. doxygenindex:: + :path: ../examples/doxygen/afterdoc/xml + +Template +-------- +.. doxygenindex:: + :path: ../examples/doxygen/template/xml + +Tag +--- +.. doxygenindex:: + :path: ../examples/doxygen/tag/xml + +Group +----- +.. doxygenindex:: + :path: ../examples/doxygen/group/xml + +Diagrams +-------- +.. doxygenindex:: + :path: ../examples/doxygen/diagrams/xml + +Memgrp +------ +.. doxygenindex:: + :path: ../examples/doxygen/memgrp/xml + +Docstring +--------- +.. doxygenindex:: + :path: ../examples/doxygen/docstring/xml + +PyExample +--------- +.. doxygenindex:: + :path: ../examples/doxygen/pyexample/xml + +Mux +--- +.. doxygenindex:: + :path: ../examples/doxygen/mux/xml + +Manual +------ +.. doxygenindex:: + :path: ../examples/doxygen/manual/xml + + + + + + diff --git a/libs/network/doc/ext/breathe/testsuite/source/embeddedrst.rst b/libs/network/doc/ext/breathe/testsuite/source/embeddedrst.rst new file mode 100644 index 000000000..ea01e7049 --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/embeddedrst.rst @@ -0,0 +1,9 @@ + + +Embedded Rst +============ + + +.. doxygenindex:: + :path: ../examples/specific/rst/xml + diff --git a/libs/network/doc/ext/breathe/testsuite/source/enum.rst b/libs/network/doc/ext/breathe/testsuite/source/enum.rst new file mode 100644 index 000000000..db2f996df --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/enum.rst @@ -0,0 +1,31 @@ + +.. _enum-example: + +doxygenenum Directive Example +=============================== + +Working Example +--------------- + +This should work:: + + .. doxygenenum:: NodeType + :project: tinyxml + +It produces this output: + +.. doxygenenum:: NodeType + :project: tinyxml + +Failing Example +--------------- + +This intentionally fails:: + + .. doxygenenum:: made_up_enum + :project: restypedef + +It produces the following warning message: + +.. warning:: doxygenenum: Cannot find enum "made_up_enum" in doxygen xml output + diff --git a/libs/network/doc/ext/breathe/testsuite/source/function.rst b/libs/network/doc/ext/breathe/testsuite/source/function.rst new file mode 100644 index 000000000..ea357f68f --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/function.rst @@ -0,0 +1,31 @@ + +.. _function-example: + +doxygenfunction Directive Example +================================= + +Working Example +--------------- + +This should work:: + + .. doxygenfunction:: open + :project: structcmd + +It produces this output: + +.. doxygenfunction:: open + :project: structcmd + +Failing Example +--------------- + +This intentionally fails:: + + .. doxygenfunction:: made_up_function + :project: structcmd + +It produces the following warning message: + +.. warning:: doxygenfunction: Cannot find function "made_up_function" in doxygen xml output + diff --git a/libs/network/doc/ext/breathe/testsuite/source/index.rst b/libs/network/doc/ext/breathe/testsuite/source/index.rst new file mode 100644 index 000000000..f94776dc1 --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/index.rst @@ -0,0 +1,80 @@ +.. BreatheExample documentation master file, created by sphinx-quickstart on Tue Feb 3 18:20:48 2009. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Breathe's documentation +======================= + +Breathe provides a bridge between the Sphinx and Doxygen documentation systems. + +It is an easy way to include Doxygen information in a set of documentation +generated by Sphinx. The aim is to produce an autodoc like support for people +who enjoy using Sphinx but work with languages other than Python. The system +relies on the Doxygen's xml output. + +Features +-------- + +* **Simple setup** - one doxygen config value, one Sphinx config value and one + directive and you'll be on your way. +* **High and low level directives** - reference the whole project, just a class or + just a function with different directives. +* **Support for multiple doxygen projects** - set it up to be aware of different + projects and refence them by name or path for each directive. +* **Allows embedded restructured text in doxygen markup** - some extra doxygen + aliases allow you to add ``\rst`` - ``\endrst`` blocks to your comments and have + the contents interpreted as restructured text. +* **Plays well with Sphinx domains** - Link to entries in the breathe output with + standard Sphinx domain references, like, ``:c:func:``. + +Contents +-------- + +.. toctree:: + :maxdepth: 1 + + quickstart + directives + contributing + codeguide + testpages + credits + +In a Nutshell +------------- + +You write code that looks a little like this: + +.. literalinclude:: nutshell.h + :language: cpp + +Then you run this:: + + doxygen + +With a setting that says this:: + + GENERATE_XML = YES + +Then in your Sphinx documentation, you add something like this:: + + .. doxygenclass:: Nutshell + :project: nutshell + +With a ``conf.py`` setting like this:: + + breathe_projects = { + "nutshell":"../examples/specific/nutshell/xml/", + } + +And you get something like this: + +---- + + .. doxygenclass:: Nutshell + :project: nutshell + +---- + +Sound reasonable? To get started, go checkout the :doc:`quickstart guide `. + diff --git a/libs/network/doc/ext/breathe/testsuite/source/inline.rst b/libs/network/doc/ext/breathe/testsuite/source/inline.rst new file mode 100644 index 000000000..c5aa2f724 --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/inline.rst @@ -0,0 +1,20 @@ + +Inline Parameter Documentation +============================== + +This is currently flawed as it doesn't know where to sensibly put the parameters +in the final description. + +It currently defaults to the top of the detail description block which means it +comes between the brief description text and the detailed description text which +is less than ideal, but attempts to programmatically figure out where the detail +description text ends have failed. Something for future work. + +Example +------- + + +.. doxygenindex:: + :path: ../examples/specific/inline/xml + + diff --git a/libs/network/doc/ext/breathe/testsuite/source/members.rst b/libs/network/doc/ext/breathe/testsuite/source/members.rst new file mode 100644 index 000000000..d92abde00 --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/members.rst @@ -0,0 +1,28 @@ + +Members Tests +============= + +All Members +----------- + +.. doxygenclass:: testnamespace::NamespacedClassTest + :path: ../examples/specific/members/xml + :members: + + +Specific Members +---------------- + +.. doxygenclass:: testnamespace::NamespacedClassTest + :path: ../examples/specific/members/xml + :members: functionS, anotherFunction + :no-link: + + +No Members +---------- + +.. doxygenclass:: testnamespace::NamespacedClassTest + :path: ../examples/specific/members/xml + :no-link: + diff --git a/libs/network/doc/ext/breathe/testsuite/source/nutshell.h b/libs/network/doc/ext/breathe/testsuite/source/nutshell.h new file mode 100644 index 000000000..8e6b66edc --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/nutshell.h @@ -0,0 +1,43 @@ + +//! An overly extended example of how to use breathe +/*! + With a little bit of a elaboration, should you feel it necessary. +*/ +class Nutshell +{ +public: + + //! Our toolset + /*! The various tools we can opt to use to crack this particular nut */ + enum Tool + { + kHammer = 0, //!< What? It does the job + kNutCrackers, //!< Boring + kNinjaThrowingStars //!< Stealthy + }; + + //! Nutshell constructor + Nutshell(); + + //! Nutshell destructor + ~Nutshell(); + + /*! Crack that shell with specified tool + + \param tool - the tool with which to crack the nut + */ + void crack( Tool tool ); + + /*! + \return Whether or not the nut is cracked + */ + bool isCracked(); + +private: + + //! Our cracked state + bool m_isCracked; + +}; + + diff --git a/libs/network/doc/ext/breathe/testsuite/source/quickstart.rst b/libs/network/doc/ext/breathe/testsuite/source/quickstart.rst new file mode 100644 index 000000000..0830c3999 --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/quickstart.rst @@ -0,0 +1,56 @@ +Quickstart +========== + +For this quickstart we assume the following prerequisites: + +* breathe was downloaded and extracted somewhere +* doxygen was installed and doxygen output (XML format) was generated for the + project that is to be documented (set GENERATE_XML tag to YES) + +We assume the following paths: + +* documentation root path: :file:`/home/me/docproj/` +* breathe path: :file:`/home/me/docproj/ext/breathe/` +* doxygen xml output: :file:`/home/me/docproj/doxyxml/` + +The documentation path should contain a folder :file:`source` containing the +:file:`conf.py` file. The doxygen xml output folder should contain the +:file:`index.xml` output file generated by doxygen. + +The following steps are required to integrate breathe functionality: + +#. add the breathe path to your conf.py by adding the following line:: + + sys.path.append( "/home/me/docproj/ext/breathe/" ) + +#. add breathe as an extension the line could look like this:: + + extensions = ['sphinx.ext.pngmath', 'sphinx.ext.todo', 'breathe' ] + +#. tell breathe about the projects:: + + breathe_projects = { "myproject": "/home/me/docproj/doxyxml/" } + +#. specify a default project:: + + breathe_default_project = "myproject" + +Once this is done you may use the the following commands:: + + ..doxygenindex:: + ..doxygenfunction:: + ..doxygenstruct:: + ..doxygenenum:: + ..doxygentypedef:: + ..doxygenclass:: + +to include documentation for different constructs. For each of these commands the +the following directives may be specified: + +``project`` + Specifies which project, as defined in the breathe_projects config value, + should be used for this directive. This overrides the default. + +``path`` + Directly specifies the path to the folder with the doxygen output. This + overrides the project and default project. \ No newline at end of file diff --git a/libs/network/doc/ext/breathe/testsuite/source/specific.rst b/libs/network/doc/ext/breathe/testsuite/source/specific.rst new file mode 100644 index 000000000..71b9062fa --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/specific.rst @@ -0,0 +1,36 @@ + +Specific Examples Test Suite +============================ + + +Typedef Examples +---------------- + +.. doxygenindex:: + :path: ../examples/specific/typedef/xml + + +Namespaced Function Examples +---------------------------- + +.. doxygenfunction:: testnamespace::NamespacedClassTest::function + :path: ../examples/specific/class/xml + +.. doxygenfunction:: testnamespace::ClassTest::function + :path: ../examples/specific/class/xml + +.. doxygenfunction:: testnamespace::ClassTest::anotherFunction + :path: ../examples/specific/class/xml + +.. doxygenfunction:: ClassTest::function + :path: ../examples/specific/class/xml + +.. doxygenfunction:: ClassTest::anotherFunction + :path: ../examples/specific/class/xml + +Alias Example +------------- + +.. doxygenfunction:: frob_foos + :path: ../examples/specific/alias/xml + diff --git a/libs/network/doc/ext/breathe/testsuite/source/struct.rst b/libs/network/doc/ext/breathe/testsuite/source/struct.rst new file mode 100644 index 000000000..c31d51a4e --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/struct.rst @@ -0,0 +1,31 @@ + +.. _struct-example: + +doxygenstruct Directive Example +=============================== + +Working Example +--------------- + +This should work:: + + .. doxygenstruct:: CoordStruct + :project: restypedef + +It produces this output: + +.. doxygenstruct:: CoordStruct + :project: restypedef + +Failing Example +--------------- + +This intentionally fails:: + + .. doxygenstruct:: made_up_struct + :project: restypedef + +It produces the following warning message: + +.. warning:: doxygenstruct: Cannot find struct "made_up_struct" in doxygen xml output + diff --git a/libs/network/doc/ext/breathe/testsuite/source/testpages.rst b/libs/network/doc/ext/breathe/testsuite/source/testpages.rst new file mode 100644 index 000000000..5b03c0e08 --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/testpages.rst @@ -0,0 +1,15 @@ + +Test Pages +========== + +.. toctree:: + :maxdepth: 1 + + doxygen + tinyxml + specific + domains + embeddedrst + inline + members + diff --git a/libs/network/doc/ext/breathe/testsuite/source/tinyxml.rst b/libs/network/doc/ext/breathe/testsuite/source/tinyxml.rst new file mode 100644 index 000000000..dc0193fa9 --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/tinyxml.rst @@ -0,0 +1,8 @@ + +TinyXML Test Suite +================== + + +.. doxygenindex:: + + diff --git a/libs/network/doc/ext/breathe/testsuite/source/typedef.rst b/libs/network/doc/ext/breathe/testsuite/source/typedef.rst new file mode 100644 index 000000000..ce6628134 --- /dev/null +++ b/libs/network/doc/ext/breathe/testsuite/source/typedef.rst @@ -0,0 +1,31 @@ + +.. _typedef-example: + +doxygentypedef Directive Example +================================ + +Working Example +--------------- + +This should work:: + + .. doxygentypedef:: UINT32 + :project: structcmd + +It produces this output: + +.. doxygentypedef:: UINT32 + :project: structcmd + +Failing Example +--------------- + +This intentionally fails:: + + .. doxygentypedef:: made_up_typedef + :project: restypedef + +It produces the following warning message: + +.. warning:: doxygentypedef: Cannot find typedef "made_up_typedef" in doxygen xml output + From 072ac233f9489c14f9a07c261f0fbcfbf963d0d9 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Tue, 15 Mar 2011 17:17:34 +0800 Subject: [PATCH 074/768] Documenting API changes for the HTTP Client. --- libs/network/doc/reference_http_client.rst | 55 +++++++++++++++++----- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/libs/network/doc/reference_http_client.rst b/libs/network/doc/reference_http_client.rst index 116ec1406..dba832420 100644 --- a/libs/network/doc/reference_http_client.rst +++ b/libs/network/doc/reference_http_client.rst @@ -122,6 +122,12 @@ Also, that code using the HTTP client will have use the following header: #include +.. note:: Starting version 0.9, cpp-netlib clients and server implementations + by default now have an externally-linked component. This is a breaking change + for code that used to rely on cpp-netlib being a header-only library, but can + inhibited by defining the ``BOOST_NETWORK_NO_LIB`` preprocessor macro before + including any cpp-netlib header. + Constructors ~~~~~~~~~~~~ @@ -130,18 +136,42 @@ initialization. ``client()`` Default constructor. -``client(client::cache_resolved)`` - Construct a client which caches resolved endpoints. -``client(client::follow_redirects)`` - Construct a client which follows HTTP redirects. [#]_ -``client(client::cache_resolved, client::follow_redirects), client(client::follow_redirects, client::cache_resolved)`` - Construct a client which caches resolved endpoints and follows HTTP - redirects. [#]_ - -.. [#] In Asynchronous Clients, redirects are not followed. This means the - response objects will contain whatever HTTP response was retrieved by the - client implementation. -.. [#] In Asynchronous Clients, only caching resolved endpoints take effect. +``client(boost::asio::io_service & io_service)`` + Construct a client to use an existing Boost.Asio ``io_service`` instance. +``template client(ArgPack const & args)`` + Pass in an argument pack. See supported parameters in the table below. + ++-------------------+-------------------------------+-------------------------+ +| Parameter Name | Type | Description | ++===================+===============================+=========================+ +| _follow_redirects | ``bool`` | Boolean to specify | +| | | whether the client | +| | | should follow HTTP | +| | | redirects. Default is | +| | | ``false``. | ++-------------------+-------------------------------+-------------------------+ +| _cache_resolved | ``bool`` | Boolean to specify | +| | | whether the client | +| | | should cache resolved | +| | | endpoints. The default | +| | | is ``false``. | ++-------------------+-------------------------------+-------------------------+ +| _io_service | ``boost::asio::io_service &`` | Reference to an | +| | | instance of a | +| | | Boost.Asio | +| | | ``io_service``. | ++-------------------+-------------------------------+-------------------------+ + +To use the above supported named parameters, you'll have code that looks like +the following: + +.. code-block:: c++ + + using namespace boost::network::http; // parameters are in this namespace + boost::asio::io_service my_io_service; + client client_(_follow_redirects=true, _cache_resolved=true, + _io_service=my_io_service); + // use client_ as normal from here on out. HTTP Methods ~~~~~~~~~~~~ @@ -193,3 +223,4 @@ Client-Specific ``client_.clear_resolved_cache()`` Clear the cache of resolved endpoints. + From 6453fd0bc615bc7056491df8d0b9a7fecea7fb6c Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Tue, 15 Mar 2011 17:17:53 +0800 Subject: [PATCH 075/768] Documenting Changes in 0.9 --- libs/network/doc/whats_new.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libs/network/doc/whats_new.rst b/libs/network/doc/whats_new.rst index 89629322d..04b88935b 100644 --- a/libs/network/doc/whats_new.rst +++ b/libs/network/doc/whats_new.rst @@ -4,6 +4,24 @@ What's New ************ +:mod:`cpp-netlib` 0.9 +--------------------- + +* **IMPORTANT BREAKING CHANGE**: By default all compile-time heavy parser + implementations are now compiled to external static libraries. In order to use + :mod:`cpp-netlib` in header-only mode, users must define the preprocessor + macro ``BOOST_NETWORK_NO_LIB`` before including any :mod:`cpp-netlib` header. + This breaks code that relied on the version 0.8.x line where the library is + strictly header-only. +* More consistent message API for client and server messages (request and + response objects). +* Refactoring of internal implementations to allow better separation of concerns + and more manageable coding/documentation. +* Client and Server constructors that support Boost.Parameter named parameters. +* Client and Server cosntructors now take in an optional reference to a Boost.Asio + ``io_service`` to use internally. +* Documentation updates to reflect new APIs. + :mod:`cpp-netlib` 0.8 --------------------- From fc4a530c4ec99c5df5aba2d41bd1712f8d54babf Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Thu, 17 Mar 2011 17:49:31 +0800 Subject: [PATCH 076/768] Removing requirement for Doxygen, backing out Breathe integration. --- libs/network/doc/Doxyfile | 1551 ------------------------------------- 1 file changed, 1551 deletions(-) delete mode 100644 libs/network/doc/Doxyfile diff --git a/libs/network/doc/Doxyfile b/libs/network/doc/Doxyfile deleted file mode 100644 index dd2bd8b0f..000000000 --- a/libs/network/doc/Doxyfile +++ /dev/null @@ -1,1551 +0,0 @@ -# Doxyfile 1.6.3 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = "cpp-netlib" - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = YES - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it parses. -# With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this tag. -# The format is ext=language, where ext is a file extension, and language is one of -# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, -# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), -# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = C++ - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = YES - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = YES - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = YES - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by -# doxygen. The layout file controls the global structure of the generated output files -# in an output format independent way. The create the layout file that represents -# doxygen's defaults, run doxygen with the -l option. You can optionally specify a -# file name after the option, if omitted DoxygenLayout.xml will be used as the name -# of the layout file. - -LAYOUT_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = NO - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = ../../../boost ../src - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = YES - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = NO - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. - -HTML_TIMESTAMP = YES - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER -# are set, an additional index file will be generated that can be used as input for -# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated -# HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. -# For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's -# filter section matches. -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before the help appears. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. - -SEARCHENGINE = YES - -# When the SERVER_BASED_SEARCH tag is enabled the search engine will be implemented using a PHP enabled web server instead of at the web client using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server based approach is that it scales better to large projects and allows full text search. The disadvances is that it is more difficult to setup -# and does not have live searching capabilities. - -SERVER_BASED_SEARCH = NO - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. -# Note that when enabling USE_PDFLATEX this option is only used for -# generating bitmaps for formulas in the HTML output, but not in the -# Makefile that is written to the output directory. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = YES - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = YES - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = YES - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = doxyxml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = BOOST_ENABLE_HTTPS - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = YES - -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. - -DOT_FONTNAME = FreeSans - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = YES - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = YES - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = YES - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES From 80d1798720846268e18c5a65f0cb5c2ae79a3b43 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 26 Mar 2011 13:03:26 +0800 Subject: [PATCH 077/768] Support OpenSSL Certificate Filename and Path The HTTP client implementation gets a couple of new options in the constructor that should allow users to provide a certificate filename to use (_openssl_certificate) or a verification path that contains the certificates (_openssl_verify_path). --- .../protocol/http/client/async_impl.hpp | 15 ++++++---- .../http/client/connection/async_base.hpp | 4 +-- .../http/client/connection/async_ssl.hpp | 11 ++++--- .../http/client/connection/sync_base.hpp | 5 ++-- .../http/client/connection/sync_ssl.hpp | 9 ++++-- boost/network/protocol/http/client/facade.hpp | 5 +++- .../protocol/http/client/parameters.hpp | 2 ++ boost/network/protocol/http/client/pimpl.hpp | 29 ++++++++++++++----- .../http/policies/async_connection.hpp | 12 +++++--- .../http/policies/pooled_connection.hpp | 20 ++++++++----- .../http/policies/simple_connection.hpp | 11 +++++-- 11 files changed, 84 insertions(+), 39 deletions(-) diff --git a/boost/network/protocol/http/client/async_impl.hpp b/boost/network/protocol/http/client/async_impl.hpp index 4b92928ca..6e944490e 100644 --- a/boost/network/protocol/http/client/async_impl.hpp +++ b/boost/network/protocol/http/client/async_impl.hpp @@ -31,12 +31,14 @@ namespace boost { namespace network { namespace http { typename string::type string_type; - async_client(bool cache_resolved, bool follow_redirect) + async_client(bool cache_resolved, bool follow_redirect, optional const & certificate_filename, optional const & verify_path) : connection_base(cache_resolved, follow_redirect), service_ptr(new boost::asio::io_service), service_(*service_ptr), resolver_(service_), - sentinel_(new boost::asio::io_service::work(service_)) + sentinel_(new boost::asio::io_service::work(service_)), + certificate_filename_(certificate_filename), + verify_path_(verify_path) { connection_base::resolver_strand_.reset(new boost::asio::io_service::strand(service_)); @@ -47,12 +49,14 @@ namespace boost { namespace network { namespace http { ))); } - async_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service) + async_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service, optional const & certificate_filename, optional const & verify_path) : connection_base(cache_resolved, follow_redirect), service_ptr(0), service_(service), resolver_(service_), - sentinel_(new boost::asio::io_service::work(service_)) + sentinel_(new boost::asio::io_service::work(service_)), + certificate_filename_(certificate_filename), + verify_path_(verify_path) { } @@ -73,7 +77,7 @@ namespace boost { namespace network { namespace http { ) { typename connection_base::connection_ptr connection_; - connection_ = connection_base::get_connection(resolver_, request_); + connection_ = connection_base::get_connection(resolver_, request_, certificate_filename_, verify_path_); return connection_->send_request(method, request_, get_body); } @@ -82,6 +86,7 @@ namespace boost { namespace network { namespace http { resolver_type resolver_; boost::shared_ptr sentinel_; boost::shared_ptr lifetime_thread_; + optional certificate_filename_, verify_path_; }; } // namespace impl diff --git a/boost/network/protocol/http/client/connection/async_base.hpp b/boost/network/protocol/http/client/connection/async_base.hpp index 6ea2b9f5a..4806fcb53 100644 --- a/boost/network/protocol/http/client/connection/async_base.hpp +++ b/boost/network/protocol/http/client/connection/async_base.hpp @@ -24,11 +24,11 @@ namespace boost { namespace network { namespace http { namespace impl { typedef basic_request request; typedef basic_response response; - static boost::shared_ptr > new_connection(resolve_function resolve, resolver_type & resolver, bool follow_redirect, bool https) { + static boost::shared_ptr > new_connection(resolve_function resolve, resolver_type & resolver, bool follow_redirect, bool https, optional certificate_filename=optional(), optional const & verify_path=optional()) { boost::shared_ptr > temp; if (https) { #ifdef BOOST_NETWORK_ENABLE_HTTPS - temp.reset(new https_async_connection(resolver, resolve, follow_redirect)); + temp.reset(new https_async_connection(resolver, resolve, follow_redirect, certificate_filename, verify_path)); return temp; #else throw std::runtime_error("HTTPS not supported."); diff --git a/boost/network/protocol/http/client/connection/async_ssl.hpp b/boost/network/protocol/http/client/connection/async_ssl.hpp index dc8360453..267a33493 100644 --- a/boost/network/protocol/http/client/connection/async_ssl.hpp +++ b/boost/network/protocol/http/client/connection/async_ssl.hpp @@ -37,11 +37,13 @@ namespace boost { namespace network { namespace http { namespace impl { resolver_type & resolver, resolve_function resolve, bool follow_redirect, - optional const & certificate_filename = optional() + optional const & certificate_filename = optional(), + optional const & verify_path = optional() ) : follow_redirect_(follow_redirect), resolver_(resolver), certificate_filename_(certificate_filename), + verify_path_(verify_path), resolve_(resolve), request_strand_(resolver.get_io_service()) {} @@ -78,9 +80,10 @@ namespace boost { namespace network { namespace http { namespace impl { boost::asio::ssl::context::sslv23_client ) ); - if (certificate_filename_) { + if (certificate_filename_ || verify_path_) { context_->set_verify_mode(boost::asio::ssl::context::verify_peer); - context_->load_verify_file(*certificate_filename_); + if (certificate_filename_) context_->load_verify_file(*certificate_filename_); + if (verify_path_) context_->add_verify_path(*verify_path_); } else { context_->set_verify_mode(boost::asio::ssl::context::verify_none); } @@ -342,7 +345,7 @@ namespace boost { namespace network { namespace http { namespace impl { bool follow_redirect_; resolver_type & resolver_; - optional certificate_filename_; + optional certificate_filename_, verify_path_; resolve_function resolve_; boost::shared_ptr context_; boost::shared_ptr > socket_; diff --git a/boost/network/protocol/http/client/connection/sync_base.hpp b/boost/network/protocol/http/client/connection/sync_base.hpp index 8c0d450ac..8314363b8 100644 --- a/boost/network/protocol/http/client/connection/sync_base.hpp +++ b/boost/network/protocol/http/client/connection/sync_base.hpp @@ -210,10 +210,11 @@ namespace boost { namespace network { namespace http { namespace impl { typedef typename string::type string_type; typedef function resolver_function_type; - static sync_connection_base * new_connection(resolver_type & resolver, resolver_function_type resolve, bool https) { + // FIXME make the certificate filename and verify path parameters be optional ranges + static sync_connection_base * new_connection(resolver_type & resolver, resolver_function_type resolve, bool https, optional const & cert_filename = optional(), optional const & verify_path = optional()) { if (https) { #ifdef BOOST_NETWORK_ENABLE_HTTPS - return dynamic_cast*>(new https_sync_connection(resolver, resolve)); + return dynamic_cast*>(new https_sync_connection(resolver, resolve, cert_filename, verify_path)); #else throw std::runtime_error("HTTPS not supported."); #endif diff --git a/boost/network/protocol/http/client/connection/sync_ssl.hpp b/boost/network/protocol/http/client/connection/sync_ssl.hpp index e323fc844..920f63bb6 100644 --- a/boost/network/protocol/http/client/connection/sync_ssl.hpp +++ b/boost/network/protocol/http/client/connection/sync_ssl.hpp @@ -25,11 +25,14 @@ namespace boost { namespace network { namespace http { namespace impl { typedef function resolver_function_type; typedef sync_connection_base_impl connection_base; - https_sync_connection(resolver_type & resolver, resolver_function_type resolve, optional const & certificate_filename = optional()) + // FIXME make the certificate filename and verify path parameters be optional ranges + https_sync_connection(resolver_type & resolver, resolver_function_type resolve, optional const & certificate_filename = optional(), optional const & verify_path = optional()) : connection_base(), resolver_(resolver), resolve_(resolve), context_(resolver.io_service(), boost::asio::ssl::context::sslv23_client), socket_(resolver.io_service(), context_) { - if (certificate_filename) { + if (certificate_filename || verify_path) { context_.set_verify_mode(boost::asio::ssl::context::verify_peer); - context_.load_verify_file(*certificate_filename); + // FIXME make the certificate filename and verify path parameters be optional ranges + if (certificate_filename) context_.load_verify_file(*certificate_filename); + if (verify_path) context_.add_verify_path(*verify_path); } else { context_.set_verify_mode(boost::asio::ssl::context::verify_none); } diff --git a/boost/network/protocol/http/client/facade.hpp b/boost/network/protocol/http/client/facade.hpp index b4bac09af..bd639bb19 100644 --- a/boost/network/protocol/http/client/facade.hpp +++ b/boost/network/protocol/http/client/facade.hpp @@ -39,7 +39,6 @@ namespace boost { namespace network { namespace http { no_io_service, has_io_service >::type()); - } response const head (request const & request_) { @@ -117,6 +116,8 @@ namespace boost { namespace network { namespace http { new pimpl_type( args[_cache_resolved|false] , args[_follow_redirects|false] + , args[_openssl_certificate|optional()] + , args[_openssl_verify_path|optional()] ) ); } @@ -128,6 +129,8 @@ namespace boost { namespace network { namespace http { args[_cache_resolved|false] , args[_follow_redirects|false] , args[_io_service] + , args[_openssl_certificate|optional()] + , args[_openssl_verify_path|optional()] ) ); } diff --git a/boost/network/protocol/http/client/parameters.hpp b/boost/network/protocol/http/client/parameters.hpp index 912255820..2d4cdcbad 100644 --- a/boost/network/protocol/http/client/parameters.hpp +++ b/boost/network/protocol/http/client/parameters.hpp @@ -12,6 +12,8 @@ namespace boost { namespace network { namespace http { BOOST_PARAMETER_NAME(follow_redirects) BOOST_PARAMETER_NAME(cache_resolved) + BOOST_PARAMETER_NAME(openssl_certificate) + BOOST_PARAMETER_NAME(openssl_verify_path) } /* http */ diff --git a/boost/network/protocol/http/client/pimpl.hpp b/boost/network/protocol/http/client/pimpl.hpp index 1afef118c..c1a17be73 100644 --- a/boost/network/protocol/http/client/pimpl.hpp +++ b/boost/network/protocol/http/client/pimpl.hpp @@ -38,19 +38,30 @@ namespace boost { namespace network { namespace http { boost::asio::io_service * service_ptr; boost::asio::io_service & service_; resolver_type resolver_; + optional certificate_file, verify_path; - sync_client(bool cache_resolved, bool follow_redirect) + sync_client(bool cache_resolved, bool follow_redirect + , optional const & certificate_file = optional() + , optional const & verify_path = optional() + ) : connection_base(cache_resolved, follow_redirect), service_ptr(new boost::asio::io_service), service_(*service_ptr), resolver_(service_) + , certificate_file(certificate_file) + , verify_path(verify_path) {} - sync_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service) + sync_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service + , optional const & certificate_file = optional() + , optional const & verify_path = optional() + ) : connection_base(cache_resolved, follow_redirect), service_ptr(0), service_(service), resolver_(service_) + , certificate_file(certificate_file) + , verify_path(verify_path) {} ~sync_client() { @@ -59,7 +70,7 @@ namespace boost { namespace network { namespace http { basic_response const request_skeleton(basic_request const & request_, string_type method, bool get_body) { typename connection_base::connection_ptr connection_; - connection_ = connection_base::get_connection(resolver_, request_); + connection_ = connection_base::get_connection(resolver_, request_, certificate_file, verify_path); return connection_->send_request(method, request_, get_body); } @@ -91,14 +102,16 @@ namespace boost { namespace network { namespace http { > >::value )); - + typedef typename impl::client_base::type base_type; - basic_client_impl(bool cache_resolved, bool follow_redirect) - : base_type(cache_resolved, follow_redirect) + typedef typename base_type::string_type string_type; + + basic_client_impl(bool cache_resolved, bool follow_redirect, optional const & certificate_filename, optional const & verify_path) + : base_type(cache_resolved, follow_redirect, certificate_filename, verify_path) {} - basic_client_impl(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service) - : base_type(cache_resolved, follow_redirect, service) + basic_client_impl(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service, optional const & certificate_filename, optional const & verify_path) + : base_type(cache_resolved, follow_redirect, service, certificate_filename, verify_path) {} ~basic_client_impl() diff --git a/boost/network/protocol/http/policies/async_connection.hpp b/boost/network/protocol/http/policies/async_connection.hpp index 12a2d070a..ba02ebdc4 100644 --- a/boost/network/protocol/http/policies/async_connection.hpp +++ b/boost/network/protocol/http/policies/async_connection.hpp @@ -34,10 +34,12 @@ namespace boost { namespace network { namespace http { bool follow_redirect, resolve_function resolve, resolver_type & resolver, - bool https + bool https, + optional const & certificate_filename, + optional const & verify_path ) { - pimpl = impl::async_connection_base::new_connection(resolve, resolver, follow_redirect, https); + pimpl = impl::async_connection_base::new_connection(resolve, resolver, follow_redirect, https, certificate_filename, verify_path); } basic_response send_request(string_type const & method, basic_request const & request_, bool get_body) { @@ -51,7 +53,7 @@ namespace boost { namespace network { namespace http { }; typedef boost::shared_ptr connection_ptr; - connection_ptr get_connection(resolver_type & resolver, basic_request const & request_) { + connection_ptr get_connection(resolver_type & resolver, basic_request const & request_, optional const & certificate_filename = optional(), optional const & verify_path = optional()) { string_type protocol_ = protocol(request_); connection_ptr connection_( new connection_impl( @@ -62,7 +64,9 @@ namespace boost { namespace network { namespace http { _1, _2, _3, _4 ) , resolver - , boost::iequals(protocol_, string_type("https")))); + , boost::iequals(protocol_, string_type("https")) + , certificate_filename + , verify_path)); return connection_; } diff --git a/boost/network/protocol/http/policies/pooled_connection.hpp b/boost/network/protocol/http/policies/pooled_connection.hpp index a15c0017b..1dc87e2df 100644 --- a/boost/network/protocol/http/policies/pooled_connection.hpp +++ b/boost/network/protocol/http/policies/pooled_connection.hpp @@ -31,13 +31,16 @@ namespace boost { namespace network { namespace http { typedef function resolver_function_type; struct connection_impl { - typedef function(resolver_type &,basic_request const &)> get_connection_function; + typedef function(resolver_type &,basic_request const &,optional const &, optional const &)> get_connection_function; - connection_impl(resolver_type & resolver, bool follow_redirect, string_type const & host, string_type const & port, resolver_function_type resolve, get_connection_function get_connection, bool https) - : pimpl(impl::sync_connection_base::new_connection(resolver, resolve, https)) + connection_impl(resolver_type & resolver, bool follow_redirect, string_type const & host, string_type const & port, resolver_function_type resolve, get_connection_function get_connection, bool https, optional const & certificate_file=optional(), optional const & verify_path=optional()) + : pimpl(impl::sync_connection_base::new_connection(resolver, resolve, https, certificate_file, verify_path)) , resolver_(resolver) , connection_follow_redirect_(follow_redirect) - , get_connection_(get_connection) {} + , get_connection_(get_connection) + , certificate_filename_(certificate_file) + , verify_path_(verify_path) + {} basic_response send_request(string_type const & method, basic_request request_, bool get_body) { return send_request_impl(method, request_, get_body); @@ -104,7 +107,7 @@ namespace boost { namespace network { namespace http { if (location_header != boost::end(location_range)) { request_.uri(location_header->second); connection_ptr connection_; - connection_ = get_connection_(resolver_, request_); + connection_ = get_connection_(resolver_, request_, certificate_filename_, verify_path_); ++count; continue; } else throw std::runtime_error("Location header not defined in redirect response."); @@ -118,6 +121,7 @@ namespace boost { namespace network { namespace http { resolver_type & resolver_; bool connection_follow_redirect_; get_connection_function get_connection_; + optional certificate_filename_, verify_path_; }; typedef shared_ptr connection_ptr; @@ -126,7 +130,7 @@ namespace boost { namespace network { namespace http { host_connection_map host_connections; bool follow_redirect_; - connection_ptr get_connection(resolver_type & resolver, basic_request const & request_) { + connection_ptr get_connection(resolver_type & resolver, basic_request const & request_, optional const & certificate_filename = optional(), optional const & verify_path = optional()) { string_type index = (request_.host() + ':') + lexical_cast(request_.port()); connection_ptr connection_; typename host_connection_map::iterator it = @@ -145,9 +149,11 @@ namespace boost { namespace network { namespace http { , boost::bind( &pooled_connection_policy::get_connection, this, - _1, _2 + _1, _2, _3, _4 ) , boost::iequals(request_.protocol(), string_type("https")) + , certificate_filename + , verify_path ) ); host_connections.insert(std::make_pair(index, connection_)); diff --git a/boost/network/protocol/http/policies/simple_connection.hpp b/boost/network/protocol/http/policies/simple_connection.hpp index 613c5f26c..de00ab1bf 100644 --- a/boost/network/protocol/http/policies/simple_connection.hpp +++ b/boost/network/protocol/http/policies/simple_connection.hpp @@ -29,11 +29,11 @@ namespace boost { namespace network { namespace http { typedef function resolver_function_type; struct connection_impl { - connection_impl(resolver_type & resolver, bool follow_redirect, string_type const & hostname, string_type const & port, resolver_function_type resolve, bool https) + connection_impl(resolver_type & resolver, bool follow_redirect, string_type const & hostname, string_type const & port, resolver_function_type resolve, bool https, optional const & certificate_filename = optional(), optional const & verify_path = optional()) : pimpl() , follow_redirect_(follow_redirect) { - pimpl.reset(impl::sync_connection_base::new_connection(resolver, resolve, https)); + pimpl.reset(impl::sync_connection_base::new_connection(resolver, resolve, https, certificate_filename, verify_path)); } basic_response send_request(string_type const & method, basic_request request_, bool get_body) { @@ -72,7 +72,10 @@ namespace boost { namespace network { namespace http { }; typedef boost::shared_ptr connection_ptr; - connection_ptr get_connection(resolver_type & resolver, basic_request const & request_) { + connection_ptr get_connection(resolver_type & resolver, basic_request const & request_ + , optional const & certificate_file = optional() + , optional const & verify_file = optional() + ) { connection_ptr connection_( new connection_impl( resolver @@ -85,6 +88,8 @@ namespace boost { namespace network { namespace http { _1, _2, _3 ) , boost::iequals(request_.protocol(), string_type("https")) + , certificate_file + , verify_file ) ); return connection_; From 4b5bd72de09dcd14ceb718975545942fdab99284 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 26 Mar 2011 14:32:26 +0800 Subject: [PATCH 078/768] Addendum to previous commit. --- boost/network/protocol/http/client.hpp | 9 +++++++++ boost/network/protocol/http/client/facade.hpp | 8 ++++---- libs/network/test/http/client_constructor_test.cpp | 4 ++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/boost/network/protocol/http/client.hpp b/boost/network/protocol/http/client.hpp index bc751f7f5..e989c8570 100644 --- a/boost/network/protocol/http/client.hpp +++ b/boost/network/protocol/http/client.hpp @@ -54,6 +54,13 @@ namespace boost { namespace network { namespace http { // _io_service : boost::asio::io_service & // -- supply an io_service to the // client + // _openssl_certificate : string + // -- the name of the certificate file + // to use + // _openssl_verify_path : string + // -- the name of the directory from + // which the certificate authority + // files can be found BOOST_PARAMETER_CONSTRUCTOR( basic_client, (base_facade_type), tag, @@ -61,6 +68,8 @@ namespace boost { namespace network { namespace http { (in_out(io_service), (boost::asio::io_service)) (follow_redirects, (bool)) (cache_resolved, (bool)) + (openssl_certificate, (string_type)) + (openssl_verify_path, (string_type)) )) // diff --git a/boost/network/protocol/http/client/facade.hpp b/boost/network/protocol/http/client/facade.hpp index bd639bb19..3d3d4ea0b 100644 --- a/boost/network/protocol/http/client/facade.hpp +++ b/boost/network/protocol/http/client/facade.hpp @@ -116,8 +116,8 @@ namespace boost { namespace network { namespace http { new pimpl_type( args[_cache_resolved|false] , args[_follow_redirects|false] - , args[_openssl_certificate|optional()] - , args[_openssl_verify_path|optional()] + , optional(args[_openssl_certificate|optional()]) + , optional(args[_openssl_verify_path|optional()]) ) ); } @@ -129,8 +129,8 @@ namespace boost { namespace network { namespace http { args[_cache_resolved|false] , args[_follow_redirects|false] , args[_io_service] - , args[_openssl_certificate|optional()] - , args[_openssl_verify_path|optional()] + , optional(args[_openssl_certificate|optional()]) + , optional(args[_openssl_verify_path|optional()]) ) ); } diff --git a/libs/network/test/http/client_constructor_test.cpp b/libs/network/test/http/client_constructor_test.cpp index 2cb304bdf..d5735ec8d 100644 --- a/libs/network/test/http/client_constructor_test.cpp +++ b/libs/network/test/http/client_constructor_test.cpp @@ -28,5 +28,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_cient_constructor_params_test, client, client http::_io_service=io_service, http::_cache_resolved=true ); + client instance3( + http::_openssl_certificate="foo", + http::_openssl_verify_path="bar" + ); } From af74f86ebf730ee7aceda84eecb29b3f19f34e68 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 26 Mar 2011 14:38:50 +0800 Subject: [PATCH 079/768] Commenting out breathe integration. --- libs/network/doc/conf.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libs/network/doc/conf.py b/libs/network/doc/conf.py index d86815fb3..dae807176 100644 --- a/libs/network/doc/conf.py +++ b/libs/network/doc/conf.py @@ -18,7 +18,8 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.append(os.path.abspath('.')) -sys.path.append(os.path.abspath('ext/breathe')) +# NOTE -- we can't use Breathe just yet because it doesn't support templates +#sys.path.append(os.path.abspath('ext/breathe')) # -- General configuration ----------------------------------------------------- @@ -29,7 +30,7 @@ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.coverage', - 'breathe', +# 'breathe', ] # Uncomment this to generate output for Github. @@ -208,8 +209,8 @@ # If false, no module index is generated. #latex_use_modindex = True -breathe_projects = {'cpp-netlib': 'doxyxml/'} +#breathe_projects = {'cpp-netlib': 'doxyxml/'} -breathe_default_project = 'cpp-netlib' +#breathe_default_project = 'cpp-netlib' From d483e48826d5038698d3e7f91a0ef2ba41371bcc Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 26 Mar 2011 14:39:19 +0800 Subject: [PATCH 080/768] Adding documentation for OpenSSL Parameters. --- libs/network/doc/reference_http_client.rst | 55 +++++++++++++--------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/libs/network/doc/reference_http_client.rst b/libs/network/doc/reference_http_client.rst index dba832420..0c7758a3c 100644 --- a/libs/network/doc/reference_http_client.rst +++ b/libs/network/doc/reference_http_client.rst @@ -141,26 +141,37 @@ initialization. ``template client(ArgPack const & args)`` Pass in an argument pack. See supported parameters in the table below. -+-------------------+-------------------------------+-------------------------+ -| Parameter Name | Type | Description | -+===================+===============================+=========================+ -| _follow_redirects | ``bool`` | Boolean to specify | -| | | whether the client | -| | | should follow HTTP | -| | | redirects. Default is | -| | | ``false``. | -+-------------------+-------------------------------+-------------------------+ -| _cache_resolved | ``bool`` | Boolean to specify | -| | | whether the client | -| | | should cache resolved | -| | | endpoints. The default | -| | | is ``false``. | -+-------------------+-------------------------------+-------------------------+ -| _io_service | ``boost::asio::io_service &`` | Reference to an | -| | | instance of a | -| | | Boost.Asio | -| | | ``io_service``. | -+-------------------+-------------------------------+-------------------------+ ++----------------------+-------------------------------+-------------------------+ +| Parameter Name | Type | Description | ++======================+===============================+=========================+ +| _follow_redirects | ``bool`` | Boolean to specify | +| | | whether the client | +| | | should follow HTTP | +| | | redirects. Default is | +| | | ``false``. | ++----------------------+-------------------------------+-------------------------+ +| _cache_resolved | ``bool`` | Boolean to specify | +| | | whether the client | +| | | should cache resolved | +| | | endpoints. The default | +| | | is ``false``. | ++----------------------+-------------------------------+-------------------------+ +| _io_service | ``boost::asio::io_service &`` | Reference to an | +| | | instance of a | +| | | Boost.Asio | +| | | ``io_service``. | ++----------------------+-------------------------------+-------------------------+ +| _openssl_certificate | string | The filename of the | +| | | certificate to load for | +| | | the SSL connection for | +| | | verification. | ++----------------------+-------------------------------+-------------------------+ +| _openssl_verify_path | string | The directory from | +| | | which the certificate | +| | | authority files are | +| | | located. | ++----------------------+-------------------------------+-------------------------+ + To use the above supported named parameters, you'll have code that looks like the following: @@ -170,7 +181,9 @@ the following: using namespace boost::network::http; // parameters are in this namespace boost::asio::io_service my_io_service; client client_(_follow_redirects=true, _cache_resolved=true, - _io_service=my_io_service); + _io_service=my_io_service + , _openssl_certificate="/tmp/my-cert" + , _openssl_verify_path="/tmp/ca-certs/"); // use client_ as normal from here on out. HTTP Methods From d8f04eaaefd41e3880b0549fb0c2619418df3c78 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 2 Apr 2011 04:30:10 +0800 Subject: [PATCH 081/768] Removing deprecated calls to resolver::io_service() - Using the correct user credentials this time. --- boost/network/protocol/http/client/connection/sync_normal.hpp | 2 +- boost/network/protocol/http/client/connection/sync_ssl.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/boost/network/protocol/http/client/connection/sync_normal.hpp b/boost/network/protocol/http/client/connection/sync_normal.hpp index 445acb51d..deab36c4e 100644 --- a/boost/network/protocol/http/client/connection/sync_normal.hpp +++ b/boost/network/protocol/http/client/connection/sync_normal.hpp @@ -27,7 +27,7 @@ namespace boost { namespace network { namespace http { namespace impl { typedef sync_connection_base_impl connection_base; http_sync_connection(resolver_type & resolver, resolver_function_type resolve) - : connection_base(), resolver_(resolver), resolve_(resolve), socket_(resolver.io_service()) { } + : connection_base(), resolver_(resolver), resolve_(resolve), socket_(resolver.get_io_service()) { } void init_socket(string_type const & hostname, string_type const & port) { connection_base::init_socket(socket_, resolver_, hostname, port, resolve_); diff --git a/boost/network/protocol/http/client/connection/sync_ssl.hpp b/boost/network/protocol/http/client/connection/sync_ssl.hpp index 920f63bb6..a7e579a7f 100644 --- a/boost/network/protocol/http/client/connection/sync_ssl.hpp +++ b/boost/network/protocol/http/client/connection/sync_ssl.hpp @@ -27,7 +27,7 @@ namespace boost { namespace network { namespace http { namespace impl { // FIXME make the certificate filename and verify path parameters be optional ranges https_sync_connection(resolver_type & resolver, resolver_function_type resolve, optional const & certificate_filename = optional(), optional const & verify_path = optional()) - : connection_base(), resolver_(resolver), resolve_(resolve), context_(resolver.io_service(), boost::asio::ssl::context::sslv23_client), socket_(resolver.io_service(), context_) { + : connection_base(), resolver_(resolver), resolve_(resolve), context_(resolver.get_io_service(), boost::asio::ssl::context::sslv23_client), socket_(resolver.get_io_service(), context_) { if (certificate_filename || verify_path) { context_.set_verify_mode(boost::asio::ssl::context::verify_peer); // FIXME make the certificate filename and verify path parameters be optional ranges From f734b3ff6ddef05063a75e995598c3ac9bd58267 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 2 Apr 2011 04:40:25 +0800 Subject: [PATCH 082/768] SFINAE-ization of Tag Dispatch System Thanks to Thomas Heller for the tips on the dramatic reduction of compile times in the cpp-netlib implementation, this commit is now generally considered a major compile-time enhancement over previous versions/iterations of the library. In this particular case the compile time reduction is actually significant just by using SFINAE and partial specialization over (ab)use of the Boost.MPL facilities. --- .../protocol/http/message/traits/version.hpp | 37 +++++++++++------- .../http/support/client_or_server.hpp | 33 +++++++++------- .../protocol/http/support/is_client.hpp | 12 +++--- .../network/protocol/http/support/is_http.hpp | 14 +++---- .../protocol/http/support/is_keepalive.hpp | 14 +++---- .../protocol/http/support/is_server.hpp | 12 +++--- .../protocol/http/support/is_simple.hpp | 17 +++----- boost/network/protocol/http/tags.hpp | 10 ++--- .../http/traits/connection_policy.hpp | 39 ++++++++++++------- boost/network/support/is_async.hpp | 13 +++---- boost/network/support/is_default_string.hpp | 16 ++++---- boost/network/support/is_default_wstring.hpp | 14 +++---- boost/network/support/is_http.hpp | 14 +++---- boost/network/support/is_keepalive.hpp | 17 +++----- boost/network/support/is_pod.hpp | 12 +++--- boost/network/support/is_simple.hpp | 17 +++----- boost/network/support/is_sync.hpp | 15 +++---- boost/network/support/is_tcp.hpp | 18 ++++----- boost/network/support/is_udp.hpp | 16 ++++---- boost/network/support/pod_or_normal.hpp | 11 ++---- boost/network/tags.hpp | 19 ++++----- boost/network/traits/char.hpp | 27 +++++++------ boost/network/traits/istream.hpp | 30 +++++++------- boost/network/traits/istringstream.hpp | 30 +++++++------- boost/network/traits/ostringstream.hpp | 29 ++++++++------ boost/network/traits/string.hpp | 30 +++++++------- 26 files changed, 262 insertions(+), 254 deletions(-) diff --git a/boost/network/protocol/http/message/traits/version.hpp b/boost/network/protocol/http/message/traits/version.hpp index 7e32ab20c..15ac4e848 100644 --- a/boost/network/protocol/http/message/traits/version.hpp +++ b/boost/network/protocol/http/message/traits/version.hpp @@ -20,23 +20,32 @@ namespace boost { namespace network { namespace http { template struct unsupported_tag; - template + template struct version - : mpl::if_< - is_async, - boost::shared_future::type>, - typename mpl::if_< + { + typedef unsupported_tag type; + }; + + template + struct version >::type> + { + typedef boost::shared_future::type> type; + }; + + template + struct version, - is_same, - is_same - >, - typename string::type, - unsupported_tag - >::type - > - {}; - + is_default_string, + is_default_wstring + > + >::type + > + { + typedef typename string::type type; + }; + } /* traits */ } /* http */ diff --git a/boost/network/protocol/http/support/client_or_server.hpp b/boost/network/protocol/http/support/client_or_server.hpp index 083b59c78..2ad74b105 100644 --- a/boost/network/protocol/http/support/client_or_server.hpp +++ b/boost/network/protocol/http/support/client_or_server.hpp @@ -11,20 +11,27 @@ #include namespace boost { namespace network { namespace http { - + template - struct client_or_server : - mpl::if_< - is_server, - tags::server, - typename mpl::if_< - is_client, - tags::client, - unsupported_tag - >::type - > - {}; - + struct unsupported_tag; + + template + struct client_or_server + { + typedef unsupported_tag type; + }; + + template + struct client_or_server >::type> + { + typedef tags::server type; + }; + + template + struct client_or_server >::type> + { + typedef tags::client type; + }; } /* http */ diff --git a/boost/network/protocol/http/support/is_client.hpp b/boost/network/protocol/http/support/is_client.hpp index c479abaf1..e15b89603 100644 --- a/boost/network/protocol/http/support/is_client.hpp +++ b/boost/network/protocol/http/support/is_client.hpp @@ -7,17 +7,15 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include namespace boost { namespace network { namespace http { + template + struct is_client : mpl::false_ {}; + template - struct is_client : - is_base_of< - tags::client, - Tag - > - {}; + struct is_client::type> : mpl::true_ {}; } /* http */ diff --git a/boost/network/protocol/http/support/is_http.hpp b/boost/network/protocol/http/support/is_http.hpp index 375af0db0..163c3f5f2 100644 --- a/boost/network/protocol/http/support/is_http.hpp +++ b/boost/network/protocol/http/support/is_http.hpp @@ -7,18 +7,16 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include namespace boost { namespace network { namespace http { + template + struct is_http : mpl::false_ {}; + template - struct is_http : - is_base_of< - tags::http, - Tag - > - {}; - + struct is_http::type> : mpl::true_ {}; + } // namespace http } // namespace network diff --git a/boost/network/protocol/http/support/is_keepalive.hpp b/boost/network/protocol/http/support/is_keepalive.hpp index 78c5d69e2..c3fa73a07 100644 --- a/boost/network/protocol/http/support/is_keepalive.hpp +++ b/boost/network/protocol/http/support/is_keepalive.hpp @@ -7,21 +7,19 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include namespace boost { namespace network { namespace http { template struct unsupported_tag; + template + struct is_keepalive : mpl::false_ {}; + template - struct is_keepalive : - is_base_of< - http::tags::keepalive - , Tag - > - {}; - + struct is_keepalive::type> : mpl::true_ {}; + } /* http */ } /* network */ diff --git a/boost/network/protocol/http/support/is_server.hpp b/boost/network/protocol/http/support/is_server.hpp index 865af3812..067e16c08 100644 --- a/boost/network/protocol/http/support/is_server.hpp +++ b/boost/network/protocol/http/support/is_server.hpp @@ -7,17 +7,15 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include namespace boost { namespace network { namespace http { + template + struct is_server : mpl::false_ {}; + template - struct is_server : - is_base_of< - tags::server, - Tag - > - {}; + struct is_server::type> : mpl::true_ {}; } /* http */ diff --git a/boost/network/protocol/http/support/is_simple.hpp b/boost/network/protocol/http/support/is_simple.hpp index 1b75bfc8e..730648f54 100644 --- a/boost/network/protocol/http/support/is_simple.hpp +++ b/boost/network/protocol/http/support/is_simple.hpp @@ -7,21 +7,16 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include namespace boost { namespace network { namespace http { + template + struct is_simple : mpl::false_ {}; + template - struct unsupported_tag; - - template - struct is_simple : - is_base_of< - tags::simple - , Tag - > - {}; - + struct is_simple::type> : mpl::true_ {}; + } /* http */ } /* network */ diff --git a/boost/network/protocol/http/tags.hpp b/boost/network/protocol/http/tags.hpp index 65287e895..93db37a69 100644 --- a/boost/network/protocol/http/tags.hpp +++ b/boost/network/protocol/http/tags.hpp @@ -10,11 +10,11 @@ namespace boost { namespace network { namespace http { namespace tags { - struct http {}; - struct keepalive {}; - struct simple {}; - struct server {}; - struct client {}; + struct http { typedef mpl::true_::type is_http; }; + struct keepalive { typedef mpl::true_::type is_keepalive; }; + struct simple { typedef mpl::true_::type is_simple; }; + struct server { typedef mpl::true_::type is_server; }; + struct client { typedef mpl::true_::type is_client; }; using namespace boost::network::tags; diff --git a/boost/network/protocol/http/traits/connection_policy.hpp b/boost/network/protocol/http/traits/connection_policy.hpp index 396e82cae..6e35570cd 100644 --- a/boost/network/protocol/http/traits/connection_policy.hpp +++ b/boost/network/protocol/http/traits/connection_policy.hpp @@ -13,28 +13,37 @@ #include #include #include +#include +#include namespace boost { namespace network { namespace http { template struct unsupported_tag; + template + struct connection_policy + { + typedef unsupported_tag type; + }; + template - struct connection_policy : - mpl::if_< - is_async, - async_connection_policy, - typename mpl::if_< - is_simple, - simple_connection_policy, - typename mpl::if_< - is_keepalive, - pooled_connection_policy, - unsupported_tag - >::type - >::type - > - {}; + struct connection_policy >::type> + { + typedef async_connection_policy type; + }; + + template + struct connection_policy, mpl::not_ > > >::type> + { + typedef simple_connection_policy type; + }; + + template + struct connection_policy, mpl::not_ > > >::type> + { + typedef pooled_connection_policy type; + }; } // namespace http diff --git a/boost/network/support/is_async.hpp b/boost/network/support/is_async.hpp index 43d814c72..d6e1f99f5 100644 --- a/boost/network/support/is_async.hpp +++ b/boost/network/support/is_async.hpp @@ -8,18 +8,15 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include -#include +#include namespace boost { namespace network { + template + struct is_async : mpl::false_ {}; + template - struct is_async : - is_base_of< - tags::async, - Tag - > - {}; + struct is_async::type> : mpl::true_ {}; } // namespace network diff --git a/boost/network/support/is_default_string.hpp b/boost/network/support/is_default_string.hpp index 31c1250b3..2a0fd824e 100644 --- a/boost/network/support/is_default_string.hpp +++ b/boost/network/support/is_default_string.hpp @@ -7,18 +7,16 @@ #define BOOST_NETWORK_SUPPORT_STRING_CHECK_20100808 #include -#include +#include namespace boost { namespace network { - + + template + struct is_default_string : mpl::false_ {}; + template - struct is_default_string : - is_base_of< - tags::default_string, - Tag - > - {}; - + struct is_default_string::type> : mpl::true_ {}; + } // namespace network } // namespace boost diff --git a/boost/network/support/is_default_wstring.hpp b/boost/network/support/is_default_wstring.hpp index 7930fc633..c414353e1 100644 --- a/boost/network/support/is_default_wstring.hpp +++ b/boost/network/support/is_default_wstring.hpp @@ -7,18 +7,16 @@ #define BOOST_NETWORK_SUPPORT_WSTRING_CHECK_20100808 #include -#include +#include namespace boost { namespace network { + template + struct is_default_wstring : mpl::false_ {}; + template - struct is_default_wstring : - is_base_of< - tags::default_wstring, - Tag - > - {}; - + struct is_default_wstring::type> : mpl::true_ {}; + } // namespace network } // namespace boost diff --git a/boost/network/support/is_http.hpp b/boost/network/support/is_http.hpp index 16f713aa0..c104e7b42 100644 --- a/boost/network/support/is_http.hpp +++ b/boost/network/support/is_http.hpp @@ -7,18 +7,16 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include namespace boost { namespace network { + template + struct is_http : mpl::false_ {}; + template - struct is_http : - is_base_of< - tags::http, - Tag - > - {}; - + struct is_http::type> : mpl::true_ {}; + } // namespace network } // namespace boost diff --git a/boost/network/support/is_keepalive.hpp b/boost/network/support/is_keepalive.hpp index f1a6e68e3..6607cd10f 100644 --- a/boost/network/support/is_keepalive.hpp +++ b/boost/network/support/is_keepalive.hpp @@ -7,21 +7,16 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include namespace boost { namespace network { + template + struct is_keepalive : mpl::false_ {}; + template - struct unsupported_tag; - - template - struct is_keepalive : - is_base_of< - tags::keepalive - , Tag - > - {}; - + struct is_keepalive::type> : mpl::true_ {}; + } /* network */ } /* boost */ diff --git a/boost/network/support/is_pod.hpp b/boost/network/support/is_pod.hpp index 60add37aa..5c1e1065c 100644 --- a/boost/network/support/is_pod.hpp +++ b/boost/network/support/is_pod.hpp @@ -7,17 +7,15 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include namespace boost { namespace network { + template + struct is_pod : mpl::false_ {}; + template - struct is_pod : - is_base_of< - tags::pod, - Tag - > - {}; + struct is_pod::type> : mpl::true_ {}; } /* network */ diff --git a/boost/network/support/is_simple.hpp b/boost/network/support/is_simple.hpp index 70894f19d..98406d41a 100644 --- a/boost/network/support/is_simple.hpp +++ b/boost/network/support/is_simple.hpp @@ -7,21 +7,16 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include namespace boost { namespace network { - - template - struct unsupported_tag; + template + struct is_simple : mpl::false_ {}; + template - struct is_simple : - is_base_of< - tags::simple - , Tag - > - {}; - + struct is_simple::type> : mpl::true_ {}; + } /* network */ } /* boost */ diff --git a/boost/network/support/is_sync.hpp b/boost/network/support/is_sync.hpp index dc86fdf2f..0ff0f7130 100644 --- a/boost/network/support/is_sync.hpp +++ b/boost/network/support/is_sync.hpp @@ -7,19 +7,16 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include -#include +#include namespace boost { namespace network { + template + struct is_sync : mpl::false_ {}; + template - struct is_sync : - is_base_of< - tags::sync, - Tag - > - {}; - + struct is_sync::type> : mpl::true_ {}; + } // namespace network } // namespace boost diff --git a/boost/network/support/is_tcp.hpp b/boost/network/support/is_tcp.hpp index 3484bc810..c041f125f 100644 --- a/boost/network/support/is_tcp.hpp +++ b/boost/network/support/is_tcp.hpp @@ -7,18 +7,18 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include +#include +#include namespace boost { namespace network { - + + template + struct is_tcp : mpl::false_ {}; + template - struct is_tcp : - is_base_of< - tags::tcp, - Tag - > - {}; - + struct is_tcp::type> : mpl::true_ {}; + } // namespace network } // namespace boost diff --git a/boost/network/support/is_udp.hpp b/boost/network/support/is_udp.hpp index 38db5a0c1..cacbc5e0e 100644 --- a/boost/network/support/is_udp.hpp +++ b/boost/network/support/is_udp.hpp @@ -7,19 +7,19 @@ // http://www.boost.org/LICENSE_1_0.txt) #include -#include +#include #include +#include +#include namespace boost { namespace network { + template + struct is_udp : mpl::false_ {}; + template - struct is_udp : - is_base_of< - tags::udp, - Tag - > - {}; - + struct is_udp::type> : mpl::true_ {}; + } // namespace network } // namespace boost diff --git a/boost/network/support/pod_or_normal.hpp b/boost/network/support/pod_or_normal.hpp index 1de090d4b..fdfcf4c12 100644 --- a/boost/network/support/pod_or_normal.hpp +++ b/boost/network/support/pod_or_normal.hpp @@ -12,14 +12,11 @@ namespace boost { namespace network { + template + struct pod_or_normal { typedef tags::normal type; }; + template - struct pod_or_normal : - mpl::if_< - is_pod - , tags::pod - , tags::normal - > - {}; + struct pod_or_normal::type> : tags::pod {}; } /* network */ diff --git a/boost/network/tags.hpp b/boost/network/tags.hpp index b652b1b87..df74703a3 100644 --- a/boost/network/tags.hpp +++ b/boost/network/tags.hpp @@ -15,15 +15,16 @@ namespace boost { namespace network { namespace tags { - struct pod {}; - struct normal {}; - struct async {}; - struct tcp {}; - struct udp {}; - struct sync {}; - struct default_string {}; - struct default_wstring {}; - + struct pod { typedef mpl::true_::type is_pod; }; + struct normal { typedef mpl::true_::type is_normal; }; + struct async { typedef mpl::true_::type is_async; }; + struct tcp { typedef mpl::true_::type is_tcp; }; + struct udp { typedef mpl::true_::type is_udp; }; + struct sync { typedef mpl::true_::type is_sync; }; + struct default_string + { typedef mpl::true_::type is_default_string; }; + struct default_wstring + { typedef mpl::true_::type is_default_wstring; }; template struct components; diff --git a/boost/network/traits/char.hpp b/boost/network/traits/char.hpp index 64472f16a..66e7dbbeb 100644 --- a/boost/network/traits/char.hpp +++ b/boost/network/traits/char.hpp @@ -16,18 +16,23 @@ namespace boost { namespace network { template struct unsupported_tag; + template + struct char_ + { + typedef unsupported_tag type; + }; + template - struct char_ : - mpl::if_< - is_default_string, - char, - typename mpl::if_< - is_default_wstring, - wchar_t, - unsupported_tag - >::type - > - {}; + struct char_ >::type> + { + typedef char type; + }; + + template + struct char_ >::type> + { + typedef wchar_t type; + }; } // namespace network diff --git a/boost/network/traits/istream.hpp b/boost/network/traits/istream.hpp index 5f0973de3..7f50bb291 100644 --- a/boost/network/traits/istream.hpp +++ b/boost/network/traits/istream.hpp @@ -10,26 +10,30 @@ #include #include #include -#include #include namespace boost { namespace network { template struct unsupported_tag; - + + template + struct istream + { + typedef unsupported_tag type; + }; + + template + struct istream >::type> + { + typedef std::istream type; + }; + template - struct istream : - mpl::if_< - is_default_string, - std::istream, - typename mpl::if_< - is_default_wstring, - std::wistream, - unsupported_tag - >::type - > - {}; + struct istream >::type> + { + typedef std::wistream type; + }; } /* network */ diff --git a/boost/network/traits/istringstream.hpp b/boost/network/traits/istringstream.hpp index 54b202621..776385b2a 100644 --- a/boost/network/traits/istringstream.hpp +++ b/boost/network/traits/istringstream.hpp @@ -11,25 +11,29 @@ # include #include #include -#include namespace boost { namespace network { template struct unsupported_tag; - + + template + struct istringstream + { + typedef unsupported_tag type; + }; + + template + struct istringstream >::type> + { + typedef std::istringstream type; + }; + template - struct istringstream : - mpl::if_< - is_default_string, - std::istringstream, - typename mpl::if_< - is_default_wstring, - std::basic_istringstream, - unsupported_tag - >::type - > - {}; + struct istringstream >::type> + { + typedef std::basic_istringstream type; + }; } // namespace network diff --git a/boost/network/traits/ostringstream.hpp b/boost/network/traits/ostringstream.hpp index b36dafa30..58e09a638 100644 --- a/boost/network/traits/ostringstream.hpp +++ b/boost/network/traits/ostringstream.hpp @@ -18,19 +18,24 @@ namespace boost { namespace network { template struct unsupported_tag; + template + struct ostringstream + { + typedef unsupported_tag type; + }; + template - struct ostringstream : - mpl::if_< - is_default_string, - std::ostringstream, - typename mpl::if_< - is_default_wstring, - std::wostringstream, - unsupported_tag - >::type - > - {}; - + struct ostringstream >::type> + { + typedef std::ostringstream type; + }; + + template + struct ostringstream >::type> + { + typedef std::wostringstream type; + }; + } // namespace network } // namespace boost diff --git a/boost/network/traits/string.hpp b/boost/network/traits/string.hpp index 0cfcc1a73..92cd88e6d 100644 --- a/boost/network/traits/string.hpp +++ b/boost/network/traits/string.hpp @@ -12,7 +12,6 @@ # include # include # include -# include #ifndef BOOST_NETWORK_DEFAULT_STRING #define BOOST_NETWORK_DEFAULT_STRING std::string @@ -26,19 +25,24 @@ namespace boost { namespace network { template struct unsupported_tag; - - template + + template struct string - : mpl::if_< - is_default_string, - BOOST_NETWORK_DEFAULT_STRING, - typename mpl::if_< - is_default_wstring, - BOOST_NETWORK_DEFAULT_WSTRING, - unsupported_tag - >::type - > - {}; + { + typedef unsupported_tag type; + }; + + template + struct string >::type> + { + typedef BOOST_NETWORK_DEFAULT_STRING type; + }; + + template + struct string >::type> + { + typedef BOOST_NETWORK_DEFAULT_WSTRING type; + }; } // namespace network From 34197784fcbc05b6d297339bfe93e5eb7ffa76c1 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 3 Apr 2011 00:29:08 +0800 Subject: [PATCH 083/768] URL Support for wide-character strings This commit finally adds support for wide characters in URI's and addresses the final test errors in the URI implementation. Step after this is the refactoring of the Spirit-based grammar to simplify the URI grammar and reduce the magic that goes on in the implementation. --- boost/network/uri/basic_uri.hpp | 12 ++- boost/network/uri/detail/impl/parse_uri.ipp | 111 ++++++++++++++++++-- boost/network/uri/detail/uri_parts.hpp | 101 ++++++++++++++---- libs/network/test/url_test.cpp | 1 + 4 files changed, 193 insertions(+), 32 deletions(-) diff --git a/boost/network/uri/basic_uri.hpp b/boost/network/uri/basic_uri.hpp index 9ad7d3013..9a2d0bee2 100644 --- a/boost/network/uri/basic_uri.hpp +++ b/boost/network/uri/basic_uri.hpp @@ -23,8 +23,10 @@ struct uri_base { : raw_(uri), parts_(), - valid_(parse_uri(raw_, parts_)) - { } + valid_(false) + { + valid_ = parse_uri(raw_, parts_); + } uri_base(const uri_base & other) : @@ -116,8 +118,9 @@ class basic_uri : public uri_base { basic_uri() : uri_base() {} basic_uri(typename uri_base::string_type const & uri) : uri_base(uri) {} + basic_uri(basic_uri const & other) : uri_base(other) {} - basic_uri & operator= (basic_uri & rhs) { + basic_uri & operator= (basic_uri rhs) { rhs.swap(*this); return *this; } @@ -223,7 +226,7 @@ is_valid(basic_uri const & uri) { } // namespace network } // namespace boost - +#ifdef BOOST_NETWORK_DEBUG // Check that the URI concept is met by the basic_uri type. #include #include @@ -233,6 +236,7 @@ BOOST_CONCEPT_ASSERT((URI >)); } // namespace uri } // namespace network } // namespace boost +#endif // BOOST_NETWORK_DEBUG #endif diff --git a/boost/network/uri/detail/impl/parse_uri.ipp b/boost/network/uri/detail/impl/parse_uri.ipp index 3bc4ae201..d8c1d888a 100644 --- a/boost/network/uri/detail/impl/parse_uri.ipp +++ b/boost/network/uri/detail/impl/parse_uri.ipp @@ -131,17 +131,100 @@ struct transform_attribute< static void post(optional &, Transformed const &) { } }; #endif + +template <> +struct transform_attribute< + boost::network::uri::detail::uri_parts_wide_base, + boost::fusion::tuple< + std::wstring &, + boost::fusion::tuple< + boost::optional&, + boost::optional&, + boost::optional &, + std::wstring & + >, + optional&, + optional& + > +#if SPIRIT_VERSION >= 0x2030 + , boost::spirit::qi::domain +#endif + > +{ + typedef + boost::fusion::tuple< + std::wstring &, + boost::fusion::tuple< + boost::optional&, + boost::optional&, + boost::optional &, + std::wstring & + >, + optional&, + optional& + > type; + + static type pre(boost::network::uri::detail::uri_parts_wide_base & parts) { + boost::fusion::tuple< + boost::optional &, + boost::optional &, + boost::optional &, + std::wstring & + > hier_part = + boost::fusion::tie( + parts.user_info, + parts.host, + parts.port, + parts.path + ); + + return boost::fusion::tie( + parts.scheme, + hier_part, + parts.query, + parts.fragment + ); +} + +static void post(boost::network::uri::detail::uri_parts_wide_base &, type const &) { } + +#if SPIRIT_VERSION >= 0x2030 +static void fail(boost::network::uri::detail::uri_parts_wide_base & val) { } +#endif +}; + } // namespace traits } // namespace spirit } // namespace boost namespace boost { namespace network { namespace uri { namespace detail { + +template +struct unsupported_string; + +template +struct choose_uri_base +{ + typedef unsupported_string type; +}; + +template +struct choose_uri_base +{ + typedef uri_parts_default_base type; +}; + +template +struct choose_uri_base +{ + typedef uri_parts_wide_base type; +}; namespace qi = boost::spirit::qi; -template -struct uri_grammar_default : qi::grammar { +template +struct uri_grammar_default : qi::grammar::type()> { uri_grammar_default() : uri_grammar_default::base_type(start, "uri") { // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" gen_delims %= qi::char_(":/?#[]@"); @@ -223,8 +306,8 @@ struct uri_grammar_default : qi::grammar { ) | ( - qi::attr(optional()) - >> qi::attr(optional()) + qi::attr(optional()) + >> qi::attr(optional()) >> qi::attr(optional()) >> ( path_absolute @@ -242,7 +325,7 @@ struct uri_grammar_default : qi::grammar { start %= uri.alias(); } - typedef std::string string_type; + typedef String string_type; qi::rule gen_delims, sub_delims, reserved, unreserved; @@ -268,7 +351,7 @@ struct uri_grammar_default : qi::grammar { >()> hier_part; // start rule of grammar - qi::rule start; + qi::rule::type()> start; // actual uri parser qi::rule< @@ -290,11 +373,11 @@ struct uri_grammar_default : qi::grammar { BOOST_NETWORK_INLINE bool parse_uri_impl(boost::iterator_range & range, uri_parts_default_base & parts, boost::network::tags::default_string) { // Qualified boost::begin and boost::end because MSVC complains - // of ambiguity on call to begin(range) and end(rand). + // of ambiguity on call to begin(range) and end(range). std::string::const_iterator start_ = boost::begin(range); std::string::const_iterator end_ = boost::end(range); - static uri_grammar_default grammar; + static uri_grammar_default grammar; bool ok = qi::parse(start_, end_, grammar, parts); @@ -302,8 +385,16 @@ BOOST_NETWORK_INLINE bool parse_uri_impl(boost::iterator_range & range, uri_parts_wide_base & parts, boost::network::tags::default_wstring) { - // TODO implement the grammar that supports wide strings - return false; // this always fails because it's not supported yet! + // Qualified boost::begin and boost::end because MSVC complains + // of ambiguity on call to begin(range) and end(range). + std::wstring::const_iterator start_ = boost::begin(range); + std::wstring::const_iterator end_ = boost::end(range); + + static uri_grammar_default grammar; + + bool ok = qi::parse(start_, end_, grammar, parts); + + return ok && start_ == end_; } } /* detail */ diff --git a/boost/network/uri/detail/uri_parts.hpp b/boost/network/uri/detail/uri_parts.hpp index ba0021a43..3bf238acf 100644 --- a/boost/network/uri/detail/uri_parts.hpp +++ b/boost/network/uri/detail/uri_parts.hpp @@ -26,6 +26,36 @@ namespace detail { string_type path; optional query; optional fragment; + + uri_parts_default_base(uri_parts_default_base const & other) + : scheme(other.scheme) + , user_info(other.user_info) + , host(other.host) + , port(other.port) + , path(other.path) + , query(other.query) + , fragment(other.fragment) + {} + + uri_parts_default_base() + {} + + uri_parts_default_base & operator=(uri_parts_default_base rhs) + { + rhs.swap(*this); + return *this; + } + + void swap(uri_parts_default_base & rhs) + { + std::swap(scheme, rhs.scheme); + std::swap(user_info, rhs.user_info); + std::swap(host, rhs.host); + std::swap(port, rhs.port); + std::swap(path, rhs.path); + std::swap(query, rhs.query); + std::swap(fragment, rhs.fragment); + } }; struct uri_parts_wide_base { @@ -37,6 +67,36 @@ namespace detail { string_type path; optional query; optional fragment; + + uri_parts_wide_base(uri_parts_wide_base const & other) + : scheme(other.scheme) + , user_info(other.user_info) + , host(other.host) + , port(other.port) + , path(other.path) + , query(other.query) + , fragment(other.fragment) + {} + + uri_parts_wide_base() + {} + + uri_parts_wide_base & operator=(uri_parts_wide_base rhs) + { + rhs.swap(*this); + return *this; + } + + void swap(uri_parts_wide_base & rhs) + { + std::swap(this->scheme, rhs.scheme); + std::swap(this->user_info, rhs.user_info); + std::swap(this->host, rhs.host); + std::swap(this->port, rhs.port); + std::swap(this->path, rhs.path); + std::swap(this->query, rhs.query); + std::swap(this->fragment, rhs.fragment); + } }; template @@ -46,23 +106,21 @@ struct uri_parts : , uri_parts_default_base , uri_parts_wide_base >::type -{}; - -template -struct uri_parts_tuple { - typedef typename string::type string_type; - - typedef typename boost::fusion::tuple< - string_type &, - boost::fusion::tuple< - optional &, - optional &, - optional &, - string_type & - >, - optional &, - optional & - > type; +{ + typedef typename mpl::if_< + is_default_string + , uri_parts_default_base + , uri_parts_wide_base + >::type base_type; + uri_parts() : base_type() {} + uri_parts(uri_parts const & other) + : base_type(other) + {} + uri_parts & operator=(uri_parts rhs) + { + swap(*this, rhs); + return *this; + } }; template @@ -93,8 +151,15 @@ bool operator==(uri_parts const & l, uri_parts const & r) { template inline bool operator!=(uri_parts const & l, uri_parts const & r) { - return !(l == r); + return (l.scheme != r.scheme) && + (l.user_info != r.user_info) && + (l.host != r.host) && + (l.port != r.port) && + (l.path != r.path) && + (l.query != r.query) && + (l.fragment != r.fragment); } + } // namespace detail } // namespace uri } // namespace network diff --git a/libs/network/test/url_test.cpp b/libs/network/test/url_test.cpp index 8390a1d97..db0463bef 100644 --- a/libs/network/test/url_test.cpp +++ b/libs/network/test/url_test.cpp @@ -212,5 +212,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, tag_types) { uri_type instance(string_type(boost::begin(url), boost::end(url))); uri_type copy; copy = instance; + BOOST_CHECK(instance.raw() == copy.raw()); BOOST_CHECK(instance == copy); } From 6a8ce1138edad7a3dc6e6afa6124999ff2aa0deb Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 4 Apr 2011 10:43:54 +0800 Subject: [PATCH 084/768] Enabling BOOST_NETWORK_DEBUG only on Debug builds. --- libs/network/test/http/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 8af6f352a..2068d35ad 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -13,7 +13,9 @@ if (OPENSSL_FOUND) add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) endif() -add_definitions(-DBOOST_NETWORK_DEBUG) +if (CMAKE_BUILD_TYPE MATCHES Debug) + add_definitions(-DBOOST_NETWORK_DEBUG) +endif() find_package( Threads ) set(Boost_USE_STATIC_LIBS ON) From 1f21307e2fe1ec6291e1d22c40aa428b51bbe113 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 4 Apr 2011 14:32:46 +0800 Subject: [PATCH 085/768] Fixing issue with stoppage and cancellation when the server starts listening. --- .../network/protocol/http/server/async_server.hpp | 14 ++++++++++---- boost/network/protocol/http/server/sync_server.hpp | 4 +++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/boost/network/protocol/http/server/async_server.hpp b/boost/network/protocol/http/server/async_server.hpp index ec105abcb..795cd789b 100644 --- a/boost/network/protocol/http/server/async_server.hpp +++ b/boost/network/protocol/http/server/async_server.hpp @@ -55,7 +55,8 @@ namespace boost { namespace network { namespace http { // stop accepting new requests and let all the existing // handlers finish. stopping = true; - acceptor.cancel(); + system::error_code ignored; + acceptor.cancel(ignored); } void listen() { @@ -101,10 +102,15 @@ namespace boost { namespace network { namespace http { tcp::resolver resolver(service_); tcp::resolver::query query(address_, port_); tcp::endpoint endpoint = *resolver.resolve(query); - acceptor.open(endpoint.protocol()); - acceptor.bind(endpoint); + + system::error_code error; + acceptor.open(endpoint.protocol(), error); + if (error) return; + acceptor.bind(endpoint, error); + if (error) return; socket_options_base::acceptor_options(acceptor); - acceptor.listen(); + acceptor.listen(asio::socket_base::max_connections, error); + if (error) return; new_connection.reset(new connection(service_, handler, thread_pool)); acceptor.async_accept(new_connection->socket(), boost::bind( diff --git a/boost/network/protocol/http/server/sync_server.hpp b/boost/network/protocol/http/server/sync_server.hpp index f92965e8c..929eaa06a 100644 --- a/boost/network/protocol/http/server/sync_server.hpp +++ b/boost/network/protocol/http/server/sync_server.hpp @@ -57,7 +57,9 @@ namespace boost { namespace network { namespace http { void stop() { // stop accepting new connections and let all the existing handlers finish. - acceptor_.cancel(); + system::error_code ignored; + acceptor_.cancel(ignored); + service_.stop(); } void listen() { From 938733b4d19f8e78b460da7779dbb89606fcb49a Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 8 Apr 2011 13:20:46 +0800 Subject: [PATCH 086/768] Fixing typo on thread_pool implementaiton. --- boost/network/utils/thread_pool.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boost/network/utils/thread_pool.hpp b/boost/network/utils/thread_pool.hpp index 15f60c4e0..1938f6d81 100644 --- a/boost/network/utils/thread_pool.hpp +++ b/boost/network/utils/thread_pool.hpp @@ -88,7 +88,7 @@ namespace boost { namespace network { namespace utils { void swap(basic_thread_pool & other) { std::swap(other.threads_, threads_); std::swap(other.io_service_, io_service_); - std::swap(other.worket_threads_, worker_threads_); + std::swap(other.worker_threads_, worker_threads_); std::swap(other.sentinel_, sentinel_); } protected: From 42c7bf69d46c66e3500758161554e65da9dbf8ec Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 8 Apr 2011 23:25:18 +0800 Subject: [PATCH 087/768] Fixing cleanup order bug in pooled connection policy Because of the refactorings that happened in the client implementation certain cleanup sequeneces that used to not be an issue is now causing some errors especially with the pooled connection policy. These cleanup issues have been partly addressed in this commit, addressing a destruction bug that is manifested in the HTTP Client get tests when a synchronous HTTP Client with keepalive support enabled in the tag used is destroyed. The actual bug is that the io_service is destroyed first before the actual pooled connection policy cleanup code is invoked, causing a segmentation fault with sockets bound to the io_service object is destroyed because the internal state of the io_service referred to is already undefined by the time the pool of sockets is destroyed. --- .../http/client/connection/sync_normal.hpp | 6 +- .../http/client/connection/sync_ssl.hpp | 1 + boost/network/protocol/http/client/pimpl.hpp | 71 +++++-------------- .../protocol/http/client/sync_impl.hpp | 49 ++++++++++--- .../http/policies/pooled_connection.hpp | 19 ++--- 5 files changed, 64 insertions(+), 82 deletions(-) diff --git a/boost/network/protocol/http/client/connection/sync_normal.hpp b/boost/network/protocol/http/client/connection/sync_normal.hpp index deab36c4e..18add4b4d 100644 --- a/boost/network/protocol/http/client/connection/sync_normal.hpp +++ b/boost/network/protocol/http/client/connection/sync_normal.hpp @@ -62,15 +62,13 @@ namespace boost { namespace network { namespace http { namespace impl { bool is_open() { return socket_.is_open(); } void close_socket() { + if (!is_open()) return; boost::system::error_code ignored; socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored); + if (ignored) return; socket_.close(ignored); } - ~http_sync_connection() { - close_socket(); - } - private: resolver_type & resolver_; diff --git a/boost/network/protocol/http/client/connection/sync_ssl.hpp b/boost/network/protocol/http/client/connection/sync_ssl.hpp index a7e579a7f..ce13a78c3 100644 --- a/boost/network/protocol/http/client/connection/sync_ssl.hpp +++ b/boost/network/protocol/http/client/connection/sync_ssl.hpp @@ -76,6 +76,7 @@ namespace boost { namespace network { namespace http { namespace impl { void close_socket() { boost::system::error_code ignored; socket_.lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored); + if (ignored) return; socket_.lowest_layer().close(ignored); } diff --git a/boost/network/protocol/http/client/pimpl.hpp b/boost/network/protocol/http/client/pimpl.hpp index c1a17be73..55df10f57 100644 --- a/boost/network/protocol/http/client/pimpl.hpp +++ b/boost/network/protocol/http/client/pimpl.hpp @@ -15,6 +15,7 @@ #include #include +#include namespace boost { namespace network { namespace http { @@ -27,63 +28,23 @@ namespace boost { namespace network { namespace http { struct async_client; template - struct sync_client : - connection_policy::type - { - typedef typename string::type string_type; - typedef typename connection_policy::type connection_base; - typedef typename resolver::type resolver_type; - friend struct basic_client_impl; - - boost::asio::io_service * service_ptr; - boost::asio::io_service & service_; - resolver_type resolver_; - optional certificate_file, verify_path; - - sync_client(bool cache_resolved, bool follow_redirect - , optional const & certificate_file = optional() - , optional const & verify_path = optional() - ) - : connection_base(cache_resolved, follow_redirect), - service_ptr(new boost::asio::io_service), - service_(*service_ptr), - resolver_(service_) - , certificate_file(certificate_file) - , verify_path(verify_path) - {} - - sync_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service - , optional const & certificate_file = optional() - , optional const & verify_path = optional() - ) - : connection_base(cache_resolved, follow_redirect), - service_ptr(0), - service_(service), - resolver_(service_) - , certificate_file(certificate_file) - , verify_path(verify_path) - {} - - ~sync_client() { - delete service_ptr; - } - - basic_response const request_skeleton(basic_request const & request_, string_type method, bool get_body) { - typename connection_base::connection_ptr connection_; - connection_ = connection_base::get_connection(resolver_, request_, certificate_file, verify_path); - return connection_->send_request(method, request_, get_body); - } - + struct sync_client; + + + template + struct client_base { + typedef unsupported_tag type; }; - + template - struct client_base - : mpl::if_< - typename is_async::type, - async_client, - sync_client - > - {}; + struct client_base >::type> { + typedef async_client type; + }; + + template + struct client_base >::type> { + typedef sync_client type; + }; } // namespace impl diff --git a/boost/network/protocol/http/client/sync_impl.hpp b/boost/network/protocol/http/client/sync_impl.hpp index 2950ed087..561cec42c 100644 --- a/boost/network/protocol/http/client/sync_impl.hpp +++ b/boost/network/protocol/http/client/sync_impl.hpp @@ -13,29 +13,56 @@ namespace boost { namespace network { namespace http { namespace impl { template - struct sync_client : - connection_policy::type + struct sync_client : + connection_policy::type { - typedef - typename connection_policy::type - connection_base; + typedef typename string::type string_type; + typedef typename connection_policy::type connection_base; + typedef typename resolver::type resolver_type; + friend struct basic_client_impl; - sync_client(bool cache_resolved, bool follow_redirect) - : connection_base(cache_resolved, follow_redirect) + boost::asio::io_service * service_ptr; + boost::asio::io_service & service_; + resolver_type resolver_; + optional certificate_file, verify_path; + + sync_client(bool cache_resolved, bool follow_redirect + , optional const & certificate_file = optional() + , optional const & verify_path = optional() + ) + : connection_base(cache_resolved, follow_redirect), + service_ptr(new boost::asio::io_service), + service_(*service_ptr), + resolver_(service_) + , certificate_file(certificate_file) + , verify_path(verify_path) + {} + + sync_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service + , optional const & certificate_file = optional() + , optional const & verify_path = optional() + ) + : connection_base(cache_resolved, follow_redirect), + service_ptr(0), + service_(service), + resolver_(service_) + , certificate_file(certificate_file) + , verify_path(verify_path) {} - ~sync_client() - { + ~sync_client() { connection_base::cleanup(); + delete service_ptr; } - + basic_response const request_skeleton(basic_request const & request_, string_type method, bool get_body) { typename connection_base::connection_ptr connection_; - connection_ = connection_base::get_connection(resolver_, request_); + connection_ = connection_base::get_connection(resolver_, request_, certificate_file, verify_path); return connection_->send_request(method, request_, get_body); } }; + } // namespace impl } // namespace http diff --git a/boost/network/protocol/http/policies/pooled_connection.hpp b/boost/network/protocol/http/policies/pooled_connection.hpp index 1dc87e2df..1fa19350e 100644 --- a/boost/network/protocol/http/policies/pooled_connection.hpp +++ b/boost/network/protocol/http/policies/pooled_connection.hpp @@ -29,6 +29,10 @@ namespace boost { namespace network { namespace http { typedef typename resolver_policy::type resolver_base; typedef typename resolver_base::resolver_type resolver_type; typedef function resolver_function_type; + + void cleanup() { + host_connection_map().swap(host_connections); + } struct connection_impl { typedef function(resolver_type &,basic_request const &,optional const &, optional const &)> get_connection_function; @@ -46,11 +50,6 @@ namespace boost { namespace network { namespace http { return send_request_impl(method, request_, get_body); } - ~connection_impl () { - pimpl->close_socket(); - pimpl.reset(); - } - private: basic_response send_request_impl(string_type const & method, basic_request request_, bool get_body) { @@ -58,7 +57,7 @@ namespace boost { namespace network { namespace http { bool retry = false; do { if (count >= BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT) - throw std::runtime_error("Redirection exceeds maximum redirect count."); + boost::throw_exception(std::runtime_error("Redirection exceeds maximum redirect count.")); basic_response response_; // check if the socket is open first @@ -110,7 +109,7 @@ namespace boost { namespace network { namespace http { connection_ = get_connection_(resolver_, request_, certificate_filename_, verify_path_); ++count; continue; - } else throw std::runtime_error("Location header not defined in redirect response."); + } else boost::throw_exception(std::runtime_error("Location header not defined in redirect response.")); } } return response_; @@ -162,13 +161,9 @@ namespace boost { namespace network { namespace http { return it->second; } - void cleanup() { - host_connection_map().swap(host_connections); - } - pooled_connection_policy(bool cache_resolved, bool follow_redirect) : resolver_base(cache_resolved), host_connections(), follow_redirect_(follow_redirect) {} - + }; } // namespace http From 9b9bd9b145bc0bd7ee01860888a6369e2a5ef542 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 8 Apr 2011 23:31:49 +0800 Subject: [PATCH 088/768] Ignoring runtime errors in inlined client test. --- libs/network/test/http/client_include_inlined.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libs/network/test/http/client_include_inlined.cpp b/libs/network/test/http/client_include_inlined.cpp index 918444f49..a83664800 100644 --- a/libs/network/test/http/client_include_inlined.cpp +++ b/libs/network/test/http/client_include_inlined.cpp @@ -11,7 +11,12 @@ int main(int argc, char * argv[]) { using namespace boost::network; http::client c; http::client::request req("http://www.boost.org/"); - http::client::response res = c.get(req); + try { + http::client::response res = c.get(req); + } catch (...) { + // ignore the error, we just want to make sure + // the interface works inlined. + } return 0; } From ba96b4f161c6e5b01708daa0d007551e84681981 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 9 Apr 2011 12:44:38 +0800 Subject: [PATCH 089/768] SFINAE-ize the server_base metafunction The server_base metafunction type serves as a means for choosing which implementation base the server will be deriving from. The SFINAE technique is used to enable the appropriate implementation of the type depending on the tag dispatch mechanism being utilized throughout the implementation. --- boost/network/protocol/http/server.hpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/boost/network/protocol/http/server.hpp b/boost/network/protocol/http/server.hpp index 0ab3e47b4..f2d86cb99 100644 --- a/boost/network/protocol/http/server.hpp +++ b/boost/network/protocol/http/server.hpp @@ -16,19 +16,21 @@ #include namespace boost { namespace network { namespace http { - + + template + struct server_base { + typedef unsupported_tag type; + }; + template - struct server_base : - mpl::if_< - is_async - , async_server_base - , typename mpl::if_< - is_sync - , sync_server_base - , unsupported_tag - >::type - > - {}; + struct server_base >::type> { + typedef async_server_base type; + }; + + template + struct server_base >::type> { + typedef sync_server_base type; + }; template struct basic_server : server_base::type From 482fcf1840b2289c0c41a37793c633f417759be7 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 9 Apr 2011 13:34:21 +0800 Subject: [PATCH 090/768] Updating documentation on server constructor options Because of the Boost.Parameter refactoring to support more options in the construction of the server instance, the documentation had to be updated to cover all available options. --- boost/network/protocol/http/server.hpp | 2 +- libs/network/doc/reference_http_server.rst | 64 ++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/boost/network/protocol/http/server.hpp b/boost/network/protocol/http/server.hpp index f2d86cb99..a15613573 100644 --- a/boost/network/protocol/http/server.hpp +++ b/boost/network/protocol/http/server.hpp @@ -82,7 +82,7 @@ namespace boost { namespace network { namespace http { (send_buffer_size, (int)) (receive_low_watermark, (int)) (send_low_watermark, (int)) - (non_blocking_io, (int)) + (non_blocking_io, (bool)) (linger, (bool)) (linger_timeout, (int))) ) diff --git a/libs/network/doc/reference_http_server.rst b/libs/network/doc/reference_http_server.rst index 0a4fbeddc..d930cc56d 100644 --- a/libs/network/doc/reference_http_server.rst +++ b/libs/network/doc/reference_http_server.rst @@ -172,6 +172,70 @@ Constructor ``std::string const &`` and handler being of type ``handler_type`` but passed in as an lvalue reference. +``template client(ArgPack const & args)`` + Pass in an argument pack. See supported parameters in the table below. + ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Parameter Name | Type | Description | ++========================+==========================================+==================================================================================================+ +| _address | string_type | The hostname or IP address from which the server should be bound to. This parameter is required. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _port | string_type | The port to which the server should bind and listen to. This parameter is required. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _handler | ``Handler &`` | An lvalue reference to an instance of ``Handler``. This parameter is required. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _thread_pool | ``boost::network::utils::thread_pool &`` | An lvalue reference to an instance of ``boost::network::utils::thread_pool`` -- this is the | +| | | thread pool from where the handler is invoked. This parameter is only applicable and required | +| | | for ``async_server`` instances. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _io_service | ``boost::asio::io_service &`` | An optional lvalue to an instance of ``boost::asio::io_service`` which allows the server to use | +| | | an already-constructed ``boost::asio::io_service`` instance instead of instantiating one that it | +| | | manages. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _reuse_address | ``bool`` | A boolean that specifies whether to re-use the address and port on which the server will be | +| | | bound to. This enables or disables the socket option for listener sockets. The default is | +| | | ``false``. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _report_aborted | ``bool`` | A boolean that specifies whether the listening socket should report aborted connection attempts | +| | | to the accept handler (an internal detail of cpp-netlib). This is put in place to allow for | +| | | future-proofing the code in case an optional error handler function is supported in later | +| | | releases of cpp-netlib. The default is ``false``. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _receive_buffer_size | ``int`` | The size of the socket's receive buffer. The default is defined by Boost.Asio and is | +| | | platform-dependent. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _send_buffer_size | ``int`` | The size of the socket's send buffer. The default is defined by Boost.Asio and is | +| | | platform-dependent. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _receive_low_watermark | ``int`` | The size of the socket's low watermark for its receive buffer. The default is defined by | +| | | Boost.Asio and is platform-dependent. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _send_buffer_size | ``int`` | The size of the socket's send low watermark for its send buffer. The default is defined by | +| | | Boost.Asio and is platform-dependent. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _non_blocking_io | ``bool`` | An optional bool to define whether the socket should use non-blocking I/O in case the platform | +| | | supports it. The default is ``true``. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _linger | ``bool`` | An optional bool to determine whether the socket should linger in case there's still data to be | +| | | sent out at the time of its closing. The default is ``true``. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _linger_timeout | ``int`` | An optional int to define the timeout to wait for socket closes before it is set to linger. | +| | | The default is ``0``. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ + +To use the above supported named parameters, you'll have code that looks like the following: + +.. code-block:: c++ + + using namespace boost::network::http; // parameters are in this namespace + boost::asio::io_service my_io_service; + boost::network::utils::thread_pool pool(2); + handler handler_instance; + async_server instance(_address="0.0.0.0", _port="80", _handler=handler_instance, + _io_service=my_io_service, _thread_pool=pool, + _reuse_address=true); + instance.run(); + Public Members `````````````` From 5b82adfa052d1ce65043328eb864128633ccdc82 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 9 Apr 2011 10:36:19 +0200 Subject: [PATCH 091/768] Changing the background image to an Orange. --- libs/network/doc/static/cpp-netlib.css | 2 +- libs/network/doc/static/orange-background.jpg | Bin 0 -> 283722 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 libs/network/doc/static/orange-background.jpg diff --git a/libs/network/doc/static/cpp-netlib.css b/libs/network/doc/static/cpp-netlib.css index 7ee3e7df5..3eed2a246 100644 --- a/libs/network/doc/static/cpp-netlib.css +++ b/libs/network/doc/static/cpp-netlib.css @@ -1,6 +1,6 @@ @import url(https://github.com/reset-fonts-grids.css); -html, body {background-image: url(https://github.com/background.jpg); background-repeat:no-repeat; background-position:right top; background-attachment:fixed} +html, body {background-image: url(https://github.com/orange-background.jpg); background-repeat:no-repeat; background-position:left top; background-attachment:fixed; background-color:black} body {font:12pt "Times New Roman", Lucida, serif; color:black} #custom-doc { width:80%;*width:720px; min-width:720px; max-width:960px; margin:auto; text-align:left; padding-top:16px; margin-top:0} #hd { padding: 4px 0 12px 0} diff --git a/libs/network/doc/static/orange-background.jpg b/libs/network/doc/static/orange-background.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e8ac2b4837c57916988d1d03cc07c2b5491a04af GIT binary patch literal 283722 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�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

nn)DwM7KXi|YJv)>zWxp7=5{0WpLc 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 DGaDVM literal 0 HcmV?d00001 From f034299530ac77e44c7e83c9b30f5b9e1bfb0b8d Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 9 Apr 2011 10:42:21 +0200 Subject: [PATCH 092/768] Updating packaged documentation for cpp-netlib 0.9. --- .../html/_sources/reference_http_client.txt | 68 +++++++-- .../html/_sources/reference_http_server.txt | 64 ++++++++ libs/network/doc/html/_sources/whats_new.txt | 18 +++ libs/network/doc/html/_static/basic.css | 23 ++- libs/network/doc/html/_static/cpp-netlib.css | 2 +- libs/network/doc/html/_static/doctools.js | 2 +- .../doc/html/_static/orange-background.jpg | Bin 0 -> 283722 bytes libs/network/doc/html/_static/searchtools.js | 2 +- libs/network/doc/html/_static/sphinxdoc.css | 2 +- libs/network/doc/html/directives.html | 31 +++- libs/network/doc/html/examples.html | 31 +++- libs/network/doc/html/examples_http.html | 27 +++- libs/network/doc/html/genindex.html | 27 +++- libs/network/doc/html/getting_started.html | 35 +++-- libs/network/doc/html/hello_world_client.html | 27 +++- libs/network/doc/html/hello_world_server.html | 27 +++- libs/network/doc/html/history.html | 31 +++- libs/network/doc/html/http.html | 27 +++- libs/network/doc/html/http_client.html | 27 +++- libs/network/doc/html/http_client_tags.html | 29 +++- libs/network/doc/html/in_depth.html | 31 +++- libs/network/doc/html/index.html | 42 ++++-- libs/network/doc/html/install.html | 31 +++- libs/network/doc/html/message.html | 31 +++- libs/network/doc/html/objects.inv | Bin 338 -> 338 bytes libs/network/doc/html/polymorphism.html | 27 +++- libs/network/doc/html/reference.html | 31 +++- .../doc/html/reference_http_client.html | 135 ++++++++++++----- .../doc/html/reference_http_request.html | 27 +++- .../doc/html/reference_http_response.html | 27 +++- .../doc/html/reference_http_server.html | 139 ++++++++++++++++-- libs/network/doc/html/references.html | 31 +++- libs/network/doc/html/search.html | 29 +++- libs/network/doc/html/searchindex.js | 2 +- libs/network/doc/html/tag_metafunctions.html | 27 +++- libs/network/doc/html/techniques.html | 31 +++- libs/network/doc/html/uri.html | 27 +++- libs/network/doc/html/whats_new.html | 51 ++++++- 38 files changed, 972 insertions(+), 247 deletions(-) create mode 100644 libs/network/doc/html/_static/orange-background.jpg diff --git a/libs/network/doc/html/_sources/reference_http_client.txt b/libs/network/doc/html/_sources/reference_http_client.txt index 116ec1406..0c7758a3c 100644 --- a/libs/network/doc/html/_sources/reference_http_client.txt +++ b/libs/network/doc/html/_sources/reference_http_client.txt @@ -122,6 +122,12 @@ Also, that code using the HTTP client will have use the following header: #include +.. note:: Starting version 0.9, cpp-netlib clients and server implementations + by default now have an externally-linked component. This is a breaking change + for code that used to rely on cpp-netlib being a header-only library, but can + inhibited by defining the ``BOOST_NETWORK_NO_LIB`` preprocessor macro before + including any cpp-netlib header. + Constructors ~~~~~~~~~~~~ @@ -130,18 +136,55 @@ initialization. ``client()`` Default constructor. -``client(client::cache_resolved)`` - Construct a client which caches resolved endpoints. -``client(client::follow_redirects)`` - Construct a client which follows HTTP redirects. [#]_ -``client(client::cache_resolved, client::follow_redirects), client(client::follow_redirects, client::cache_resolved)`` - Construct a client which caches resolved endpoints and follows HTTP - redirects. [#]_ - -.. [#] In Asynchronous Clients, redirects are not followed. This means the - response objects will contain whatever HTTP response was retrieved by the - client implementation. -.. [#] In Asynchronous Clients, only caching resolved endpoints take effect. +``client(boost::asio::io_service & io_service)`` + Construct a client to use an existing Boost.Asio ``io_service`` instance. +``template client(ArgPack const & args)`` + Pass in an argument pack. See supported parameters in the table below. + ++----------------------+-------------------------------+-------------------------+ +| Parameter Name | Type | Description | ++======================+===============================+=========================+ +| _follow_redirects | ``bool`` | Boolean to specify | +| | | whether the client | +| | | should follow HTTP | +| | | redirects. Default is | +| | | ``false``. | ++----------------------+-------------------------------+-------------------------+ +| _cache_resolved | ``bool`` | Boolean to specify | +| | | whether the client | +| | | should cache resolved | +| | | endpoints. The default | +| | | is ``false``. | ++----------------------+-------------------------------+-------------------------+ +| _io_service | ``boost::asio::io_service &`` | Reference to an | +| | | instance of a | +| | | Boost.Asio | +| | | ``io_service``. | ++----------------------+-------------------------------+-------------------------+ +| _openssl_certificate | string | The filename of the | +| | | certificate to load for | +| | | the SSL connection for | +| | | verification. | ++----------------------+-------------------------------+-------------------------+ +| _openssl_verify_path | string | The directory from | +| | | which the certificate | +| | | authority files are | +| | | located. | ++----------------------+-------------------------------+-------------------------+ + + +To use the above supported named parameters, you'll have code that looks like +the following: + +.. code-block:: c++ + + using namespace boost::network::http; // parameters are in this namespace + boost::asio::io_service my_io_service; + client client_(_follow_redirects=true, _cache_resolved=true, + _io_service=my_io_service + , _openssl_certificate="/tmp/my-cert" + , _openssl_verify_path="/tmp/ca-certs/"); + // use client_ as normal from here on out. HTTP Methods ~~~~~~~~~~~~ @@ -193,3 +236,4 @@ Client-Specific ``client_.clear_resolved_cache()`` Clear the cache of resolved endpoints. + diff --git a/libs/network/doc/html/_sources/reference_http_server.txt b/libs/network/doc/html/_sources/reference_http_server.txt index 0a4fbeddc..d930cc56d 100644 --- a/libs/network/doc/html/_sources/reference_http_server.txt +++ b/libs/network/doc/html/_sources/reference_http_server.txt @@ -172,6 +172,70 @@ Constructor ``std::string const &`` and handler being of type ``handler_type`` but passed in as an lvalue reference. +``template client(ArgPack const & args)`` + Pass in an argument pack. See supported parameters in the table below. + ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Parameter Name | Type | Description | ++========================+==========================================+==================================================================================================+ +| _address | string_type | The hostname or IP address from which the server should be bound to. This parameter is required. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _port | string_type | The port to which the server should bind and listen to. This parameter is required. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _handler | ``Handler &`` | An lvalue reference to an instance of ``Handler``. This parameter is required. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _thread_pool | ``boost::network::utils::thread_pool &`` | An lvalue reference to an instance of ``boost::network::utils::thread_pool`` -- this is the | +| | | thread pool from where the handler is invoked. This parameter is only applicable and required | +| | | for ``async_server`` instances. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _io_service | ``boost::asio::io_service &`` | An optional lvalue to an instance of ``boost::asio::io_service`` which allows the server to use | +| | | an already-constructed ``boost::asio::io_service`` instance instead of instantiating one that it | +| | | manages. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _reuse_address | ``bool`` | A boolean that specifies whether to re-use the address and port on which the server will be | +| | | bound to. This enables or disables the socket option for listener sockets. The default is | +| | | ``false``. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _report_aborted | ``bool`` | A boolean that specifies whether the listening socket should report aborted connection attempts | +| | | to the accept handler (an internal detail of cpp-netlib). This is put in place to allow for | +| | | future-proofing the code in case an optional error handler function is supported in later | +| | | releases of cpp-netlib. The default is ``false``. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _receive_buffer_size | ``int`` | The size of the socket's receive buffer. The default is defined by Boost.Asio and is | +| | | platform-dependent. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _send_buffer_size | ``int`` | The size of the socket's send buffer. The default is defined by Boost.Asio and is | +| | | platform-dependent. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _receive_low_watermark | ``int`` | The size of the socket's low watermark for its receive buffer. The default is defined by | +| | | Boost.Asio and is platform-dependent. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _send_buffer_size | ``int`` | The size of the socket's send low watermark for its send buffer. The default is defined by | +| | | Boost.Asio and is platform-dependent. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _non_blocking_io | ``bool`` | An optional bool to define whether the socket should use non-blocking I/O in case the platform | +| | | supports it. The default is ``true``. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _linger | ``bool`` | An optional bool to determine whether the socket should linger in case there's still data to be | +| | | sent out at the time of its closing. The default is ``true``. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ +| _linger_timeout | ``int`` | An optional int to define the timeout to wait for socket closes before it is set to linger. | +| | | The default is ``0``. | ++------------------------+------------------------------------------+--------------------------------------------------------------------------------------------------+ + +To use the above supported named parameters, you'll have code that looks like the following: + +.. code-block:: c++ + + using namespace boost::network::http; // parameters are in this namespace + boost::asio::io_service my_io_service; + boost::network::utils::thread_pool pool(2); + handler handler_instance; + async_server instance(_address="0.0.0.0", _port="80", _handler=handler_instance, + _io_service=my_io_service, _thread_pool=pool, + _reuse_address=true); + instance.run(); + Public Members `````````````` diff --git a/libs/network/doc/html/_sources/whats_new.txt b/libs/network/doc/html/_sources/whats_new.txt index 89629322d..04b88935b 100644 --- a/libs/network/doc/html/_sources/whats_new.txt +++ b/libs/network/doc/html/_sources/whats_new.txt @@ -4,6 +4,24 @@ What's New ************ +:mod:`cpp-netlib` 0.9 +--------------------- + +* **IMPORTANT BREAKING CHANGE**: By default all compile-time heavy parser + implementations are now compiled to external static libraries. In order to use + :mod:`cpp-netlib` in header-only mode, users must define the preprocessor + macro ``BOOST_NETWORK_NO_LIB`` before including any :mod:`cpp-netlib` header. + This breaks code that relied on the version 0.8.x line where the library is + strictly header-only. +* More consistent message API for client and server messages (request and + response objects). +* Refactoring of internal implementations to allow better separation of concerns + and more manageable coding/documentation. +* Client and Server constructors that support Boost.Parameter named parameters. +* Client and Server cosntructors now take in an optional reference to a Boost.Asio + ``io_service`` to use internally. +* Documentation updates to reflect new APIs. + :mod:`cpp-netlib` 0.8 --------------------- diff --git a/libs/network/doc/html/_static/basic.css b/libs/network/doc/html/_static/basic.css index 69f30d4fb..32630d54c 100644 --- a/libs/network/doc/html/_static/basic.css +++ b/libs/network/doc/html/_static/basic.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- basic theme. * - * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -213,6 +213,24 @@ p.rubric { font-weight: bold; } +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + .align-left { text-align: left; } @@ -395,7 +413,7 @@ dl.glossary dt { } .footnote:target { - background-color: #ffa + background-color: #ffa; } .line-block { @@ -426,6 +444,7 @@ dl.glossary dt { pre { overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ } td.linenos pre { diff --git a/libs/network/doc/html/_static/cpp-netlib.css b/libs/network/doc/html/_static/cpp-netlib.css index 7ee3e7df5..3eed2a246 100644 --- a/libs/network/doc/html/_static/cpp-netlib.css +++ b/libs/network/doc/html/_static/cpp-netlib.css @@ -1,6 +1,6 @@ @import url(https://github.com/reset-fonts-grids.css); -html, body {background-image: url(https://github.com/background.jpg); background-repeat:no-repeat; background-position:right top; background-attachment:fixed} +html, body {background-image: url(https://github.com/orange-background.jpg); background-repeat:no-repeat; background-position:left top; background-attachment:fixed; background-color:black} body {font:12pt "Times New Roman", Lucida, serif; color:black} #custom-doc { width:80%;*width:720px; min-width:720px; max-width:960px; margin:auto; text-align:left; padding-top:16px; margin-top:0} #hd { padding: 4px 0 12px 0} diff --git a/libs/network/doc/html/_static/doctools.js b/libs/network/doc/html/_static/doctools.js index eeea95ea5..8b9bd2c0e 100644 --- a/libs/network/doc/html/_static/doctools.js +++ b/libs/network/doc/html/_static/doctools.js @@ -4,7 +4,7 @@ * * Sphinx JavaScript utilties for all documentation. * - * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/libs/network/doc/html/_static/orange-background.jpg b/libs/network/doc/html/_static/orange-background.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e8ac2b4837c57916988d1d03cc07c2b5491a04af GIT binary patch literal 283722 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�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

nn)DwM7KXi|YJv)>zWxp7=5{0WpLc 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 DGaDVM literal 0 HcmV?d00001 diff --git a/libs/network/doc/html/_static/searchtools.js b/libs/network/doc/html/_static/searchtools.js index 5cbfe004b..dae92b5e5 100644 --- a/libs/network/doc/html/_static/searchtools.js +++ b/libs/network/doc/html/_static/searchtools.js @@ -4,7 +4,7 @@ * * Sphinx JavaScript utilties for the full-text search. * - * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/libs/network/doc/html/_static/sphinxdoc.css b/libs/network/doc/html/_static/sphinxdoc.css index c7e6e335a..0a4280747 100644 --- a/libs/network/doc/html/_static/sphinxdoc.css +++ b/libs/network/doc/html/_static/sphinxdoc.css @@ -5,7 +5,7 @@ * Sphinx stylesheet -- sphinxdoc theme. Originally created by * Armin Ronacher for Werkzeug. * - * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/libs/network/doc/html/directives.html b/libs/network/doc/html/directives.html index 6a1ef4b2e..ba2564ec6 100644 --- a/libs/network/doc/html/directives.html +++ b/libs/network/doc/html/directives.html @@ -7,13 +7,13 @@ - Directives — cpp-netlib v0.8 documentation + Directives — cpp-netlib v0.9 documentation - + - + + +

-

cpp-netlib v0.8 documentation

+

cpp-netlib v0.9 documentation

diff --git a/libs/network/doc/html/searchindex.js b/libs/network/doc/html/searchindex.js index 783d8dc4c..28f5dae08 100644 --- a/libs/network/doc/html/searchindex.js +++ b/libs/network/doc/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({objects:{},terms:{directive_typ:7,all:[15,9,16,17,10,11,20,7,12,23,4,13,14],code:[6,9,16,15,18,10,20,7,21,12,23,24,13,14],skeleton:18,chain:7,illustr:18,queri:[11,19],forbidden:16,lack:24,basic_messag:[4,19,5],four:17,concept:[16,0,17,19,11,7,4,5],lend:7,follow:[15,9,16,17,18,19,10,11,20,7,3,12,23,4,13,21],lookup:4,ptr:15,abid:[11,7],hierarch:19,content:[6,4,16,23],decid:[15,18,24],"const":[9,16,17,10,11,7,23,4],system:[23,7,13,16],range_iter:9,send:[12,16],concret:7,swap:[4,18,19],sens:[9,1,7,23],"_follow_redirect":23,stock_repli:[9,16,10],sent:[23,16],unzip:13,everi:[4,24],risk:13,straightforward:10,fals:[23,16],"void":[15,9,16,17,18,19,10,11,4],multi:10,nich:24,netlib:[0,2,3,4,5,6,7,8,9,10,11,23,13,14,15,16,17,18,19,20,21,12,24],endpoint:23,fan:13,veri:16,affect:23,default_:[15,18,9],exact:9,relev:20,look:[6,9,16,15,18,10,20,7,23,4,13,5],span:5,http_async_serv:16,administr:10,level:[6,13,24],michael:[13,24],upload:16,iter:9,factori:[15,4,7],"try":[20,16,10],vector:[18,11,16],verif:23,cooki:23,refer:[6,9,16,0,19,10,7,23,2,4,13,14],impli:4,tel:19,throught:12,peek:6,natur:7,yourself:13,direct:[6,0,17,11,24,7,12,4,8,5],transform:[4,7],sourceforg:[6,13,24],handler_typ:16,second:[11,9],cost:14,design:3,chang:[9,18,7,23,13,14],pass:[9,16,18,10,20,7,12,23,4],download:[6,13],further:[12,19],port_typ:11,port:[9,16,17,19,10,11,20],even:[4,7,11,17],"_cache_resolv":23,what:[6,16,15,18,10,11,20,23,4,14],msysgit:13,barrier:24,repli:10,section:[9,16,17,11,23,4],advanc:8,abl:[13,16],sln:13,overload:[9,16,10],access:[9,16,17,11,20,7,24],delet:[23,9,12],absolut:19,version:[6,16,15,18,17,19,11,12,23,13,14],directori:[23,13],source_wrapp:4,dsel:7,"new":[6,15,18,19,7,13,14],net:[6,13],boost:[6,9,16,17,1,19,10,18,11,20,12,23,24,13,14],method:[23,11,12,9,10],manag:[23,16,14],xml:20,full:[6,19,13,22,17],deriv:[15,11],whose:18,usag:[12,20,16,10],gener:[15,16,0,19,11,7,23,2,4,24,13,5],never:24,unauthor:16,here:[15,9,16,19,10,12,23],bodi:[6,9,16,17,18,10,11,20,12,23,4],let:[18,20,13,10],argv:[12,20,10],address:[9,16,1,10,20,23],path:[11,9,13,19],along:13,rudimentari:7,modifi:[0,17,11,23,4,5],sinc:[12,18,20],valu:[15,9,16,17,1,10,11,23,4],wait:[23,16],convert:[4,19,11,17],convers:4,shift:7,anymor:18,larger:21,step:[12,13],cert:23,cerr:[20,9,10],behav:23,http_keepalive_8bit_tcp_resolv:[23,1,9],action:16,http_client:[12,9],implement:[6,9,16,0,15,1,17,19,18,11,7,23,4,14,13,5],narrow:[11,17],portabl:24,semant:[6,4,7,16,15],via:[6,20],repositori:[6,13],appli:[4,7],"while":[9,4,24,7,15],multiple_choic:16,expect:23,releas:[6,16,17,11,23,13],unix:[13,19],api:[6,16,0,17,19,11,23,14],famili:18,visibl:9,instal:[6,13,22],gatekeep:13,unit:14,regex:13,argc:[12,20,10],from:[6,9,16,17,18,19,10,11,20,7,12,23,4,13],describ:[23,16,3,19,8],would:[9,16,18,10,4,13],commun:[6,3,24],distinct:16,doubl:19,upgrad:[23,16,14],subvers:13,websit:12,few:13,program:[15,21,24,19,10],call:[9,16,18,10,7,4,13],taken:16,clear_head:[4,11,17],type:[15,9,16,17,18,19,11,7,23,4,24],until:23,minor:[23,11],more:[6,16,4,14,13,24],reachabl:18,chapter:8,headers_rang:[11,9,17],afford:7,smtp:[4,24],swappabl:[4,18,19],relat:16,notic:[18,9],site:13,warn:[23,11,16,17],visual:13,accept:[7,16],known:19,git:[6,13],hold:[23,1,9],unpack:13,cach:23,content_typ:23,must:[13,14],basic_respons:[9,17],none:16,dcmake_c_compil:13,join:[6,13,16],internal_server_error:16,scalabl:16,alia:[13,17],work:[11,13,17],uniqu:15,histori:[6,24],annoi:24,remain:[15,7],tag:[6,9,16,15,1,17,19,11,23,4,14,18,8],can:[6,9,16,15,18,19,10,20,7,21,12,23,4,13],caveat:13,socket:16,fulfil:24,root:[11,18],fetch:23,aliv:[23,1,9,16],proof:16,control:[18,13,16],heart:9,encapsul:[9,1,7,4,23],tar:13,give:16,process:[9,19],lock:16,pthread:[12,20,10],share:[23,1,9,16,10],templat:[6,9,16,15,18,17,19,11,7,23,2,4,24,13,5],high:24,sourc:[6,9,17,10,11,2,4,13,24],want:[15,16,18,20,23,4,13],explos:15,tarbal:13,http_async_8bit_udp_resolv:[23,1,9],serial:16,keep:[15,9,1,7,23,18],unsign:[23,11,9,17],occur:[11,17],string:[6,9,16,17,18,19,10,11,20,12,23,4],low:16,alwai:16,differenti:[16,10],put:[23,9,16],end:[9,24],goal:24,"_send_buffer_s":16,anoth:[16,19],classifi:19,divis:4,how:[18,19,10,20,21,13],scale:16,delete_:23,sever:[16,8],pure:[15,4],subdirectori:12,opt:13,instead:[18,13,16],simpl:[6,9,16,19,10,20,7,12,4],mpl:[18,14],stock:10,resourc:[13,10],dive:[12,20,21,10],earlier:[15,20],hello_world_cli:20,fluid:15,status_messag:17,befor:[23,20,16,14],xzf:13,attent:7,commit:24,mai:[6,9,16,10,23,4,13],multipl:16,data:[9,16,19,20,23,4],parallel:13,util:16,github:[6,19,24,13,23],attempt:[16,14],practic:3,third:10,date_tim:13,light:[6,24],author:[23,19],explicit:4,element:19,issu:[6,13],inform:[6,13,16],"switch":[15,11],maintain:[7,13,16],environ:[13,10],allow:[6,16,15,18,7,12,4,14],mechan:[18,9],order:[12,7,14],talk:[11,17],arg:[23,16],oper:[9,16,17,10,11,7,23,4],composit:18,help:16,xmpp:[4,24],offici:[6,13],move:7,becaus:[15,4,7,16],cross:[6,24],paper:[6,2],through:[11,9,13,16],size_t:16,still:[16,17,18,11,23,13],vari:[15,4,18],dynam:[6,15,16,23,8],paramet:[9,16,17,18,11,7,23,4,13,14],write:[6,20,16,24],typedef:[9,16,18,10,23,4],group:24,fit:16,fix:14,complex:[12,13,19],unsupported_tag:18,better:[16,14],platform:[6,24,13,16],window:13,pend:16,headers_contain:[4,17],whole:[12,18,13,17],zip:13,mail:[6,13],hidden:[23,7],main:[12,20,13,10],might:[18,9],easier:4,"break":[23,15,9,14],non:[4,16,19],multimap:9,"return":[15,9,16,17,1,10,11,20,7,12,23,4,14],greater:[12,10],thei:[9,1,19,23,4,18],handl:[15,16,10],smarter:18,safe:[23,10],initi:[23,24,16,14],devel:[6,13],http_default_8bit_udp_resolv:[23,1,9,11,17],framework:10,facilit:15,now:[17,10,11,23,13,14],discuss:[6,13],nor:4,choic:13,term:[23,4,16],opaqu:[18,19],name:[9,16,17,11,23,4,13,14],realist:3,edit:16,separ:14,easili:24,slide:[6,2],http_server:[11,16,17],timeout:16,each:[23,4,12,13,16],debug:13,found:[6,16,10,12,13,24],higher:[6,13],side:[15,10],mean:[23,4,13,16],compil:[23,16,7,13,14],dcmake_cxx_compil:13,weight:[6,24],list:[6,16,17,18,10,11,13],chunk:16,continu:[16,24],functor:[9,10],realli:20,heavi:[13,14],ensur:[4,18,10],set_statu:16,"static":[6,15,18,7,23,8,14],connect:[6,9,16,15,1,20,12,23],someth:[9,4,7,16,18],our:[18,13,24],happen:23,patch:13,unique_ptr:15,orient:[15,7],special:[15,9,17,18,11,7,4],out:[23,13,16],variabl:13,ftp:[19,24],shown:[23,16],safeti:18,network:[6,9,16,17,18,19,10,11,20,3,12,23,4,24],webservic:20,goe:13,open:24,req:16,predefin:9,profil:16,typenam:[18,4,11,17],adapt:4,rel:19,internet:13,print:[12,9],current:[23,16,19],merg:13,correct:[15,4,9],rational:7,after:[12,16,19],iostream:[12,20,7,10],linear:16,insid:[9,16],watermark:16,my_io_servic:[23,16],manipul:[4,16],situat:[15,7,16],differ:[6,9,16,0,15,18,17,19,11,7,23,4,14,5],free:[4,16],standard:[7,24],standalon:15,reason:13,base:[15,18,19,7,4,13],latest:[6,13],ask:[6,13],org:[6,9,19,12],"byte":16,version_minor:[23,1,9,11],bash:19,netib:23,chose:4,your:[23,9,13,16],suffici:13,thread:[9,16,1,10,23,14],document:[16,0,17,11,20,23,13,14],prescrib:13,synchron:[9,16,0,1,10,23],unavoid:15,thing:[15,17,18,11,12,13],enforc:11,place:16,some_xml_str:20,lifetim:23,assign:[4,16,19],first:[15,9,19,10,11,12,4,13],origin:[18,9],softwar:24,major:[23,11,24],"_openssl_certif":23,directli:[23,16],conform:9,onc:[23,18,12,13,16],independ:[23,7,16],qualiti:24,number:[9,16,1,10,18,11,23,4,13],placehold:18,uri_:9,instruct:13,alreadi:[16,17,11,23,14,24],done:[15,9,16,18,11,4,13],bad_gatewai:16,lboost_system:[12,20,10],lvalu:[4,16],stabl:13,"_reuse_address":16,miss:24,primari:[18,16],size:16,take:[9,16,19,10,7,23,4,14],given:[6,9,16,15,18,17,19,11,4],"long":16,actual:16,com:[6,19,13,20,23],messag:[6,17,11,24,7,12,23,4,14,5],width:23,associ:[18,4,17,11,16],top:[13,24],sometim:[4,18],wrapper:[9,0,17,11,4,5,14],destination_:[11,17],compos:5,time:[7,16,14],interfac:[9,16,0,1,11,7,23],scheme:[11,9,19],zipfil:13,"final":12,boil:7,listen:[16,10],adher:16,udp:[23,1,9],shell:[20,13,10],consol:12,option:[16,24,13,14],especi:16,namespac:[6,9,16,17,18,10,11,20,12,23],tool:[9,13],copi:[23,4,16,19],specifi:[9,16,1,19,12,23,4,13],aptli:9,next:[12,16],appropri:[23,11,17,13,16],pars:[19,9,16,14],mostli:13,than:[18,16],http_version_major:23,serv:18,wide:[11,17],liter:5,john:19,target:[7,24],instanc:[9,16,17,18,19,11,23,4],provid:[6,9,17,1,19,10,11,23,18,24],deanberri:13,remov:[4,11,17],http_client1:12,basic_cli:[23,9],structur:[12,18],charact:23,project:[6,13,24],matter:16,reus:7,not_accept:16,store:[23,4,16],str:20,bind:16,other:[6,16,18,7,23,2,4,24],iterator_rang:16,seri:[3,16],pre:[10,5],"function":[15,9,16,0,18,24,7,23,4,14,5],fashion:7,payload:[4,20],abov:[9,16,1,19,10,18,23,13],pertain:4,add_head:[4,11,17],modern:6,ani:[15,9,16,10,12,23,4,13,14],packag:13,properli:[23,16],manner:[23,11,18,16,17],have:[15,9,16,1,10,18,20,7,12,23,4,13,24],tabl:[23,4,9,16,17],need:[15,16,18,10,3,12,23,13,24],seen:10,dedic:23,well:[4,7,16],repeatedli:24,caus:[23,1,9,18],shared_futur:17,status_t:16,techniqu:[6,18,15,7,8],lib:[12,20,10],callback:16,service_unavail:16,self:7,note:[16,17,19,10,20,23,4,13],also:[6,9,16,15,1,17,10,18,11,7,23,4,13,24],client:[6,9,16,0,1,24,10,21,11,20,3,12,23,14,5],headers_:[9,17],indic:[23,1,9],combin:[15,18],soap:24,singl:[23,12,9,16,10],asio:[23,24,16,14],begin:9,sure:10,distribut:[23,12,24,13,16],plenti:24,normal:[23,11],buffer:[18,16],conncetionptr:16,compress:12,deleg:9,most:[4,16],said:19,abus:7,pair:[11,17],"class":[15,9,16,17,18,19,10,11,7,23,4,5],tradit:13,don:[9,1,18,12,23,13],url:[12,20,13],clear:[23,4],later:16,cover:[4,14],uri:[6,9,15,19,11,2,12,5,14],doe:[16,17,19,10,11,23,4,13],declar:[11,9,17],directive2:7,directive1:7,readcallback:16,usual:[11,7,17],notion:[4,7],came:9,connection_ptr:16,show:[21,20,16,19],awar:24,inherit_linearli:18,syntax:[9,12,2,19,5],concurr:16,radic:14,protocol:[6,19,10,11,20,7,3,12,23,4,24,5],trivial:[9,7],find:[6,13],foo_direct:4,redirect:23,"_address":16,onli:[15,9,16,1,19,18,7,23,13,14],submit:[6,13,24],locat:23,pointer:[23,16],explain:12,response_head:[9,16],solut:13,state:[7,16],makefil:13,should:[15,9,16,18,10,23,4,13],prolong:7,configur:[6,14,13,10],hello_world:10,meant:[18,4,17,11,16],set_head:16,variou:23,get:[6,9,17,18,10,20,12,23,13,24],simplest:12,stop:16,kind:[6,3,15],soon:16,ssl:[23,15],is_base_of:18,mainten:13,progress:6,report:[6,13,16],metafunct:[6,4,18,8],requir:[15,16,17,19,11,4,13,24],embedd:[9,14],receiv:16,enabl:[18,24,13,16],emb:[23,16],ietf:9,applac:16,"_port":16,rfc:[9,2,19,12],"default":[15,9,16,1,12,23,4,18,14],common:[12,4,3,24],contain:[16,17,18,10,7,21,4],status_typ:16,where:[15,9,16,18,11,20,7,23,4,24,14],async_serv:16,"_openssl_verify_path":23,certif:23,set:[15,16,17,10,11,7,3,23,4,5],requesthandl:9,truli:7,"_thread_pool":16,assumpt:9,packet:4,increasingli:24,see:[9,16,1,10,23,18],result:[17,18,19,11,7,4],respons:[6,9,16,0,17,1,10,20,12,23,14],close:[6,12,9,13,16],best:2,concern:14,polymorph:[6,15,8],statu:[17,9,16,10],flexibl:[12,18,7],extend:[18,7,24],correctli:[11,17],"_report_abort":16,pattern:[23,4,7,16,15],review:6,easi:[6,20,24],enumer:10,hpp:[16,18,10,20,12,23],user_info:19,written:[11,17],bridg:15,listinfo:[6,13],between:19,"import":[16,14],awai:16,approach:[15,18],across:[23,10],signatur:16,accord:[4,19],syntact:[4,7],status_message_:17,web:[13,24],cannot:[23,16],comp:19,were:16,hello_world_serv:[20,10],extens:[9,18,7],job:13,preprocessor:[23,14],request_:[6,23],overhaul:14,come:[15,11,7,13,17],endl:[12,20,9,19,10],addit:[15,7,13,19],both:[9,16,17,1,11,21,23],metaprogram:[18,2,13],berri:[13,24],cycl:23,response_:[6,23],howev:[18,9],alon:15,default_wstr:18,against:16,etc:24,handler_inst:16,context:[18,7],logic:[9,4,7,16,12],mani:[23,24,13,14],uint16_t:17,clone:13,among:18,simpli:[9,11,7],publicli:[11,16,17],stream:[23,12,16,14],point:[6,4,18],instanti:16,schedul:16,logic_error:16,dispatch:[15,4,9,18,14],header:[6,9,16,15,18,17,10,11,7,12,23,4,13,14],rpc:20,dcmake_build_typ:13,suppli:[9,16,19],linux:13,comput:[13,16],pod:[4,11],guid:[6,2,13,22],assum:[16,17,11,20,23,4,13],summar:4,mailto:19,question:[6,13],becom:24,creat:[15,16,17,10,11,20,12,13],version_major:[23,1,9,11],"_receive_buffer_s":16,three:[23,4,9,16,5],been:[23,16,24],accessor:[4,11,17],compon:[23,4,21,18,19],much:15,treat:11,modif:4,acceptor:16,strategi:[23,15],bzip:13,basic_uri:[9,19,5],clariti:12,target_typ:7,argument:[9,16,10,12,23,4],assert:[9,19],made:[23,20,16,10],craft:20,understand:16,togeth:24,demand:24,"catch":[20,10],rang:16,synchronoushandl:16,present:[6,12],"case":[15,9,16,17,18,10,11,23,4,13],inhibit:23,therefor:[9,24],rfc1738:9,gnu:13,plain:15,servic:24,properti:[9,4,7,18],commerci:13,act:13,aim:8,defin:[15,9,16,18,19,10,7,23,4,13,14],invok:[16,13,10],boost_root:[12,20,13,10],behavior:[23,18,9,15],error:[12,16],thrash:13,aid:3,invoc:16,anchor:11,loop:16,pack:[23,16],real:18,layer:[6,24,7,15],remove_head:[4,11,17],almost:16,them:[23,11,16,17],destin:[4,11,17],"_non_blocking_io":16,itself:[18,7],motiv:[6,24],new_statu:16,boost_network_enable_http:14,no_cont:16,conn:16,headers_container_typ:[11,17],peopl:6,develop:[6,10,3,12,13,24],welcom:6,minim:14,perform:[16,11,20,23,4,24],suggest:11,make:[6,9,15,1,10,18,20,12,23,13],intermediari:4,same:[15,9,18,10,7,23,13,24],check:[6,12,13,14],member:[15,9,16,0,10,23],fragment:19,when:[15,4,16,24],html:9,http_keepalive_8bit_udp_resolv:[23,1,9],eventu:[6,24],start:[6,18,16,13,23],complet:[12,13],overal:18,http:[6,9,16,0,15,1,17,24,19,10,21,11,20,2,3,12,23,4,14,13,5],hostnam:16,imagin:20,ostringstream:20,nest:[9,16,17,18,11,7,4],chainabl:7,upon:16,effect:[23,11,17],user:[9,16,1,19,7,23,13,14],extern:[23,15,14],typic:[4,9,13],built:[23,12,13,15],underneath:[23,14],lower:[24,14],xjf:13,kept:[16,24],equival:18,choos:[23,4,11,13],entri:24,builder:19,string_typ:[18,11,16,17],facad:14,inherit:18,without:[12,7],person:13,exampl:[6,9,16,18,19,10,20,7,3,12,23,4,13,21],reflect:14,thi:[15,9,16,0,17,1,24,19,10,18,11,20,7,12,23,4,14,13,8],directiven:7,error_cod:16,everyth:19,left:[18,7],load:23,construct:[16,17,19,11,23,4],identifi:[4,19],cout:[12,20,9,19],just:[9,17,18,10,11,20,4,13],object:[6,9,16,15,1,17,10,11,7,12,23,4,24,14],boost_network_no_lib:[23,14],tcp:[23,1,9,15],activ:[23,1,9,24],clear_resolved_cach:23,virtual:15,part:[9,17,19,11,4,14],derived1:15,derived0:15,synchronushandl:16,yet:[18,16],languag:24,previous:[16,10],"_handler":16,struct:[15,9,16,18,10,7,4],expos:16,had:24,except:[15,9,1,10,20,23],littl:[15,18],add:[12,4,17,11,13],is_valid:19,http_default_8bit_tcp_resolv:[23,1,9],versa:4,overview:[19,5],ado:12,adl:[4,18],subsequ:[15,11,17],source_:[11,17],smart:[23,16],build:[6,9,10,20,21,12,13,24],bin:19,applic:[6,16,17,11,20,3,12,23,24,13,21],torvald:13,which:[6,9,16,15,18,19,10,20,7,12,23,4,13],format:7,read:[13,16],wstring:[11,18,17],boost_network_http_server_connection_header_buffer_max_s:16,asynchronoushandl:16,world:[21,16,3,20,10],bit:[11,17],if_:18,resid:[12,9],like:[6,9,16,15,18,10,20,7,23,4,13],specif:[19,10,2,23,4,13],filenam:23,docutil:5,signal:12,echo_serv:9,sstream:20,ipp:10,integ:11,noth:15,collect:24,"boolean":[23,16],necessari:10,either:[4,17,24,11,16],mikhailberi:[6,13],output:19,not_modifi:16,decis:15,depend:[9,16,17,11,23,4,13],underli:[9,4,7,18],encount:[23,16],www:[6,9,19,12],right:[18,16],dean:[13,24],"_linger":16,deal:[15,16,10],simplifi:7,manual:[6,0],status_:17,interact:13,some:[6,16,15,18,17,19,11,8,14],pipelin:16,resolv:[23,1,9],certain:[9,4,7,16,18],intern:[9,16,18,11,23,14],unspecifi:[11,17],sampl:[13,16],inlin:[11,7,18,17],home:[13,24],indirect:[15,7],server:[6,9,16,0,1,24,19,10,21,11,20,3,12,23,14,5],titl:1,librari:[6,15,18,17,11,7,3,23,4,24,13,14],tmp:23,connectionptr:16,not_found:16,lead:7,abort:16,"_io_servic":[23,16],broad:7,though:[15,12],octet:23,achiev:8,"_receive_low_watermark":16,body_:[11,17],tracker:6,larg:[18,16],slash:19,moved_temporarili:16,foo:[15,4,18],localhost:20,mode:14,msvc:14,core:4,who:13,run:[16,10,20,21,12,13,14],power:[13,19],"enum":16,migrat:24,http_statu:16,broken:19,host:[11,19,9,13,10],although:[15,4,18,13,16],http_version_minor:23,post:[23,20,9,12],"throw":[23,16],stage:[12,20,10],session:23,about:[6,16,17,10,11,2,13],central:4,greatli:15,linger:16,memori:[23,24,13,16],slightli:18,page:[6,13],basic_serv:9,stand:19,constructor:[9,16,19,10,12,23,14],bz2:13,input_rang:16,disabl:16,block:[23,1,9,16],wire:7,thread_pool:16,own:[23,16,24],erro:23,cosntructor:14,default_str:18,around:[23,16],within:[13,0,16],encod:[11,17],bound:16,two:[23,11,9,16,10],down:[9,7,19,15],creativ:15,empti:4,wrap:[15,4,17],default_tag:18,updat:14,destructor:15,mere:4,constraint:24,server_:10,string_tag:18,wai:[18,9,16,19],area:4,transfer:16,support:[6,9,16,15,18,17,19,10,11,7,12,23,4,24,13,14],snmp:4,http_async_8bit_tcp_resolv:[23,1,9],fast:6,custom:23,avail:[15,16,23,4,24,13,14],stuck:13,reli:[23,14],handler:[15,14,9,16,10],bad_request:16,includ:[16,17,19,10,11,20,7,12,23,14],lot:[15,13],suit:13,forward:9,submiss:6,strictli:14,repetit:14,individu:13,fork:13,head:[23,9,12],creation:7,gzip:13,form:[9,4,7,18,19],enough:[7,13],linu:13,basic:[4,7],idea:18,link:[6,13,23],translat:18,newer:[23,16],line:[6,19,10,20,12,13,14],icmp:4,"true":[23,16],bug:[13,14],reset:15,pull:13,immedi:[7,16],utf:[11,17],input:[15,7],consist:[6,24,19,14],possibl:[6,12,15],whether:[15,16,19,11,23,4,14],asynchron:[23,16,0,14],not_support:16,below:[9,16,17,19,12,23,13],those:[11,17,8],otherwis:[15,11,13,19],problem:15,similar:[9,16,1,18,20,7,23,4,13],impl:10,significantli:16,version_:17,model:[16,17,11,7,23,4,13],featur:[18,13,24],artifact:13,io_servic:[23,16,14],"int":[15,16,17,10,20,12,23],retriev:[4,19,11,17],"abstract":[15,12,10],parser:[9,19,14],command:[19,13,20,10],deep:7,repres:16,"char":[12,20,16,10],boostcon:[6,2],exist:[23,13,24],"8bit":23,file:[6,16,13,19,23],request:[6,9,16,0,10,11,20,12,23,13,14],sneak:6,face:[23,16],std:[6,9,16,17,18,19,10,11,20,12],fill:23,echo:9,denot:[18,16],readi:[23,14],macro:[23,14],cmake:[6,13],infosystem:19,nonetheless:4,"7zip":13,todo:7,client_:[6,23],excel:24,detail:[9,16,17,1,10,11,12,23,4],refactor:14,event:16,finish:[23,16],valid:[4,9],bool:[23,16],futur:[6,9,16,17,1,19,23],branch:13,trait:[18,17],test:[13,14],you:[6,9,16,15,18,10,20,12,23,13],runtim:15,intend:[6,16,13,23],determin:[18,9,16],fulli:[23,24],subdivid:19,sequenc:23,introduc:23,source_typ:4,gcc:13,"_linger_timeout":16,definit:[18,4,19,11,16],"public":[9,16,0],intent:24,embed:[21,16,10],pool:[16,14],svn:13,moved_perman:16,studio:13,vice:4,argpack:[23,16],info:19,descript:[9,16,17,1,19,11,23,4],microsoft:13,not_impl:16,basic_request:[11,9],depth:[6,5],ignor:18,fact:12,potenti:16,tcp_resolv:23,cpp:[0,2,3,4,5,6,7,8,9,10,11,23,13,14,15,16,17,18,19,20,21,12,24],invari:18,hello:[21,16,3,20,10],legend:[4,17,11,19,16]},objtypes:{},titles:["Reference Manual","<no title>","References","Examples","The message template","An in-depth look at the cpp-netlib","C++ Network Library","Directives","Techniques","HTTP implementation","“Hello world” HTTP server","HTTP Request","HTTP client","Getting Started","What’s New","Static and dynamic polymorphism","HTTP Server API","HTTP Response","Tag metafunctions","The URI template","“Hello world” HTTP client","HTTP examples","Full installation guide","HTTP Client API","Project history"],objnames:{},filenames:["reference","http_client_tags","references","examples","message","in_depth","index","directives","techniques","http","hello_world_server","reference_http_request","http_client","getting_started","whats_new","polymorphism","reference_http_server","reference_http_response","tag_metafunctions","uri","hello_world_client","examples_http","install","reference_http_client","history"]}) \ No newline at end of file +Search.setIndex({objects:{},terms:{directive_typ:7,all:[15,9,16,17,10,11,20,7,12,23,4,13,14],code:[6,9,16,15,18,10,20,7,21,12,23,24,13,14],skeleton:18,chain:7,illustr:18,queri:[11,19],forbidden:16,lack:24,icmp:4,basic_messag:[6,4,19,5],four:17,concept:[6,16,0,17,19,11,7,4,5],follow:[15,9,16,17,18,19,10,11,20,7,3,12,23,4,13,21],ptr:15,abid:[11,7],hierarch:19,whose:18,decid:[15,18,24],"const":[6,9,16,17,10,11,7,23,4],bzip:13,range_iter:9,send:[12,16],concret:7,swap:[4,18,19],string_tag:18,sens:[9,1,7,23],set:[15,16,17,10,11,7,3,23,4,5],"_follow_redirect":23,stock_repli:[6,9,16,10],sent:[23,16],unzip:13,everi:[4,24],risk:13,straightforward:10,fals:[23,16],"void":[6,9,16,15,18,17,19,10,11,4],inhibit:23,nich:24,netlib:[0,2,3,4,5,6,7,8,9,10,11,23,13,14,15,16,17,18,19,20,21,12,24],endpoint:23,fan:13,veri:16,affect:23,default_:[15,18,9],exact:9,relev:20,rfc1738:9,http_async_serv:16,administr:10,level:[6,13,24],michael:[13,24],upload:16,iter:9,correct:[15,4,9],"try":[20,16,10],vector:[18,11,16],verif:23,cooki:23,still:[16,17,18,11,23,13],impli:4,tel:19,throught:12,core:4,natur:7,direct:[6,0,17,11,24,7,12,4,8,5],commerci:13,handler_typ:16,second:[11,9],cost:14,design:3,pass:[9,16,18,10,20,7,12,23,4],download:[6,13],further:[12,19],port_typ:11,port:[9,16,17,19,10,11,20],even:[4,7,11,17],"_cache_resolv":23,what:[6,16,15,18,10,11,20,23,4,14],msysgit:13,insid:[9,16],repli:10,section:[9,16,17,11,23,4],watermark:16,abl:[13,16],invok:[16,13,10],overload:[9,16,10],access:[9,16,17,11,20,7,24],delet:[23,9,12],version:[6,16,15,18,17,19,11,12,23,13,14],source_wrapp:4,underneath:[23,14],"new":[6,15,18,19,7,13,14],net:[6,13],liter:5,boost:[6,9,16,17,1,19,10,18,11,20,12,23,24,13,14],method:[23,11,12,9,10],manag:[23,16,14],redirect:23,full:[6,19,13,22,17],deriv:[15,11],"_address":16,gener:[6,16,0,15,19,11,7,23,2,4,24,13,5],never:24,unauthor:16,here:[15,9,16,19,10,12,23],bodi:[6,9,16,17,18,10,11,20,12,23,4],let:[18,20,13,10],free:[4,16],address:[9,16,1,10,20,23],path:[11,9,13,19],along:13,rudimentari:7,modifi:[6,0,17,11,23,4,5],sinc:[12,18,20],valu:[15,9,16,17,1,10,11,23,4],wait:[23,16],convert:[4,19,11,17],convers:4,shift:7,anymor:18,larger:21,host:[11,19,9,13,10],anchor:11,cert:23,base:[15,18,19,7,4,13],cerr:[6,20,9,10],behav:23,http_keepalive_8bit_tcp_resolv:[23,1,9],action:16,http_client:[12,9],chang:[9,18,7,23,13,14],narrow:[11,17],portabl:24,semant:[6,4,7,16,15],via:[6,20],although:[15,4,18,13,16],appli:[4,7],multiple_choic:16,put:[23,9,16],unix:[13,19],api:[6,16,0,17,19,11,23,14],famili:18,visibl:9,instal:[6,13,22],post:[23,20,9,12],unit:14,regex:13,version_minor:[23,1,9,11],from:[6,9,16,17,18,19,10,11,20,7,12,23,4,13],describ:[23,16,3,19,8],zip:13,commun:[6,3,24],distinct:16,doubl:19,upgrad:[23,16,14],subvers:13,websit:12,few:13,program:[15,21,24,19,10],call:[9,16,18,10,7,4,13],taken:16,clear_head:[4,11,17],type:[15,9,16,17,18,19,11,7,23,4,24],until:23,minor:[23,11],more:[6,16,4,14,13,24],reachabl:18,wrapper:[6,9,0,17,11,4,14,5],headers_rang:[11,9,17],afford:7,smtp:[4,24],swappabl:[4,18,19],relat:16,notic:[18,9],site:13,warn:[23,11,16,17],visual:13,depth:[6,5],accept:[7,16],known:19,actual:16,hold:[23,1,9],unpack:13,cach:23,content_typ:23,must:[13,14],placehold:18,none:16,dcmake_c_compil:13,join:[6,13,16],internal_server_error:16,scalabl:16,alia:[13,17],work:[11,13,17],uniqu:15,histori:[6,24],annoi:24,remain:[15,7],tag:[6,9,16,15,1,17,19,11,23,4,14,18,8],can:[6,9,16,15,18,19,10,20,7,21,12,23,4,13],caveat:13,root:[11,18],fetch:23,aliv:[23,1,9,16],proof:16,control:[18,13,16],heart:9,encapsul:[9,1,7,4,23],tar:13,give:16,process:[9,19],lock:16,no_cont:16,share:[23,1,9,16,10],sln:13,templat:[6,9,16,15,18,17,19,11,7,23,2,4,24,13,5],high:24,sourc:[6,9,17,10,11,2,4,13,24],want:[15,16,18,20,23,4,13],explos:15,tarbal:13,http_async_8bit_udp_resolv:[23,1,9],serial:16,unavoid:15,unsign:[23,11,9,17],occur:[11,17],string:[6,9,16,17,18,19,10,11,20,12,23,4],low:16,alwai:16,differenti:[16,10],end:[9,24],goal:24,anoth:[16,19],classifi:19,write:[6,20,16,24],how:[18,19,10,20,21,13],conn:16,pure:[15,4],subdirectori:12,opt:13,instead:[18,13,16],greatli:15,simpl:[6,9,16,19,10,20,7,12,4],mpl:[18,14],stock:10,resourc:[13,10],dive:[12,20,21,10],earlier:[15,20],hello_world_cli:20,constraint:24,status_messag:17,befor:[23,20,16,14],xzf:13,attent:7,mai:[6,9,16,10,23,4,13],multipl:16,data:[9,16,19,20,23,4],parallel:13,util:16,github:[6,19,24,13,23],attempt:[16,14],practic:3,third:10,date_tim:13,opaqu:[18,19],valid:[4,9],minim:14,explicit:4,element:19,issu:[6,13],inform:[6,13,16],"switch":[15,11],maintain:[7,13,16],environ:[13,10],allow:[6,16,15,18,7,12,4,14],mechan:[18,9],order:[12,7,14],talk:[11,17],origin:[18,9],composit:18,help:16,xmpp:[4,24],offici:[6,13],move:7,becaus:[15,4,7,16],intermediari:4,paper:[6,2],through:[11,9,13,16],left:[18,7],size_t:16,flexibl:[12,18,7],vari:[15,4,18],dynam:[6,15,16,23,8],paramet:[9,16,17,18,11,7,23,4,13,14],divis:4,typedef:[6,9,16,18,10,23,4],group:24,fit:16,fix:14,conncetionptr:16,unsupported_tag:18,better:[16,14],platform:[6,24,13,16],window:[6,13],pend:16,bin:19,mail:[6,13],hidden:[23,7],main:[6,20,12,13,10],might:[18,9],easier:4,non:[4,16,19],multimap:9,"return":[15,9,16,17,1,10,11,20,7,12,23,4,14],greater:[12,10],thei:[9,1,19,23,4,18],handl:[15,16,10],smarter:18,safe:[23,10],initi:[23,24,16,14],devel:[6,13],"break":[23,15,9,14],framework:10,facilit:15,now:[17,10,11,23,13,14],discuss:[6,13],nor:4,choic:13,term:[23,4,16],eventu:[6,24],mere:4,name:[9,16,17,11,23,4,13,14],realist:3,edit:16,separ:14,easili:24,slide:[6,2],exampl:[6,9,16,18,19,10,20,7,3,12,23,4,13,21],submit:[6,13,24],http_server:[6,11,16,17],timeout:16,each:[23,4,12,13,16],debug:13,fulli:[23,24],complet:[12,13],side:[15,10],mean:[23,4,13,16],compil:[23,16,7,13,14],dcmake_cxx_compil:13,weight:[6,24],applac:16,list:[6,16,17,18,10,11,13],chunk:16,continu:[16,24],functor:[9,10],realli:20,heavi:[13,14],wrap:[15,4,17],set_statu:16,"static":[6,15,18,7,23,8,14],expect:23,default_tag:18,our:[18,13,24],happen:23,"_port":16,unique_ptr:15,orient:[15,7],special:[6,9,15,18,17,11,7,4],out:[23,13,16],variabl:13,ftp:[19,24],shown:[23,16],safeti:18,network:[6,9,16,17,18,19,10,11,20,3,12,23,4,24],webservic:20,goe:13,tcp_resolv:23,req:16,rational:7,content:[6,4,16,23],typenam:[18,4,11,17],adapt:4,rel:19,internet:13,print:[12,9],current:[23,16,19],factori:[15,4,7],model:[16,17,11,7,23,4,13],after:[12,16,19],iostream:[12,20,7,10],linear:16,barrier:24,advanc:8,my_io_servic:[23,16],manipul:[4,16],situat:[15,7,16],given:[6,9,16,15,18,17,19,11,4],argv:[6,20,12,10],sneak:6,significantli:16,standalon:15,reason:13,git:[6,13],releas:[6,16,17,11,23,13],org:[6,9,19,12],"byte":16,argc:[12,20,10],bash:19,netib:23,wai:[18,9,16,19],thread:[9,16,1,10,23,14],prescrib:13,synchron:[6,9,16,0,1,10,23],keep:[15,9,1,7,23,18],thing:[15,17,18,11,12,13],enforc:11,place:16,some_xml_str:20,lifetim:23,assign:[4,16,19],first:[15,9,19,10,11,12,4,13],oper:[6,9,16,17,10,11,7,23,4],softwar:24,major:[23,11,24],"_openssl_certif":23,directli:[23,16],certif:23,onc:[23,18,12,13,16],independ:[23,7,16],qualiti:24,number:[9,16,1,10,18,11,23,4,13],yourself:13,uri_:9,instruct:13,alreadi:[16,17,11,23,14,24],done:[15,9,16,18,11,4,13],bad_gatewai:16,lboost_system:[12,20,10],stabl:13,"_reuse_address":16,open:24,payload:[4,20],size:16,differ:[6,9,16,0,15,18,17,19,11,7,23,4,14,5],width:23,associ:[18,4,17,11,16],top:[13,24],system:[23,7,13,16],messag:[6,17,11,24,7,12,23,4,14,5],destination_:[11,17],bad_request:16,scheme:[11,9,19],zipfil:13,"final":12,boil:7,listen:[16,10],adher:16,udp:[23,1,9],shell:[20,13,10],consol:12,option:[16,24,13,14],especi:16,namespac:[6,9,16,17,18,10,11,20,12,23],tool:[9,13],copi:[23,4,16,19],specifi:[9,16,1,19,12,23,4,13],aptli:9,xjf:13,pars:[19,9,16,14],mostli:13,review:6,than:[18,16],http_version_major:23,serv:18,wide:[11,17],kind:[6,3,15],john:19,target:[7,24],provid:[6,9,17,1,19,10,11,23,18,24],remov:[4,11,17],http_client1:12,basic_cli:[23,9],structur:[12,18],charact:23,project:[6,13,24],matter:16,reus:7,not_accept:16,store:[23,4,16],str:20,light:[6,24],iterator_rang:16,seri:[3,16],pre:[10,5],fork:13,fashion:7,comput:[13,16],behavior:[23,18,9,15],facad:14,add_head:[4,11,17],sometim:[4,18],ani:[15,9,16,10,12,23,4,13,14],packag:13,properli:[23,16],manner:[23,11,18,16,17],have:[15,9,16,1,10,18,20,7,12,23,4,13,24],tabl:[23,4,9,16,17],need:[15,16,18,10,3,12,23,13,24],seen:10,dedic:23,repeatedli:24,caus:[23,1,9,18],shared_futur:17,status_t:16,techniqu:[6,18,15,7,8],lib:[12,20,10],callback:16,directiven:7,self:7,expos:16,note:[16,17,19,10,20,23,4,13],also:[6,9,16,15,1,17,10,18,11,7,23,4,13,24],without:[12,7],decis:15,headers_:[9,17],indic:[23,1,9],combin:[15,18],concern:14,soap:24,singl:[23,12,9,16,10],asio:[23,24,16,14],begin:9,sure:10,distribut:[23,12,24,13,16],plenti:24,normal:[23,11],buffer:[18,16],who:13,compress:12,deleg:9,most:[4,16],wire:7,abus:7,pair:[11,17],bz2:13,"class":[15,9,16,17,18,19,10,11,7,23,4,5],three:[23,4,9,16,5],tradit:13,todo:7,don:[9,1,18,12,23,13],url:[12,20,13],clear:[23,4],later:16,cover:[4,14],uri:[6,9,15,19,11,2,12,5,14],doe:[16,17,19,10,11,23,4,13],declar:[11,9,17],directive2:7,directive1:7,readcallback:16,usual:[11,7,17],microsoft:13,came:9,connection_ptr:16,show:[21,20,16,19],awar:24,inherit_linearli:18,concurr:16,syntax:[6,9,19,2,12,5],session:23,migrat:24,radic:14,identifi:[4,19],trivial:[9,7],find:[6,13],foo_direct:4,xml:20,absolut:19,onli:[15,9,16,1,19,18,7,23,13,14],bind:16,locat:23,pointer:[23,16],explain:12,response_head:[9,16],solut:13,written:[11,17],should:[15,9,16,18,10,23,4,13],prolong:7,configur:[6,14,13,10],hello_world:10,meant:[18,4,17,11,16],set_head:16,variou:23,get:[6,9,17,18,10,20,12,23,13,24],between:19,stop:16,fluid:15,soon:16,ssl:[23,15],is_base_of:18,mainten:13,"import":[16,14],report:[6,13,16],metafunct:[6,4,18,8],requir:[15,16,17,19,11,4,13,24],embedd:[9,14],receiv:16,enabl:[18,24,13,16],had:24,emb:[23,16],ietf:9,"_send_buffer_s":16,ipp:10,excel:24,entri:24,patch:13,rfc:[9,2,19,12],whether:[15,16,19,11,23,4,14],common:[12,4,3,24],contain:[16,17,18,10,7,21,4],status_typ:16,where:[15,9,16,18,11,20,7,23,4,24,14],async_serv:16,conform:9,lvalu:[4,16],primari:[18,16],requesthandl:9,truli:7,invari:18,"_thread_pool":16,accord:[4,19],packet:4,derived1:15,see:[9,16,1,10,23,18],result:[17,18,19,11,7,4],arg:[6,16,23],close:[6,12,9,13,16],retriev:[4,19,11,17],best:2,chose:4,polymorph:[6,15,8],statu:[17,9,16,10],said:19,status_message_:17,correctli:[11,17],"_report_abort":16,pattern:[23,4,7,16,15],someth:[9,4,7,16,18],enumer:10,user_info:19,state:[7,16],bridg:15,listinfo:[6,13],simplest:12,progress:6,awai:16,approach:[15,18],across:[23,10],signatur:16,assumpt:9,handler_:6,predefin:9,syntact:[4,7],extend:[18,7,24],"_handler":16,cannot:[23,16],ask:[6,13],were:16,hello_world_serv:[20,10],extens:[9,18,7],job:13,preprocessor:[23,14],request_:[6,23],overhaul:14,headers_contain:[4,17],endl:[12,20,9,19,10],addit:[15,7,13,19],both:[9,16,17,1,11,21,23],metaprogram:[6,18,2,13],berri:[13,24],cycl:23,response_:[6,23],howev:[18,9],alon:15,default_wstr:18,against:16,constructor:[9,16,19,10,12,23,14],etc:24,instanc:[9,16,17,18,19,11,23,4],present:[6,12],context:[18,7],logic:[9,4,7,16,12],bool:[23,16],mani:[23,24,13,14],whole:[12,18,13,17],clone:13,among:18,simpli:[9,11,7],publicli:[11,16,17],stream:[23,12,16,14],point:[6,4,18],instanti:16,schedul:16,logic_error:16,dispatch:[15,4,9,18,14],header:[6,9,16,15,18,17,10,11,7,12,23,4,13,14],rpc:20,littl:[15,18],suppli:[9,16,19],pod:[4,11],guid:[6,2,13,22],assum:[16,17,11,20,23,4,13],summar:4,mailto:19,becom:24,io_servic:[23,16,14],version_major:[23,1,9,11],"_receive_buffer_s":16,handler_inst:16,compos:5,been:[23,16,24],accessor:[4,11,17],compon:[23,4,21,18,19],destructor:15,much:15,treat:11,modif:4,individu:13,acceptor:16,strategi:[23,15],modern:6,bit:[11,17],immedi:[7,16],basic_uri:[6,9,19,5],clariti:12,target_typ:7,argument:[9,16,10,12,23,4],assert:[9,19],craft:20,understand:16,togeth:24,demand:24,"catch":[20,10],rang:16,repres:16,synchronoushandl:16,resid:[12,9],standard:[7,24],"case":[15,9,16,17,18,10,11,23,4,13],multi:10,therefor:[9,24],look:[6,9,16,15,18,10,20,7,23,4,13,5],gnu:13,deanberri:13,servic:24,properti:[9,4,7,18],sourceforg:[6,13,24],aim:8,defin:[15,9,16,18,19,10,7,23,4,13,14],"while":[9,4,24,7,15],smart:[23,16],abov:[9,16,1,19,10,18,23,13],error:[6,16,12],thrash:13,aid:3,invoc:16,pertain:4,loop:16,pack:[23,16],real:18,layer:[6,24,7,15],would:[9,16,18,10,4,13],almost:16,them:[23,11,16,17],destin:[4,11,17],"_non_blocking_io":16,itself:[18,7],motiv:[6,24],new_statu:16,boost_network_enable_http:14,pthread:[12,20,10],sever:[16,8],headers_container_typ:[11,17],develop:[6,10,3,12,13,24],welcom:6,author:[23,19],perform:[16,11,20,23,4,24],suggest:11,make:[6,9,15,1,10,18,20,12,23,13],cross:[6,24],same:[15,9,18,10,7,23,13,24],check:[6,12,13,14],member:[6,9,16,0,15,10,23],fragment:19,complex:[12,13,19],http_keepalive_8bit_udp_resolv:[23,1,9],come:[15,11,7,13,17],document:[16,0,17,11,20,23,13,14],start:[6,18,16,13,23],higher:[6,13],overal:18,http:[6,9,16,0,15,1,17,24,19,10,21,11,20,2,3,12,23,4,14,13,5],hostnam:16,http_version_minor:23,imagin:20,nest:[9,16,17,18,11,7,4],chainabl:7,upon:16,effect:[23,11,17],user:[9,16,1,19,7,23,13,14],extern:[23,15,14],build:[6,9,10,20,21,12,13,24],respons:[6,9,16,0,17,1,10,20,12,23,14],typic:[4,9,13],built:[23,12,13,15],http_default_8bit_udp_resolv:[23,1,9,11,17],lower:[24,14],appropri:[23,11,17,13,16],kept:[16,24],equival:18,choos:[23,4,11,13],com:[6,19,13,20,23],builder:19,string_typ:[6,11,18,16,17],well:[4,7,16],inherit:18,person:13,client:[6,9,16,0,1,24,10,21,11,20,3,12,23,14,5],reflect:14,thi:[15,9,16,0,17,1,24,19,10,18,11,20,7,12,23,4,14,13,8],service_unavail:16,error_cod:16,everyth:19,latest:[6,13],load:23,construct:[16,17,19,11,23,4],protocol:[6,19,10,11,20,7,3,12,23,4,24,5],cout:[12,20,9,19],just:[9,17,18,10,11,20,4,13],object:[6,9,16,15,1,17,10,11,7,12,23,4,24,14],boost_network_no_lib:[23,14],tcp:[23,1,9,15],activ:[23,1,9,24],clear_resolved_cach:23,refactor:14,increasingli:24,derived0:15,yet:[18,16],languag:24,previous:[16,10],web:[13,24],struct:[6,9,16,15,18,10,7,4],easi:[6,20,24],snmp:4,makefil:13,except:[15,9,1,10,20,23],dcmake_build_typ:13,add:[12,4,17,11,13],is_valid:19,http_default_8bit_tcp_resolv:[23,1,9],versa:4,overview:[6,19,5],trait:[18,17],ado:12,adl:[4,18],subsequ:[15,11,17],source_:[11,17],boost_root:[12,20,13,10],take:[9,16,19,10,7,23,4,14],dsel:7,applic:[6,16,17,11,20,3,12,23,24,13,21],torvald:13,which:[6,9,16,15,18,19,10,20,7,12,23,4,13],format:7,read:[13,16],wstring:[11,18,17],boost_network_http_server_connection_header_buffer_max_s:16,asynchronoushandl:16,world:[6,16,10,20,21,3],part:[9,17,19,11,4,14],linux:[6,13],if_:18,mikhailberi:[6,13],like:[15,9,16,18,10,20,7,23,4,13],specif:[19,10,2,23,4,13],filenam:23,uint16_t:17,signal:12,echo_serv:9,sstream:20,html:9,integ:11,noth:15,collect:24,"boolean":[23,16],necessari:10,either:[4,17,24,11,16],docutil:5,http_async_8bit_tcp_resolv:[23,1,9],output:19,mode:14,not_modifi:16,depend:[9,16,17,11,23,4,13],fulfil:24,encount:[23,16],www:[6,9,19,12],right:[18,16],dean:[13,24],"_linger":16,deal:[15,16,10],simplifi:7,manual:[6,0],status_:17,interact:13,some:[6,16,15,18,17,19,11,8,14],pipelin:16,resolv:[23,1,9],intern:[9,16,18,11,23,14],unspecifi:[11,17],sampl:[13,16],home:[13,24],indirect:[15,7],server:[6,9,16,0,1,24,19,10,21,11,20,3,12,23,14,5],librari:[6,15,18,17,11,7,3,23,4,24,13,14],tmp:23,basic_serv:9,connectionptr:16,scale:16,lead:7,abort:16,"_io_servic":[23,16],broad:7,though:[15,12],octet:23,achiev:8,"_receive_low_watermark":16,body_:[11,17],tracker:6,larg:[18,16],slash:19,moved_temporarili:16,foo:[15,4,18],localhost:20,refer:[6,9,16,0,19,10,7,23,2,4,13,14],msvc:14,peek:6,command:[19,13,20,10],run:[6,16,10,20,21,12,13,14],power:[13,19],"enum":16,usag:[12,20,16,10],fast:6,http_statu:16,broken:19,step:[12,13],repositori:[6,13],found:[6,16,10,12,13,24],gatekeep:13,"throw":[23,16],stage:[12,20,10],chapter:8,about:[6,16,17,10,11,2,13],central:4,socket:16,linger:16,memori:[23,24,13,16],slightli:18,page:[6,13],delete_:23,stand:19,act:13,commit:24,comp:19,input_rang:16,disabl:16,block:[23,1,9,16],underli:[9,4,7,18],thread_pool:16,own:[23,16,24],erro:23,cosntructor:14,default_str:18,around:[23,16],within:[13,0,16],encod:[11,17],bound:16,two:[23,11,9,16,10],down:[9,7,19,15],creativ:15,empti:4,ensur:[4,18,10],synchronushandl:16,updat:14,next:[12,16],your:[23,9,13,16],merg:13,client_:[6,23],server_:[6,10],span:5,log:6,suffici:13,area:4,transfer:16,support:[6,9,16,15,18,17,19,10,11,7,12,23,4,24,13,14],question:[6,13],transform:[4,7],"long":16,custom:23,avail:[15,16,23,4,24,13,14],stuck:13,reli:[23,14],plain:15,interfac:[9,16,0,1,11,7,23],includ:[16,17,19,10,11,20,7,12,23,14],lot:[15,13],suit:13,forward:9,submiss:6,strictli:14,repetit:14,remove_head:[4,11,17],"function":[6,9,16,0,15,18,24,7,23,4,14,5],head:[23,9,12],creation:7,gzip:13,form:[9,4,7,18,19],enough:[7,13],handler:[6,9,16,15,10,14],linu:13,basic:[4,7],idea:18,link:[6,13,23],translat:18,newer:[23,16],line:[6,19,10,20,12,13,14],inlin:[11,7,18,17],"true":[23,16],bug:[13,14],reset:15,pull:13,made:[23,20,16,10],utf:[11,17],input:[15,7],consist:[6,24,19,14],possibl:[6,12,15],"default":[15,9,16,1,12,23,4,18,14],asynchron:[6,14,16,0,23],not_support:16,below:[9,16,17,19,12,23,13],argpack:[23,16],those:[11,17,8],otherwis:[15,11,13,19],problem:15,similar:[9,16,1,18,20,7,23,4,13],impl:10,connect:[6,9,16,15,1,20,12,23],version_:17,featur:[18,13,24],artifact:13,creat:[15,16,17,10,11,20,12,13],"int":[6,16,15,17,10,20,12,23],certain:[9,4,7,16,18],"abstract":[15,12,10],parser:[9,19,14],ostringstream:20,deep:7,"_openssl_verify_path":23,"char":[6,20,12,16,10],boostcon:[6,2],implement:[6,9,16,0,15,1,17,19,18,11,7,23,4,14,13,5],"8bit":23,file:[6,16,13,19,23],request:[6,9,16,0,10,11,20,12,23,13,14],exist:[23,13,24],face:[23,16],std:[6,9,16,17,18,19,10,11,20,12],fill:23,echo:9,denot:[18,16],readi:[23,14],macro:[23,14],cmake:[6,13],infosystem:19,nonetheless:4,"7zip":13,titl:1,hpp:[16,18,10,20,12,23],when:[15,4,16,24],detail:[9,16,17,1,10,11,12,23,4],virtual:15,event:16,finish:[23,16],other:[6,16,18,7,23,2,4,24],lookup:4,futur:[6,9,16,17,1,19,23],branch:13,peopl:6,test:[13,14],you:[6,9,16,15,18,10,20,12,23,13],runtim:15,miss:24,intend:[6,16,13,23],determin:[18,9,16],lend:7,subdivid:19,sequenc:23,introduc:23,source_typ:4,gcc:13,"_linger_timeout":16,definit:[18,4,19,11,16],"public":[9,16,0],intent:24,embed:[21,16,10],not_found:16,pool:[16,14],svn:13,moved_perman:16,studio:13,vice:4,directori:[23,13],info:[6,19],descript:[9,16,17,1,19,11,23,4],notion:[4,7],not_impl:16,basic_request:[11,9],basic_respons:[9,17],ignor:18,fact:12,potenti:16,time:[7,16,14],cpp:[0,2,3,4,5,6,7,8,9,10,11,23,13,14,15,16,17,18,19,20,21,12,24],profil:16,hello:[6,16,10,20,21,3],legend:[4,17,11,19,16]},objtypes:{},titles:["Reference Manual","<no title>","References","Examples","The message template","An in-depth look at the cpp-netlib","C++ Network Library","Directives","Techniques","HTTP implementation","“Hello world” HTTP server","HTTP Request","HTTP client","Getting Started","What’s New","Static and dynamic polymorphism","HTTP Server API","HTTP Response","Tag metafunctions","The URI template","“Hello world” HTTP client","HTTP examples","Full installation guide","HTTP Client API","Project history"],objnames:{},filenames:["reference","http_client_tags","references","examples","message","in_depth","index","directives","techniques","http","hello_world_server","reference_http_request","http_client","getting_started","whats_new","polymorphism","reference_http_server","reference_http_response","tag_metafunctions","uri","hello_world_client","examples_http","install","reference_http_client","history"]}) \ No newline at end of file diff --git a/libs/network/doc/html/tag_metafunctions.html b/libs/network/doc/html/tag_metafunctions.html index a70fd1a0f..48e65d2ce 100644 --- a/libs/network/doc/html/tag_metafunctions.html +++ b/libs/network/doc/html/tag_metafunctions.html @@ -214,9 +214,8 @@

Using Tags - + - +

diff --git a/libs/network/doc/html/techniques.html b/libs/network/doc/html/techniques.html index 653cf769e..35780c9d6 100644 --- a/libs/network/doc/html/techniques.html +++ b/libs/network/doc/html/techniques.html @@ -77,9 +77,8 @@

Techniques - + - +

diff --git a/libs/network/doc/html/uri.html b/libs/network/doc/html/uri.html index 7235687d4..e7556f641 100644 --- a/libs/network/doc/html/uri.html +++ b/libs/network/doc/html/uri.html @@ -84,7 +84,7 @@

Generic URI Syntax Overview":" to be a part of the path:

-_images/mailto_uri.png +_images/mailto_uri2.png

A hierarchical URI is identified by a double slash ("//") after the scheme and a scheme-specific component, which RFC 3986 defines to be:

@@ -99,10 +99,10 @@

Generic URI Syntax Overview +_images/ftp_uri2.png

Note that the authority is further subdivided into different elements. Another example, using HTTP is given below:

-_images/http_uri.png +_images/http_uri2.png

The difference here between the path in a hierarchical URI and that in the example above for the non-hierarchical URI.

@@ -217,9 +217,8 @@

URI - - diff --git a/libs/network/doc/html/whats_new.html b/libs/network/doc/html/whats_new.html index 097cac1b7..fe8325687 100644 --- a/libs/network/doc/html/whats_new.html +++ b/libs/network/doc/html/whats_new.html @@ -128,9 +128,8 @@

cpp-netlib - - From b3dc2902dfa8c568a65969dd654427e35da799f5 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 18 Apr 2011 21:55:39 +1000 Subject: [PATCH 111/768] Adding missing images. --- libs/network/doc/html/_images/boost6.png | Bin 0 -> 13364 bytes libs/network/doc/html/_images/boost7.png | Bin 0 -> 13364 bytes libs/network/doc/html/_images/ftp_uri2.png | Bin 0 -> 25570 bytes libs/network/doc/html/_images/http_uri2.png | Bin 0 -> 20719 bytes libs/network/doc/html/_images/mailto_uri2.png | Bin 0 -> 10220 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 libs/network/doc/html/_images/boost6.png create mode 100644 libs/network/doc/html/_images/boost7.png create mode 100644 libs/network/doc/html/_images/ftp_uri2.png create mode 100644 libs/network/doc/html/_images/http_uri2.png create mode 100644 libs/network/doc/html/_images/mailto_uri2.png diff --git a/libs/network/doc/html/_images/boost6.png b/libs/network/doc/html/_images/boost6.png new file mode 100644 index 0000000000000000000000000000000000000000..0714ca2004bbf91389d33166afc449cba84b39be GIT binary patch literal 13364 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 literal 0 HcmV?d00001 diff --git a/libs/network/doc/html/_images/boost7.png b/libs/network/doc/html/_images/boost7.png new file mode 100644 index 0000000000000000000000000000000000000000..0714ca2004bbf91389d33166afc449cba84b39be GIT binary patch literal 13364 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 literal 0 HcmV?d00001 diff --git a/libs/network/doc/html/_images/ftp_uri2.png b/libs/network/doc/html/_images/ftp_uri2.png new file mode 100644 index 0000000000000000000000000000000000000000..f77d3c87b891e86d794e2ee60255b1f95baf2ddc GIT binary patch literal 25570 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 c6AV1V Date: Mon, 25 Apr 2011 01:34:04 +1000 Subject: [PATCH 112/768] Fixes #40 : Write headers and status in one packet This commit removes the additional call to write when an HTTP response is written out from the asynchronous server that causes browsers to choke when the status line does not come with the headers in a single frame. --- .../protocol/http/server/async_connection.hpp | 96 +++++-------------- 1 file changed, 24 insertions(+), 72 deletions(-) diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index 1f566f2ff..9d3b46aa6 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -140,9 +140,7 @@ namespace boost { namespace network { namespace http { , handler(handler) , thread_pool_(thread_pool) , headers_already_sent(false) - , first_line_already_sent(false) , headers_in_progress(false) - , first_line_in_progress(false) , headers_buffer(BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE) { new_start = read_buffer_.begin(); @@ -167,26 +165,30 @@ namespace boost { namespace network { namespace http { template void set_headers(Range headers) { lock_guard lock(headers_mutex); - if (first_line_in_progress || headers_in_progress || headers_already_sent) + if (headers_in_progress || headers_already_sent) boost::throw_exception(std::logic_error("Headers have already been sent.")); if (error_encountered) boost::throw_exception(boost::system::system_error(*error_encountered)); typedef constants consts; - headers_buffer.consume(headers_buffer.size()); - std::ostream stream(&headers_buffer); - if (!boost::empty(headers)) { - typedef typename Range::const_iterator iterator; - typedef typename string::type string_type; - boost::transform(headers, - std::ostream_iterator(stream), - linearize_header()); - } else { + { + std::ostream stream(&headers_buffer); + stream + << consts::http_slash() << 1<< consts::dot() << 1 << consts::space() + << status << consts::space() << status_message(status) + << consts::crlf(); + if (!boost::empty(headers)) { + typedef typename Range::const_iterator iterator; + typedef typename string::type string_type; + boost::transform(headers, + std::ostream_iterator(stream), + linearize_header()); + } else { + stream << consts::crlf(); + } stream << consts::crlf(); } - stream << consts::crlf(); - stream.flush(); write_headers_only( boost::bind( @@ -307,8 +309,8 @@ namespace boost { namespace network { namespace http { asio::io_service::strand strand; Handler & handler; utils::thread_pool & thread_pool_; - volatile bool headers_already_sent, first_line_already_sent, headers_in_progress, first_line_in_progress; - asio::streambuf headers_buffer, first_line_buffer; + volatile bool headers_already_sent, headers_in_progress; + asio::streambuf headers_buffer; boost::recursive_mutex headers_mutex; buffer_type read_buffer_; @@ -468,23 +470,12 @@ namespace boost { namespace network { namespace http { } void client_error() { - status = bad_request; - write_first_line( - strand.wrap( - boost::bind( - &async_connection::client_error_first_line_written - , async_connection::shared_from_this() - , asio::placeholders::error - , asio::placeholders::bytes_transferred))); - } - - void client_error_first_line_written(boost::system::error_code const & ec, std::size_t bytes_transferred) { static char const * bad_request = "HTTP/1.0 400 Bad Request\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nBad Request."; asio::async_write( socket() - , asio::buffer(bad_request, 115) + , asio::buffer(bad_request, strlen(bad_request)) , strand.wrap( boost::bind( &async_connection::client_error_sent @@ -505,60 +496,21 @@ namespace boost { namespace network { namespace http { void do_nothing() {} - template - void write_first_line(Callback callback) { - lock_guard lock(headers_mutex); - if (first_line_in_progress) return; - first_line_in_progress = true; - - typedef constants consts; - first_line_buffer.consume(first_line_buffer.size()); - std::ostream first_line_stream(&first_line_buffer); - first_line_stream - << consts::http_slash() << 1<< consts::dot() << 1 << consts::space() - << status << consts::space() << status_message(status) - << consts::crlf() - << std::flush - ; - asio::async_write( - socket() - , first_line_buffer - , callback); - } - void write_headers_only(boost::function callback) { if (headers_in_progress) return; headers_in_progress = true; - - write_first_line( - strand.wrap( + asio::async_write( + socket() + , headers_buffer + , strand.wrap( boost::bind( - &async_connection::handle_first_line_written + &async_connection::handle_write_headers , async_connection::shared_from_this() , callback , asio::placeholders::error , asio::placeholders::bytes_transferred))); } - void handle_first_line_written(boost::function callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { - lock_guard lock(headers_mutex); - if (!ec) { - first_line_already_sent = true; - asio::async_write( - socket() - , headers_buffer - , strand.wrap( - boost::bind( - &async_connection::handle_write_headers - , async_connection::shared_from_this() - , callback - , asio::placeholders::error - , asio::placeholders::bytes_transferred))); - } else { - error_encountered = in_place(ec); - } - } - void handle_write_headers(boost::function callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { lock_guard lock(headers_mutex); if (!ec) { From ead53cf40e83302e11fe2e3ce5f625106e16148e Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 25 Apr 2011 01:36:26 +1000 Subject: [PATCH 113/768] Adding settings for clang in Jamfile. --- libs/network/test/Jamfile.v2 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/network/test/Jamfile.v2 b/libs/network/test/Jamfile.v2 index 318894c6e..f9ea75977 100644 --- a/libs/network/test/Jamfile.v2 +++ b/libs/network/test/Jamfile.v2 @@ -31,6 +31,9 @@ project network_test : darwin:-lpthread darwin:-lssl darwin:-lcrypto + clang:-lpthread + clang:-lssl + clang:-lcrypto cygwin,gcc:_WIN32_WINNT=0x0501 cygwin,gcc:__USE_W32_SOCKETS cygwin,gcc:ws2_32 From 438923814e5b316bd8c77e8f9fbf7edfc1ca4541 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 25 Apr 2011 22:20:40 +1000 Subject: [PATCH 114/768] Fixes #41 : Use Boost.Parameter in HTTP Client API member functions. --- boost/network/protocol/http/client/facade.hpp | 114 ++++++++++-------- .../protocol/http/client/parameters.hpp | 4 + 2 files changed, 70 insertions(+), 48 deletions(-) diff --git a/boost/network/protocol/http/client/facade.hpp b/boost/network/protocol/http/client/facade.hpp index 3d3d4ea0b..d0793fab0 100644 --- a/boost/network/protocol/http/client/facade.hpp +++ b/boost/network/protocol/http/client/facade.hpp @@ -41,62 +41,80 @@ namespace boost { namespace network { namespace http { >::type()); } - response const head (request const & request_) { - return pimpl->request_skeleton(request_, "HEAD", false); + BOOST_PARAMETER_MEMBER_FUNCTION((response const), head, tag, (required (request,(request const &)))) { + return pimpl->request_skeleton(request, "HEAD", false); } - response const get (request const & request_) { - return pimpl->request_skeleton(request_, "GET", true); + BOOST_PARAMETER_MEMBER_FUNCTION((response const), get , tag, (required (request,(request const &)))) { + return pimpl->request_skeleton(request, "GET", true); } - response const post (request const & request_) { - return pimpl->request_skeleton(request_, "POST", true); + BOOST_PARAMETER_MEMBER_FUNCTION((response const), post, tag, + (required + (request,(request)) // yes sir, we make a copy of the original request. + ) + (optional + (body,(string_type const &),string_type()) + (content_type,(string_type const &),string_type()) + ) + ) { + if (body != string_type()) { + request << remove_header("Content-Length") + << header("Content-Length", boost::lexical_cast(body.size())) + << boost::network::body(body); + } + typename headers_range >::type content_type_headers = + headers(request)["Content-Type"]; + if (content_type != string_type()) { + if (!boost::empty(content_type_headers)) + request << remove_header("Content-Type"); + request << header("Content-Type", content_type); + } else { + if (boost::empty(content_type_headers)) { + typedef typename char_::type char_type; + static char_type content_type[] = "x-application/octet-stream"; + request << header("Content-Type", content_type); + } + } + return pimpl->request_skeleton(request, "POST", true); } - response const post (request request_, string_type const & content_type, string_type const & body_) { - if (!boost::empty(headers(request_)["Content-Type"])) - request_ << remove_header("Content-Type"); - - request_ << ::boost::network::body(body_) - << header("Content-Type", content_type) - << header("Content-Length", boost::lexical_cast(body_.size())); - return post(request_); - } - - response const post (request const & request_, string_type const & body_) { - string_type content_type = "x-application/octet-stream"; - typename headers_range::type content_type_headers = - headers(request_)["Content-Type"]; - if (!boost::empty(content_type_headers)) - content_type = boost::begin(content_type_headers)->second; - return post(request_, content_type, body_); - } - - response const put (request const & request_) { - return pimpl->request_skeleton(request_, "PUT", true); - } - - response const put (request const & request_, string_type const & body_) { - string_type content_type = "x-application/octet-stream"; - typename headers_range::type content_type_headers = - headers(request_)["Content-Type"]; - if (!boost::empty(content_type_headers)) - content_type = boost::begin(content_type_headers)->second; - return put(request_, content_type, body_); - } - - response const put (request request_, string_type const & content_type, string_type const & body_) { - if (!boost::empty(headers(request_)["Content-Type"])) - request_ << remove_header("Content-Type"); - - request_ << ::boost::network::body(body_) - << header("Content-Type", content_type) - << header("Content-Length", boost::lexical_cast(body_.size())); - return put(request_); + BOOST_PARAMETER_MEMBER_FUNCTION((response const), put , tag, + (required + (request,(request)) // yes sir, we make a copy of the original request. + ) + (optional + (body,(string_type const &),string_type()) + (content_type,(string_type const &),string_type()) + ) + ) { + if (body != string_type()) { + request << remove_header("Content-Length") + << header("Content-Length", boost::lexical_cast(body.size())) + << boost::network::body(body); + } + typename headers_range >::type content_type_headers = + headers(request)["Content-Type"]; + if (content_type != string_type()) { + if (!boost::empty(content_type_headers)) + request << remove_header("Content-Type"); + request << header("Content-Type", content_type); + } else { + if (boost::empty(content_type_headers)) { + typedef typename char_::type char_type; + static char_type content_type[] = "x-application/octet-stream"; + request << header("Content-Type", content_type); + } + } + return pimpl->request_skeleton(request, "PUT", true); } - response const delete_ (request const & request_) { - return pimpl->request_skeleton(request_, "DELETE", true); + BOOST_PARAMETER_MEMBER_FUNCTION((response const), delete_, tag, + (required + (request,(request const &)) + ) + ) { + return pimpl->request_skeleton(request, "DELETE", true); } void clear_resolved_cache() { diff --git a/boost/network/protocol/http/client/parameters.hpp b/boost/network/protocol/http/client/parameters.hpp index 2d4cdcbad..43174599c 100644 --- a/boost/network/protocol/http/client/parameters.hpp +++ b/boost/network/protocol/http/client/parameters.hpp @@ -15,6 +15,10 @@ namespace boost { namespace network { namespace http { BOOST_PARAMETER_NAME(openssl_certificate) BOOST_PARAMETER_NAME(openssl_verify_path) + BOOST_PARAMETER_NAME(request) + BOOST_PARAMETER_NAME(body) + BOOST_PARAMETER_NAME(content_type) + } /* http */ } /* network */ From fd459e36b0b864a2af2ec035931416f944729da6 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Tue, 26 Apr 2011 00:00:56 +1000 Subject: [PATCH 115/768] Fixes #42 : Defaulting to Asynchronous Client. --- boost/network/protocol/http/client.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/boost/network/protocol/http/client.hpp b/boost/network/protocol/http/client.hpp index e989c8570..8134bb83e 100644 --- a/boost/network/protocol/http/client.hpp +++ b/boost/network/protocol/http/client.hpp @@ -77,7 +77,11 @@ namespace boost { namespace network { namespace http { }; - typedef basic_client client; +#ifndef BOOST_NETWORK_HTTP_DEFAULT_TAG +#define BOOST_NETWORK_HTTP_DEFAULT_TAG tags::http_async_8bit_udp_resolve +#endif + + typedef basic_client client; } // namespace http From 5f8cf0fb3156ec97f4a7534a3e4593ec386e80f8 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Tue, 26 Apr 2011 00:01:33 +1000 Subject: [PATCH 116/768] Fixes #43 : Adding documentation for BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG. --- libs/network/doc/whats_new.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libs/network/doc/whats_new.rst b/libs/network/doc/whats_new.rst index 04b88935b..64a3e10f1 100644 --- a/libs/network/doc/whats_new.rst +++ b/libs/network/doc/whats_new.rst @@ -13,6 +13,11 @@ macro ``BOOST_NETWORK_NO_LIB`` before including any :mod:`cpp-netlib` header. This breaks code that relied on the version 0.8.x line where the library is strictly header-only. +* Fix issue #41: Introduce a macro ``BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG`` + which makes the default HTTP client use ``tags::http_async_8bit_udp_resolve`` + as the tag. +* Fix issue #40: Write the status line and headers in a single buffer write + instead of two writes. * More consistent message API for client and server messages (request and response objects). * Refactoring of internal implementations to allow better separation of concerns From 8f8eb7a94357ca42181bf3c7d02a6833f4ee2f16 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Tue, 26 Apr 2011 00:03:28 +1000 Subject: [PATCH 117/768] Fixes #42 : Use BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG, default to HTTP 1.1. --- boost/network/protocol/http/client.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/boost/network/protocol/http/client.hpp b/boost/network/protocol/http/client.hpp index 8134bb83e..fbed395ea 100644 --- a/boost/network/protocol/http/client.hpp +++ b/boost/network/protocol/http/client.hpp @@ -77,11 +77,11 @@ namespace boost { namespace network { namespace http { }; -#ifndef BOOST_NETWORK_HTTP_DEFAULT_TAG -#define BOOST_NETWORK_HTTP_DEFAULT_TAG tags::http_async_8bit_udp_resolve +#ifndef BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG +#define BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG tags::http_async_8bit_udp_resolve #endif - typedef basic_client client; + typedef basic_client client; } // namespace http From c647fb65e6a44b2386a7e9fde086a35966924987 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Apr 2011 16:43:39 +1000 Subject: [PATCH 118/768] Fixed behaviour of async_server when calling run/stop from multiple thread simultaneously. Added tests for different sequences of calling run/stop on async_server. --- .../protocol/http/server/async_server.hpp | 63 +++++--- libs/network/test/http/CMakeLists.txt | 1 + libs/network/test/http/Jamfile.v2 | 2 + .../server_async_run_stop_concurrency.cpp | 139 ++++++++++++++++++ 4 files changed, 184 insertions(+), 21 deletions(-) create mode 100644 libs/network/test/http/server_async_run_stop_concurrency.cpp diff --git a/boost/network/protocol/http/server/async_server.hpp b/boost/network/protocol/http/server/async_server.hpp index 056a0447a..bd0bde2af 100644 --- a/boost/network/protocol/http/server/async_server.hpp +++ b/boost/network/protocol/http/server/async_server.hpp @@ -23,6 +23,7 @@ namespace boost { namespace network { namespace http { typedef typename boost::network::http::response_header::type response_header; typedef async_connection connection; typedef shared_ptr connection_ptr; + typedef boost::unique_lock scoped_mutex_lock; template async_server_base(ArgPack const & args) @@ -44,6 +45,7 @@ namespace boost { namespace network { namespace http { , stopping(false) , new_connection() , listening_mutex_() + , stopping_mutex_() , listening(false) {} @@ -55,15 +57,21 @@ namespace boost { namespace network { namespace http { void stop() { // stop accepting new requests and let all the existing // handlers finish. - stopping = true; - system::error_code ignored; - acceptor.close(ignored); + scoped_mutex_lock listening_lock(listening_mutex_); + if (listening) { // we dont bother stopping if we arent currently listening + scoped_mutex_lock stopping_lock(stopping_mutex_); + stopping = true; + system::error_code ignored; + acceptor.close(ignored); + listening = false; + service_.post(boost::bind(&async_server_base::handle_stop, this)); + } } void listen() { - boost::unique_lock listening_lock(listening_mutex_); + scoped_mutex_lock listening_lock(listening_mutex_); BOOST_NETWORK_MESSAGE("Listening on " << address_ << ':' << port_); - if (!listening) start_listening(); + if (!listening) start_listening(); // we only initialize our acceptor/sockets if we arent already listening if (!listening) { BOOST_NETWORK_MESSAGE("Error listening on " << address_ << ':' << port_); boost::throw_exception(std::runtime_error("Error listening on provided port.")); @@ -78,28 +86,36 @@ namespace boost { namespace network { namespace http { bool stopping; connection_ptr new_connection; boost::mutex listening_mutex_; + boost::mutex stopping_mutex_; bool listening; + + void handle_stop() { + scoped_mutex_lock stopping_lock(stopping_mutex_); + if (stopping) service_.stop(); // a user may have started listening again before the stop command is reached + } void handle_accept(boost::system::error_code const & ec) { + { + scoped_mutex_lock stopping_lock(stopping_mutex_); + if (stopping) return; // we dont want to add another handler instance, and we dont want to know about errors for a socket we dont need anymore + } if (!ec) { socket_options_base::socket_options(new_connection->socket()); new_connection->start(); - if (!stopping) { - new_connection.reset( - new connection( - service_ - , handler - , thread_pool - ) - ); - acceptor.async_accept(new_connection->socket(), - boost::bind( - &async_server_base::handle_accept - , this - , boost::asio::placeholders::error - ) - ); - } + new_connection.reset( + new connection( + service_ + , handler + , thread_pool + ) + ); + acceptor.async_accept(new_connection->socket(), + boost::bind( + &async_server_base::handle_accept + , this + , boost::asio::placeholders::error + ) + ); } else { BOOST_NETWORK_MESSAGE("Error accepting connection, reason: " << ec); } @@ -109,6 +125,9 @@ namespace boost { namespace network { namespace http { using boost::asio::ip::tcp; system::error_code error; + + service_.reset(); // this allows repeated cycles of run -> stop -> run + tcp::resolver resolver(service_); tcp::resolver::query query(address_, port_); tcp::resolver::iterator endpoint_iterator = resolver.resolve(query, error); @@ -140,6 +159,8 @@ namespace boost { namespace network { namespace http { , this , boost::asio::placeholders::error)); listening = true; + scoped_mutex_lock stopping_lock(stopping_mutex_); + stopping = false; // if we were in the process of stopping, we revoke that command and continue listening BOOST_NETWORK_MESSAGE("Now listening on socket: '" << address_ << ":" << port_ << "'"); } }; diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 2068d35ad..5a63ee13a 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -70,6 +70,7 @@ if (Boost_FOUND) server_hello_world server_async server_async_less_copy + server_async_run_stop_concurrency ) set ( PORT 8000 ) foreach ( test ${SERVER_TESTS} ) diff --git a/libs/network/test/http/Jamfile.v2 b/libs/network/test/http/Jamfile.v2 index 1de319cdb..b62c5b0f5 100644 --- a/libs/network/test/http/Jamfile.v2 +++ b/libs/network/test/http/Jamfile.v2 @@ -34,10 +34,12 @@ run url_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; exe http_async_server : server_async.cpp /cpp-netlib//cppnetlib-server-parsers ; exe hello_world : server_hello_world.cpp /cpp-netlib//cppnetlib-server-parsers ; exe http_async_less_copy_server : server_async_less_copy.cpp /cpp-netlib//cppnetlib-server-parsers ; +exe http_async_run_stop_concurrency_server : server_async_run_stop_concurrency.cpp /cpp-netlib//cppnetlib-server-parsers ; make httplib_acceptance.passed : ../httplib_acceptance.py hello_world : @httplib_acceptance ; make httplib_async_acceptance.passed : ../httplib_acceptance.py http_async_server : @httplib_acceptance ; make httplib_async_less_copy_acceptance.passed : ../httplib_acceptance.py http_async_less_copy_server : @httplib_acceptance ; +make httplib_async_run_stop_concurrency_acceptance.passed : ../httplib_acceptance.py http_async_run_stop_concurrency_server : @httplib_acceptance ; actions httplib_acceptance { export TEST_SCRIPT=`echo "$(>)" | awk '{print $1}'` diff --git a/libs/network/test/http/server_async_run_stop_concurrency.cpp b/libs/network/test/http/server_async_run_stop_concurrency.cpp new file mode 100644 index 000000000..d85e0dfb7 --- /dev/null +++ b/libs/network/test/http/server_async_run_stop_concurrency.cpp @@ -0,0 +1,139 @@ +#define BOOST_TEST_MODULE HTTP Asynchronous Server Tests + +#include +#include +#include + +namespace http = boost::network::http; +namespace util = boost::network::utils; + +struct dummy_async_handler; +typedef http::async_server async_server; + +struct dummy_async_handler { + void operator()(async_server::request const & req, + async_server::connection_ptr conn) { + // Really, this is just for testing purposes + } +}; + +// In this batch of tests we ensure that calling run and stop on an async_server, in any sequence, is thread safe. + +int main(int argc, char * argv[]) { + dummy_async_handler async_handler; + +#define ASYNC_SERVER_TEST_CONFIG \ + http::_address = "127.0.0.1", \ + http::_port = "80", \ + http::_handler = async_handler, \ + http::_thread_pool = pool, \ + http::_reuse_address = true + +#define ASYNC_SERVER_SLEEP_TIME \ + boost::posix_time::milliseconds(100) + + // stop from main thread + { + BOOST_NETWORK_MESSAGE("TEST: stop without running"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + server_instance.stop(); + } + + // run-stop from main thread + { + BOOST_NETWORK_MESSAGE("TEST: stop from main thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + server_instance.stop(); + running_thread.join(); + } + + // run-stop from another thread + { + BOOST_NETWORK_MESSAGE("TEST: stop from another thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + stopping_thread.join(); + running_thread.join(); + } + + // run-stop-run-stop from another thread + { + BOOST_NETWORK_MESSAGE("TEST: run-stop-run-stop from another thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + stopping_thread.join(); + running_thread.join(); + second_stopping_thread.join(); + second_running_thread.join(); + } + + // run-run-stop from another thread + { + BOOST_NETWORK_MESSAGE("TEST: run-run-stop from another thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + stopping_thread.join(); + running_thread.join(); + second_running_thread.join(); + } + + // run-stop-stop from another thread + { + BOOST_NETWORK_MESSAGE("TEST: run-stop-stop from another thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + stopping_thread.join(); + second_stopping_thread.join(); + running_thread.join(); + } + +#undef ASYNC_SERVER_TEST_CONFIG + + return 0; +} From 19b932b4f54290df7c46efc8b8fb3f3bdaf78f7b Mon Sep 17 00:00:00 2001 From: Nick Migel Date: Sat, 7 May 2011 00:50:30 +0200 Subject: [PATCH 119/768] fixed shutdown call for sync and async connections removed close call - socket will be closed automatically whet out of scoup --- boost/network/protocol/http/server/async_connection.hpp | 3 +-- boost/network/protocol/http/server/sync_connection.hpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/boost/network/protocol/http/server/async_connection.hpp b/boost/network/protocol/http/server/async_connection.hpp index 9d3b46aa6..377ec5738 100644 --- a/boost/network/protocol/http/server/async_connection.hpp +++ b/boost/network/protocol/http/server/async_connection.hpp @@ -148,8 +148,7 @@ namespace boost { namespace network { namespace http { ~async_connection() throw () { boost::system::error_code ignored; - socket_.shutdown(asio::ip::tcp::socket::shutdown_both, ignored); - socket_.close(ignored); + socket_.shutdown(asio::ip::tcp::socket::shutdown_receive, ignored); } /** Function: template set_headers(Range headers) diff --git a/boost/network/protocol/http/server/sync_connection.hpp b/boost/network/protocol/http/server/sync_connection.hpp index 86154369d..32d562b93 100644 --- a/boost/network/protocol/http/server/sync_connection.hpp +++ b/boost/network/protocol/http/server/sync_connection.hpp @@ -247,8 +247,7 @@ namespace boost { namespace network { namespace http { if (!ec) { using boost::asio::ip::tcp; boost::system::error_code ignored_ec; - socket_.shutdown(tcp::socket::shutdown_both, ignored_ec); - socket_.close(ignored_ec); + socket_.shutdown(tcp::socket::shutdown_receive, ignored_ec); } } From 7099700af7dea7eb4d6a4096e8d9e44b5e6c2f66 Mon Sep 17 00:00:00 2001 From: demozon Date: Mon, 9 May 2011 00:04:34 -0700 Subject: [PATCH 120/768] Return const reference from get functions The const versions of destination(), source(), body() and headers() returned either a temporary or a non const reference. Changed the to return a const references. This makes them work with boost::iterator_ranges. --- boost/network/message.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/boost/network/message.hpp b/boost/network/message.hpp index 42821fdac..190018b67 100644 --- a/boost/network/message.hpp +++ b/boost/network/message.hpp @@ -83,7 +83,7 @@ namespace boost { namespace network { _headers.erase(key); } - headers_container_type & headers() const { + headers_container_type const & headers() const { return _headers; } @@ -95,7 +95,7 @@ namespace boost { namespace network { _body = body_; } - string_type body() const { + string_type const & body() const { return _body; } @@ -107,7 +107,7 @@ namespace boost { namespace network { _source = source_; } - string_type source() const { + string_type const & source() const { return _source; } @@ -119,7 +119,7 @@ namespace boost { namespace network { _destination = destination_; } - string_type destination() const { + string_type const & destination() const { return _destination; } From c78ca0d173f34e0d14ecd7b874624a3d0a275eac Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Thu, 16 Jun 2011 22:59:20 +1000 Subject: [PATCH 121/768] Adding support for Asynchronous Body Handling. Fixes #53 #27 #3 --- boost/network/protocol/http/client.hpp | 1 + .../protocol/http/client/async_impl.hpp | 9 +- .../http/client/connection/async_base.hpp | 7 +- .../http/client/connection/async_normal.hpp | 112 +++++++++++------- .../connection/async_protocol_handler.hpp | 14 +-- .../http/client/connection/async_ssl.hpp | 3 +- boost/network/protocol/http/client/facade.hpp | 25 +++- boost/network/protocol/http/client/macros.hpp | 18 +++ .../protocol/http/client/parameters.hpp | 1 + .../protocol/http/client/sync_impl.hpp | 5 +- .../http/policies/async_connection.hpp | 5 +- .../http/policies/pooled_connection.hpp | 3 +- .../http/policies/simple_connection.hpp | 3 +- .../test/http/client_get_streaming_test.cpp | 45 +++++++ .../test/http/server_async_less_copy.cpp | 1 + 15 files changed, 187 insertions(+), 65 deletions(-) create mode 100644 boost/network/protocol/http/client/macros.hpp create mode 100644 libs/network/test/http/client_get_streaming_test.cpp diff --git a/boost/network/protocol/http/client.hpp b/boost/network/protocol/http/client.hpp index fbed395ea..2a8b1770c 100644 --- a/boost/network/protocol/http/client.hpp +++ b/boost/network/protocol/http/client.hpp @@ -25,6 +25,7 @@ #include #include +#include namespace boost { namespace network { namespace http { diff --git a/boost/network/protocol/http/client/async_impl.hpp b/boost/network/protocol/http/client/async_impl.hpp index 6e944490e..d4e730f9a 100644 --- a/boost/network/protocol/http/client/async_impl.hpp +++ b/boost/network/protocol/http/client/async_impl.hpp @@ -31,6 +31,10 @@ namespace boost { namespace network { namespace http { typename string::type string_type; + typedef + function const &, system::error_code const &)> + body_callback_function_type; + async_client(bool cache_resolved, bool follow_redirect, optional const & certificate_filename, optional const & verify_path) : connection_base(cache_resolved, follow_redirect), service_ptr(new boost::asio::io_service), @@ -73,12 +77,13 @@ namespace boost { namespace network { namespace http { basic_response const request_skeleton( basic_request const & request_, string_type const & method, - bool get_body + bool get_body, + body_callback_function_type callback ) { typename connection_base::connection_ptr connection_; connection_ = connection_base::get_connection(resolver_, request_, certificate_filename_, verify_path_); - return connection_->send_request(method, request_, get_body); + return connection_->send_request(method, request_, get_body, callback); } boost::asio::io_service * service_ptr; diff --git a/boost/network/protocol/http/client/connection/async_base.hpp b/boost/network/protocol/http/client/connection/async_base.hpp index 4806fcb53..8916fedc2 100644 --- a/boost/network/protocol/http/client/connection/async_base.hpp +++ b/boost/network/protocol/http/client/connection/async_base.hpp @@ -23,6 +23,9 @@ namespace boost { namespace network { namespace http { namespace impl { typedef typename string::type string_type; typedef basic_request request; typedef basic_response response; + typedef + function const &, system::error_code const &)> + body_callback_function_type; static boost::shared_ptr > new_connection(resolve_function resolve, resolver_type & resolver, bool follow_redirect, bool https, optional certificate_filename=optional(), optional const & verify_path=optional()) { boost::shared_ptr > temp; @@ -39,7 +42,9 @@ namespace boost { namespace network { namespace http { namespace impl { return temp; } - virtual response start(request const & request, string_type const & method, bool get_body) = 0; + virtual response start(request const & request, string_type const & method, bool get_body, body_callback_function_type callback) = 0; + + virtual ~async_connection_base() {} }; diff --git a/boost/network/protocol/http/client/connection/async_normal.hpp b/boost/network/protocol/http/client/connection/async_normal.hpp index 0c19c11d1..e8be7c741 100644 --- a/boost/network/protocol/http/client/connection/async_normal.hpp +++ b/boost/network/protocol/http/client/connection/async_normal.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include namespace boost { namespace network { namespace http { namespace impl { @@ -45,6 +46,7 @@ namespace boost { namespace network { namespace http { namespace impl { typedef typename base::string_type string_type; typedef typename base::request request; typedef typename base::resolver_base::resolve_function resolve_function; + typedef typename base::body_callback_function_type body_callback_function_type; http_async_connection( resolver_type & resolver, @@ -58,7 +60,7 @@ namespace boost { namespace network { namespace http { namespace impl { {} - virtual response start(request const & request, string_type const & method, bool get_body) { + virtual response start(request const & request, string_type const & method, bool get_body, body_callback_function_type callback) { response response_; this->init_response(response_, get_body); linearize(request, method, version_major, version_minor, @@ -71,13 +73,16 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &http_async_connection::handle_resolved, http_async_connection::shared_from_this(), - port_, get_body, + port_, get_body, callback, _1, _2))); return response_; } private: - void handle_resolved(boost::uint16_t port, bool get_body, boost::system::error_code const & ec, resolver_iterator_pair endpoint_range) { + + http_async_connection(http_async_connection const &); // = delete + + void handle_resolved(boost::uint16_t port, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, resolver_iterator_pair endpoint_range) { resolver_iterator iter = boost::begin(endpoint_range); if (!ec && !boost::empty(endpoint_range)) { boost::asio::ip::tcp::endpoint endpoint( @@ -92,7 +97,8 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &http_async_connection::handle_connected, http_async_connection::shared_from_this(), - port, get_body, std::make_pair(++iter, resolver_iterator()), + port, get_body, callback, + std::make_pair(++iter, resolver_iterator()), boost::asio::placeholders::error ))); } else { @@ -107,7 +113,7 @@ namespace boost { namespace network { namespace http { namespace impl { } } - void handle_connected(boost::uint16_t port, bool get_body, resolver_iterator_pair endpoint_range, boost::system::error_code const & ec) { + void handle_connected(boost::uint16_t port, bool get_body, body_callback_function_type callback, resolver_iterator_pair endpoint_range, boost::system::error_code const & ec) { if (!ec) { boost::asio::async_write( *socket_ @@ -116,7 +122,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &http_async_connection::handle_sent_request, http_async_connection::shared_from_this(), - get_body, + get_body, callback, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ))); @@ -135,7 +141,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &http_async_connection::handle_connected, http_async_connection::shared_from_this(), - port, get_body, std::make_pair(++iter, resolver_iterator()), + port, get_body, callback, std::make_pair(++iter, resolver_iterator()), boost::asio::placeholders::error ))); } else { @@ -157,22 +163,19 @@ namespace boost { namespace network { namespace http { namespace impl { version, status, status_message, headers, body }; - void handle_sent_request(bool get_body, boost::system::error_code const & ec, std::size_t bytes_transferred) { + void handle_sent_request(bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { if (!ec) { - boost::asio::async_read( - *socket_, - boost::asio::mutable_buffers_1( - this->part.c_array(), - this->part.size()), + socket_->async_read_some( + boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), request_strand_.wrap( boost::bind( &http_async_connection::handle_received_data, http_async_connection::shared_from_this(), - version, get_body, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); + version, get_body, callback, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred))); } else { - boost::system::system_error error( - ec ? ec : boost::asio::error::host_not_found - ); + boost::system::system_error error(ec); this->version_promise.set_exception(boost::copy_exception(error)); this->status_promise.set_exception(boost::copy_exception(error)); this->status_message_promise.set_exception(boost::copy_exception(error)); @@ -183,7 +186,7 @@ namespace boost { namespace network { namespace http { namespace impl { } } - void handle_received_data(state_t state, bool get_body, boost::system::error_code const & ec, std::size_t bytes_transferred) { + void handle_received_data(state_t state, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { if (!ec || ec == boost::asio::error::eof) { logic::tribool parsed_ok; size_t remainder; @@ -195,7 +198,8 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &http_async_connection::handle_received_data, http_async_connection::shared_from_this(), - status, get_body, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + status, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) ) ); @@ -207,7 +211,8 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &http_async_connection::handle_received_data, http_async_connection::shared_from_this(), - status_message, get_body, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + status_message, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) ) ); @@ -219,7 +224,8 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &http_async_connection::handle_received_data, http_async_connection::shared_from_this(), - headers, get_body, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + headers, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) ) ); @@ -231,7 +237,8 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &http_async_connection::handle_received_data, http_async_connection::shared_from_this(), - body, get_body, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + body, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) ) ); @@ -246,7 +253,8 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &http_async_connection::handle_received_data, http_async_connection::shared_from_this(), - body, get_body, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + body, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) ), remainder); @@ -257,29 +265,53 @@ namespace boost { namespace network { namespace http { namespace impl { return; } if (ec == boost::asio::error::eof) { - string_type body; - std::swap(body, this->partial_parsed); - body.append( - this->part.begin() - , bytes_transferred - ); - this->body_promise.set_value(body); + if (!callback.empty()) { + typename protocol_base::buffer_type::const_iterator begin = this->part.begin(), end = begin; + std::advance(end, bytes_transferred); + callback(make_iterator_range(begin, end), ec); + this->body_promise.set_value(""); + } else { + string_type body_string; + std::swap(body_string, this->partial_parsed); + body_string.append( + this->part.begin() + , bytes_transferred + ); + this->body_promise.set_value(body_string); + } // TODO set the destination value somewhere! this->destination_promise.set_value(""); this->source_promise.set_value(""); this->part.assign('\0'); this->response_parser_.reset(); } else { - this->parse_body( - *socket_, - request_strand_.wrap( - boost::bind( - &http_async_connection::handle_received_data, - http_async_connection::shared_from_this(), - body, get_body, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred); + if (!callback.empty()) { + typename protocol_base::buffer_type::const_iterator begin = this->part.begin(), end = begin; + std::advance(end, bytes_transferred); + callback(make_iterator_range(begin, end), ec); + socket_->async_read_some( + boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), + request_strand_.wrap( + boost::bind( + &http_async_connection::handle_received_data, + http_async_connection::shared_from_this(), + body, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred) + ) + ); + } else { + this->parse_body( + *socket_, + request_strand_.wrap( + boost::bind( + &http_async_connection::handle_received_data, + http_async_connection::shared_from_this(), + body, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + ) + ), + bytes_transferred); + } } break; default: diff --git a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp index 8d67de527..0d4c71f32 100644 --- a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp +++ b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp @@ -79,8 +79,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::end(result_range) ); part_begin = part.begin(); - boost::asio::async_read( - socket_, + socket_.async_read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); @@ -119,7 +118,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::end(result_range) ); part_begin = part.begin(); - boost::asio::async_read(socket_, + socket_.async_read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); @@ -155,8 +154,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::begin(result_range), boost::end(result_range)); part_begin = part.begin(); - boost::asio::async_read( - socket_, + socket_.async_read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); @@ -225,8 +223,7 @@ namespace boost { namespace network { namespace http { namespace impl { } else { partial_parsed.append(boost::begin(result_range), boost::end(result_range)); part_begin = part.begin(); - boost::asio::async_read( - socket_, + socket_.async_read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); @@ -244,8 +241,7 @@ namespace boost { namespace network { namespace http { namespace impl { void parse_body(Socket & socket_, Callback callback, size_t bytes) { partial_parsed.append(part_begin, bytes); part_begin = part.begin(); - boost::asio::async_read( - socket_, + socket_.async_read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); diff --git a/boost/network/protocol/http/client/connection/async_ssl.hpp b/boost/network/protocol/http/client/connection/async_ssl.hpp index 267a33493..6aecd1160 100644 --- a/boost/network/protocol/http/client/connection/async_ssl.hpp +++ b/boost/network/protocol/http/client/connection/async_ssl.hpp @@ -32,6 +32,7 @@ namespace boost { namespace network { namespace http { namespace impl { typedef typename base::string_type string_type; typedef typename base::request request; typedef typename base::resolver_base::resolve_function resolve_function; + typedef typename base::body_callback_function_type body_callback_function_type; https_async_connection( resolver_type & resolver, @@ -49,7 +50,7 @@ namespace boost { namespace network { namespace http { namespace impl { {} - virtual response start(request const & request, string_type const & method, bool get_body) { + virtual response start(request const & request, string_type const & method, bool get_body, body_callback_function_type callback) { response response_; this->init_response(response_, get_body); linearize(request, method, version_major, version_minor, diff --git a/boost/network/protocol/http/client/facade.hpp b/boost/network/protocol/http/client/facade.hpp index d0793fab0..eb9c191d0 100644 --- a/boost/network/protocol/http/client/facade.hpp +++ b/boost/network/protocol/http/client/facade.hpp @@ -26,6 +26,7 @@ namespace boost { namespace network { namespace http { typedef basic_request request; typedef basic_response response; typedef basic_client_impl pimpl_type; + typedef function const &,system::error_code const &)> body_callback_function_type; template basic_client_facade(ArgPack const & args) @@ -42,11 +43,18 @@ namespace boost { namespace network { namespace http { } BOOST_PARAMETER_MEMBER_FUNCTION((response const), head, tag, (required (request,(request const &)))) { - return pimpl->request_skeleton(request, "HEAD", false); + return pimpl->request_skeleton(request, "HEAD", false, body_callback_function_type()); } - BOOST_PARAMETER_MEMBER_FUNCTION((response const), get , tag, (required (request,(request const &)))) { - return pimpl->request_skeleton(request, "GET", true); + BOOST_PARAMETER_MEMBER_FUNCTION((response const), get , tag, + (required + (request,(request const &)) + ) + (optional + (body_handler,(body_callback_function_type),body_callback_function_type()) + ) + ) { + return pimpl->request_skeleton(request, "GET", true, body_handler); } BOOST_PARAMETER_MEMBER_FUNCTION((response const), post, tag, @@ -56,6 +64,7 @@ namespace boost { namespace network { namespace http { (optional (body,(string_type const &),string_type()) (content_type,(string_type const &),string_type()) + (body_handler,(body_callback_function_type),body_callback_function_type()) ) ) { if (body != string_type()) { @@ -76,7 +85,7 @@ namespace boost { namespace network { namespace http { request << header("Content-Type", content_type); } } - return pimpl->request_skeleton(request, "POST", true); + return pimpl->request_skeleton(request, "POST", true, body_handler); } BOOST_PARAMETER_MEMBER_FUNCTION((response const), put , tag, @@ -86,6 +95,7 @@ namespace boost { namespace network { namespace http { (optional (body,(string_type const &),string_type()) (content_type,(string_type const &),string_type()) + (body_handler,(body_callback_function_type),body_callback_function_type()) ) ) { if (body != string_type()) { @@ -106,15 +116,18 @@ namespace boost { namespace network { namespace http { request << header("Content-Type", content_type); } } - return pimpl->request_skeleton(request, "PUT", true); + return pimpl->request_skeleton(request, "PUT", true, body_handler); } BOOST_PARAMETER_MEMBER_FUNCTION((response const), delete_, tag, (required (request,(request const &)) ) + (optional + (body_handler,(body_callback_function_type),body_callback_function_type()) + ) ) { - return pimpl->request_skeleton(request, "DELETE", true); + return pimpl->request_skeleton(request, "DELETE", true, body_handler); } void clear_resolved_cache() { diff --git a/boost/network/protocol/http/client/macros.hpp b/boost/network/protocol/http/client/macros.hpp new file mode 100644 index 000000000..92c9f5e8c --- /dev/null +++ b/boost/network/protocol/http/client/macros.hpp @@ -0,0 +1,18 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 +#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 + +// Copyright 2011 Dean Michael Berris . +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +#ifndef BOOST_NETWORK_HTTP_BODY_CALLBACK +#define BOOST_NETWORK_HTTP_BODY_CALLBACK(function_name, range_name, error_name) \ + void function_name (boost::iterator_range const & range_name, boost::system::error_code const & error_name) +#endif + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 */ + diff --git a/boost/network/protocol/http/client/parameters.hpp b/boost/network/protocol/http/client/parameters.hpp index 43174599c..dade4e756 100644 --- a/boost/network/protocol/http/client/parameters.hpp +++ b/boost/network/protocol/http/client/parameters.hpp @@ -18,6 +18,7 @@ namespace boost { namespace network { namespace http { BOOST_PARAMETER_NAME(request) BOOST_PARAMETER_NAME(body) BOOST_PARAMETER_NAME(content_type) + BOOST_PARAMETER_NAME(body_handler) } /* http */ diff --git a/boost/network/protocol/http/client/sync_impl.hpp b/boost/network/protocol/http/client/sync_impl.hpp index 561cec42c..b81c2198a 100644 --- a/boost/network/protocol/http/client/sync_impl.hpp +++ b/boost/network/protocol/http/client/sync_impl.hpp @@ -19,6 +19,7 @@ namespace boost { namespace network { namespace http { typedef typename string::type string_type; typedef typename connection_policy::type connection_base; typedef typename resolver::type resolver_type; + typedef function const &, system::error_code const &)> body_callback_function_type; friend struct basic_client_impl; boost::asio::io_service * service_ptr; @@ -55,10 +56,10 @@ namespace boost { namespace network { namespace http { delete service_ptr; } - basic_response const request_skeleton(basic_request const & request_, string_type method, bool get_body) { + basic_response const request_skeleton(basic_request const & request_, string_type method, bool get_body, body_callback_function_type callback) { typename connection_base::connection_ptr connection_; connection_ = connection_base::get_connection(resolver_, request_, certificate_file, verify_path); - return connection_->send_request(method, request_, get_body); + return connection_->send_request(method, request_, get_body, callback); } }; diff --git a/boost/network/protocol/http/policies/async_connection.hpp b/boost/network/protocol/http/policies/async_connection.hpp index ba02ebdc4..ea353a781 100644 --- a/boost/network/protocol/http/policies/async_connection.hpp +++ b/boost/network/protocol/http/policies/async_connection.hpp @@ -28,6 +28,7 @@ namespace boost { namespace network { namespace http { typedef typename resolver_policy::type resolver_base; typedef typename resolver_base::resolver_type resolver_type; typedef typename resolver_base::resolve_function resolve_function; + typedef function const &, system::error_code const &)> body_callback_function_type; struct connection_impl { connection_impl( @@ -42,8 +43,8 @@ namespace boost { namespace network { namespace http { pimpl = impl::async_connection_base::new_connection(resolve, resolver, follow_redirect, https, certificate_filename, verify_path); } - basic_response send_request(string_type const & method, basic_request const & request_, bool get_body) { - return pimpl->start(request_, method, get_body); + basic_response send_request(string_type const & method, basic_request const & request_, bool get_body, body_callback_function_type callback) { + return pimpl->start(request_, method, get_body, callback); } private: diff --git a/boost/network/protocol/http/policies/pooled_connection.hpp b/boost/network/protocol/http/policies/pooled_connection.hpp index 1fa19350e..c90289e6f 100644 --- a/boost/network/protocol/http/policies/pooled_connection.hpp +++ b/boost/network/protocol/http/policies/pooled_connection.hpp @@ -29,6 +29,7 @@ namespace boost { namespace network { namespace http { typedef typename resolver_policy::type resolver_base; typedef typename resolver_base::resolver_type resolver_type; typedef function resolver_function_type; + typedef function const &, system::error_code const &)> body_callback_function_type; void cleanup() { host_connection_map().swap(host_connections); @@ -46,7 +47,7 @@ namespace boost { namespace network { namespace http { , verify_path_(verify_path) {} - basic_response send_request(string_type const & method, basic_request request_, bool get_body) { + basic_response send_request(string_type const & method, basic_request request_, bool get_body, body_callback_function_type callback) { return send_request_impl(method, request_, get_body); } diff --git a/boost/network/protocol/http/policies/simple_connection.hpp b/boost/network/protocol/http/policies/simple_connection.hpp index de00ab1bf..72f6a6974 100644 --- a/boost/network/protocol/http/policies/simple_connection.hpp +++ b/boost/network/protocol/http/policies/simple_connection.hpp @@ -27,6 +27,7 @@ namespace boost { namespace network { namespace http { typedef typename resolver_policy::type resolver_base; typedef typename resolver_base::resolver_type resolver_type; typedef function resolver_function_type; + typedef function const &, system::error_code const &)> body_callback_function_type; struct connection_impl { connection_impl(resolver_type & resolver, bool follow_redirect, string_type const & hostname, string_type const & port, resolver_function_type resolve, bool https, optional const & certificate_filename = optional(), optional const & verify_path = optional()) @@ -36,7 +37,7 @@ namespace boost { namespace network { namespace http { pimpl.reset(impl::sync_connection_base::new_connection(resolver, resolve, https, certificate_filename, verify_path)); } - basic_response send_request(string_type const & method, basic_request request_, bool get_body) { + basic_response send_request(string_type const & method, basic_request request_, bool get_body, body_callback_function_type callback) { basic_response response_; do { pimpl->init_socket(request_.host(), lexical_cast(request_.port())); diff --git a/libs/network/test/http/client_get_streaming_test.cpp b/libs/network/test/http/client_get_streaming_test.cpp new file mode 100644 index 000000000..814e77aab --- /dev/null +++ b/libs/network/test/http/client_get_streaming_test.cpp @@ -0,0 +1,45 @@ +// Copyright 2011 Dean Michael Berris <mikhailberis@gmail.com>. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE HTTP 1.1 Get Streaming Test +#include +#include +#include "client_types.hpp" + +namespace net = boost::network; +namespace http = boost::network::http; + +struct body_handler { + + explicit body_handler(std::string & body) + : body(body) {} + + BOOST_NETWORK_HTTP_BODY_CALLBACK(operator(), range, error) { + std::cout << "Length: " << std::distance(boost::begin(range), boost::end(range)) << std::endl; + body.append(boost::begin(range), boost::end(range)); + } + + std::string & body; + +}; + + +BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_streaming_test, client, client_types) { + typename client::request request("http://www.boost.org/"); + client client_; + typename client::response response; + typename client::string_type body_string; + body_handler handler_instance(body_string); + BOOST_CHECK_NO_THROW( response = client_.get(request, http::_body_handler=handler_instance) ); + typename net::headers_range::type range = headers(response)["Content-Type"]; + BOOST_CHECK ( !boost::empty(range) ); + BOOST_CHECK ( body(response).size() != 0 ); + BOOST_CHECK_EQUAL ( response.version().substr(0, 7), std::string("HTTP/1.") ); + BOOST_CHECK_EQUAL ( response.status(), 200u ); + BOOST_CHECK_EQUAL ( response.status_message(), std::string("OK") ); + typename client::string_type dummy_body = body(response); + BOOST_CHECK_EQUAL ( dummy_body, typename client::string_type() ); +} + diff --git a/libs/network/test/http/server_async_less_copy.cpp b/libs/network/test/http/server_async_less_copy.cpp index 628035666..73d8aa5f3 100644 --- a/libs/network/test/http/server_async_less_copy.cpp +++ b/libs/network/test/http/server_async_less_copy.cpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace net = boost::network; namespace http = boost::network::http; From a85ddb2f00d93369d5e3baf1cb0f06c9d0f37537 Mon Sep 17 00:00:00 2001 From: Antoine Tremblay Date: Tue, 24 May 2011 14:30:33 -0400 Subject: [PATCH 122/768] Fixed soreuse acceptor option Set acceptor options before bind since the reuse_address option must be set at that point. --- boost/network/protocol/http/server/async_server.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boost/network/protocol/http/server/async_server.hpp b/boost/network/protocol/http/server/async_server.hpp index bd0bde2af..c56af236e 100644 --- a/boost/network/protocol/http/server/async_server.hpp +++ b/boost/network/protocol/http/server/async_server.hpp @@ -141,12 +141,12 @@ namespace boost { namespace network { namespace http { BOOST_NETWORK_MESSAGE("Error opening socket: " << address_ << ":" << port_); return; } + socket_options_base::acceptor_options(acceptor); acceptor.bind(endpoint, error); if (error) { BOOST_NETWORK_MESSAGE("Error binding socket: " << address_ << ":" << port_); return; } - socket_options_base::acceptor_options(acceptor); acceptor.listen(asio::socket_base::max_connections, error); if (error) { BOOST_NETWORK_MESSAGE("Error listening on socket: '" << error << "' on " << address_ << ":" << port_); From 958434500364ef38d6ed82bd4b29b458385d42db Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 17 Jun 2011 01:51:48 +1000 Subject: [PATCH 123/768] Adjusting test to only support streaming in asynchronous clients for now. --- CMakeLists.txt | 5 ++ .../http/client/connection/async_normal.hpp | 53 ++++++++++++------- libs/network/test/http/CMakeLists.txt | 5 +- .../test/http/client_get_streaming_test.cpp | 27 +++++----- libs/network/test/http/client_types.hpp | 24 +++++++++ 5 files changed, 79 insertions(+), 35 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da469b718..4aedc4e6f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,11 @@ cmake_minimum_required(VERSION 2.6) project(CPP-NETLIB) find_package( Boost 1.41.0 ) set(CMAKE_VERBOSE_MAKEFILE true) + +if (CMAKE_BUILD_TYPE MATCHES Debug) + add_definitions(-DBOOST_NETWORK_DEBUG) +endif() + if (Boost_FOUND) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTI_THREADED ON) diff --git a/boost/network/protocol/http/client/connection/async_normal.hpp b/boost/network/protocol/http/client/connection/async_normal.hpp index e8be7c741..8c3567cf7 100644 --- a/boost/network/protocol/http/client/connection/async_normal.hpp +++ b/boost/network/protocol/http/client/connection/async_normal.hpp @@ -8,6 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#include #include #include #include @@ -237,7 +238,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &http_async_connection::handle_received_data, http_async_connection::shared_from_this(), - body, get_body, callback, + headers, get_body, callback, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) ) @@ -247,29 +248,43 @@ namespace boost { namespace network { namespace http { namespace impl { this->body_promise.set_value(""); return; } - this->parse_body( - *socket_, - request_strand_.wrap( - boost::bind( - &http_async_connection::handle_received_data, - http_async_connection::shared_from_this(), - body, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - remainder); - break; - case body: - if (!get_body) { + if (callback) { + typename protocol_base::buffer_type::const_iterator begin = this->part.begin(); + std::advance(begin, remainder); + typename protocol_base::buffer_type::const_iterator end = begin; + std::advance(end, this->part.size() - remainder); + callback(make_iterator_range(begin, end), ec); + socket_->async_read_some( + boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), + request_strand_.wrap( + boost::bind( + &http_async_connection::handle_received_data, + http_async_connection::shared_from_this(), + body, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred) + ) + ); this->body_promise.set_value(""); - return; + } else { + this->parse_body( + *socket_, + request_strand_.wrap( + boost::bind( + &http_async_connection::handle_received_data, + http_async_connection::shared_from_this(), + body, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + ) + ), + remainder); } + break; + case body: if (ec == boost::asio::error::eof) { - if (!callback.empty()) { + if (callback) { typename protocol_base::buffer_type::const_iterator begin = this->part.begin(), end = begin; std::advance(end, bytes_transferred); callback(make_iterator_range(begin, end), ec); - this->body_promise.set_value(""); } else { string_type body_string; std::swap(body_string, this->partial_parsed); @@ -285,7 +300,7 @@ namespace boost { namespace network { namespace http { namespace impl { this->part.assign('\0'); this->response_parser_.reset(); } else { - if (!callback.empty()) { + if (callback) { typename protocol_base::buffer_type::const_iterator begin = this->part.begin(), end = begin; std::advance(end, bytes_transferred); callback(make_iterator_range(begin, end), ec); diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 5a63ee13a..a129d3adf 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -13,10 +13,6 @@ if (OPENSSL_FOUND) add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) endif() -if (CMAKE_BUILD_TYPE MATCHES Debug) - add_definitions(-DBOOST_NETWORK_DEBUG) -endif() - find_package( Threads ) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) @@ -28,6 +24,7 @@ if (Boost_FOUND) client_get_different_port_test client_get_timeout_test client_localhost_normal_test + client_get_streaming_test ) if (OPENSSL_FOUND) set ( TESTS ${TESTS} client_localhost_ssl_test ) diff --git a/libs/network/test/http/client_get_streaming_test.cpp b/libs/network/test/http/client_get_streaming_test.cpp index 814e77aab..19009fa23 100644 --- a/libs/network/test/http/client_get_streaming_test.cpp +++ b/libs/network/test/http/client_get_streaming_test.cpp @@ -6,6 +6,7 @@ #define BOOST_TEST_MODULE HTTP 1.1 Get Streaming Test #include #include +#include #include "client_types.hpp" namespace net = boost::network; @@ -17,7 +18,6 @@ struct body_handler { : body(body) {} BOOST_NETWORK_HTTP_BODY_CALLBACK(operator(), range, error) { - std::cout << "Length: " << std::distance(boost::begin(range), boost::end(range)) << std::endl; body.append(boost::begin(range), boost::end(range)); } @@ -26,20 +26,23 @@ struct body_handler { }; -BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_streaming_test, client, client_types) { +BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_streaming_test, client, async_only_client_types) { typename client::request request("http://www.boost.org/"); - client client_; typename client::response response; typename client::string_type body_string; + typename client::string_type dummy_body; body_handler handler_instance(body_string); - BOOST_CHECK_NO_THROW( response = client_.get(request, http::_body_handler=handler_instance) ); - typename net::headers_range::type range = headers(response)["Content-Type"]; - BOOST_CHECK ( !boost::empty(range) ); - BOOST_CHECK ( body(response).size() != 0 ); - BOOST_CHECK_EQUAL ( response.version().substr(0, 7), std::string("HTTP/1.") ); - BOOST_CHECK_EQUAL ( response.status(), 200u ); - BOOST_CHECK_EQUAL ( response.status_message(), std::string("OK") ); - typename client::string_type dummy_body = body(response); - BOOST_CHECK_EQUAL ( dummy_body, typename client::string_type() ); + { + client client_; + BOOST_CHECK_NO_THROW( response = client_.get(request, http::_body_handler=handler_instance) ); + typename net::headers_range::type range = headers(response)["Content-Type"]; + BOOST_CHECK ( !boost::empty(range) ); + BOOST_CHECK_EQUAL ( body(response).size(), 0u ); + BOOST_CHECK_EQUAL ( response.version().substr(0, 7), std::string("HTTP/1.") ); + BOOST_CHECK_EQUAL ( response.status(), 200u ); + BOOST_CHECK_EQUAL ( response.status_message(), std::string("OK") ); + dummy_body = body(response); + } + BOOST_CHECK ( dummy_body == typename client::string_type() ); } diff --git a/libs/network/test/http/client_types.hpp b/libs/network/test/http/client_types.hpp index 4dc069e26..3bed03afe 100644 --- a/libs/network/test/http/client_types.hpp +++ b/libs/network/test/http/client_types.hpp @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include namespace mpl = boost::mpl ; @@ -41,4 +43,26 @@ typedef mpl::joint_view< , client_1_1 >::type client_types; +typedef + mpl::joint_view< + mpl::transform< + mpl::remove_if< + tag_types, + boost::network::is_sync< + boost::mpl::_ + > + >::type, + client_adapter<1,0> + >::type, + mpl::transform< + mpl::remove_if< + tag_types, + boost::network::is_sync< + boost::mpl::_ + > + >::type, + client_adapter<1,1> + >::type + >::type async_only_client_types; + #endif /* CLIENT_TYPES_ROOWQCLE */ From b741b4fee158418822d7e87049503688d9a9b9e2 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Wed, 3 Aug 2011 16:17:17 +1000 Subject: [PATCH 124/768] Addressing short read bugs, general cleanup. --- boost/network/protocol/http/client.hpp | 2 +- .../protocol/http/client/async_impl.hpp | 10 +- .../http/client/connection/async_normal.hpp | 94 ++++---- .../connection/async_protocol_handler.hpp | 213 +++++++++++++----- .../http/client/connection/async_ssl.hpp | 202 ++++++++++------- boost/network/protocol/http/client/facade.hpp | 18 +- .../protocol/http/parser/incremental.hpp | 20 +- .../http/policies/async_connection.hpp | 6 +- .../test/http/client_constructor_test.cpp | 2 +- libs/network/test/http/client_get_test.cpp | 7 +- .../http/client_localhost_normal_test.cpp | 64 +++--- libs/network/test/server/cgi-bin/echo_body.py | 1 + .../test/server/cgi-bin/echo_headers.py | 1 + .../test/server/cgi-bin/multiline-header.py | 3 +- .../test/server/cgi-bin/requestinfo.py | 1 + libs/network/test/server/http_test_server.py | 2 - 16 files changed, 400 insertions(+), 246 deletions(-) diff --git a/boost/network/protocol/http/client.hpp b/boost/network/protocol/http/client.hpp index 2a8b1770c..5460691b9 100644 --- a/boost/network/protocol/http/client.hpp +++ b/boost/network/protocol/http/client.hpp @@ -66,7 +66,7 @@ namespace boost { namespace network { namespace http { BOOST_PARAMETER_CONSTRUCTOR( basic_client, (base_facade_type), tag, (optional - (in_out(io_service), (boost::asio::io_service)) + (in_out(io_service), (boost::asio::io_service&)) (follow_redirects, (bool)) (cache_resolved, (bool)) (openssl_certificate, (string_type)) diff --git a/boost/network/protocol/http/client/async_impl.hpp b/boost/network/protocol/http/client/async_impl.hpp index d4e730f9a..66844b271 100644 --- a/boost/network/protocol/http/client/async_impl.hpp +++ b/boost/network/protocol/http/client/async_impl.hpp @@ -18,7 +18,7 @@ namespace boost { namespace network { namespace http { namespace impl { template - struct async_client : + struct async_client : connection_policy::type { typedef @@ -31,7 +31,7 @@ namespace boost { namespace network { namespace http { typename string::type string_type; - typedef + typedef function const &, system::error_code const &)> body_callback_function_type; @@ -75,11 +75,11 @@ namespace boost { namespace network { namespace http { } basic_response const request_skeleton( - basic_request const & request_, - string_type const & method, + basic_request const & request_, + string_type const & method, bool get_body, body_callback_function_type callback - ) + ) { typename connection_base::connection_ptr connection_; connection_ = connection_base::get_connection(resolver_, request_, certificate_filename_, verify_path_); diff --git a/boost/network/protocol/http/client/connection/async_normal.hpp b/boost/network/protocol/http/client/connection/async_normal.hpp index 8c3567cf7..b3b106a0a 100644 --- a/boost/network/protocol/http/client/connection/async_normal.hpp +++ b/boost/network/protocol/http/client/connection/async_normal.hpp @@ -51,12 +51,12 @@ namespace boost { namespace network { namespace http { namespace impl { http_async_connection( resolver_type & resolver, - resolve_function resolve, - bool follow_redirect - ) : + resolve_function resolve, + bool follow_redirect + ) : follow_redirect_(follow_redirect), resolver_(resolver), - resolve_(resolve), + resolve_(resolve), request_strand_(resolver.get_io_service()) {} @@ -68,7 +68,7 @@ namespace boost { namespace network { namespace http { namespace impl { std::ostreambuf_iterator::type>(&command_streambuf)); this->method = method; boost::uint16_t port_ = port(request); - resolve_(resolver_, host(request), + resolve_(resolver_, host(request), port_, request_strand_.wrap( boost::bind( @@ -83,6 +83,17 @@ namespace boost { namespace network { namespace http { namespace impl { http_async_connection(http_async_connection const &); // = delete + void set_errors(boost::system::error_code const & ec) { + boost::system::system_error error(ec); + this->version_promise.set_exception(boost::copy_exception(error)); + this->status_promise.set_exception(boost::copy_exception(error)); + this->status_message_promise.set_exception(boost::copy_exception(error)); + this->headers_promise.set_exception(boost::copy_exception(error)); + this->source_promise.set_exception(boost::copy_exception(error)); + this->destination_promise.set_exception(boost::copy_exception(error)); + this->body_promise.set_exception(boost::copy_exception(error)); + } + void handle_resolved(boost::uint16_t port, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, resolver_iterator_pair endpoint_range) { resolver_iterator iter = boost::begin(endpoint_range); if (!ec && !boost::empty(endpoint_range)) { @@ -103,14 +114,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::asio::placeholders::error ))); } else { - boost::system::system_error error(ec ? ec : boost::asio::error::host_not_found); - this->version_promise.set_exception(boost::copy_exception(error)); - this->status_promise.set_exception(boost::copy_exception(error)); - this->status_message_promise.set_exception(boost::copy_exception(error)); - this->headers_promise.set_exception(boost::copy_exception(error)); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - this->body_promise.set_exception(boost::copy_exception(error)); + set_errors(ec ? ec : boost::asio::error::host_not_found); } } @@ -123,7 +127,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &http_async_connection::handle_sent_request, http_async_connection::shared_from_this(), - get_body, callback, + get_body, callback, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ))); @@ -146,16 +150,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::asio::placeholders::error ))); } else { - boost::system::system_error error( - ec ? ec : boost::asio::error::host_not_found - ); - this->version_promise.set_exception(boost::copy_exception(error)); - this->status_promise.set_exception(boost::copy_exception(error)); - this->status_message_promise.set_exception(boost::copy_exception(error)); - this->headers_promise.set_exception(boost::copy_exception(error)); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - this->body_promise.set_exception(boost::copy_exception(error)); + set_errors(ec ? ec : boost::asio::error::host_not_found); } } } @@ -173,36 +168,34 @@ namespace boost { namespace network { namespace http { namespace impl { &http_async_connection::handle_received_data, http_async_connection::shared_from_this(), version, get_body, callback, - boost::asio::placeholders::error, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); } else { - boost::system::system_error error(ec); - this->version_promise.set_exception(boost::copy_exception(error)); - this->status_promise.set_exception(boost::copy_exception(error)); - this->status_message_promise.set_exception(boost::copy_exception(error)); - this->headers_promise.set_exception(boost::copy_exception(error)); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - this->body_promise.set_exception(boost::copy_exception(error)); + set_errors(ec); } } void handle_received_data(state_t state, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { if (!ec || ec == boost::asio::error::eof) { + // Sanity check + if (ec == boost::asio::error::eof && state < headers) { + return; + } logic::tribool parsed_ok; size_t remainder; switch(state) { case version: - parsed_ok = + parsed_ok = this->parse_version(*socket_, request_strand_.wrap( boost::bind( &http_async_connection::handle_received_data, http_async_connection::shared_from_this(), - status, get_body, callback, + version, get_body, callback, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) - ) + ), + bytes_transferred ); if (parsed_ok != true) return; case status: @@ -212,10 +205,11 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &http_async_connection::handle_received_data, http_async_connection::shared_from_this(), - status_message, get_body, callback, + status, get_body, callback, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) - ) + ), + bytes_transferred ); if (parsed_ok != true) return; case status_message: @@ -225,10 +219,11 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &http_async_connection::handle_received_data, http_async_connection::shared_from_this(), - headers, get_body, callback, + status_message, get_body, callback, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) - ) + ), + bytes_transferred ); if (parsed_ok != true) return; case headers: @@ -241,7 +236,8 @@ namespace boost { namespace network { namespace http { namespace impl { headers, get_body, callback, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) - ) + ), + bytes_transferred ); if (parsed_ok != true) return; if (!get_body) { @@ -253,8 +249,9 @@ namespace boost { namespace network { namespace http { namespace impl { std::advance(begin, remainder); typename protocol_base::buffer_type::const_iterator end = begin; std::advance(end, this->part.size() - remainder); + this->body_promise.set_value(""); callback(make_iterator_range(begin, end), ec); - socket_->async_read_some( + socket_->async_read_some( boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), request_strand_.wrap( boost::bind( @@ -264,7 +261,6 @@ namespace boost { namespace network { namespace http { namespace impl { boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred) ) ); - this->body_promise.set_value(""); } else { this->parse_body( *socket_, @@ -278,7 +274,7 @@ namespace boost { namespace network { namespace http { namespace impl { ), remainder); } - break; + return; case body: if (ec == boost::asio::error::eof) { if (callback) { @@ -304,7 +300,7 @@ namespace boost { namespace network { namespace http { namespace impl { typename protocol_base::buffer_type::const_iterator begin = this->part.begin(), end = begin; std::advance(end, bytes_transferred); callback(make_iterator_range(begin, end), ec); - socket_->async_read_some( + socket_->async_read_some( boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), request_strand_.wrap( boost::bind( @@ -328,7 +324,7 @@ namespace boost { namespace network { namespace http { namespace impl { bytes_transferred); } } - break; + return; default: BOOST_ASSERT(false && "Bug, report this to the developers!"); } @@ -337,13 +333,13 @@ namespace boost { namespace network { namespace http { namespace impl { this->source_promise.set_exception(boost::copy_exception(error)); this->destination_promise.set_exception(boost::copy_exception(error)); switch (state) { - case version: + case version: this->version_promise.set_exception(boost::copy_exception(error)); - case status: + case status: this->status_promise.set_exception(boost::copy_exception(error)); case status_message: this->status_message_promise.set_exception(boost::copy_exception(error)); - case headers: + case headers: this->headers_promise.set_exception(boost::copy_exception(error)); case body: this->body_promise.set_exception(boost::copy_exception(error)); diff --git a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp index 0d4c71f32..f9dc0aa87 100644 --- a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp +++ b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp @@ -1,11 +1,14 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_20101015 -#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_20101015 +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_ +#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_ // Copyright 2010 (C) Dean Michael Berris +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include #include namespace boost { namespace network { namespace http { namespace impl { @@ -16,21 +19,53 @@ namespace boost { namespace network { namespace http { namespace impl { typedef typename string::type string_type; +#ifdef BOOST_NETWORK_DEBUG + struct debug_escaper { + string_type & string; + explicit debug_escaper(string_type & string_) + : string(string_) {} + debug_escaper(debug_escaper const & other) + : string(other.string) {} + void operator()(typename string_type::value_type input) { + if (!algorithm::is_print()(input)) { + typename ostringstream::type escaped_stream; + if (input == '\r') { + string.append("\\r"); + } else if (input == '\n') { + string.append("\\n"); + } else { + escaped_stream << "\\x" << static_cast(input); + string.append(escaped_stream.str()); + } + } else { + string.push_back(input); + } + } + }; +#endif + template void init_response(ResponseType & response_, bool get_body) { - boost::shared_future source_future(source_promise.get_future()); + boost::shared_future source_future( + source_promise.get_future()); source(response_, source_future); - boost::shared_future destination_future(destination_promise.get_future()); + boost::shared_future destination_future( + destination_promise.get_future()); destination(response_, destination_future); - boost::shared_future::type> headers_future(headers_promise.get_future()); + boost::shared_future::type> + headers_future(headers_promise.get_future()); headers(response_, headers_future); - boost::shared_future body_future(body_promise.get_future()); + boost::shared_future body_future( + body_promise.get_future()); body(response_, body_future); - boost::shared_future version_future(version_promise.get_future()); + boost::shared_future version_future( + version_promise.get_future()); version(response_, version_future); - boost::shared_future status_future(status_promise.get_future()); + boost::shared_future status_future( + status_promise.get_future()); status(response_, status_future); - boost::shared_future status_message_future(status_message_promise.get_future()); + boost::shared_future status_message_future( + status_message_promise.get_future()); status_message(response_, status_message_future); } @@ -51,24 +86,43 @@ namespace boost { namespace network { namespace http { namespace impl { }; template - logic::tribool parse_version(Socket & socket_, Callback callback) { + logic::tribool parse_version(Socket & socket_, + Callback callback, + size_t bytes) { logic::tribool parsed_ok; - typename boost::iterator_range result_range; + part_begin = part.begin(); + typename buffer_type::const_iterator part_end = part.begin(); + std::advance(part_end, bytes); + typename boost::iterator_range + result_range, + input_range = boost::make_iterator_range(part_begin, part_end); fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( response_parser_type::http_version_done, - part); + input_range); if (parsed_ok == true) { string_type version; std::swap(version, partial_parsed); - version.append(boost::begin(result_range), boost::end(result_range)); + version.append(boost::begin(result_range), + boost::end(result_range)); algorithm::trim(version); version_promise.set_value(version); part_begin = boost::end(result_range); } else if (parsed_ok == false) { +#ifdef BOOST_NETWORK_DEBUG + string_type escaped; + debug_escaper escaper(escaped); + std::for_each(part_begin, part_end, escaper); + BOOST_NETWORK_MESSAGE("[parser:" + << response_parser_.state() + << "] buffer contents: \"" + << escaped + << "\""); +#endif std::runtime_error error("Invalid Version Part."); version_promise.set_exception(boost::copy_exception(error)); status_promise.set_exception(boost::copy_exception(error)); - status_message_promise.set_exception(boost::copy_exception(error)); + status_message_promise.set_exception( + boost::copy_exception(error)); headers_promise.set_exception(boost::copy_exception(error)); source_promise.set_exception(boost::copy_exception(error)); destination_promise.set_exception(boost::copy_exception(error)); @@ -88,10 +142,14 @@ namespace boost { namespace network { namespace http { namespace impl { } template - logic::tribool parse_status(Socket & socket_, Callback callback) { + logic::tribool parse_status(Socket & socket_, + Callback callback, + size_t bytes) { logic::tribool parsed_ok; - typename buffer_type::const_iterator part_end = part.end(); - typename boost::iterator_range result_range, + typename buffer_type::const_iterator part_end = part.begin(); + std::advance(part_end, bytes); + typename boost::iterator_range + result_range, input_range = boost::make_iterator_range(part_begin, part_end); fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( response_parser_type::http_status_done, @@ -99,22 +157,35 @@ namespace boost { namespace network { namespace http { namespace impl { if (parsed_ok == true) { string_type status; std::swap(status, partial_parsed); - status.append(boost::begin(result_range), boost::end(result_range)); + status.append(boost::begin(result_range), + boost::end(result_range)); trim(status); - boost::uint16_t status_int = lexical_cast(status); + boost::uint16_t status_int = + lexical_cast(status); status_promise.set_value(status_int); part_begin = boost::end(result_range); } else if (parsed_ok == false) { +#ifdef BOOST_NETWORK_DEBUG + string_type escaped; + debug_escaper escaper(escaped); + std::for_each(part_begin, part_end, escaper); + BOOST_NETWORK_MESSAGE("[parser:" + << response_parser_.state() + << "] buffer contents: \"" + << escaped + << "\""); +#endif std::runtime_error error("Invalid status part."); status_promise.set_exception(boost::copy_exception(error)); - status_message_promise.set_exception(boost::copy_exception(error)); + status_message_promise.set_exception( + boost::copy_exception(error)); headers_promise.set_exception(boost::copy_exception(error)); source_promise.set_exception(boost::copy_exception(error)); destination_promise.set_exception(boost::copy_exception(error)); body_promise.set_exception(boost::copy_exception(error)); } else { partial_parsed.append( - boost::begin(result_range), + boost::begin(result_range), boost::end(result_range) ); part_begin = part.begin(); @@ -127,10 +198,14 @@ namespace boost { namespace network { namespace http { namespace impl { } template - logic::tribool parse_status_message(Socket & socket_, Callback callback) { + logic::tribool parse_status_message(Socket & socket_, + Callback callback, + size_t bytes) { logic::tribool parsed_ok; - typename buffer_type::const_iterator part_end = part.end(); - typename boost::iterator_range result_range, + typename buffer_type::const_iterator part_end = part.begin(); + std::advance(part_end, bytes); + typename boost::iterator_range + result_range, input_range = boost::make_iterator_range(part_begin, part_end); fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( response_parser_type::http_status_message_done, @@ -138,20 +213,32 @@ namespace boost { namespace network { namespace http { namespace impl { if (parsed_ok == true) { string_type status_message; std::swap(status_message, partial_parsed); - status_message.append(boost::begin(result_range), boost::end(result_range)); + status_message.append(boost::begin(result_range), + boost::end(result_range)); algorithm::trim(status_message); status_message_promise.set_value(status_message); part_begin = boost::end(result_range); } else if (parsed_ok == false) { +#ifdef BOOST_NETWORK_DEBUG + string_type escaped; + debug_escaper escaper(escaped); + std::for_each(part_begin, part_end, escaper); + BOOST_NETWORK_MESSAGE("[parser:" + << response_parser_.state() + << "] buffer contents: \"" + << escaped + << "\""); +#endif std::runtime_error error("Invalid status message part."); - status_message_promise.set_exception(boost::copy_exception(error)); + status_message_promise.set_exception( + boost::copy_exception(error)); headers_promise.set_exception(boost::copy_exception(error)); source_promise.set_exception(boost::copy_exception(error)); destination_promise.set_exception(boost::copy_exception(error)); body_promise.set_exception(boost::copy_exception(error)); } else { partial_parsed.append( - boost::begin(result_range), + boost::begin(result_range), boost::end(result_range)); part_begin = part.begin(); socket_.async_read_some( @@ -163,28 +250,31 @@ namespace boost { namespace network { namespace http { namespace impl { } void parse_headers_real(string_type & headers_part) { - typename boost::iterator_range + typename boost::iterator_range input_range = boost::make_iterator_range(headers_part) , result_range; logic::tribool parsed_ok; - response_parser_type headers_parser(response_parser_type::http_header_line_done); + response_parser_type headers_parser( + response_parser_type::http_header_line_done); typename headers_container::type headers; std::pair header_pair; while (!boost::empty(input_range)) { - fusion::tie(parsed_ok, result_range) = headers_parser.parse_until( - response_parser_type::http_header_colon - , input_range); - if (headers_parser.state() != response_parser_type::http_header_colon) break; - header_pair.first = string_type( - boost::begin(result_range), - boost::end(result_range)); + fusion::tie(parsed_ok, result_range) = + headers_parser.parse_until( + response_parser_type::http_header_colon, + input_range); + if (headers_parser.state() + != response_parser_type::http_header_colon) + break; + header_pair.first = string_type(boost::begin(result_range), + boost::end(result_range)); input_range.advance_begin(boost::distance(result_range)); - fusion::tie(parsed_ok, result_range) = headers_parser.parse_until( - response_parser_type::http_header_line_done - , input_range); - header_pair.second = string_type( - boost::begin(result_range), - boost::end(result_range)); + fusion::tie(parsed_ok, result_range) = + headers_parser.parse_until( + response_parser_type::http_header_line_done, + input_range); + header_pair.second = string_type(boost::begin(result_range), + boost::end(result_range)); input_range.advance_begin(boost::distance(result_range)); trim(header_pair.first); @@ -200,10 +290,14 @@ namespace boost { namespace network { namespace http { namespace impl { } template - fusion::tuple parse_headers(Socket & socket_, Callback callback) { + fusion::tuple parse_headers(Socket & socket_, + Callback callback, + size_t bytes) { logic::tribool parsed_ok; - typename buffer_type::const_iterator part_end = part.end(); - typename boost::iterator_range result_range, + typename buffer_type::const_iterator part_end = part.begin(); + std::advance(part_end, bytes); + typename boost::iterator_range + result_range, input_range = boost::make_iterator_range(part_begin, part_end); fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( response_parser_type::http_headers_done, @@ -211,17 +305,32 @@ namespace boost { namespace network { namespace http { namespace impl { if (parsed_ok == true) { string_type headers_string; std::swap(headers_string, partial_parsed); - headers_string.append(boost::begin(result_range), boost::end(result_range)); + headers_string.append(boost::begin(result_range), + boost::end(result_range)); part_begin = boost::end(result_range); this->parse_headers_real(headers_string); } else if (parsed_ok == false) { + // We want to output the contents of the buffer that caused + // the error in debug builds. +#ifdef BOOST_NETWORK_DEBUG + string_type escaped; + debug_escaper escaper(escaped); + std::for_each(part_begin, part_end, escaper); + BOOST_NETWORK_MESSAGE("[parser:" + << response_parser_.state() + << "] buffer contents: \"" + << escaped + << "\" consumed length: " + << boost::distance(result_range)); +#endif std::runtime_error error("Invalid header part."); headers_promise.set_exception(boost::copy_exception(error)); body_promise.set_exception(boost::copy_exception(error)); source_promise.set_exception(boost::copy_exception(error)); destination_promise.set_exception(boost::copy_exception(error)); } else { - partial_parsed.append(boost::begin(result_range), boost::end(result_range)); + partial_parsed.append(boost::begin(result_range), + boost::end(result_range)); part_begin = part.begin(); socket_.async_read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), @@ -229,7 +338,7 @@ namespace boost { namespace network { namespace http { namespace impl { ); } return fusion::make_tuple( - parsed_ok, + parsed_ok, std::distance( boost::end(result_range) , part_end @@ -241,7 +350,7 @@ namespace boost { namespace network { namespace http { namespace impl { void parse_body(Socket & socket_, Callback callback, size_t bytes) { partial_parsed.append(part_begin, bytes); part_begin = part.begin(); - socket_.async_read_some( + socket_.async_read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); @@ -263,13 +372,13 @@ namespace boost { namespace network { namespace http { namespace impl { string_type partial_parsed; }; - + } /* impl */ - + } /* http */ } /* network */ - + } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_ASYNC_PROTOCOL_HANDLER_HPP_20101015 */ diff --git a/boost/network/protocol/http/client/connection/async_ssl.hpp b/boost/network/protocol/http/client/connection/async_ssl.hpp index 6aecd1160..1b2af32f1 100644 --- a/boost/network/protocol/http/client/connection/async_ssl.hpp +++ b/boost/network/protocol/http/client/connection/async_ssl.hpp @@ -3,6 +3,7 @@ // Copyright 2010 (C) Dean Michael Berris // Copyright 2010 (C) Sinefunc, Inc. +// Copyright 2011 Dean Michael Berris (dberris@google.com). // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -36,16 +37,16 @@ namespace boost { namespace network { namespace http { namespace impl { https_async_connection( resolver_type & resolver, - resolve_function resolve, + resolve_function resolve, bool follow_redirect, - optional const & certificate_filename = optional(), + optional const & certificate_filename = optional(), optional const & verify_path = optional() - ) : + ) : follow_redirect_(follow_redirect), resolver_(resolver), certificate_filename_(certificate_filename), verify_path_(verify_path), - resolve_(resolve), + resolve_(resolve), request_strand_(resolver.get_io_service()) {} @@ -57,19 +58,19 @@ namespace boost { namespace network { namespace http { namespace impl { std::ostreambuf_iterator::type>(&command_streambuf)); this->method = method; boost::uint16_t port_ = port(request); - resolve_(resolver_, host(request), + resolve_(resolver_, host(request), port_, request_strand_.wrap( boost::bind( &https_async_connection::handle_resolved, https_async_connection::shared_from_this(), - port_, get_body, + port_, get_body, callback, _1, _2))); return response_; } private: - void handle_resolved(boost::uint16_t port, bool get_body, boost::system::error_code const & ec, resolver_iterator_pair endpoint_range) { + void handle_resolved(boost::uint16_t port, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, resolver_iterator_pair endpoint_range) { resolver_iterator iter = boost::begin(endpoint_range); if (!ec && !boost::empty(endpoint_range)) { boost::asio::ip::tcp::endpoint endpoint( @@ -99,7 +100,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &https_async_connection::handle_connected, https_async_connection::shared_from_this(), - port, get_body, std::make_pair(++iter, resolver_iterator()), + port, get_body, callback, std::make_pair(++iter, resolver_iterator()), boost::asio::placeholders::error ))); } else { @@ -114,14 +115,14 @@ namespace boost { namespace network { namespace http { namespace impl { } } - void handle_connected(boost::uint16_t port, bool get_body, resolver_iterator_pair endpoint_range, boost::system::error_code const & ec) { + void handle_connected(boost::uint16_t port, bool get_body, body_callback_function_type callback, resolver_iterator_pair endpoint_range, boost::system::error_code const & ec) { if (!ec) { socket_->async_handshake(boost::asio::ssl::stream_base::client, request_strand_.wrap( boost::bind( &https_async_connection::handle_handshake, https_async_connection::shared_from_this(), - port, get_body, + port, get_body, callback, boost::asio::placeholders::error ) ) @@ -144,7 +145,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &https_async_connection::handle_connected, https_async_connection::shared_from_this(), - port, get_body, std::make_pair(++iter, resolver_iterator()), + port, get_body, callback, std::make_pair(++iter, resolver_iterator()), boost::asio::placeholders::error ))); } else { @@ -162,30 +163,30 @@ namespace boost { namespace network { namespace http { namespace impl { } } - void handle_handshake(boost::uint16_t port, bool get_body, boost::system::error_code const & ec) { + void handle_handshake(boost::uint16_t port, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec) { if (!ec) { - boost::asio::async_write( - *socket_ - , command_streambuf - , request_strand_.wrap( - boost::bind( - &https_async_connection::handle_sent_request, - https_async_connection::shared_from_this(), - get_body, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred - ))); + boost::asio::async_write( + *socket_ + , command_streambuf + , request_strand_.wrap( + boost::bind( + &https_async_connection::handle_sent_request, + https_async_connection::shared_from_this(), + get_body, callback, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred + ))); } else { - boost::system::system_error error( - ec ? ec : boost::asio::error::host_not_found - ); - this->version_promise.set_exception(boost::copy_exception(error)); - this->status_promise.set_exception(boost::copy_exception(error)); - this->status_message_promise.set_exception(boost::copy_exception(error)); - this->headers_promise.set_exception(boost::copy_exception(error)); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - this->body_promise.set_exception(boost::copy_exception(error)); + boost::system::system_error error( + ec ? ec : boost::asio::error::host_not_found + ); + this->version_promise.set_exception(boost::copy_exception(error)); + this->status_promise.set_exception(boost::copy_exception(error)); + this->status_message_promise.set_exception(boost::copy_exception(error)); + this->headers_promise.set_exception(boost::copy_exception(error)); + this->source_promise.set_exception(boost::copy_exception(error)); + this->destination_promise.set_exception(boost::copy_exception(error)); + this->body_promise.set_exception(boost::copy_exception(error)); } } @@ -193,18 +194,18 @@ namespace boost { namespace network { namespace http { namespace impl { version, status, status_message, headers, body }; - void handle_sent_request(bool get_body, boost::system::error_code const & ec, std::size_t bytes_transferred) { + void handle_sent_request(bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { if (!ec) { - boost::asio::async_read( - *socket_, + socket_->async_read_some( boost::asio::mutable_buffers_1( - this->part.c_array(), + this->part.c_array(), this->part.size()), request_strand_.wrap( boost::bind( &https_async_connection::handle_received_data, https_async_connection::shared_from_this(), - version, get_body, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); + version, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); } else { boost::system::system_error error( ec ? ec : boost::asio::error::host_not_found @@ -219,22 +220,24 @@ namespace boost { namespace network { namespace http { namespace impl { } } - void handle_received_data(state_t state, bool get_body, boost::system::error_code const & ec, std::size_t bytes_transferred) { + void handle_received_data(state_t state, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { if (!ec || ec == boost::asio::error::eof) { logic::tribool parsed_ok; size_t remainder; switch(state) { case version: - parsed_ok = + parsed_ok = this->parse_version( *socket_, request_strand_.wrap( boost::bind( &https_async_connection::handle_received_data, https_async_connection::shared_from_this(), - status, get_body, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + status, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) - ) + ), + bytes_transferred ); if (parsed_ok != true) return; case status: @@ -244,9 +247,11 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &https_async_connection::handle_received_data, https_async_connection::shared_from_this(), - status_message, get_body, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + status_message, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) - ) + ), + bytes_transferred ); if (parsed_ok != true) return; case status_message: @@ -256,9 +261,11 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &https_async_connection::handle_received_data, https_async_connection::shared_from_this(), - headers, get_body, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + headers, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) - ) + ), + bytes_transferred ); if (parsed_ok != true) return; case headers: @@ -268,44 +275,32 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &https_async_connection::handle_received_data, https_async_connection::shared_from_this(), - body, get_body, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + headers, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) - ) + ), + bytes_transferred ); if (parsed_ok != true) return; if (!get_body) { this->body_promise.set_value(""); return; } - this->parse_body( - *socket_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - body, get_body, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - remainder); - break; - case body: - if (!get_body) { + if (callback) { + typename protocol_base::buffer_type::const_iterator begin = this->part.begin(); + std::advance(begin, remainder); + typename protocol_base::buffer_type::const_iterator end = begin; + std::advance(end, this->part.size() - remainder); + callback(make_iterator_range(begin, end), ec); + socket_->async_read_some( + boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), + request_strand_.wrap( + boost::bind( + &https_async_connection::handle_received_data, + https_async_connection::shared_from_this(), + body, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); this->body_promise.set_value(""); - return; - } - if (ec == boost::asio::error::eof) { - string_type body; - std::swap(body, this->partial_parsed); - body.append( - this->part.begin() - , bytes_transferred - ); - this->body_promise.set_value(body); - // TODO set the destination value somewhere! - this->destination_promise.set_value(""); - this->source_promise.set_value(""); - this->part.assign('\0'); - this->response_parser_.reset(); } else { this->parse_body( *socket_, @@ -313,10 +308,59 @@ namespace boost { namespace network { namespace http { namespace impl { boost::bind( &https_async_connection::handle_received_data, https_async_connection::shared_from_this(), - body, get_body, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + body, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ) ), - bytes_transferred); + remainder); + } + break; + case body: + if (ec == boost::asio::error::eof) { + if (callback) { + typename protocol_base::buffer_type::const_iterator begin = this->part.begin(), end = begin; + std::advance(end, bytes_transferred); + callback(make_iterator_range(begin, end), ec); + } else { + string_type body; + std::swap(body, this->partial_parsed); + body.append( + this->part.begin() + , bytes_transferred + ); + this->body_promise.set_value(body); + } + // TODO set the destination value somewhere! + this->destination_promise.set_value(""); + this->source_promise.set_value(""); + this->part.assign('\0'); + this->response_parser_.reset(); + } else { + if (callback) { + typename protocol_base::buffer_type::const_iterator begin = this->part.begin(), end = begin; + std::advance(end, bytes_transferred); + callback(make_iterator_range(begin, end), ec); + socket_->async_read_some( + boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), + request_strand_.wrap( + boost::bind( + &https_async_connection::handle_received_data, + https_async_connection::shared_from_this(), + body, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); + } else { + this->parse_body( + *socket_, + request_strand_.wrap( + boost::bind( + &https_async_connection::handle_received_data, + https_async_connection::shared_from_this(), + body, get_body, callback, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred + ) + ), + bytes_transferred); + } } break; default: @@ -354,7 +398,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::asio::streambuf command_streambuf; string_type method; }; - + } // namespace impl } // namespace http diff --git a/boost/network/protocol/http/client/facade.hpp b/boost/network/protocol/http/client/facade.hpp index eb9c191d0..639fb7277 100644 --- a/boost/network/protocol/http/client/facade.hpp +++ b/boost/network/protocol/http/client/facade.hpp @@ -31,7 +31,7 @@ namespace boost { namespace network { namespace http { template basic_client_facade(ArgPack const & args) { - init_pimpl(args, + init_pimpl(args, typename mpl::if_< is_same< typename parameter::value_type::type, @@ -46,8 +46,8 @@ namespace boost { namespace network { namespace http { return pimpl->request_skeleton(request, "HEAD", false, body_callback_function_type()); } - BOOST_PARAMETER_MEMBER_FUNCTION((response const), get , tag, - (required + BOOST_PARAMETER_MEMBER_FUNCTION((response const), get , tag, + (required (request,(request const &)) ) (optional @@ -57,11 +57,11 @@ namespace boost { namespace network { namespace http { return pimpl->request_skeleton(request, "GET", true, body_handler); } - BOOST_PARAMETER_MEMBER_FUNCTION((response const), post, tag, - (required + BOOST_PARAMETER_MEMBER_FUNCTION((response const), post, tag, + (required (request,(request)) // yes sir, we make a copy of the original request. ) - (optional + (optional (body,(string_type const &),string_type()) (content_type,(string_type const &),string_type()) (body_handler,(body_callback_function_type),body_callback_function_type()) @@ -88,11 +88,11 @@ namespace boost { namespace network { namespace http { return pimpl->request_skeleton(request, "POST", true, body_handler); } - BOOST_PARAMETER_MEMBER_FUNCTION((response const), put , tag, - (required + BOOST_PARAMETER_MEMBER_FUNCTION((response const), put , tag, + (required (request,(request)) // yes sir, we make a copy of the original request. ) - (optional + (optional (body,(string_type const &),string_type()) (content_type,(string_type const &),string_type()) (body_handler,(body_callback_function_type),body_callback_function_type()) diff --git a/boost/network/protocol/http/parser/incremental.hpp b/boost/network/protocol/http/parser/incremental.hpp index 6a07a5a1c..44c4c2a2e 100644 --- a/boost/network/protocol/http/parser/incremental.hpp +++ b/boost/network/protocol/http/parser/incremental.hpp @@ -1,10 +1,12 @@ #ifndef BOOST_NETWORK_PROTOCOL_HTTP_PARSER_INCREMENTAL_HPP_20100909 #define BOOST_NETWORK_PROTOCOL_HTTP_PARSER_INCREMENTAL_HPP_20100909 -// Copyright Dean Michael Berris 2010. +// Copyright Dean Michael Berris 2010. +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) #include #include @@ -15,7 +17,7 @@ #include namespace boost { namespace network { namespace http { - + template struct response_parser { @@ -47,11 +49,11 @@ namespace boost { namespace network { namespace http { explicit response_parser (state_t state=http_response_begin) : state_(state) {} - response_parser (response_parser const & other) + response_parser (response_parser const & other) : state_(other.state_) {} ~response_parser () {} - + void swap(response_parser & other) { std::swap(other.state_, this->state_); } @@ -63,7 +65,6 @@ namespace boost { namespace network { namespace http { template fusion::tuple > parse_until(state_t stop_state, Range & range_) { - //FIXME -- find a way to make better use of the Boost.String_algorithm classifiers logic::tribool parsed_ok(logic::indeterminate); typename Range::const_iterator start = boost::begin(range_), current = start, @@ -263,7 +264,6 @@ namespace boost { namespace network { namespace http { local_range = boost::make_iterator_range(current, end); } if (state_ == stop_state) parsed_ok = true; - else parsed_ok = false; return fusion::make_tuple(parsed_ok,boost::make_iterator_range(start, current)); } @@ -279,12 +279,12 @@ namespace boost { namespace network { namespace http { state_t state_; }; - + } /* http */ } /* network */ - + } /* boost */ #endif diff --git a/boost/network/protocol/http/policies/async_connection.hpp b/boost/network/protocol/http/policies/async_connection.hpp index ea353a781..bfbd7d446 100644 --- a/boost/network/protocol/http/policies/async_connection.hpp +++ b/boost/network/protocol/http/policies/async_connection.hpp @@ -29,11 +29,11 @@ namespace boost { namespace network { namespace http { typedef typename resolver_base::resolver_type resolver_type; typedef typename resolver_base::resolve_function resolve_function; typedef function const &, system::error_code const &)> body_callback_function_type; - + struct connection_impl { connection_impl( - bool follow_redirect, - resolve_function resolve, + bool follow_redirect, + resolve_function resolve, resolver_type & resolver, bool https, optional const & certificate_filename, diff --git a/libs/network/test/http/client_constructor_test.cpp b/libs/network/test/http/client_constructor_test.cpp index d5735ec8d..9fa0b15b2 100644 --- a/libs/network/test/http/client_constructor_test.cpp +++ b/libs/network/test/http/client_constructor_test.cpp @@ -15,6 +15,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_constructor_test, client, client_types client instance; boost::asio::io_service io_service; client instance2(io_service); + client instance3(http::_io_service=io_service); } BOOST_AUTO_TEST_CASE_TEMPLATE(http_cient_constructor_params_test, client, client_types) { @@ -33,4 +34,3 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_cient_constructor_params_test, client, client http::_openssl_verify_path="bar" ); } - diff --git a/libs/network/test/http/client_get_test.cpp b/libs/network/test/http/client_get_test.cpp index fbbf04505..15c7d19ee 100644 --- a/libs/network/test/http/client_get_test.cpp +++ b/libs/network/test/http/client_get_test.cpp @@ -15,10 +15,10 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_test, client, client_types) { typename client::request request("http://www.boost.org/"); client client_; typename client::response response; - BOOST_CHECK_NO_THROW ( response = client_.get(request) ); + BOOST_REQUIRE_NO_THROW ( response = client_.get(request) ); typename net::headers_range::type range = headers(response)["Content-Type"]; BOOST_CHECK ( !boost::empty(range) ); - BOOST_CHECK ( body(response).size() != 0 ); + BOOST_REQUIRE_NO_THROW ( BOOST_CHECK ( body(response).size() != 0 ) ); BOOST_CHECK_EQUAL ( response.version().substr(0,7), std::string("HTTP/1.") ); BOOST_CHECK_EQUAL ( response.status(), 200u ); BOOST_CHECK_EQUAL ( response.status_message(), std::string("OK") ); @@ -32,8 +32,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(https_client_get_test, client, client_types) { typename client::response response_ = client_.get(request); typename net::headers_range::type range = headers(response_)["Content-Type"]; BOOST_CHECK ( boost::begin(range) != boost::end(range) ); - BOOST_CHECK ( body(response_).size() != 0 ); + BOOST_REQUIRE_NO_THROW ( BOOST_CHECK( body(response_).size() != 0 ) ); } #endif - diff --git a/libs/network/test/http/client_localhost_normal_test.cpp b/libs/network/test/http/client_localhost_normal_test.cpp index 4302db03d..3a3711c1c 100644 --- a/libs/network/test/http/client_localhost_normal_test.cpp +++ b/libs/network/test/http/client_localhost_normal_test.cpp @@ -27,7 +27,7 @@ using std::endl; namespace { const std::string base_url = "http://localhost:8000/"; const std::string cgi_url = base_url + "/cgi-bin/requestinfo.py"; - + struct running_server_fixture { // NOTE: Can't use BOOST_REQUIRE_MESSAGE here, as Boost.Test data structures @@ -36,15 +36,15 @@ namespace { if( !server.start() ) cout << "Failed to start HTTP server for test!" << endl; } - + ~running_server_fixture() { if( !server.stop() ) cout << "Failed to stop HTTP server for test!" << endl; } - + http_test_server server; }; - + std::size_t readfile(std::ifstream& file, std::vector& buffer) { using std::ios; @@ -54,10 +54,10 @@ namespace { return buffer.size(); } - + std::map parse_headers(std::string const& body) { std::map headers; - + std::istringstream stream(body); while (stream.good()) { @@ -74,10 +74,10 @@ namespace { } } } - + return headers; } - + std::string get_content_length(std::string const& content) { return boost::lexical_cast(content.length()); } @@ -85,8 +85,8 @@ namespace { } #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) - // Uncomment the below if you're running Python pre-2.6. There was a bug - // in the Python HTTP server for earlier versions that causes this test + // Uncomment the below if you're running Python pre-2.6. There was a bug + // in the Python HTTP server for earlier versions that causes this test // case to fail. //BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(text_query_preserves_crlf, 2); #endif @@ -98,7 +98,8 @@ BOOST_AUTO_TEST_CASE(body_test) { using namespace boost::network; http::client::request request_(base_url); http::client client_; - http::client::response response_ = client_.get(request_); + http::client::response response_; + BOOST_REQUIRE_NO_THROW( response_ = client_.get(request_) ); BOOST_CHECK(body(response_).size() != 0); } @@ -107,7 +108,8 @@ BOOST_AUTO_TEST_CASE(text_content_type_test) { using namespace boost::network; http::client::request request_(base_url); http::client client_; - http::client::response response_ = client_.get(request_); + http::client::response response_; + BOOST_REQUIRE_NO_THROW( response_ = client_.get(request_) ); BOOST_REQUIRE(headers(response_).count("Content-type") != 0); headers_range::type range = headers(response_)["Content-type"]; BOOST_CHECK(boost::begin(range)->first == "Content-type"); @@ -119,7 +121,8 @@ BOOST_AUTO_TEST_CASE(binary_content_type_test) { using namespace boost::network; http::client::request request_(base_url + "/boost.jpg"); http::client client_; - http::client::response response_ = client_.get(request_); + http::client::response response_; + BOOST_REQUIRE_NO_THROW( response_ = client_.get(request_) ); BOOST_REQUIRE(headers(response_).count("Content-type") != 0); headers_range::type range = headers(response_)["Content-type"]; BOOST_CHECK(boost::begin(range)->first == "Content-type"); @@ -131,7 +134,8 @@ BOOST_AUTO_TEST_CASE(content_length_header_test) { using namespace boost::network; http::client::request request_(base_url + "/test.xml"); http::client client_; - http::client::response response_ = client_.get(request_); + http::client::response response_; + BOOST_REQUIRE_NO_THROW( response_ = client_.get(request_) ); BOOST_REQUIRE(headers(response_).count("Content-Length") != 0); headers_range::type range = headers(response_)["Content-Length"]; BOOST_CHECK_EQUAL(boost::begin(range)->first, "Content-Length"); @@ -144,8 +148,9 @@ BOOST_AUTO_TEST_CASE(text_query_preserves_crlf) { using namespace boost::network; http::client::request request_(base_url + "/test.xml"); http::client client_; - http::client::response response_ = client_.get(request_); - + http::client::response response_; + BOOST_REQUIRE_NO_THROW( response_ = client_.get(request_) ); + http::client::response::string_type body_ = body(response_); BOOST_CHECK(body(response_).size() != 0); @@ -156,7 +161,7 @@ BOOST_AUTO_TEST_CASE(text_query_preserves_crlf) { file.clear(); file.open("server/test.xml", ios::in | ios::binary); } - + BOOST_REQUIRE_MESSAGE( file, "Could not open local test.xml"); std::vector memblock; @@ -177,27 +182,27 @@ BOOST_AUTO_TEST_CASE(binary_file_query) { http::client::request request_(base_url + "/boost.jpg"); http::client client_; http::client::response response_; - BOOST_CHECK_NO_THROW(response_ = client_.get(request_)); - + BOOST_REQUIRE_NO_THROW(response_ = client_.get(request_)); + http::client::response::string_type body_ = body(response_); BOOST_CHECK(body_.size() != 0); using std::ios; - + std::ifstream file("libs/network/test/server/boost.jpg", ios::in | ios::binary); if( ! file ) { file.clear(); file.open("server/boost.jpg", ios::in | ios::binary); } - + BOOST_REQUIRE_MESSAGE( file, "Could not open boost.jpg locally"); - std::vector memblock; + std::vector memblock; std::size_t size = readfile(file, memblock); BOOST_CHECK(size != 0); BOOST_CHECK_EQUAL(body_.size(), size); - + std::pair::iterator, std::string::const_iterator> diff_pos = std::mismatch(memblock.begin(), memblock.end(), body_.begin()); BOOST_CHECK_EQUAL(boost::numeric_cast(diff_pos.first - memblock.begin()), size); } @@ -247,7 +252,8 @@ BOOST_AUTO_TEST_CASE(head_test) { using namespace boost::network; http::client::request request_(base_url + "/test.xml"); http::client client_; - http::client::response response_ = client_.head(request_); + http::client::response response_; + BOOST_REQUIRE_NO_THROW( response_ = client_.head(request_) ); BOOST_REQUIRE(headers(response_).count("Content-Length") != 0); headers_range::type range = headers(response_)["Content-Length"]; BOOST_CHECK_EQUAL(boost::begin(range)->first, "Content-Length"); @@ -272,7 +278,7 @@ BOOST_AUTO_TEST_CASE(post_with_explicit_headers) { http::client c; http::client::response r; BOOST_REQUIRE_NO_THROW(r = c.post(req)); - + std::map headers = parse_headers(body(r)); BOOST_CHECK_EQUAL(headers["content-length"], content_length); BOOST_CHECK_EQUAL(headers["content-type"], content_type); @@ -290,7 +296,7 @@ BOOST_AUTO_TEST_CASE(post_with_implicit_headers) { http::client c; http::client::response r; BOOST_REQUIRE_NO_THROW(r = c.post(req, postdata)); - + std::map headers = parse_headers(body(r)); BOOST_CHECK_EQUAL(headers["content-length"], get_content_length(postdata)); BOOST_CHECK_EQUAL(headers["content-type"], "x-application/octet-stream"); @@ -309,7 +315,7 @@ BOOST_AUTO_TEST_CASE(post_with_explicit_content_type) { http::client c; http::client::response r; BOOST_REQUIRE_NO_THROW(r = c.post(req, content_type, postdata)); - + std::map headers = parse_headers(body(r)); BOOST_CHECK_EQUAL(headers["content-length"], get_content_length(postdata)); BOOST_CHECK_EQUAL(headers["content-type"], content_type); @@ -338,11 +344,11 @@ BOOST_AUTO_TEST_CASE(post_with_custom_headers) { http::client::request req(base_url + "/cgi-bin/echo_headers.py"); req << header("X-Cpp-Netlib", "rocks!"); - + http::client c; http::client::response r; BOOST_REQUIRE_NO_THROW(r = c.post(req, std::string())); - + std::map headers = parse_headers(body(r)); BOOST_CHECK_EQUAL(headers["x-cpp-netlib"], "rocks!"); } diff --git a/libs/network/test/server/cgi-bin/echo_body.py b/libs/network/test/server/cgi-bin/echo_body.py index ca95c9bdf..51d62aff9 100755 --- a/libs/network/test/server/cgi-bin/echo_body.py +++ b/libs/network/test/server/cgi-bin/echo_body.py @@ -14,6 +14,7 @@ import os, sys sys.stdout.write( "Content-type: text/plain; charset=us-ascii\r\n\r\n" ) +sys.stdout.write( "\r\n" ) # POST data/form data is available in the .value property sys.stdout.write( cgi.FieldStorage().value ) diff --git a/libs/network/test/server/cgi-bin/echo_headers.py b/libs/network/test/server/cgi-bin/echo_headers.py index c0feb9902..8546e01e3 100755 --- a/libs/network/test/server/cgi-bin/echo_headers.py +++ b/libs/network/test/server/cgi-bin/echo_headers.py @@ -13,6 +13,7 @@ import cgisupport sys.stdout.write( "Content-type: text/plain; charset=us-ascii\r\n\r\n" ) +sys.stdout.write( "\r\n" ) hdrs = cgisupport.http_headers(os.environ.get('HTTP_ALL_HEADERS')) diff --git a/libs/network/test/server/cgi-bin/multiline-header.py b/libs/network/test/server/cgi-bin/multiline-header.py index ef451ce8b..ce66a2887 100755 --- a/libs/network/test/server/cgi-bin/multiline-header.py +++ b/libs/network/test/server/cgi-bin/multiline-header.py @@ -16,6 +16,7 @@ print "X-CppNetlib-Test: multi-line-header\r\n" print " that-should-concatenate\r\n" print "Content-type: text/plain; charset=us-ascii\r\n\r\n" +print "\r\n" form = cgi.FieldStorage() qstring = "" @@ -28,7 +29,6 @@ except ValueError: print "Error parsing query string." - print "Query string:", qstring print "GET parameters:", @@ -42,4 +42,3 @@ if i not in qstring_dict.keys(): print i,"-",form.getfirst(i, ""),";", print - diff --git a/libs/network/test/server/cgi-bin/requestinfo.py b/libs/network/test/server/cgi-bin/requestinfo.py index 109c0320f..332c36637 100755 --- a/libs/network/test/server/cgi-bin/requestinfo.py +++ b/libs/network/test/server/cgi-bin/requestinfo.py @@ -15,6 +15,7 @@ sys.stdout.write( "HTTP/1.0 200 Requestinfo.py Output follows\r\n" ) sys.stdout.write( "Content-type: text/plain; charset=us-ascii\r\n\r\n" ) +sys.stdout.write( "\r\n" ) form = cgi.FieldStorage() qstring = "" diff --git a/libs/network/test/server/http_test_server.py b/libs/network/test/server/http_test_server.py index d312d7c98..ba96c4fe9 100644 --- a/libs/network/test/server/http_test_server.py +++ b/libs/network/test/server/http_test_server.py @@ -9,7 +9,6 @@ # It will be used to test the http::client interface of the library import BaseHTTPServer -import SimpleHTTPServer import CGIHTTPServer import os @@ -33,4 +32,3 @@ def run_server(server_class=BaseHTTPServer.HTTPServer, handler_class=HttpTestHan if __name__ == '__main__': run_server() - From 56b4ef86a35498da021b946e95d46da795a5fade Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Wed, 3 Aug 2011 17:21:30 +1000 Subject: [PATCH 125/768] Updating documentation. --- README.rst | 13 +- boost/network/protocol/http/client.hpp | 4 +- libs/network/doc/getting_started.rst | 13 +- libs/network/doc/hello_world_server.rst | 20 +-- .../doc/html/_sources/getting_started.txt | 13 +- .../doc/html/_sources/hello_world_server.txt | 20 +-- libs/network/doc/html/_sources/index.txt | 2 +- .../html/_sources/reference_http_client.txt | 122 ++++++++++++++++-- libs/network/doc/html/_sources/whats_new.txt | 16 +++ libs/network/doc/html/directives.html | 2 +- libs/network/doc/html/getting_started.html | 14 +- libs/network/doc/html/index.html | 10 +- .../doc/html/reference_http_client.html | 101 ++++++++++++++- .../doc/html/reference_http_request.html | 11 -- libs/network/doc/html/searchindex.js | 2 +- libs/network/doc/html/uri.html | 6 +- libs/network/doc/html/whats_new.html | 25 +++- libs/network/doc/index.rst | 2 +- libs/network/doc/reference_http_client.rst | 122 ++++++++++++++++-- libs/network/doc/whats_new.rst | 11 ++ 20 files changed, 440 insertions(+), 89 deletions(-) diff --git a/README.rst b/README.rst index 6f1c9f458..02792cb30 100644 --- a/README.rst +++ b/README.rst @@ -167,26 +167,21 @@ repository. It is recommended that forks be made against the upstream repostory and pull requests be submitted against the upstream repository so that patches and other implementations can be curated by the original maintainer. -Contact and Commercial Support ------------------------------- +Contact and Support +------------------- In case you have any questions or would like to make feature requests, you can contact the development team through the `developers mailing list`_ -or by filing issues at http://github.com/mikhailberis/cpp-netlib/issues. +or by filing issues at http://github.com/cpp-netlib/cpp-netlib/issues. .. _`developers mailing list`: https://lists.sourceforge.net/lists/listinfo/cpp-netlib-devel You can reach the maintainers of the project through:: - Dean Michael Berris - mikhailberis@gmail.com + Dean Michael Berris (dberris@google.com) Glyn Matthews Mike Dickey -At this time, paid commercial support is available for cpp-netlib being offered -by the maintainers. In case you have any questions, please feel free to contact -any one of the maintainers above or anybody on the developers mailing list. - diff --git a/boost/network/protocol/http/client.hpp b/boost/network/protocol/http/client.hpp index 5460691b9..78a0619bf 100644 --- a/boost/network/protocol/http/client.hpp +++ b/boost/network/protocol/http/client.hpp @@ -34,7 +34,7 @@ namespace boost { namespace network { namespace http { : basic_client_facade { private: - typedef basic_client_facade + typedef basic_client_facade base_facade_type; public: typedef basic_request request; @@ -65,7 +65,7 @@ namespace boost { namespace network { namespace http { BOOST_PARAMETER_CONSTRUCTOR( basic_client, (base_facade_type), tag, - (optional + (optional (in_out(io_service), (boost::asio::io_service&)) (follow_redirects, (bool)) (cache_resolved, (bool)) diff --git a/libs/network/doc/getting_started.rst b/libs/network/doc/getting_started.rst index 2818e2e28..5543968a8 100644 --- a/libs/network/doc/getting_started.rst +++ b/libs/network/doc/getting_started.rst @@ -70,7 +70,7 @@ Getting Boost ============= :mod:`cpp-netlib` depends on Boost_. It should work for any version -of Boost above 1.43.0. If Boost is not installed on your system, the +of Boost above 1.45.0. If Boost is not installed on your system, the latest package can be found on the `Boost web-site`_. The environment variable ``BOOST_ROOT`` must be defined, which must be the full path name of the top directory of the Boost distribution. Although Boost @@ -90,6 +90,11 @@ still requires linking with `Boost.System`_, `Boost.Date_time`_, and .. _`Boost Getting Started`: http://www.boost.org/doc/libs/release/more/getting_started/index.html +.. warning:: There is a known incompatibility between :mod:`cpp-netlib` and + Boost 1.46.1 on some compilers. It is not recommended to use :mod:`cpp-netlib` + with Boost 1.46.1. Some have reported though that Boost 1.47.0 + and :mod:`cpp-netlib` work together better. + Getting CMake ============= @@ -168,9 +173,5 @@ for the project at http://github.com/cpp-netlib/cpp-netlib/issues. You can also opt to join the developers mailing list for a more personal interaction with the developers of the project. You can join the mailing list -through https://lists.sourceforge.net/lists/listinfo/cpp-netlib-devel. - -You may also choose to get commercial support from: - - Dean Michael Berris - +through https://groups.google.com/group/cpp-netlib. diff --git a/libs/network/doc/hello_world_server.rst b/libs/network/doc/hello_world_server.rst index 592981d0c..09a679859 100644 --- a/libs/network/doc/hello_world_server.rst +++ b/libs/network/doc/hello_world_server.rst @@ -38,12 +38,12 @@ simple response to any HTTP request. int main(int argc, char * argv[]) { - + if (argc != 3) { std::cerr << "Usage: " << argv[0] << " address port" << std::endl; return 1; } - + try { hello_world handler; server server_(argv[1], argv[2], handler); @@ -53,7 +53,7 @@ simple response to any HTTP request. std::cerr << e.what() << std::endl; return 1; } - + return 0; } @@ -115,9 +115,9 @@ This header contains all the code needed to develop an HTTP server with ``hello_world`` is a functor class which handles HTTP requests. All the operator does here is return an HTTP response with HTTP code 200 and the body ``"Hello, !"``. The ```` in this case would be -the IP address of the client that made the request. +the IP address of the client that made the request. -There are a number of pre-defined stock replies differentiated by +There are a number of pre-defined stock replies differentiated by status code with configurable bodies. All the supported enumeration values for the response status codes can be found @@ -134,10 +134,10 @@ the port on which the server will listen. The third argument is the the handler object defined previously. .. note:: In this example, the server is specifically made to be single-threaded. - In a multi-threaded server, you would invoke the ``hello_world::run`` member - method in a set of threads. In a multi-threaded environment you would also - make sure that the handler does all the necessary synchronization for shared - resources across threads. The handler is passed by reference to the server - constructor and you should ensure that any calls to the ``operator()`` overload + In a multi-threaded server, you would invoke the ``hello_world::run`` member + method in a set of threads. In a multi-threaded environment you would also + make sure that the handler does all the necessary synchronization for shared + resources across threads. The handler is passed by reference to the server + constructor and you should ensure that any calls to the ``operator()`` overload are thread-safe. diff --git a/libs/network/doc/html/_sources/getting_started.txt b/libs/network/doc/html/_sources/getting_started.txt index 2818e2e28..5543968a8 100644 --- a/libs/network/doc/html/_sources/getting_started.txt +++ b/libs/network/doc/html/_sources/getting_started.txt @@ -70,7 +70,7 @@ Getting Boost ============= :mod:`cpp-netlib` depends on Boost_. It should work for any version -of Boost above 1.43.0. If Boost is not installed on your system, the +of Boost above 1.45.0. If Boost is not installed on your system, the latest package can be found on the `Boost web-site`_. The environment variable ``BOOST_ROOT`` must be defined, which must be the full path name of the top directory of the Boost distribution. Although Boost @@ -90,6 +90,11 @@ still requires linking with `Boost.System`_, `Boost.Date_time`_, and .. _`Boost Getting Started`: http://www.boost.org/doc/libs/release/more/getting_started/index.html +.. warning:: There is a known incompatibility between :mod:`cpp-netlib` and + Boost 1.46.1 on some compilers. It is not recommended to use :mod:`cpp-netlib` + with Boost 1.46.1. Some have reported though that Boost 1.47.0 + and :mod:`cpp-netlib` work together better. + Getting CMake ============= @@ -168,9 +173,5 @@ for the project at http://github.com/cpp-netlib/cpp-netlib/issues. You can also opt to join the developers mailing list for a more personal interaction with the developers of the project. You can join the mailing list -through https://lists.sourceforge.net/lists/listinfo/cpp-netlib-devel. - -You may also choose to get commercial support from: - - Dean Michael Berris - +through https://groups.google.com/group/cpp-netlib. diff --git a/libs/network/doc/html/_sources/hello_world_server.txt b/libs/network/doc/html/_sources/hello_world_server.txt index 592981d0c..09a679859 100644 --- a/libs/network/doc/html/_sources/hello_world_server.txt +++ b/libs/network/doc/html/_sources/hello_world_server.txt @@ -38,12 +38,12 @@ simple response to any HTTP request. int main(int argc, char * argv[]) { - + if (argc != 3) { std::cerr << "Usage: " << argv[0] << " address port" << std::endl; return 1; } - + try { hello_world handler; server server_(argv[1], argv[2], handler); @@ -53,7 +53,7 @@ simple response to any HTTP request. std::cerr << e.what() << std::endl; return 1; } - + return 0; } @@ -115,9 +115,9 @@ This header contains all the code needed to develop an HTTP server with ``hello_world`` is a functor class which handles HTTP requests. All the operator does here is return an HTTP response with HTTP code 200 and the body ``"Hello, !"``. The ```` in this case would be -the IP address of the client that made the request. +the IP address of the client that made the request. -There are a number of pre-defined stock replies differentiated by +There are a number of pre-defined stock replies differentiated by status code with configurable bodies. All the supported enumeration values for the response status codes can be found @@ -134,10 +134,10 @@ the port on which the server will listen. The third argument is the the handler object defined previously. .. note:: In this example, the server is specifically made to be single-threaded. - In a multi-threaded server, you would invoke the ``hello_world::run`` member - method in a set of threads. In a multi-threaded environment you would also - make sure that the handler does all the necessary synchronization for shared - resources across threads. The handler is passed by reference to the server - constructor and you should ensure that any calls to the ``operator()`` overload + In a multi-threaded server, you would invoke the ``hello_world::run`` member + method in a set of threads. In a multi-threaded environment you would also + make sure that the handler does all the necessary synchronization for shared + resources across threads. The handler is passed by reference to the server + constructor and you should ensure that any calls to the ``operator()`` overload are thread-safe. diff --git a/libs/network/doc/html/_sources/index.txt b/libs/network/doc/html/_sources/index.txt index b4df6b217..ef56ddb3c 100644 --- a/libs/network/doc/html/_sources/index.txt +++ b/libs/network/doc/html/_sources/index.txt @@ -105,7 +105,7 @@ Support You can ask questions, join the discussion, and report issues to the developers mailing list by joining via: - https://lists.sourceforge.net/lists/listinfo/cpp-netlib-devel + https://groups.google.com/group/cpp-netlib You may also file issues on the Github_ issue tracker at: diff --git a/libs/network/doc/html/_sources/reference_http_client.txt b/libs/network/doc/html/_sources/reference_http_client.txt index 0c7758a3c..9b63c5e6d 100644 --- a/libs/network/doc/html/_sources/reference_http_client.txt +++ b/libs/network/doc/html/_sources/reference_http_client.txt @@ -8,7 +8,7 @@ General :mod:`cpp-netlib` includes and implements a number of HTTP clients that you can use and embed in your own applications. All of the HTTP client implementations: - * **Cannot be copied.** This means you may have to store instances of the + * **Cannot be copied.** This means you may have to store instances of the clients in dynamic memory if you intend to use them as function parameters or pass them around in smart pointers or by reference. * **Assume that requests made are independent of each other.** There currently @@ -18,11 +18,14 @@ use and embed in your own applications. All of the HTTP client implementations: case you want to upgrade the implementation you are using in your application will be distributed as header-only implementations, which means you have to re-compile your application to use a newer version of the implementations. - + The HTTP clients all share the same API, but the internals are documented in terms of what is different and what to expect with the different implementations. +As of 0.9.1 the default implementation for the :mod:`cpp-netlib` HTTP client is +asynchronous. + Implementations --------------- @@ -60,14 +63,14 @@ Synchronous Clients ~~~~~~~~~~~~~~~~~~~ Of the client tags shown in the table, the following makes the ``basic_client`` -behave as a fully synchronous client. +behave as a fully synchronous client. * **http_default_8bit_tcp_resolve** * **http_default_8bit_udp_resolve** * **http_keepalive_8bit_tcp_resolve** * **http_keepalive_8bit_udp_resolve** -The synchronous client implements all the operations of the client underneath +The synchronous client implements all the operations of the client underneath the interface all block to wait for I/O to finish. All the member methods are synchronous and will block until the response object is ready or throws if erros are encountered in the performance of the HTTP requests. @@ -84,10 +87,10 @@ manner: * **http_async_8bit_tcp_resolve** * **http_async_8bit_udp_resolve** -An asynchronous client implementation means that``basic_client<...>`` is an -`Active Object`_. This means that the client has and manages its own lifetime -thread, and returns values that are asynchronously filled in. The response -object encapsulates Boost.Thread_ futures which get filled in once the values +An asynchronous client implementation means that``basic_client<...>`` is an +`Active Object`_. This means that the client has and manages its own lifetime +thread, and returns values that are asynchronously filled in. The response +object encapsulates Boost.Thread_ futures which get filled in once the values are available. .. _Boost.Thread: http://www.boost.org/libs/thread @@ -177,7 +180,7 @@ To use the above supported named parameters, you'll have code that looks like the following: .. code-block:: c++ - + using namespace boost::network::http; // parameters are in this namespace boost::asio::io_service my_io_service; client client_(_follow_redirects=true, _cache_resolved=true, @@ -197,38 +200,87 @@ and that there is an appropriately constructed response object named .. code-block:: c++ + using namespace boost::network::http; // parameters are here client client_(); client::request request_("http://cpp-netib.github.com/"); client::response response_; ``response_ = client_.get(request_)`` Perform an HTTP GET request. +``response_ = client_.get(request_, _body_handler=callback)`` + Perform an HTTP GET request, and have the body chunks be handled by the + ``callback`` parameter. The signature of ``callback`` should be the following: + ``void(iterator_range const &, boost::system::error_code const + &)``. ``response_ = client_.head(request_)`` Perform an HTTP HEAD request. ``response_ = client_.post(request_)`` Perform an HTTP POST, use the data already set in the request object which includes the headers, and the body. +``response_ = client_.post(request_, _body_handler=callback)`` + Perform an HTTP POST request, and have the body chunks be handled by the + ``callback`` parameter. The signature of ``callback`` should be the following: + ``void(iterator_range const &, boost::system::error_code const + &)``. ``response_ = client_.post(request_, body)`` Body is a string of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. The default content-type used is ``x-application/octet-stream``. +``response_ = client_.post(request_, body, _body_handler=callback)`` + Body is a string of type ``boost::network::string::type`` where ``Tag`` + is the HTTP Client's ``Tag``. The default content-type used is + ``x-application/octet-stream``. Have the response body chunks be handled by + the ``callback`` parameter. The signature of ``callback`` should be the + following: ``void(iterator_range const &, + boost::system::error_code const &)``. ``response_ = client_.post(request_, content_type, body)`` The body and content_type parameters are of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. This uses the request object's other headers. +``response_ = client_.post(request_, content_type, body, _body_handler=callback)`` + The body and content_type parameters are of type + ``boost::network::string::type`` where ``Tag`` is the HTTP Client's + ``Tag``. This uses the request object's other headers. Have the response + body chunks be handled by the ``callback`` parameter. The signature of + ``callback`` should be the following: ``void(iterator_range const + &, boost::system::error_code const &)``. ``response_ = client_.put(request_)`` Perform an HTTP PUT, use the data already set in the request object which includes the headers, and the body. +``response_ = client_.put(request_, _body_handler=callback)`` + Perform an HTTP PUT request, and have the body chunks be handled by the + ``callback`` parameter. The signature of ``callback`` should be the following: + ``void(iterator_range const &, boost::system::error_code const + &)``. ``response_ = client_.put(request_, body)`` Body is a string of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. The default content-type used is ``x-application/octet-stream``. +``response_ = client_.put(request_, body, _body_handler=callback)`` + Body is a string of type ``boost::network::string::type`` where ``Tag`` + is the HTTP Client's ``Tag``. The default content-type used is + ``x-application/octet-stream``. Have the response body chunks be handled by + the ``callback`` parameter. The signature of ``callback`` should be the + following: ``void(iterator_range const &, + boost::system::error_code const &)``. ``response_ = client_.put(request_, content_type, body)`` The body and content_type parameters are of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. This uses the request object's other headers. +``response_ = client_.put(request_, content_type, body, _body_handler=callback)`` + The body and content_type parameters are of type + ``boost::network::string::type`` where ``Tag`` is the HTTP Client's + ``Tag``. This uses the request object's other headers. Have the response + body chunks be handled by the ``callback`` parameter. The signature of + ``callback`` should be the following: ``void(iterator_range const + &, boost::system::error_code const &)``. ``response_ = client_.delete_(request_)`` Perform an HTTP DELETE request. +``response_ = client_.delete_(request_, _body_handler=callback)`` + Perform an HTTP DELETE request, and have the response body chunks be handled + by the ``callback`` parameter. The signature of ``callback`` should be the + following: ``void(iterator_range const &, + boost::system::error_code const &)``. Client-Specific ~~~~~~~~~~~~~~~ @@ -237,3 +289,55 @@ Client-Specific Clear the cache of resolved endpoints. +Streaming Body Handler +~~~~~~~~~~~~~~~~~~~~~~ + +As of v0.9.1 the library now offers a way to support a streaming body callback +function in all HTTP requests that expect a body part (GET, PUT, POST, DELETE). +A convenience macro is also provided to make callback handlers easier to write. +This macro is called `BOOST_NETWORK_HTTP_BODY_CALLBACK` which allows users to +write the following code to easily create functions or function objects that +are compatible with the callback function requirements. + +An example of how to use the macro is shown below: + +.. code-block:: c++ + + struct body_handler { + explicit body_handler(std::string & body) + : body(body) {} + + BOOST_NETWORK_HTTP_BODY_CALLBACK(operator(), range, error) { + // in here, range is the Boost.Range iterator_range, and error is + // the Boost.System error code. + if (!error) + body.append(boost::begin(range), boost::end(range)); + } + + std::string & body; + }; + + // somewhere else + std::string some_string; + response_ = client_.get(request("http://cpp-netlib.github.com/"), + _body_handler=body_handler(some_string)); + +You can also use if for standalone functions instead if you don't want or need +to create a function object. + +.. code-block:: c++ + + BOOST_NETWORK_HTTP_BODY_CALLBACK(print_body, range, error) { + if (!error) + std::cout << "Received " << boost::distance(range) << "bytes." + << std::endl; + else + std::cout << "Error: " << error << std::endl; + } + + // somewhere else + response_ = client_.get(request("http://cpp-netlib.github.com/"), + _body_handler=print_body); + +The `BOOST_NETWORK_HTTP_BODY_CALLBACK` macro is defined in +`boost/network/protocol/http/client/macros.hpp`. diff --git a/libs/network/doc/html/_sources/whats_new.txt b/libs/network/doc/html/_sources/whats_new.txt index 04b88935b..e02c73313 100644 --- a/libs/network/doc/html/_sources/whats_new.txt +++ b/libs/network/doc/html/_sources/whats_new.txt @@ -7,12 +7,28 @@ :mod:`cpp-netlib` 0.9 --------------------- +v0.9.1 +~~~~~~ +* Introduced macro ``BOOST_NETWORK_DEFAULT_TAG`` to allow for programmatically + defining the default flag to use throughout the compilation unit. +* Support for streaming body handlers when performing HTTP client operations. + See documentation for HTTP client interface for more information. +* Numerous bug fixes from v0.9.0. +* Google, Inc. contributions. + +v0.9.0 +~~~~~~ * **IMPORTANT BREAKING CHANGE**: By default all compile-time heavy parser implementations are now compiled to external static libraries. In order to use :mod:`cpp-netlib` in header-only mode, users must define the preprocessor macro ``BOOST_NETWORK_NO_LIB`` before including any :mod:`cpp-netlib` header. This breaks code that relied on the version 0.8.x line where the library is strictly header-only. +* Fix issue #41: Introduce a macro ``BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG`` + which makes the default HTTP client use ``tags::http_async_8bit_udp_resolve`` + as the tag. +* Fix issue #40: Write the status line and headers in a single buffer write + instead of two writes. * More consistent message API for client and server messages (request and response objects). * Refactoring of internal implementations to allow better separation of concerns diff --git a/libs/network/doc/html/directives.html b/libs/network/doc/html/directives.html index 9bcab8c86..1a200b0e9 100644 --- a/libs/network/doc/html/directives.html +++ b/libs/network/doc/html/directives.html @@ -108,7 +108,7 @@

Directives} -
+

Todo

An example using a directive.

diff --git a/libs/network/doc/html/getting_started.html b/libs/network/doc/html/getting_started.html index 80c5c0af3..4eb7b0349 100644 --- a/libs/network/doc/html/getting_started.html +++ b/libs/network/doc/html/getting_started.html @@ -107,7 +107,7 @@

Downloading a development version

Getting Boost

cpp-netlib depends on Boost. It should work for any version -of Boost above 1.43.0. If Boost is not installed on your system, the +of Boost above 1.45.0. If Boost is not installed on your system, the latest package can be found on the Boost web-site. The environment variable BOOST_ROOT must be defined, which must be the full path name of the top directory of the Boost distribution. Although Boost @@ -119,6 +119,13 @@

Getting BoostYou can follow the steps in the Boost Getting Started guide to install Boost into your development system.

+
+

Warning

+

There is a known incompatibility between cpp-netlib and +Boost 1.46.1 on some compilers. It is not recommended to use cpp-netlib +with Boost 1.46.1. Some have reported though that Boost 1.47.0 +and cpp-netlib work together better.

+

Getting CMake

@@ -187,10 +194,7 @@

Reporting Issues, Getting Supporthttp://github.com/cpp-netlib/cpp-netlib/issues.

You can also opt to join the developers mailing list for a more personal interaction with the developers of the project. You can join the mailing list -through https://lists.sourceforge.net/lists/listinfo/cpp-netlib-devel.

-

You may also choose to get commercial support from:

-
-
Dean Michael Berris - <me@deanberris.com>
+through https://groups.google.com/group/cpp-netlib.

diff --git a/libs/network/doc/html/index.html b/libs/network/doc/html/index.html index ea3c5c292..6371046ce 100644 --- a/libs/network/doc/html/index.html +++ b/libs/network/doc/html/index.html @@ -58,7 +58,7 @@

cpp-netlib v0.9 documentation

C++ Network Library

-_images/boost7.png +_images/boost.png

Welcome

The cpp-netlib is a library that provides application layer @@ -132,7 +132,7 @@

Supporthttps://lists.sourceforge.net/lists/listinfo/cpp-netlib-devel

+

You may also file issues on the Github issue tracker at:

@@ -142,7 +142,11 @@

Contents

Implementations

@@ -320,7 +322,8 @@

HTTP Methodsrequest_ and that there is an appropriately constructed response object named response_ like the following:

-
client client_();
+
using namespace boost::network::http;  // parameters are here
+client client_();
 client::request request_("http://cpp-netib.github.com/");
 client::response response_;
 
@@ -328,32 +331,80 @@

HTTP Methods
response_ = client_.get(request_)
Perform an HTTP GET request.
+
response_ = client_.get(request_, _body_handler=callback)
+
Perform an HTTP GET request, and have the body chunks be handled by the +callback parameter. The signature of callback should be the following: +void(iterator_range<char const *> const &, boost::system::error_code const +&).
response_ = client_.head(request_)
Perform an HTTP HEAD request.
response_ = client_.post(request_)
Perform an HTTP POST, use the data already set in the request object which includes the headers, and the body.
+
response_ = client_.post(request_, _body_handler=callback)
+
Perform an HTTP POST request, and have the body chunks be handled by the +callback parameter. The signature of callback should be the following: +void(iterator_range<char const *> const &, boost::system::error_code const +&).
response_ = client_.post(request_, body)
Body is a string of type boost::network::string<Tag>::type where Tag is the HTTP Client’s Tag. The default content-type used is x-application/octet-stream.
+
response_ = client_.post(request_, body, _body_handler=callback)
+
Body is a string of type boost::network::string<Tag>::type where Tag +is the HTTP Client’s Tag. The default content-type used is +x-application/octet-stream. Have the response body chunks be handled by +the callback parameter. The signature of callback should be the +following: void(iterator_range<char const *> const &, +boost::system::error_code const &).
response_ = client_.post(request_, content_type, body)
The body and content_type parameters are of type boost::network::string<Tag>::type where Tag is the HTTP Client’s Tag. This uses the request object’s other headers.
+
response_ = client_.post(request_, content_type, body, _body_handler=callback)
+
The body and content_type parameters are of type +boost::network::string<Tag>::type where Tag is the HTTP Client’s +Tag. This uses the request object’s other headers. Have the response +body chunks be handled by the callback parameter. The signature of +callback should be the following: void(iterator_range<char const *> const +&, boost::system::error_code const &).
response_ = client_.put(request_)
Perform an HTTP PUT, use the data already set in the request object which includes the headers, and the body.
+
response_ = client_.put(request_, _body_handler=callback)
+
Perform an HTTP PUT request, and have the body chunks be handled by the +callback parameter. The signature of callback should be the following: +void(iterator_range<char const *> const &, boost::system::error_code const +&).
response_ = client_.put(request_, body)
Body is a string of type boost::network::string<Tag>::type where Tag is the HTTP Client’s Tag. The default content-type used is x-application/octet-stream.
+
response_ = client_.put(request_, body, _body_handler=callback)
+
Body is a string of type boost::network::string<Tag>::type where Tag +is the HTTP Client’s Tag. The default content-type used is +x-application/octet-stream. Have the response body chunks be handled by +the callback parameter. The signature of callback should be the +following: void(iterator_range<char const *> const &, +boost::system::error_code const &).
response_ = client_.put(request_, content_type, body)
The body and content_type parameters are of type boost::network::string<Tag>::type where Tag is the HTTP Client’s Tag. This uses the request object’s other headers.
+
response_ = client_.put(request_, content_type, body, _body_handler=callback)
+
The body and content_type parameters are of type +boost::network::string<Tag>::type where Tag is the HTTP Client’s +Tag. This uses the request object’s other headers. Have the response +body chunks be handled by the callback parameter. The signature of +callback should be the following: void(iterator_range<char const *> const +&, boost::system::error_code const &).
response_ = client_.delete_(request_)
Perform an HTTP DELETE request.
+
response_ = client_.delete_(request_, _body_handler=callback)
+
Perform an HTTP DELETE request, and have the response body chunks be handled +by the callback parameter. The signature of callback should be the +following: void(iterator_range<char const *> const &, +boost::system::error_code const &).

@@ -363,6 +414,53 @@

Client-Specific +

Streaming Body Handler

+

As of v0.9.1 the library now offers a way to support a streaming body callback +function in all HTTP requests that expect a body part (GET, PUT, POST, DELETE). +A convenience macro is also provided to make callback handlers easier to write. +This macro is called BOOST_NETWORK_HTTP_BODY_CALLBACK which allows users to +write the following code to easily create functions or function objects that +are compatible with the callback function requirements.

+

An example of how to use the macro is shown below:

+
struct body_handler {
+    explicit body_handler(std::string & body)
+    : body(body) {}
+
+    BOOST_NETWORK_HTTP_BODY_CALLBACK(operator(), range, error) {
+        // in here, range is the Boost.Range iterator_range, and error is
+        // the Boost.System error code.
+        if (!error)
+            body.append(boost::begin(range), boost::end(range));
+    }
+
+    std::string & body;
+};
+
+// somewhere else
+std::string some_string;
+response_ = client_.get(request("http://cpp-netlib.github.com/"),
+                        _body_handler=body_handler(some_string));
+
+
+

You can also use if for standalone functions instead if you don’t want or need +to create a function object.

+
BOOST_NETWORK_HTTP_BODY_CALLBACK(print_body, range, error) {
+    if (!error)
+        std::cout << "Received " << boost::distance(range) << "bytes."
+                  << std::endl;
+    else
+        std::cout << "Error: " << error << std::endl;
+}
+
+// somewhere else
+response_ = client_.get(request("http://cpp-netlib.github.com/"),
+                        _body_handler=print_body);
+
+
+

The BOOST_NETWORK_HTTP_BODY_CALLBACK macro is defined in +boost/network/protocol/http/client/macros.hpp.

+

@@ -388,6 +486,7 @@

Table Of Contents

  • Constructors
  • HTTP Methods
  • Client-Specific
  • +
  • Streaming Body Handler
  • diff --git a/libs/network/doc/html/reference_http_request.html b/libs/network/doc/html/reference_http_request.html index 3103bee46..35645c822 100644 --- a/libs/network/doc/html/reference_http_request.html +++ b/libs/network/doc/html/reference_http_request.html @@ -280,17 +280,6 @@

    Directives
    request << directive(...);
     

    -
    -

    Warning

    -

    There are two versions of directives, those that are applicable to -messages that support narrow strings (std::string) and those that are -applicable to messages that support wide strings (std::wstring). The -cpp-netlib implementation still does not convert wide strings into -UTF-8 encoded narrow strings. This will be implemented in subsequent -library releases.

    -

    For now all the implemented directives are listed, even if some of them still -do not implement things correctly.

    -
    unspecified source(std::string const & source_)
    Create a source directive with a std::string as a parameter, to be set diff --git a/libs/network/doc/html/searchindex.js b/libs/network/doc/html/searchindex.js index 28f5dae08..d1464f3b3 100644 --- a/libs/network/doc/html/searchindex.js +++ b/libs/network/doc/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({objects:{},terms:{directive_typ:7,all:[15,9,16,17,10,11,20,7,12,23,4,13,14],code:[6,9,16,15,18,10,20,7,21,12,23,24,13,14],skeleton:18,chain:7,illustr:18,queri:[11,19],forbidden:16,lack:24,icmp:4,basic_messag:[6,4,19,5],four:17,concept:[6,16,0,17,19,11,7,4,5],follow:[15,9,16,17,18,19,10,11,20,7,3,12,23,4,13,21],ptr:15,abid:[11,7],hierarch:19,whose:18,decid:[15,18,24],"const":[6,9,16,17,10,11,7,23,4],bzip:13,range_iter:9,send:[12,16],concret:7,swap:[4,18,19],string_tag:18,sens:[9,1,7,23],set:[15,16,17,10,11,7,3,23,4,5],"_follow_redirect":23,stock_repli:[6,9,16,10],sent:[23,16],unzip:13,everi:[4,24],risk:13,straightforward:10,fals:[23,16],"void":[6,9,16,15,18,17,19,10,11,4],inhibit:23,nich:24,netlib:[0,2,3,4,5,6,7,8,9,10,11,23,13,14,15,16,17,18,19,20,21,12,24],endpoint:23,fan:13,veri:16,affect:23,default_:[15,18,9],exact:9,relev:20,rfc1738:9,http_async_serv:16,administr:10,level:[6,13,24],michael:[13,24],upload:16,iter:9,correct:[15,4,9],"try":[20,16,10],vector:[18,11,16],verif:23,cooki:23,still:[16,17,18,11,23,13],impli:4,tel:19,throught:12,core:4,natur:7,direct:[6,0,17,11,24,7,12,4,8,5],commerci:13,handler_typ:16,second:[11,9],cost:14,design:3,pass:[9,16,18,10,20,7,12,23,4],download:[6,13],further:[12,19],port_typ:11,port:[9,16,17,19,10,11,20],even:[4,7,11,17],"_cache_resolv":23,what:[6,16,15,18,10,11,20,23,4,14],msysgit:13,insid:[9,16],repli:10,section:[9,16,17,11,23,4],watermark:16,abl:[13,16],invok:[16,13,10],overload:[9,16,10],access:[9,16,17,11,20,7,24],delet:[23,9,12],version:[6,16,15,18,17,19,11,12,23,13,14],source_wrapp:4,underneath:[23,14],"new":[6,15,18,19,7,13,14],net:[6,13],liter:5,boost:[6,9,16,17,1,19,10,18,11,20,12,23,24,13,14],method:[23,11,12,9,10],manag:[23,16,14],redirect:23,full:[6,19,13,22,17],deriv:[15,11],"_address":16,gener:[6,16,0,15,19,11,7,23,2,4,24,13,5],never:24,unauthor:16,here:[15,9,16,19,10,12,23],bodi:[6,9,16,17,18,10,11,20,12,23,4],let:[18,20,13,10],free:[4,16],address:[9,16,1,10,20,23],path:[11,9,13,19],along:13,rudimentari:7,modifi:[6,0,17,11,23,4,5],sinc:[12,18,20],valu:[15,9,16,17,1,10,11,23,4],wait:[23,16],convert:[4,19,11,17],convers:4,shift:7,anymor:18,larger:21,host:[11,19,9,13,10],anchor:11,cert:23,base:[15,18,19,7,4,13],cerr:[6,20,9,10],behav:23,http_keepalive_8bit_tcp_resolv:[23,1,9],action:16,http_client:[12,9],chang:[9,18,7,23,13,14],narrow:[11,17],portabl:24,semant:[6,4,7,16,15],via:[6,20],although:[15,4,18,13,16],appli:[4,7],multiple_choic:16,put:[23,9,16],unix:[13,19],api:[6,16,0,17,19,11,23,14],famili:18,visibl:9,instal:[6,13,22],post:[23,20,9,12],unit:14,regex:13,version_minor:[23,1,9,11],from:[6,9,16,17,18,19,10,11,20,7,12,23,4,13],describ:[23,16,3,19,8],zip:13,commun:[6,3,24],distinct:16,doubl:19,upgrad:[23,16,14],subvers:13,websit:12,few:13,program:[15,21,24,19,10],call:[9,16,18,10,7,4,13],taken:16,clear_head:[4,11,17],type:[15,9,16,17,18,19,11,7,23,4,24],until:23,minor:[23,11],more:[6,16,4,14,13,24],reachabl:18,wrapper:[6,9,0,17,11,4,14,5],headers_rang:[11,9,17],afford:7,smtp:[4,24],swappabl:[4,18,19],relat:16,notic:[18,9],site:13,warn:[23,11,16,17],visual:13,depth:[6,5],accept:[7,16],known:19,actual:16,hold:[23,1,9],unpack:13,cach:23,content_typ:23,must:[13,14],placehold:18,none:16,dcmake_c_compil:13,join:[6,13,16],internal_server_error:16,scalabl:16,alia:[13,17],work:[11,13,17],uniqu:15,histori:[6,24],annoi:24,remain:[15,7],tag:[6,9,16,15,1,17,19,11,23,4,14,18,8],can:[6,9,16,15,18,19,10,20,7,21,12,23,4,13],caveat:13,root:[11,18],fetch:23,aliv:[23,1,9,16],proof:16,control:[18,13,16],heart:9,encapsul:[9,1,7,4,23],tar:13,give:16,process:[9,19],lock:16,no_cont:16,share:[23,1,9,16,10],sln:13,templat:[6,9,16,15,18,17,19,11,7,23,2,4,24,13,5],high:24,sourc:[6,9,17,10,11,2,4,13,24],want:[15,16,18,20,23,4,13],explos:15,tarbal:13,http_async_8bit_udp_resolv:[23,1,9],serial:16,unavoid:15,unsign:[23,11,9,17],occur:[11,17],string:[6,9,16,17,18,19,10,11,20,12,23,4],low:16,alwai:16,differenti:[16,10],end:[9,24],goal:24,anoth:[16,19],classifi:19,write:[6,20,16,24],how:[18,19,10,20,21,13],conn:16,pure:[15,4],subdirectori:12,opt:13,instead:[18,13,16],greatli:15,simpl:[6,9,16,19,10,20,7,12,4],mpl:[18,14],stock:10,resourc:[13,10],dive:[12,20,21,10],earlier:[15,20],hello_world_cli:20,constraint:24,status_messag:17,befor:[23,20,16,14],xzf:13,attent:7,mai:[6,9,16,10,23,4,13],multipl:16,data:[9,16,19,20,23,4],parallel:13,util:16,github:[6,19,24,13,23],attempt:[16,14],practic:3,third:10,date_tim:13,opaqu:[18,19],valid:[4,9],minim:14,explicit:4,element:19,issu:[6,13],inform:[6,13,16],"switch":[15,11],maintain:[7,13,16],environ:[13,10],allow:[6,16,15,18,7,12,4,14],mechan:[18,9],order:[12,7,14],talk:[11,17],origin:[18,9],composit:18,help:16,xmpp:[4,24],offici:[6,13],move:7,becaus:[15,4,7,16],intermediari:4,paper:[6,2],through:[11,9,13,16],left:[18,7],size_t:16,flexibl:[12,18,7],vari:[15,4,18],dynam:[6,15,16,23,8],paramet:[9,16,17,18,11,7,23,4,13,14],divis:4,typedef:[6,9,16,18,10,23,4],group:24,fit:16,fix:14,conncetionptr:16,unsupported_tag:18,better:[16,14],platform:[6,24,13,16],window:[6,13],pend:16,bin:19,mail:[6,13],hidden:[23,7],main:[6,20,12,13,10],might:[18,9],easier:4,non:[4,16,19],multimap:9,"return":[15,9,16,17,1,10,11,20,7,12,23,4,14],greater:[12,10],thei:[9,1,19,23,4,18],handl:[15,16,10],smarter:18,safe:[23,10],initi:[23,24,16,14],devel:[6,13],"break":[23,15,9,14],framework:10,facilit:15,now:[17,10,11,23,13,14],discuss:[6,13],nor:4,choic:13,term:[23,4,16],eventu:[6,24],mere:4,name:[9,16,17,11,23,4,13,14],realist:3,edit:16,separ:14,easili:24,slide:[6,2],exampl:[6,9,16,18,19,10,20,7,3,12,23,4,13,21],submit:[6,13,24],http_server:[6,11,16,17],timeout:16,each:[23,4,12,13,16],debug:13,fulli:[23,24],complet:[12,13],side:[15,10],mean:[23,4,13,16],compil:[23,16,7,13,14],dcmake_cxx_compil:13,weight:[6,24],applac:16,list:[6,16,17,18,10,11,13],chunk:16,continu:[16,24],functor:[9,10],realli:20,heavi:[13,14],wrap:[15,4,17],set_statu:16,"static":[6,15,18,7,23,8,14],expect:23,default_tag:18,our:[18,13,24],happen:23,"_port":16,unique_ptr:15,orient:[15,7],special:[6,9,15,18,17,11,7,4],out:[23,13,16],variabl:13,ftp:[19,24],shown:[23,16],safeti:18,network:[6,9,16,17,18,19,10,11,20,3,12,23,4,24],webservic:20,goe:13,tcp_resolv:23,req:16,rational:7,content:[6,4,16,23],typenam:[18,4,11,17],adapt:4,rel:19,internet:13,print:[12,9],current:[23,16,19],factori:[15,4,7],model:[16,17,11,7,23,4,13],after:[12,16,19],iostream:[12,20,7,10],linear:16,barrier:24,advanc:8,my_io_servic:[23,16],manipul:[4,16],situat:[15,7,16],given:[6,9,16,15,18,17,19,11,4],argv:[6,20,12,10],sneak:6,significantli:16,standalon:15,reason:13,git:[6,13],releas:[6,16,17,11,23,13],org:[6,9,19,12],"byte":16,argc:[12,20,10],bash:19,netib:23,wai:[18,9,16,19],thread:[9,16,1,10,23,14],prescrib:13,synchron:[6,9,16,0,1,10,23],keep:[15,9,1,7,23,18],thing:[15,17,18,11,12,13],enforc:11,place:16,some_xml_str:20,lifetim:23,assign:[4,16,19],first:[15,9,19,10,11,12,4,13],oper:[6,9,16,17,10,11,7,23,4],softwar:24,major:[23,11,24],"_openssl_certif":23,directli:[23,16],certif:23,onc:[23,18,12,13,16],independ:[23,7,16],qualiti:24,number:[9,16,1,10,18,11,23,4,13],yourself:13,uri_:9,instruct:13,alreadi:[16,17,11,23,14,24],done:[15,9,16,18,11,4,13],bad_gatewai:16,lboost_system:[12,20,10],stabl:13,"_reuse_address":16,open:24,payload:[4,20],size:16,differ:[6,9,16,0,15,18,17,19,11,7,23,4,14,5],width:23,associ:[18,4,17,11,16],top:[13,24],system:[23,7,13,16],messag:[6,17,11,24,7,12,23,4,14,5],destination_:[11,17],bad_request:16,scheme:[11,9,19],zipfil:13,"final":12,boil:7,listen:[16,10],adher:16,udp:[23,1,9],shell:[20,13,10],consol:12,option:[16,24,13,14],especi:16,namespac:[6,9,16,17,18,10,11,20,12,23],tool:[9,13],copi:[23,4,16,19],specifi:[9,16,1,19,12,23,4,13],aptli:9,xjf:13,pars:[19,9,16,14],mostli:13,review:6,than:[18,16],http_version_major:23,serv:18,wide:[11,17],kind:[6,3,15],john:19,target:[7,24],provid:[6,9,17,1,19,10,11,23,18,24],remov:[4,11,17],http_client1:12,basic_cli:[23,9],structur:[12,18],charact:23,project:[6,13,24],matter:16,reus:7,not_accept:16,store:[23,4,16],str:20,light:[6,24],iterator_rang:16,seri:[3,16],pre:[10,5],fork:13,fashion:7,comput:[13,16],behavior:[23,18,9,15],facad:14,add_head:[4,11,17],sometim:[4,18],ani:[15,9,16,10,12,23,4,13,14],packag:13,properli:[23,16],manner:[23,11,18,16,17],have:[15,9,16,1,10,18,20,7,12,23,4,13,24],tabl:[23,4,9,16,17],need:[15,16,18,10,3,12,23,13,24],seen:10,dedic:23,repeatedli:24,caus:[23,1,9,18],shared_futur:17,status_t:16,techniqu:[6,18,15,7,8],lib:[12,20,10],callback:16,directiven:7,self:7,expos:16,note:[16,17,19,10,20,23,4,13],also:[6,9,16,15,1,17,10,18,11,7,23,4,13,24],without:[12,7],decis:15,headers_:[9,17],indic:[23,1,9],combin:[15,18],concern:14,soap:24,singl:[23,12,9,16,10],asio:[23,24,16,14],begin:9,sure:10,distribut:[23,12,24,13,16],plenti:24,normal:[23,11],buffer:[18,16],who:13,compress:12,deleg:9,most:[4,16],wire:7,abus:7,pair:[11,17],bz2:13,"class":[15,9,16,17,18,19,10,11,7,23,4,5],three:[23,4,9,16,5],tradit:13,todo:7,don:[9,1,18,12,23,13],url:[12,20,13],clear:[23,4],later:16,cover:[4,14],uri:[6,9,15,19,11,2,12,5,14],doe:[16,17,19,10,11,23,4,13],declar:[11,9,17],directive2:7,directive1:7,readcallback:16,usual:[11,7,17],microsoft:13,came:9,connection_ptr:16,show:[21,20,16,19],awar:24,inherit_linearli:18,concurr:16,syntax:[6,9,19,2,12,5],session:23,migrat:24,radic:14,identifi:[4,19],trivial:[9,7],find:[6,13],foo_direct:4,xml:20,absolut:19,onli:[15,9,16,1,19,18,7,23,13,14],bind:16,locat:23,pointer:[23,16],explain:12,response_head:[9,16],solut:13,written:[11,17],should:[15,9,16,18,10,23,4,13],prolong:7,configur:[6,14,13,10],hello_world:10,meant:[18,4,17,11,16],set_head:16,variou:23,get:[6,9,17,18,10,20,12,23,13,24],between:19,stop:16,fluid:15,soon:16,ssl:[23,15],is_base_of:18,mainten:13,"import":[16,14],report:[6,13,16],metafunct:[6,4,18,8],requir:[15,16,17,19,11,4,13,24],embedd:[9,14],receiv:16,enabl:[18,24,13,16],had:24,emb:[23,16],ietf:9,"_send_buffer_s":16,ipp:10,excel:24,entri:24,patch:13,rfc:[9,2,19,12],whether:[15,16,19,11,23,4,14],common:[12,4,3,24],contain:[16,17,18,10,7,21,4],status_typ:16,where:[15,9,16,18,11,20,7,23,4,24,14],async_serv:16,conform:9,lvalu:[4,16],primari:[18,16],requesthandl:9,truli:7,invari:18,"_thread_pool":16,accord:[4,19],packet:4,derived1:15,see:[9,16,1,10,23,18],result:[17,18,19,11,7,4],arg:[6,16,23],close:[6,12,9,13,16],retriev:[4,19,11,17],best:2,chose:4,polymorph:[6,15,8],statu:[17,9,16,10],said:19,status_message_:17,correctli:[11,17],"_report_abort":16,pattern:[23,4,7,16,15],someth:[9,4,7,16,18],enumer:10,user_info:19,state:[7,16],bridg:15,listinfo:[6,13],simplest:12,progress:6,awai:16,approach:[15,18],across:[23,10],signatur:16,assumpt:9,handler_:6,predefin:9,syntact:[4,7],extend:[18,7,24],"_handler":16,cannot:[23,16],ask:[6,13],were:16,hello_world_serv:[20,10],extens:[9,18,7],job:13,preprocessor:[23,14],request_:[6,23],overhaul:14,headers_contain:[4,17],endl:[12,20,9,19,10],addit:[15,7,13,19],both:[9,16,17,1,11,21,23],metaprogram:[6,18,2,13],berri:[13,24],cycl:23,response_:[6,23],howev:[18,9],alon:15,default_wstr:18,against:16,constructor:[9,16,19,10,12,23,14],etc:24,instanc:[9,16,17,18,19,11,23,4],present:[6,12],context:[18,7],logic:[9,4,7,16,12],bool:[23,16],mani:[23,24,13,14],whole:[12,18,13,17],clone:13,among:18,simpli:[9,11,7],publicli:[11,16,17],stream:[23,12,16,14],point:[6,4,18],instanti:16,schedul:16,logic_error:16,dispatch:[15,4,9,18,14],header:[6,9,16,15,18,17,10,11,7,12,23,4,13,14],rpc:20,littl:[15,18],suppli:[9,16,19],pod:[4,11],guid:[6,2,13,22],assum:[16,17,11,20,23,4,13],summar:4,mailto:19,becom:24,io_servic:[23,16,14],version_major:[23,1,9,11],"_receive_buffer_s":16,handler_inst:16,compos:5,been:[23,16,24],accessor:[4,11,17],compon:[23,4,21,18,19],destructor:15,much:15,treat:11,modif:4,individu:13,acceptor:16,strategi:[23,15],modern:6,bit:[11,17],immedi:[7,16],basic_uri:[6,9,19,5],clariti:12,target_typ:7,argument:[9,16,10,12,23,4],assert:[9,19],craft:20,understand:16,togeth:24,demand:24,"catch":[20,10],rang:16,repres:16,synchronoushandl:16,resid:[12,9],standard:[7,24],"case":[15,9,16,17,18,10,11,23,4,13],multi:10,therefor:[9,24],look:[6,9,16,15,18,10,20,7,23,4,13,5],gnu:13,deanberri:13,servic:24,properti:[9,4,7,18],sourceforg:[6,13,24],aim:8,defin:[15,9,16,18,19,10,7,23,4,13,14],"while":[9,4,24,7,15],smart:[23,16],abov:[9,16,1,19,10,18,23,13],error:[6,16,12],thrash:13,aid:3,invoc:16,pertain:4,loop:16,pack:[23,16],real:18,layer:[6,24,7,15],would:[9,16,18,10,4,13],almost:16,them:[23,11,16,17],destin:[4,11,17],"_non_blocking_io":16,itself:[18,7],motiv:[6,24],new_statu:16,boost_network_enable_http:14,pthread:[12,20,10],sever:[16,8],headers_container_typ:[11,17],develop:[6,10,3,12,13,24],welcom:6,author:[23,19],perform:[16,11,20,23,4,24],suggest:11,make:[6,9,15,1,10,18,20,12,23,13],cross:[6,24],same:[15,9,18,10,7,23,13,24],check:[6,12,13,14],member:[6,9,16,0,15,10,23],fragment:19,complex:[12,13,19],http_keepalive_8bit_udp_resolv:[23,1,9],come:[15,11,7,13,17],document:[16,0,17,11,20,23,13,14],start:[6,18,16,13,23],higher:[6,13],overal:18,http:[6,9,16,0,15,1,17,24,19,10,21,11,20,2,3,12,23,4,14,13,5],hostnam:16,http_version_minor:23,imagin:20,nest:[9,16,17,18,11,7,4],chainabl:7,upon:16,effect:[23,11,17],user:[9,16,1,19,7,23,13,14],extern:[23,15,14],build:[6,9,10,20,21,12,13,24],respons:[6,9,16,0,17,1,10,20,12,23,14],typic:[4,9,13],built:[23,12,13,15],http_default_8bit_udp_resolv:[23,1,9,11,17],lower:[24,14],appropri:[23,11,17,13,16],kept:[16,24],equival:18,choos:[23,4,11,13],com:[6,19,13,20,23],builder:19,string_typ:[6,11,18,16,17],well:[4,7,16],inherit:18,person:13,client:[6,9,16,0,1,24,10,21,11,20,3,12,23,14,5],reflect:14,thi:[15,9,16,0,17,1,24,19,10,18,11,20,7,12,23,4,14,13,8],service_unavail:16,error_cod:16,everyth:19,latest:[6,13],load:23,construct:[16,17,19,11,23,4],protocol:[6,19,10,11,20,7,3,12,23,4,24,5],cout:[12,20,9,19],just:[9,17,18,10,11,20,4,13],object:[6,9,16,15,1,17,10,11,7,12,23,4,24,14],boost_network_no_lib:[23,14],tcp:[23,1,9,15],activ:[23,1,9,24],clear_resolved_cach:23,refactor:14,increasingli:24,derived0:15,yet:[18,16],languag:24,previous:[16,10],web:[13,24],struct:[6,9,16,15,18,10,7,4],easi:[6,20,24],snmp:4,makefil:13,except:[15,9,1,10,20,23],dcmake_build_typ:13,add:[12,4,17,11,13],is_valid:19,http_default_8bit_tcp_resolv:[23,1,9],versa:4,overview:[6,19,5],trait:[18,17],ado:12,adl:[4,18],subsequ:[15,11,17],source_:[11,17],boost_root:[12,20,13,10],take:[9,16,19,10,7,23,4,14],dsel:7,applic:[6,16,17,11,20,3,12,23,24,13,21],torvald:13,which:[6,9,16,15,18,19,10,20,7,12,23,4,13],format:7,read:[13,16],wstring:[11,18,17],boost_network_http_server_connection_header_buffer_max_s:16,asynchronoushandl:16,world:[6,16,10,20,21,3],part:[9,17,19,11,4,14],linux:[6,13],if_:18,mikhailberi:[6,13],like:[15,9,16,18,10,20,7,23,4,13],specif:[19,10,2,23,4,13],filenam:23,uint16_t:17,signal:12,echo_serv:9,sstream:20,html:9,integ:11,noth:15,collect:24,"boolean":[23,16],necessari:10,either:[4,17,24,11,16],docutil:5,http_async_8bit_tcp_resolv:[23,1,9],output:19,mode:14,not_modifi:16,depend:[9,16,17,11,23,4,13],fulfil:24,encount:[23,16],www:[6,9,19,12],right:[18,16],dean:[13,24],"_linger":16,deal:[15,16,10],simplifi:7,manual:[6,0],status_:17,interact:13,some:[6,16,15,18,17,19,11,8,14],pipelin:16,resolv:[23,1,9],intern:[9,16,18,11,23,14],unspecifi:[11,17],sampl:[13,16],home:[13,24],indirect:[15,7],server:[6,9,16,0,1,24,19,10,21,11,20,3,12,23,14,5],librari:[6,15,18,17,11,7,3,23,4,24,13,14],tmp:23,basic_serv:9,connectionptr:16,scale:16,lead:7,abort:16,"_io_servic":[23,16],broad:7,though:[15,12],octet:23,achiev:8,"_receive_low_watermark":16,body_:[11,17],tracker:6,larg:[18,16],slash:19,moved_temporarili:16,foo:[15,4,18],localhost:20,refer:[6,9,16,0,19,10,7,23,2,4,13,14],msvc:14,peek:6,command:[19,13,20,10],run:[6,16,10,20,21,12,13,14],power:[13,19],"enum":16,usag:[12,20,16,10],fast:6,http_statu:16,broken:19,step:[12,13],repositori:[6,13],found:[6,16,10,12,13,24],gatekeep:13,"throw":[23,16],stage:[12,20,10],chapter:8,about:[6,16,17,10,11,2,13],central:4,socket:16,linger:16,memori:[23,24,13,16],slightli:18,page:[6,13],delete_:23,stand:19,act:13,commit:24,comp:19,input_rang:16,disabl:16,block:[23,1,9,16],underli:[9,4,7,18],thread_pool:16,own:[23,16,24],erro:23,cosntructor:14,default_str:18,around:[23,16],within:[13,0,16],encod:[11,17],bound:16,two:[23,11,9,16,10],down:[9,7,19,15],creativ:15,empti:4,ensur:[4,18,10],synchronushandl:16,updat:14,next:[12,16],your:[23,9,13,16],merg:13,client_:[6,23],server_:[6,10],span:5,log:6,suffici:13,area:4,transfer:16,support:[6,9,16,15,18,17,19,10,11,7,12,23,4,24,13,14],question:[6,13],transform:[4,7],"long":16,custom:23,avail:[15,16,23,4,24,13,14],stuck:13,reli:[23,14],plain:15,interfac:[9,16,0,1,11,7,23],includ:[16,17,19,10,11,20,7,12,23,14],lot:[15,13],suit:13,forward:9,submiss:6,strictli:14,repetit:14,remove_head:[4,11,17],"function":[6,9,16,0,15,18,24,7,23,4,14,5],head:[23,9,12],creation:7,gzip:13,form:[9,4,7,18,19],enough:[7,13],handler:[6,9,16,15,10,14],linu:13,basic:[4,7],idea:18,link:[6,13,23],translat:18,newer:[23,16],line:[6,19,10,20,12,13,14],inlin:[11,7,18,17],"true":[23,16],bug:[13,14],reset:15,pull:13,made:[23,20,16,10],utf:[11,17],input:[15,7],consist:[6,24,19,14],possibl:[6,12,15],"default":[15,9,16,1,12,23,4,18,14],asynchron:[6,14,16,0,23],not_support:16,below:[9,16,17,19,12,23,13],argpack:[23,16],those:[11,17,8],otherwis:[15,11,13,19],problem:15,similar:[9,16,1,18,20,7,23,4,13],impl:10,connect:[6,9,16,15,1,20,12,23],version_:17,featur:[18,13,24],artifact:13,creat:[15,16,17,10,11,20,12,13],"int":[6,16,15,17,10,20,12,23],certain:[9,4,7,16,18],"abstract":[15,12,10],parser:[9,19,14],ostringstream:20,deep:7,"_openssl_verify_path":23,"char":[6,20,12,16,10],boostcon:[6,2],implement:[6,9,16,0,15,1,17,19,18,11,7,23,4,14,13,5],"8bit":23,file:[6,16,13,19,23],request:[6,9,16,0,10,11,20,12,23,13,14],exist:[23,13,24],face:[23,16],std:[6,9,16,17,18,19,10,11,20,12],fill:23,echo:9,denot:[18,16],readi:[23,14],macro:[23,14],cmake:[6,13],infosystem:19,nonetheless:4,"7zip":13,titl:1,hpp:[16,18,10,20,12,23],when:[15,4,16,24],detail:[9,16,17,1,10,11,12,23,4],virtual:15,event:16,finish:[23,16],other:[6,16,18,7,23,2,4,24],lookup:4,futur:[6,9,16,17,1,19,23],branch:13,peopl:6,test:[13,14],you:[6,9,16,15,18,10,20,12,23,13],runtim:15,miss:24,intend:[6,16,13,23],determin:[18,9,16],lend:7,subdivid:19,sequenc:23,introduc:23,source_typ:4,gcc:13,"_linger_timeout":16,definit:[18,4,19,11,16],"public":[9,16,0],intent:24,embed:[21,16,10],not_found:16,pool:[16,14],svn:13,moved_perman:16,studio:13,vice:4,directori:[23,13],info:[6,19],descript:[9,16,17,1,19,11,23,4],notion:[4,7],not_impl:16,basic_request:[11,9],basic_respons:[9,17],ignor:18,fact:12,potenti:16,time:[7,16,14],cpp:[0,2,3,4,5,6,7,8,9,10,11,23,13,14,15,16,17,18,19,20,21,12,24],profil:16,hello:[6,16,10,20,21,3],legend:[4,17,11,19,16]},objtypes:{},titles:["Reference Manual","<no title>","References","Examples","The message template","An in-depth look at the cpp-netlib","C++ Network Library","Directives","Techniques","HTTP implementation","“Hello world” HTTP server","HTTP Request","HTTP client","Getting Started","What’s New","Static and dynamic polymorphism","HTTP Server API","HTTP Response","Tag metafunctions","The URI template","“Hello world” HTTP client","HTTP examples","Full installation guide","HTTP Client API","Project history"],objnames:{},filenames:["reference","http_client_tags","references","examples","message","in_depth","index","directives","techniques","http","hello_world_server","reference_http_request","http_client","getting_started","whats_new","polymorphism","reference_http_server","reference_http_response","tag_metafunctions","uri","hello_world_client","examples_http","install","reference_http_client","history"]}) \ No newline at end of file +Search.setIndex({objects:{},terms:{directive_typ:7,all:[15,9,16,17,10,11,20,7,12,23,4,13,14],code:[6,9,16,15,18,10,20,7,21,12,23,24,13,14],skeleton:18,chain:7,illustr:18,queri:[11,19],forbidden:16,lack:24,icmp:4,basic_messag:[6,4,19,5],four:17,concept:[6,16,0,17,19,11,7,4,5],follow:[15,9,16,17,18,19,10,11,20,7,3,12,23,4,13,21],synchronushandl:16,ptr:15,abid:[11,7],hierarch:19,whose:18,decid:[15,18,24],"const":[6,9,16,17,10,11,7,23,4],boost_network_http_body_callback:23,flexibl:[12,18,7],range_iter:9,send:[12,16],concret:7,swap:[4,18,19],string_tag:18,sens:[9,1,7,23],"_follow_redirect":23,stock_repli:[6,9,16,10],sent:[23,16],liter:5,everi:[4,24],risk:13,straightforward:10,fals:[23,16],"void":[6,9,16,15,18,17,19,10,11,23,4],inhibit:23,nich:24,netlib:[0,2,3,4,5,6,7,8,9,10,11,23,13,14,15,16,17,18,19,20,21,12,24],endpoint:23,fan:13,veri:16,affect:23,default_:[15,18,9],exact:9,relev:20,rfc1738:9,http_async_serv:16,administr:10,level:[6,13,24],who:13,michael:[13,24],upload:16,iter:9,correct:[15,4,9],"try":[20,16,10],vector:[18,11,16],verif:23,cooki:23,argpack:[23,16],impli:4,tel:19,throught:12,core:4,natur:7,direct:[6,0,17,11,24,7,12,4,8,5],handler_typ:16,second:[11,9],cost:14,design:3,pass:[9,16,18,10,20,7,12,23,4],download:[6,13],further:[12,19],port_typ:11,port:[9,16,17,19,10,11,20],append:23,even:[4,7,17],"_cache_resolv":23,what:[6,16,15,18,10,11,20,23,4,14],msysgit:13,insid:[9,16],repli:10,section:[9,16,17,11,23,4],watermark:16,abl:[13,16],"_linger_timeout":16,overload:[9,16,10],access:[9,16,17,11,20,7,24],delet:[23,9,12],version:[6,16,15,18,17,19,11,12,23,13,14],source_wrapp:4,underneath:[23,14],"new":[6,15,18,19,7,13,14],boost:[6,9,16,17,1,19,10,18,11,20,12,23,24,13,14],method:[23,11,12,9,10],redirect:23,full:[6,19,13,22,17],deriv:[15,11],"_address":16,gener:[6,16,0,15,19,11,7,23,2,4,24,13,5],never:24,unauthor:16,here:[15,9,16,19,10,12,23],boost_network_http_client_default_tag:14,bodi:[6,9,16,17,18,10,11,20,12,23,4,14],let:[18,20,13,10],free:[4,16],address:[9,16,1,10,20,23],path:[11,9,13,19],along:13,rudimentari:7,modifi:[6,0,17,11,23,4,5],sinc:[12,18,20],valu:[15,9,16,17,1,10,11,23,4],wait:[23,16],convert:[4,19,11,17],convers:4,shift:7,anymor:18,larger:21,host:[11,19,9,13,10],anchor:11,cert:23,base:[15,18,19,7,4,13],cerr:[6,20,9,10],behav:23,http_keepalive_8bit_tcp_resolv:[23,1,9],action:16,http_client:[12,9],chang:[9,18,7,23,13,14],narrow:17,portabl:24,semant:[6,4,7,16,15],via:[6,20],although:[15,4,18,13,16],appli:[4,7],multiple_choic:16,put:[23,9,16],unix:[13,19],api:[6,16,0,17,19,11,23,14],famili:18,visibl:9,instal:[6,13,22],post:[23,20,9,12],unit:14,regex:13,version_minor:[23,1,9,11],from:[6,9,16,17,18,19,10,11,20,7,12,23,4,13,14],describ:[23,16,3,19,8],zip:13,commun:[6,3,24],distinct:16,doubl:19,upgrad:[23,16,14],subvers:13,websit:12,few:13,program:[15,21,24,19,10],call:[9,16,18,10,7,23,4,13],recommend:13,taken:16,clear_head:[4,11,17],type:[15,9,16,17,18,19,11,7,23,4,24],until:23,minor:[23,11],more:[6,16,4,14,13,24],reachabl:18,wrapper:[6,9,0,17,11,4,14,5],headers_rang:[11,9,17],afford:7,smtp:[4,24],swappabl:[4,18,19],relat:16,notic:[18,9],site:13,warn:[23,17,13,16],visual:13,depth:[6,5],accept:[7,16],known:[13,19],actual:16,hold:[23,1,9],unpack:13,cach:23,content_typ:23,must:[13,14],placehold:18,none:16,dcmake_c_compil:13,join:[6,13,16],internal_server_error:16,scalabl:16,alia:[13,17],work:[11,13,17],uniqu:15,histori:[6,24],annoi:24,remain:[15,7],tag:[6,9,16,15,1,17,19,11,23,4,14,18,8],can:[6,9,16,15,18,19,10,20,7,21,12,23,4,13],caveat:13,root:[11,18],fetch:23,aliv:[23,1,9,16],proof:16,control:[18,13,16],heart:9,encapsul:[9,1,7,4,23],tar:13,give:16,process:[9,19],lock:16,no_cont:16,share:[23,1,9,16,10],sln:13,templat:[6,9,16,15,18,17,19,11,7,23,2,4,24,13,5],high:24,sourc:[6,9,17,10,11,2,4,13,24],want:[15,16,18,20,23,4,13],explos:15,tarbal:13,http_async_8bit_udp_resolv:[23,1,9,14],serial:16,unavoid:15,unsign:[23,11,9,17],occur:[11,17],some_xml_str:20,string:[6,9,16,17,18,19,10,11,20,12,23,4],low:16,alwai:16,differenti:[16,10],multipl:16,goal:24,programmat:14,anoth:[16,19],classifi:19,write:[6,16,20,23,24,14],how:[18,19,10,20,21,23,13],scale:16,conn:16,pure:[15,4],subdirectori:12,opt:13,instead:[23,18,16,13,14],greatli:15,simpl:[6,9,16,19,10,20,7,12,4],mpl:[18,14],stock:10,resourc:[13,10],dive:[12,20,21,10],earlier:[15,20],sneak:6,constraint:24,status_messag:17,befor:[23,20,16,14],xzf:13,attent:7,mai:[6,9,16,10,23,4],end:[23,9,24],data:[9,16,19,20,23,4],parallel:13,util:16,github:[6,19,24,13,23],attempt:[16,14],practic:3,third:10,date_tim:13,light:[6,24],valid:[4,9],minim:14,explicit:[23,4],element:19,issu:[6,13,14],inform:[6,16,13,14],"switch":[15,11],maintain:[7,13,16],environ:[13,10],allow:[6,16,15,18,7,12,23,4,14],mechan:[18,9],order:[12,7,14],talk:[11,17],origin:[18,9],composit:18,help:16,xmpp:[4,24],offici:[6,13],move:7,becaus:[15,4,7,16],intermediari:4,paper:[6,2],through:[11,9,13,16],left:[18,7],size_t:16,still:[23,18,17,13,16],vari:[15,4,18],dynam:[6,15,16,23,8],paramet:[9,16,17,18,11,7,23,4,13,14],divis:4,typedef:[6,9,16,18,10,23,4],group:[6,13,24],fit:16,fix:14,unsupported_tag:18,better:[16,13,14],platform:[6,24,13,16],window:[6,13],pend:16,bin:19,mail:[6,13],hidden:[23,7],main:[6,20,12,13,10],might:[18,9],easier:[23,4],non:[4,16,19],multimap:9,"return":[15,9,16,17,1,10,11,20,7,12,23,4,14],greater:[12,10],thei:[9,1,19,23,4,18],handl:[23,15,16,10],smarter:18,safe:[23,10],initi:[23,24,16,14],"break":[23,15,9,14],framework:10,facilit:15,now:[23,14,17,13,10],discuss:[6,13],nor:4,choic:13,term:[23,4,16],eventu:[6,24],somewher:23,name:[9,16,17,11,23,4,13,14],realist:3,edit:16,separ:14,easili:[23,24],slide:[6,2],exampl:[6,9,16,18,19,10,20,7,3,12,23,4,13,21],submit:[6,13,24],http_server:[6,11,16,17],timeout:16,each:[23,4,12,13,16],debug:13,fulli:[23,24],complet:[12,13],side:[15,10],mean:[23,4,13,16],compil:[23,16,7,13,14],dcmake_cxx_compil:13,weight:[6,24],list:[6,16,17,18,10,13],chunk:[23,16],continu:[16,24],functor:[9,10],realli:20,heavi:[13,14],wrap:[15,4,17],set_statu:16,"static":[6,15,18,7,23,8,14],expect:23,our:[18,13,24],happen:23,"_port":16,unique_ptr:15,orient:[15,7],special:[6,9,15,18,17,11,7,4],out:[23,13,16],variabl:13,ftp:[19,24],shown:[23,16],safeti:18,network:[6,9,16,17,18,19,10,11,20,3,12,23,4,24],webservic:20,goe:13,tcp_resolv:23,req:16,rational:7,content:[6,4,16,23],typenam:[18,4,11,17],adapt:4,rel:19,internet:13,print:[12,9],current:[23,16,19],factori:[15,4,7],model:[16,17,11,7,23,4,13],after:[12,16,19],iostream:[12,20,7,10],linear:16,barrier:24,advanc:8,my_io_servic:[23,16],manipul:[4,16],situat:[15,7,16],given:[6,9,16,15,18,17,19,11,4],argv:[6,20,12,10],hello_world_cli:20,significantli:16,standalon:[23,15],reason:13,git:[6,13],releas:[6,16,17,13,23],org:[6,9,19,12],"byte":[23,16],argc:[12,20,10],bash:19,netib:23,wai:[23,18,9,16,19],thread:[9,16,1,10,23,14],prescrib:13,synchron:[6,9,16,0,1,10,23],keep:[15,9,1,7,23,18],thing:[15,18,12,13,17],enforc:11,place:16,"_send_buffer_s":16,lifetim:23,assign:[4,16,19],first:[15,9,19,10,11,12,4,13],oper:[6,9,16,17,10,11,7,23,4,14],softwar:24,major:[23,11,24],"_openssl_certif":23,directli:[23,16],certif:23,onc:[23,18,12,13,16],independ:[23,7,16],qualiti:24,number:[9,16,1,10,18,11,23,4,13],yourself:13,uri_:9,instruct:13,alreadi:[16,17,11,23,14,24],done:[15,9,16,18,11,4,13],bad_gatewai:16,lboost_system:[12,20,10],stabl:13,"_reuse_address":16,open:24,connection_ptr:16,size:16,differ:[6,9,16,0,15,18,17,19,11,7,23,4,14,5],width:23,associ:[18,4,17,11,16],top:[13,24],system:[23,7,13,16],messag:[6,17,11,24,7,12,23,4,14,5],destination_:[11,17],mikhailberi:[6,13],bad_request:16,scheme:[11,9,19],zipfil:13,"final":12,boil:7,listen:[16,10],adher:16,udp:[23,1,9],shell:[20,13,10],consol:12,option:[16,24,13,14],distanc:23,especi:16,namespac:[6,9,16,17,18,10,11,20,12,23],tool:[9,13],copi:[23,4,16,19],specifi:[9,16,1,19,12,23,4,13],aptli:9,xjf:13,pars:[19,9,16,14],mostli:13,review:6,than:[18,16],http_version_major:23,serv:18,wide:17,kind:[6,3,15],conveni:23,target:[7,24],provid:[6,9,17,1,19,10,11,23,18,24],remov:[4,11,17],http_client1:12,basic_cli:[23,9],structur:[12,18],charact:23,project:[6,13,24],matter:16,reus:7,not_accept:16,store:[23,4,16],str:20,opaqu:[18,19],iterator_rang:[23,16],seri:[3,16],pre:[10,5],fork:13,fashion:7,payload:[4,20],behavior:[23,18,9,15],boostcon:[6,2],facad:14,add_head:[4,11,17],sometim:[4,18],ani:[15,9,16,10,12,23,4,13,14],packag:13,properli:[23,16],manner:[23,11,18,16,17],have:[15,9,16,1,10,18,20,7,12,23,4,13,24],tabl:[23,4,9,16,17],need:[15,16,18,10,3,12,23,13,24],seen:10,dedic:23,incompat:13,infosystem:19,repeatedli:24,boost_network_default_tag:14,caus:[23,1,9,18],shared_futur:17,status_t:16,techniqu:[6,18,15,7,8],lib:[12,20,10],callback:[23,16],directiven:7,self:7,expos:16,note:[16,17,19,10,20,23,4,13],also:[6,9,16,15,1,17,10,18,11,7,23,4,13,24],without:[12,7],decis:15,take:[9,16,19,10,7,23,4,14],indic:[23,1,9],combin:[15,18],concern:14,soap:24,singl:[9,16,10,23,12,14],asio:[23,24,16,14],begin:[23,9],sure:10,distribut:[23,12,24,13,16],plenti:24,normal:[23,11],buffer:[18,16,14],conncetionptr:16,compress:12,deleg:9,most:[4,16],wire:7,abus:7,pair:[11,17],"class":[15,9,16,17,18,19,10,11,7,23,4,5],three:[23,4,9,16,5],tradit:13,todo:7,found:[6,16,10,12,13,24],don:[9,1,18,12,23,13],url:[12,20,13],clear:[23,4],later:16,cover:[4,14],uri:[6,9,15,19,11,2,12,5,14],doe:[16,17,19,10,23,4,13],declar:[11,9,17],directive2:7,directive1:7,pattern:[23,4,7,16,15],readcallback:16,usual:[11,7,17],microsoft:13,came:9,show:[21,20,16,19],awar:24,inherit_linearli:18,syntax:[6,9,19,2,12,5],concurr:16,migrat:24,radic:14,identifi:[4,19],trivial:[9,7],find:[6,13],foo_direct:4,cout:[23,20,9,19,12],xml:20,absolut:19,onli:[15,9,16,1,19,18,7,23,13,14],bind:16,locat:23,explain:12,response_head:[9,16],solut:13,enough:[7,13],should:[15,9,16,18,10,23,4,13],prolong:7,configur:[6,14,13,10],hello_world:10,meant:[18,4,17,11,16],set_head:16,contribut:14,variou:23,get:[6,9,17,18,10,20,12,23,13,24],between:[13,19],stop:16,fluid:15,soon:16,ssl:[23,15],is_base_of:18,mainten:13,"import":[16,14],report:[6,13,16],metafunct:[6,4,18,8],requir:[15,16,17,19,11,23,4,13,24],embedd:[9,14],receiv:[23,16],enabl:[18,24,13,16],had:24,emb:[23,16],ietf:9,applac:16,ipp:10,excel:24,patch:13,rfc:[9,2,19,12],whether:[15,16,19,11,23,4,14],common:[12,4,3,24],though:[15,13,12],contain:[16,17,18,10,7,21,4],status_typ:16,where:[15,9,16,18,11,20,7,23,4,24,14],async_serv:16,conform:9,set:[15,16,17,10,11,7,3,23,4,5],primari:[18,16],requesthandl:9,truli:7,invari:18,"_thread_pool":16,accord:[4,19],packet:4,derived1:15,see:[9,16,1,10,23,18,14],result:[17,18,19,11,7,4],arg:[6,16,23],close:[6,12,9,13,16],best:2,chose:4,polymorph:[6,15,8],statu:[14,9,16,17,10],said:19,status_message_:17,correctli:17,"_report_abort":16,pointer:[23,16],someth:[9,4,7,16,18],"_body_handl":23,user_info:19,written:[11,17],bridg:15,john:19,simplest:12,progress:6,awai:16,approach:[15,18],across:[23,10],signatur:[23,16],assumpt:9,handler_:6,predefin:9,syntact:[4,7],extend:[18,7,24],"_handler":16,numer:14,ask:[6,13],were:16,hello_world_serv:[20,10],extens:[9,18,7],job:13,preprocessor:[23,14],request_:[6,23],overhaul:14,headers_contain:[4,17],endl:[9,19,10,20,23,12],addit:[15,7,13,19],both:[9,16,17,1,11,21,23],metaprogram:[6,18,2,13],berri:[13,24],cycl:23,response_:[6,23],pertain:4,alon:15,default_wstr:18,against:16,constructor:[9,16,19,10,12,23,14],etc:24,instanc:[9,16,17,18,19,11,23,4],context:[18,7],logic:[9,4,7,16,12],bool:[23,16],mani:[23,24,13,14],com:[6,19,13,20,23],clone:13,among:18,simpli:[9,11,7],publicli:[11,16,17],stream:[23,12,16,14],point:[6,4,18],instanti:16,schedul:16,logic_error:16,dispatch:[15,4,9,18,14],header:[6,9,16,15,18,17,10,11,7,12,23,4,13,14],rpc:20,littl:[15,18],suppli:[9,16,19],comput:[13,16],pod:[4,11],not_found:16,assum:[16,17,11,20,23,4,13],summar:4,trait:[18,17],mailto:19,becom:24,io_servic:[23,16,14],version_major:[23,1,9,11],"_receive_buffer_s":16,handler_inst:16,compos:5,been:[23,16,24],accessor:[4,11,17],compon:[23,4,21,18,19],destructor:15,much:15,treat:11,modif:4,acceptor:16,strategi:[23,15],modern:6,bit:[11,17],immedi:[7,16],basic_uri:[6,9,19,5],clariti:12,target_typ:7,argument:[9,16,10,12,23,4],assert:[9,19],unzip:13,craft:20,understand:16,togeth:[13,24],demand:24,"catch":[20,10],rang:[23,16],repres:16,synchronoushandl:16,present:[6,12],"case":[15,9,16,17,18,10,11,23,4,13],multi:10,therefor:[9,24],look:[6,9,16,15,18,10,20,7,23,4,13,5],gnu:13,plain:15,servic:24,properti:[9,4,7,18],sourceforg:24,aim:8,defin:[15,9,16,18,19,10,7,23,4,13,14],"while":[9,4,24,7,15],smart:[23,16],abov:[9,16,1,19,10,18,23,13],error:[6,12,16,23],thrash:13,aid:3,invoc:16,howev:[18,9],loop:16,pack:[23,16],real:18,layer:[6,24,7,15],would:[9,16,18,10,4,13],remove_head:[4,11,17],almost:16,some_str:23,them:[23,16,17],destin:[4,11,17],"_non_blocking_io":16,itself:[18,7],motiv:[6,24],new_statu:16,boost_network_enable_http:14,pthread:[12,20,10],sever:[16,8],headers_container_typ:[11,17],develop:[6,10,3,12,13,24],welcom:6,author:[23,19],perform:[16,11,20,23,4,24,14],suggest:11,make:[6,9,15,1,10,18,20,12,23,13,14],cross:[6,24],same:[15,9,18,10,7,23,13,24],check:[6,12,13,14],member:[6,9,16,0,15,10,23],fragment:19,complex:[12,13,19],session:23,http_keepalive_8bit_udp_resolv:[23,1,9],come:[15,11,7,13,17],document:[16,0,17,11,20,23,13,14],start:[6,18,16,13,23],higher:[6,13],overal:18,http:[6,9,16,0,15,1,17,24,19,10,21,11,20,2,3,12,23,4,14,13,5],hostnam:16,imagin:20,nest:[9,16,17,18,11,7,4],chainabl:7,upon:16,effect:[23,11,17],user:[9,16,1,19,7,23,13,14],extern:[23,15,14],build:[6,9,10,20,21,12,13,24],respons:[6,9,16,0,17,1,10,20,12,23,14],typic:[4,9,13],bz2:13,http_default_8bit_udp_resolv:[23,1,9,11,17],lower:[24,14],appropri:[23,11,17,13,16],kept:[16,24],equival:18,choos:[23,4,11,13],whole:[12,18,13,17],builder:19,string_typ:[6,11,18,16,17],well:[4,7,16],inherit:18,person:13,client:[6,9,16,0,1,24,10,21,11,20,3,12,23,14,5],reflect:14,thi:[15,9,16,0,17,1,24,19,10,18,11,20,7,12,23,4,14,13,8],service_unavail:16,error_cod:[23,16],everyth:19,latest:[6,13],load:23,construct:[16,17,19,11,23,4],protocol:[6,19,10,11,20,7,3,12,23,4,24,5],entri:24,just:[9,17,18,10,11,20,4,13],object:[6,9,16,15,1,17,10,11,7,12,23,4,24,14],boost_network_no_lib:[23,14],tcp:[23,1,9,15],activ:[23,1,9,24],clear_resolved_cach:23,fact:12,refactor:14,increasingli:24,derived0:15,body_handl:23,yet:[18,16],languag:24,previous:[16,10],web:[13,24],struct:[6,9,16,15,18,10,7,23,4],easi:[6,20,24],snmp:4,makefil:13,except:[15,9,1,10,20,23],dcmake_build_typ:13,add:[12,4,17,11,13],is_valid:19,http_default_8bit_tcp_resolv:[23,1,9],versa:4,overview:[6,19,5],compat:23,ado:12,adl:[4,18],subsequ:[15,17],source_:[11,17],boost_root:[12,20,13,10],headers_:[9,17],dsel:7,applic:[6,16,17,20,3,12,23,24,13,21],torvald:13,mere:4,which:[6,9,16,15,18,19,10,20,7,12,23,4,13,14],format:7,read:[13,16],wstring:[11,18,17],boost_network_http_server_connection_header_buffer_max_s:16,built:[23,12,13,15],asynchronoushandl:16,world:[6,16,10,20,21,3],part:[9,17,19,11,23,4,14],linux:[6,13],if_:18,resid:[12,9],like:[15,9,16,18,10,20,7,23,4,13],specif:[19,10,2,23,4,13],filenam:23,uint16_t:17,signal:12,echo_serv:9,cannot:[23,16],html:9,integ:11,noth:15,collect:24,"boolean":[23,16],necessari:10,either:[4,17,24,11,16],docutil:5,http_async_8bit_tcp_resolv:[23,1,9],http_version_minor:23,mode:14,not_modifi:16,manag:[23,16,14],depend:[9,16,17,11,23,4,13],fulfil:24,encount:[23,16],www:[6,9,19,12],right:[18,16],dean:[13,24],"_linger":16,deal:[15,16,10],simplifi:7,sstream:20,status_:17,interact:13,some:[6,16,15,18,17,19,8,13,14],pipelin:16,resolv:[23,1,9],certain:[9,4,7,16,18],intern:[9,16,18,11,23,14],enumer:10,sampl:[13,16],home:[13,24],indirect:[15,7],server:[6,9,16,0,1,24,19,10,21,11,20,3,12,23,14,5],librari:[6,15,18,17,11,7,3,23,4,24,13,14],tmp:23,basic_serv:9,connectionptr:16,guid:[6,2,13,22],lead:7,abort:16,"_io_servic":[23,16],broad:7,lvalu:[4,16],octet:23,achiev:8,"_receive_low_watermark":16,body_:[11,17],tracker:6,larg:[18,16],slash:19,sequenc:23,moved_temporarili:16,foo:[15,4,18],localhost:20,refer:[6,9,16,0,19,10,7,23,2,4,13,14],msvc:14,peek:6,command:[19,13,20,10],run:[6,16,10,20,21,12,13,14],power:[13,19],"enum":16,usag:[12,20,16,10],fast:6,els:23,http_statu:16,broken:19,step:[12,13],repositori:[6,13],output:19,gatekeep:13,"throw":[23,16],stage:[12,20,10],chapter:8,manual:[6,0],about:[6,16,17,10,11,2,13],central:4,socket:16,linger:16,memori:[23,24,13,16],slightli:18,page:[6,13],delete_:23,stand:19,act:13,commit:24,comp:19,input_rang:16,disabl:16,block:[23,1,9,16],underli:[9,4,7,18],thread_pool:16,own:[23,16,24],erro:23,cosntructor:14,default_str:18,around:[23,16],within:[13,0,16],encod:17,bound:16,two:[9,16,10,11,23,14],down:[9,7,19,15],creativ:15,empti:4,ensur:[4,18,10],default_tag:18,updat:14,next:[12,16],your:[23,9,13,16],merg:13,client_:[6,23],server_:[6,10],span:5,log:6,suffici:13,area:4,transfer:16,support:[6,9,16,15,18,17,19,10,11,7,12,23,4,24,13,14],question:[6,13],transform:[4,7],"long":16,custom:23,avail:[15,16,23,4,24,13,14],stuck:13,reli:[23,14],handler:[6,9,16,15,10,23,14],interfac:[9,16,0,1,11,7,23,14],includ:[16,17,19,10,11,20,7,12,23,14],lot:[15,13],suit:13,forward:9,submiss:6,strictli:14,repetit:14,individu:13,"function":[6,9,16,0,15,18,24,7,23,4,14,5],head:[23,9,12],creation:7,gzip:13,form:[9,4,7,18,19],offer:23,linu:13,basic:[4,7],idea:18,state:[7,16],link:[6,13,23],translat:18,newer:[23,16],line:[6,19,10,20,12,13,14],inlin:[11,7,18,17],"true":[23,16],bug:[13,14],reset:15,pull:13,made:[23,20,16,10],utf:17,input:[15,7],consist:[6,24,19,14],possibl:[6,12,15],"default":[15,9,16,1,12,23,4,18,14],asynchron:[6,14,16,0,23],not_support:16,below:[9,16,17,19,12,23,13],unspecifi:[11,17],those:[17,8],otherwis:[15,11,13,19],problem:15,similar:[9,16,1,18,20,7,23,4,13],impl:10,connect:[6,9,16,15,1,20,12,23],version_:17,featur:[18,13,24],artifact:13,creat:[15,16,17,10,11,20,12,23,13],"int":[6,16,15,17,10,20,12,23],retriev:[4,19,11,17],"abstract":[15,12,10],parser:[9,19,14],ostringstream:20,deep:7,"_openssl_verify_path":23,"char":[6,16,10,20,23,12],bzip:13,implement:[6,9,16,0,15,1,17,19,18,11,7,23,4,14,13,5],"8bit":23,file:[6,16,13,19,23],request:[6,9,16,0,10,11,20,12,23,13,14],exist:[23,13,24],face:[23,16],std:[6,9,16,17,18,19,10,11,20,12,23],fill:23,echo:9,denot:[18,16],readi:[23,14],macro:[23,14],cmake:[6,13],googl:[6,13,14],nonetheless:4,"7zip":13,titl:1,hpp:[16,18,10,20,12,23],when:[15,4,24,16,14],detail:[9,16,17,1,10,11,12,23,4],virtual:15,event:16,finish:[23,16],other:[6,16,18,7,23,2,4,24],lookup:4,futur:[6,9,16,17,1,19,23],branch:13,peopl:6,test:[13,14],you:[6,9,16,15,18,10,20,12,23,13],runtim:15,miss:24,intend:[6,16,13,23],determin:[18,9,16],lend:7,subdivid:19,print_bodi:23,introduc:[23,14],source_typ:4,gcc:13,definit:[18,4,19,11,16],"public":[9,16,0],intent:24,embed:[21,16,10],throughout:14,pool:[16,14],svn:13,moved_perman:16,studio:13,standard:[7,24],vice:4,directori:[23,13],info:[6,19],descript:[9,16,17,1,19,11,23,4],flag:14,notion:[4,7],not_impl:16,basic_request:[11,9],basic_respons:[9,17],ignor:18,invok:[16,13,10],potenti:16,time:[7,16,14],cpp:[0,2,3,4,5,6,7,8,9,10,11,23,13,14,15,16,17,18,19,20,21,12,24],profil:16,inc:14,hello:[6,16,10,20,21,3],legend:[4,17,11,19,16]},objtypes:{},titles:["Reference Manual","<no title>","References","Examples","The message template","An in-depth look at the cpp-netlib","C++ Network Library","Directives","Techniques","HTTP implementation","“Hello world” HTTP server","HTTP Request","HTTP client","Getting Started","What’s New","Static and dynamic polymorphism","HTTP Server API","HTTP Response","Tag metafunctions","The URI template","“Hello world” HTTP client","HTTP examples","Full installation guide","HTTP Client API","Project history"],objnames:{},filenames:["reference","http_client_tags","references","examples","message","in_depth","index","directives","techniques","http","hello_world_server","reference_http_request","http_client","getting_started","whats_new","polymorphism","reference_http_server","reference_http_response","tag_metafunctions","uri","hello_world_client","examples_http","install","reference_http_client","history"]}) \ No newline at end of file diff --git a/libs/network/doc/html/uri.html b/libs/network/doc/html/uri.html index e7556f641..e127337e5 100644 --- a/libs/network/doc/html/uri.html +++ b/libs/network/doc/html/uri.html @@ -84,7 +84,7 @@

    Generic URI Syntax Overview":" to be a part of the path:

    -_images/mailto_uri2.png +_images/mailto_uri.png

    A hierarchical URI is identified by a double slash ("//") after the scheme and a scheme-specific component, which RFC 3986 defines to be:

    @@ -99,10 +99,10 @@

    Generic URI Syntax Overview +_images/ftp_uri.png

    Note that the authority is further subdivided into different elements. Another example, using HTTP is given below:

    -_images/http_uri2.png +_images/http_uri.png

    The difference here between the path in a hierarchical URI and that in the example above for the non-hierarchical URI.

    diff --git a/libs/network/doc/html/whats_new.html b/libs/network/doc/html/whats_new.html index fe8325687..1ea138e85 100644 --- a/libs/network/doc/html/whats_new.html +++ b/libs/network/doc/html/whats_new.html @@ -63,6 +63,19 @@

    cpp-netlib v0.9 documentation

    What’s New

    cpp-netlib 0.9

    +
    +

    v0.9.1

    +
      +
    • Introduced macro BOOST_NETWORK_DEFAULT_TAG to allow for programmatically +defining the default flag to use throughout the compilation unit.
    • +
    • Support for streaming body handlers when performing HTTP client operations. +See documentation for HTTP client interface for more information.
    • +
    • Numerous bug fixes from v0.9.0.
    • +
    • Google, Inc. contributions.
    • +
    +
    +
    +

    v0.9.0

    • IMPORTANT BREAKING CHANGE: By default all compile-time heavy parser implementations are now compiled to external static libraries. In order to use @@ -70,6 +83,11 @@

      cpp-netlibBOOST_NETWORK_NO_LIB before including any cpp-netlib header. This breaks code that relied on the version 0.8.x line where the library is strictly header-only.

    • +
    • Fix issue #41: Introduce a macro BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG +which makes the default HTTP client use tags::http_async_8bit_udp_resolve +as the tag.
    • +
    • Fix issue #40: Write the status line and headers in a single buffer write +instead of two writes.
    • More consistent message API for client and server messages (request and response objects).
    • Refactoring of internal implementations to allow better separation of concerns @@ -80,6 +98,7 @@

      cpp-netlibDocumentation updates to reflect new APIs.

    +

    cpp-netlib 0.8

      @@ -135,7 +154,11 @@

      cpp-netlibTable Of Contents

      • What’s New
          -
        • cpp-netlib 0.9
        • +
        • cpp-netlib 0.9 +
        • cpp-netlib 0.8
        • cpp-netlib 0.7
        • cpp-netlib 0.6
        • diff --git a/libs/network/doc/index.rst b/libs/network/doc/index.rst index b4df6b217..ef56ddb3c 100644 --- a/libs/network/doc/index.rst +++ b/libs/network/doc/index.rst @@ -105,7 +105,7 @@ Support You can ask questions, join the discussion, and report issues to the developers mailing list by joining via: - https://lists.sourceforge.net/lists/listinfo/cpp-netlib-devel + https://groups.google.com/group/cpp-netlib You may also file issues on the Github_ issue tracker at: diff --git a/libs/network/doc/reference_http_client.rst b/libs/network/doc/reference_http_client.rst index 0c7758a3c..9b63c5e6d 100644 --- a/libs/network/doc/reference_http_client.rst +++ b/libs/network/doc/reference_http_client.rst @@ -8,7 +8,7 @@ General :mod:`cpp-netlib` includes and implements a number of HTTP clients that you can use and embed in your own applications. All of the HTTP client implementations: - * **Cannot be copied.** This means you may have to store instances of the + * **Cannot be copied.** This means you may have to store instances of the clients in dynamic memory if you intend to use them as function parameters or pass them around in smart pointers or by reference. * **Assume that requests made are independent of each other.** There currently @@ -18,11 +18,14 @@ use and embed in your own applications. All of the HTTP client implementations: case you want to upgrade the implementation you are using in your application will be distributed as header-only implementations, which means you have to re-compile your application to use a newer version of the implementations. - + The HTTP clients all share the same API, but the internals are documented in terms of what is different and what to expect with the different implementations. +As of 0.9.1 the default implementation for the :mod:`cpp-netlib` HTTP client is +asynchronous. + Implementations --------------- @@ -60,14 +63,14 @@ Synchronous Clients ~~~~~~~~~~~~~~~~~~~ Of the client tags shown in the table, the following makes the ``basic_client`` -behave as a fully synchronous client. +behave as a fully synchronous client. * **http_default_8bit_tcp_resolve** * **http_default_8bit_udp_resolve** * **http_keepalive_8bit_tcp_resolve** * **http_keepalive_8bit_udp_resolve** -The synchronous client implements all the operations of the client underneath +The synchronous client implements all the operations of the client underneath the interface all block to wait for I/O to finish. All the member methods are synchronous and will block until the response object is ready or throws if erros are encountered in the performance of the HTTP requests. @@ -84,10 +87,10 @@ manner: * **http_async_8bit_tcp_resolve** * **http_async_8bit_udp_resolve** -An asynchronous client implementation means that``basic_client<...>`` is an -`Active Object`_. This means that the client has and manages its own lifetime -thread, and returns values that are asynchronously filled in. The response -object encapsulates Boost.Thread_ futures which get filled in once the values +An asynchronous client implementation means that``basic_client<...>`` is an +`Active Object`_. This means that the client has and manages its own lifetime +thread, and returns values that are asynchronously filled in. The response +object encapsulates Boost.Thread_ futures which get filled in once the values are available. .. _Boost.Thread: http://www.boost.org/libs/thread @@ -177,7 +180,7 @@ To use the above supported named parameters, you'll have code that looks like the following: .. code-block:: c++ - + using namespace boost::network::http; // parameters are in this namespace boost::asio::io_service my_io_service; client client_(_follow_redirects=true, _cache_resolved=true, @@ -197,38 +200,87 @@ and that there is an appropriately constructed response object named .. code-block:: c++ + using namespace boost::network::http; // parameters are here client client_(); client::request request_("http://cpp-netib.github.com/"); client::response response_; ``response_ = client_.get(request_)`` Perform an HTTP GET request. +``response_ = client_.get(request_, _body_handler=callback)`` + Perform an HTTP GET request, and have the body chunks be handled by the + ``callback`` parameter. The signature of ``callback`` should be the following: + ``void(iterator_range const &, boost::system::error_code const + &)``. ``response_ = client_.head(request_)`` Perform an HTTP HEAD request. ``response_ = client_.post(request_)`` Perform an HTTP POST, use the data already set in the request object which includes the headers, and the body. +``response_ = client_.post(request_, _body_handler=callback)`` + Perform an HTTP POST request, and have the body chunks be handled by the + ``callback`` parameter. The signature of ``callback`` should be the following: + ``void(iterator_range const &, boost::system::error_code const + &)``. ``response_ = client_.post(request_, body)`` Body is a string of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. The default content-type used is ``x-application/octet-stream``. +``response_ = client_.post(request_, body, _body_handler=callback)`` + Body is a string of type ``boost::network::string::type`` where ``Tag`` + is the HTTP Client's ``Tag``. The default content-type used is + ``x-application/octet-stream``. Have the response body chunks be handled by + the ``callback`` parameter. The signature of ``callback`` should be the + following: ``void(iterator_range const &, + boost::system::error_code const &)``. ``response_ = client_.post(request_, content_type, body)`` The body and content_type parameters are of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. This uses the request object's other headers. +``response_ = client_.post(request_, content_type, body, _body_handler=callback)`` + The body and content_type parameters are of type + ``boost::network::string::type`` where ``Tag`` is the HTTP Client's + ``Tag``. This uses the request object's other headers. Have the response + body chunks be handled by the ``callback`` parameter. The signature of + ``callback`` should be the following: ``void(iterator_range const + &, boost::system::error_code const &)``. ``response_ = client_.put(request_)`` Perform an HTTP PUT, use the data already set in the request object which includes the headers, and the body. +``response_ = client_.put(request_, _body_handler=callback)`` + Perform an HTTP PUT request, and have the body chunks be handled by the + ``callback`` parameter. The signature of ``callback`` should be the following: + ``void(iterator_range const &, boost::system::error_code const + &)``. ``response_ = client_.put(request_, body)`` Body is a string of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. The default content-type used is ``x-application/octet-stream``. +``response_ = client_.put(request_, body, _body_handler=callback)`` + Body is a string of type ``boost::network::string::type`` where ``Tag`` + is the HTTP Client's ``Tag``. The default content-type used is + ``x-application/octet-stream``. Have the response body chunks be handled by + the ``callback`` parameter. The signature of ``callback`` should be the + following: ``void(iterator_range const &, + boost::system::error_code const &)``. ``response_ = client_.put(request_, content_type, body)`` The body and content_type parameters are of type ``boost::network::string::type`` where ``Tag`` is the HTTP Client's ``Tag``. This uses the request object's other headers. +``response_ = client_.put(request_, content_type, body, _body_handler=callback)`` + The body and content_type parameters are of type + ``boost::network::string::type`` where ``Tag`` is the HTTP Client's + ``Tag``. This uses the request object's other headers. Have the response + body chunks be handled by the ``callback`` parameter. The signature of + ``callback`` should be the following: ``void(iterator_range const + &, boost::system::error_code const &)``. ``response_ = client_.delete_(request_)`` Perform an HTTP DELETE request. +``response_ = client_.delete_(request_, _body_handler=callback)`` + Perform an HTTP DELETE request, and have the response body chunks be handled + by the ``callback`` parameter. The signature of ``callback`` should be the + following: ``void(iterator_range const &, + boost::system::error_code const &)``. Client-Specific ~~~~~~~~~~~~~~~ @@ -237,3 +289,55 @@ Client-Specific Clear the cache of resolved endpoints. +Streaming Body Handler +~~~~~~~~~~~~~~~~~~~~~~ + +As of v0.9.1 the library now offers a way to support a streaming body callback +function in all HTTP requests that expect a body part (GET, PUT, POST, DELETE). +A convenience macro is also provided to make callback handlers easier to write. +This macro is called `BOOST_NETWORK_HTTP_BODY_CALLBACK` which allows users to +write the following code to easily create functions or function objects that +are compatible with the callback function requirements. + +An example of how to use the macro is shown below: + +.. code-block:: c++ + + struct body_handler { + explicit body_handler(std::string & body) + : body(body) {} + + BOOST_NETWORK_HTTP_BODY_CALLBACK(operator(), range, error) { + // in here, range is the Boost.Range iterator_range, and error is + // the Boost.System error code. + if (!error) + body.append(boost::begin(range), boost::end(range)); + } + + std::string & body; + }; + + // somewhere else + std::string some_string; + response_ = client_.get(request("http://cpp-netlib.github.com/"), + _body_handler=body_handler(some_string)); + +You can also use if for standalone functions instead if you don't want or need +to create a function object. + +.. code-block:: c++ + + BOOST_NETWORK_HTTP_BODY_CALLBACK(print_body, range, error) { + if (!error) + std::cout << "Received " << boost::distance(range) << "bytes." + << std::endl; + else + std::cout << "Error: " << error << std::endl; + } + + // somewhere else + response_ = client_.get(request("http://cpp-netlib.github.com/"), + _body_handler=print_body); + +The `BOOST_NETWORK_HTTP_BODY_CALLBACK` macro is defined in +`boost/network/protocol/http/client/macros.hpp`. diff --git a/libs/network/doc/whats_new.rst b/libs/network/doc/whats_new.rst index 64a3e10f1..e02c73313 100644 --- a/libs/network/doc/whats_new.rst +++ b/libs/network/doc/whats_new.rst @@ -7,6 +7,17 @@ :mod:`cpp-netlib` 0.9 --------------------- +v0.9.1 +~~~~~~ +* Introduced macro ``BOOST_NETWORK_DEFAULT_TAG`` to allow for programmatically + defining the default flag to use throughout the compilation unit. +* Support for streaming body handlers when performing HTTP client operations. + See documentation for HTTP client interface for more information. +* Numerous bug fixes from v0.9.0. +* Google, Inc. contributions. + +v0.9.0 +~~~~~~ * **IMPORTANT BREAKING CHANGE**: By default all compile-time heavy parser implementations are now compiled to external static libraries. In order to use :mod:`cpp-netlib` in header-only mode, users must define the preprocessor From 233b0f1f1616a51d6a34c2a98c0080b883b67f57 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Wed, 3 Aug 2011 17:25:59 +1000 Subject: [PATCH 126/768] Minor documentation fix-up. --- libs/network/doc/html/_sources/reference_http_client.txt | 6 +++--- libs/network/doc/html/reference_http_client.html | 6 +++--- libs/network/doc/html/searchindex.js | 2 +- libs/network/doc/reference_http_client.rst | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libs/network/doc/html/_sources/reference_http_client.txt b/libs/network/doc/html/_sources/reference_http_client.txt index 9b63c5e6d..12b1389e2 100644 --- a/libs/network/doc/html/_sources/reference_http_client.txt +++ b/libs/network/doc/html/_sources/reference_http_client.txt @@ -295,7 +295,7 @@ Streaming Body Handler As of v0.9.1 the library now offers a way to support a streaming body callback function in all HTTP requests that expect a body part (GET, PUT, POST, DELETE). A convenience macro is also provided to make callback handlers easier to write. -This macro is called `BOOST_NETWORK_HTTP_BODY_CALLBACK` which allows users to +This macro is called ``BOOST_NETWORK_HTTP_BODY_CALLBACK`` which allows users to write the following code to easily create functions or function objects that are compatible with the callback function requirements. @@ -339,5 +339,5 @@ to create a function object. response_ = client_.get(request("http://cpp-netlib.github.com/"), _body_handler=print_body); -The `BOOST_NETWORK_HTTP_BODY_CALLBACK` macro is defined in -`boost/network/protocol/http/client/macros.hpp`. +The ``BOOST_NETWORK_HTTP_BODY_CALLBACK`` macro is defined in +``boost/network/protocol/http/client/macros.hpp``. diff --git a/libs/network/doc/html/reference_http_client.html b/libs/network/doc/html/reference_http_client.html index 3c5e07bb8..b086249c5 100644 --- a/libs/network/doc/html/reference_http_client.html +++ b/libs/network/doc/html/reference_http_client.html @@ -419,7 +419,7 @@

          Streaming Body HandlerAs of v0.9.1 the library now offers a way to support a streaming body callback function in all HTTP requests that expect a body part (GET, PUT, POST, DELETE). A convenience macro is also provided to make callback handlers easier to write. -This macro is called BOOST_NETWORK_HTTP_BODY_CALLBACK which allows users to +This macro is called BOOST_NETWORK_HTTP_BODY_CALLBACK which allows users to write the following code to easily create functions or function objects that are compatible with the callback function requirements.

          An example of how to use the macro is shown below:

          @@ -458,8 +458,8 @@

          Streaming Body Handler_body_handler=print_body);

    -

    The BOOST_NETWORK_HTTP_BODY_CALLBACK macro is defined in -boost/network/protocol/http/client/macros.hpp.

    +

    The BOOST_NETWORK_HTTP_BODY_CALLBACK macro is defined in +boost/network/protocol/http/client/macros.hpp.

    diff --git a/libs/network/doc/html/searchindex.js b/libs/network/doc/html/searchindex.js index d1464f3b3..bcaf43cd5 100644 --- a/libs/network/doc/html/searchindex.js +++ b/libs/network/doc/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({objects:{},terms:{directive_typ:7,all:[15,9,16,17,10,11,20,7,12,23,4,13,14],code:[6,9,16,15,18,10,20,7,21,12,23,24,13,14],skeleton:18,chain:7,illustr:18,queri:[11,19],forbidden:16,lack:24,icmp:4,basic_messag:[6,4,19,5],four:17,concept:[6,16,0,17,19,11,7,4,5],follow:[15,9,16,17,18,19,10,11,20,7,3,12,23,4,13,21],synchronushandl:16,ptr:15,abid:[11,7],hierarch:19,whose:18,decid:[15,18,24],"const":[6,9,16,17,10,11,7,23,4],boost_network_http_body_callback:23,flexibl:[12,18,7],range_iter:9,send:[12,16],concret:7,swap:[4,18,19],string_tag:18,sens:[9,1,7,23],"_follow_redirect":23,stock_repli:[6,9,16,10],sent:[23,16],liter:5,everi:[4,24],risk:13,straightforward:10,fals:[23,16],"void":[6,9,16,15,18,17,19,10,11,23,4],inhibit:23,nich:24,netlib:[0,2,3,4,5,6,7,8,9,10,11,23,13,14,15,16,17,18,19,20,21,12,24],endpoint:23,fan:13,veri:16,affect:23,default_:[15,18,9],exact:9,relev:20,rfc1738:9,http_async_serv:16,administr:10,level:[6,13,24],who:13,michael:[13,24],upload:16,iter:9,correct:[15,4,9],"try":[20,16,10],vector:[18,11,16],verif:23,cooki:23,argpack:[23,16],impli:4,tel:19,throught:12,core:4,natur:7,direct:[6,0,17,11,24,7,12,4,8,5],handler_typ:16,second:[11,9],cost:14,design:3,pass:[9,16,18,10,20,7,12,23,4],download:[6,13],further:[12,19],port_typ:11,port:[9,16,17,19,10,11,20],append:23,even:[4,7,17],"_cache_resolv":23,what:[6,16,15,18,10,11,20,23,4,14],msysgit:13,insid:[9,16],repli:10,section:[9,16,17,11,23,4],watermark:16,abl:[13,16],"_linger_timeout":16,overload:[9,16,10],access:[9,16,17,11,20,7,24],delet:[23,9,12],version:[6,16,15,18,17,19,11,12,23,13,14],source_wrapp:4,underneath:[23,14],"new":[6,15,18,19,7,13,14],boost:[6,9,16,17,1,19,10,18,11,20,12,23,24,13,14],method:[23,11,12,9,10],redirect:23,full:[6,19,13,22,17],deriv:[15,11],"_address":16,gener:[6,16,0,15,19,11,7,23,2,4,24,13,5],never:24,unauthor:16,here:[15,9,16,19,10,12,23],boost_network_http_client_default_tag:14,bodi:[6,9,16,17,18,10,11,20,12,23,4,14],let:[18,20,13,10],free:[4,16],address:[9,16,1,10,20,23],path:[11,9,13,19],along:13,rudimentari:7,modifi:[6,0,17,11,23,4,5],sinc:[12,18,20],valu:[15,9,16,17,1,10,11,23,4],wait:[23,16],convert:[4,19,11,17],convers:4,shift:7,anymor:18,larger:21,host:[11,19,9,13,10],anchor:11,cert:23,base:[15,18,19,7,4,13],cerr:[6,20,9,10],behav:23,http_keepalive_8bit_tcp_resolv:[23,1,9],action:16,http_client:[12,9],chang:[9,18,7,23,13,14],narrow:17,portabl:24,semant:[6,4,7,16,15],via:[6,20],although:[15,4,18,13,16],appli:[4,7],multiple_choic:16,put:[23,9,16],unix:[13,19],api:[6,16,0,17,19,11,23,14],famili:18,visibl:9,instal:[6,13,22],post:[23,20,9,12],unit:14,regex:13,version_minor:[23,1,9,11],from:[6,9,16,17,18,19,10,11,20,7,12,23,4,13,14],describ:[23,16,3,19,8],zip:13,commun:[6,3,24],distinct:16,doubl:19,upgrad:[23,16,14],subvers:13,websit:12,few:13,program:[15,21,24,19,10],call:[9,16,18,10,7,23,4,13],recommend:13,taken:16,clear_head:[4,11,17],type:[15,9,16,17,18,19,11,7,23,4,24],until:23,minor:[23,11],more:[6,16,4,14,13,24],reachabl:18,wrapper:[6,9,0,17,11,4,14,5],headers_rang:[11,9,17],afford:7,smtp:[4,24],swappabl:[4,18,19],relat:16,notic:[18,9],site:13,warn:[23,17,13,16],visual:13,depth:[6,5],accept:[7,16],known:[13,19],actual:16,hold:[23,1,9],unpack:13,cach:23,content_typ:23,must:[13,14],placehold:18,none:16,dcmake_c_compil:13,join:[6,13,16],internal_server_error:16,scalabl:16,alia:[13,17],work:[11,13,17],uniqu:15,histori:[6,24],annoi:24,remain:[15,7],tag:[6,9,16,15,1,17,19,11,23,4,14,18,8],can:[6,9,16,15,18,19,10,20,7,21,12,23,4,13],caveat:13,root:[11,18],fetch:23,aliv:[23,1,9,16],proof:16,control:[18,13,16],heart:9,encapsul:[9,1,7,4,23],tar:13,give:16,process:[9,19],lock:16,no_cont:16,share:[23,1,9,16,10],sln:13,templat:[6,9,16,15,18,17,19,11,7,23,2,4,24,13,5],high:24,sourc:[6,9,17,10,11,2,4,13,24],want:[15,16,18,20,23,4,13],explos:15,tarbal:13,http_async_8bit_udp_resolv:[23,1,9,14],serial:16,unavoid:15,unsign:[23,11,9,17],occur:[11,17],some_xml_str:20,string:[6,9,16,17,18,19,10,11,20,12,23,4],low:16,alwai:16,differenti:[16,10],multipl:16,goal:24,programmat:14,anoth:[16,19],classifi:19,write:[6,16,20,23,24,14],how:[18,19,10,20,21,23,13],scale:16,conn:16,pure:[15,4],subdirectori:12,opt:13,instead:[23,18,16,13,14],greatli:15,simpl:[6,9,16,19,10,20,7,12,4],mpl:[18,14],stock:10,resourc:[13,10],dive:[12,20,21,10],earlier:[15,20],sneak:6,constraint:24,status_messag:17,befor:[23,20,16,14],xzf:13,attent:7,mai:[6,9,16,10,23,4],end:[23,9,24],data:[9,16,19,20,23,4],parallel:13,util:16,github:[6,19,24,13,23],attempt:[16,14],practic:3,third:10,date_tim:13,light:[6,24],valid:[4,9],minim:14,explicit:[23,4],element:19,issu:[6,13,14],inform:[6,16,13,14],"switch":[15,11],maintain:[7,13,16],environ:[13,10],allow:[6,16,15,18,7,12,23,4,14],mechan:[18,9],order:[12,7,14],talk:[11,17],origin:[18,9],composit:18,help:16,xmpp:[4,24],offici:[6,13],move:7,becaus:[15,4,7,16],intermediari:4,paper:[6,2],through:[11,9,13,16],left:[18,7],size_t:16,still:[23,18,17,13,16],vari:[15,4,18],dynam:[6,15,16,23,8],paramet:[9,16,17,18,11,7,23,4,13,14],divis:4,typedef:[6,9,16,18,10,23,4],group:[6,13,24],fit:16,fix:14,unsupported_tag:18,better:[16,13,14],platform:[6,24,13,16],window:[6,13],pend:16,bin:19,mail:[6,13],hidden:[23,7],main:[6,20,12,13,10],might:[18,9],easier:[23,4],non:[4,16,19],multimap:9,"return":[15,9,16,17,1,10,11,20,7,12,23,4,14],greater:[12,10],thei:[9,1,19,23,4,18],handl:[23,15,16,10],smarter:18,safe:[23,10],initi:[23,24,16,14],"break":[23,15,9,14],framework:10,facilit:15,now:[23,14,17,13,10],discuss:[6,13],nor:4,choic:13,term:[23,4,16],eventu:[6,24],somewher:23,name:[9,16,17,11,23,4,13,14],realist:3,edit:16,separ:14,easili:[23,24],slide:[6,2],exampl:[6,9,16,18,19,10,20,7,3,12,23,4,13,21],submit:[6,13,24],http_server:[6,11,16,17],timeout:16,each:[23,4,12,13,16],debug:13,fulli:[23,24],complet:[12,13],side:[15,10],mean:[23,4,13,16],compil:[23,16,7,13,14],dcmake_cxx_compil:13,weight:[6,24],list:[6,16,17,18,10,13],chunk:[23,16],continu:[16,24],functor:[9,10],realli:20,heavi:[13,14],wrap:[15,4,17],set_statu:16,"static":[6,15,18,7,23,8,14],expect:23,our:[18,13,24],happen:23,"_port":16,unique_ptr:15,orient:[15,7],special:[6,9,15,18,17,11,7,4],out:[23,13,16],variabl:13,ftp:[19,24],shown:[23,16],safeti:18,network:[6,9,16,17,18,19,10,11,20,3,12,23,4,24],webservic:20,goe:13,tcp_resolv:23,req:16,rational:7,content:[6,4,16,23],typenam:[18,4,11,17],adapt:4,rel:19,internet:13,print:[12,9],current:[23,16,19],factori:[15,4,7],model:[16,17,11,7,23,4,13],after:[12,16,19],iostream:[12,20,7,10],linear:16,barrier:24,advanc:8,my_io_servic:[23,16],manipul:[4,16],situat:[15,7,16],given:[6,9,16,15,18,17,19,11,4],argv:[6,20,12,10],hello_world_cli:20,significantli:16,standalon:[23,15],reason:13,git:[6,13],releas:[6,16,17,13,23],org:[6,9,19,12],"byte":[23,16],argc:[12,20,10],bash:19,netib:23,wai:[23,18,9,16,19],thread:[9,16,1,10,23,14],prescrib:13,synchron:[6,9,16,0,1,10,23],keep:[15,9,1,7,23,18],thing:[15,18,12,13,17],enforc:11,place:16,"_send_buffer_s":16,lifetim:23,assign:[4,16,19],first:[15,9,19,10,11,12,4,13],oper:[6,9,16,17,10,11,7,23,4,14],softwar:24,major:[23,11,24],"_openssl_certif":23,directli:[23,16],certif:23,onc:[23,18,12,13,16],independ:[23,7,16],qualiti:24,number:[9,16,1,10,18,11,23,4,13],yourself:13,uri_:9,instruct:13,alreadi:[16,17,11,23,14,24],done:[15,9,16,18,11,4,13],bad_gatewai:16,lboost_system:[12,20,10],stabl:13,"_reuse_address":16,open:24,connection_ptr:16,size:16,differ:[6,9,16,0,15,18,17,19,11,7,23,4,14,5],width:23,associ:[18,4,17,11,16],top:[13,24],system:[23,7,13,16],messag:[6,17,11,24,7,12,23,4,14,5],destination_:[11,17],mikhailberi:[6,13],bad_request:16,scheme:[11,9,19],zipfil:13,"final":12,boil:7,listen:[16,10],adher:16,udp:[23,1,9],shell:[20,13,10],consol:12,option:[16,24,13,14],distanc:23,especi:16,namespac:[6,9,16,17,18,10,11,20,12,23],tool:[9,13],copi:[23,4,16,19],specifi:[9,16,1,19,12,23,4,13],aptli:9,xjf:13,pars:[19,9,16,14],mostli:13,review:6,than:[18,16],http_version_major:23,serv:18,wide:17,kind:[6,3,15],conveni:23,target:[7,24],provid:[6,9,17,1,19,10,11,23,18,24],remov:[4,11,17],http_client1:12,basic_cli:[23,9],structur:[12,18],charact:23,project:[6,13,24],matter:16,reus:7,not_accept:16,store:[23,4,16],str:20,opaqu:[18,19],iterator_rang:[23,16],seri:[3,16],pre:[10,5],fork:13,fashion:7,payload:[4,20],behavior:[23,18,9,15],boostcon:[6,2],facad:14,add_head:[4,11,17],sometim:[4,18],ani:[15,9,16,10,12,23,4,13,14],packag:13,properli:[23,16],manner:[23,11,18,16,17],have:[15,9,16,1,10,18,20,7,12,23,4,13,24],tabl:[23,4,9,16,17],need:[15,16,18,10,3,12,23,13,24],seen:10,dedic:23,incompat:13,infosystem:19,repeatedli:24,boost_network_default_tag:14,caus:[23,1,9,18],shared_futur:17,status_t:16,techniqu:[6,18,15,7,8],lib:[12,20,10],callback:[23,16],directiven:7,self:7,expos:16,note:[16,17,19,10,20,23,4,13],also:[6,9,16,15,1,17,10,18,11,7,23,4,13,24],without:[12,7],decis:15,take:[9,16,19,10,7,23,4,14],indic:[23,1,9],combin:[15,18],concern:14,soap:24,singl:[9,16,10,23,12,14],asio:[23,24,16,14],begin:[23,9],sure:10,distribut:[23,12,24,13,16],plenti:24,normal:[23,11],buffer:[18,16,14],conncetionptr:16,compress:12,deleg:9,most:[4,16],wire:7,abus:7,pair:[11,17],"class":[15,9,16,17,18,19,10,11,7,23,4,5],three:[23,4,9,16,5],tradit:13,todo:7,found:[6,16,10,12,13,24],don:[9,1,18,12,23,13],url:[12,20,13],clear:[23,4],later:16,cover:[4,14],uri:[6,9,15,19,11,2,12,5,14],doe:[16,17,19,10,23,4,13],declar:[11,9,17],directive2:7,directive1:7,pattern:[23,4,7,16,15],readcallback:16,usual:[11,7,17],microsoft:13,came:9,show:[21,20,16,19],awar:24,inherit_linearli:18,syntax:[6,9,19,2,12,5],concurr:16,migrat:24,radic:14,identifi:[4,19],trivial:[9,7],find:[6,13],foo_direct:4,cout:[23,20,9,19,12],xml:20,absolut:19,onli:[15,9,16,1,19,18,7,23,13,14],bind:16,locat:23,explain:12,response_head:[9,16],solut:13,enough:[7,13],should:[15,9,16,18,10,23,4,13],prolong:7,configur:[6,14,13,10],hello_world:10,meant:[18,4,17,11,16],set_head:16,contribut:14,variou:23,get:[6,9,17,18,10,20,12,23,13,24],between:[13,19],stop:16,fluid:15,soon:16,ssl:[23,15],is_base_of:18,mainten:13,"import":[16,14],report:[6,13,16],metafunct:[6,4,18,8],requir:[15,16,17,19,11,23,4,13,24],embedd:[9,14],receiv:[23,16],enabl:[18,24,13,16],had:24,emb:[23,16],ietf:9,applac:16,ipp:10,excel:24,patch:13,rfc:[9,2,19,12],whether:[15,16,19,11,23,4,14],common:[12,4,3,24],though:[15,13,12],contain:[16,17,18,10,7,21,4],status_typ:16,where:[15,9,16,18,11,20,7,23,4,24,14],async_serv:16,conform:9,set:[15,16,17,10,11,7,3,23,4,5],primari:[18,16],requesthandl:9,truli:7,invari:18,"_thread_pool":16,accord:[4,19],packet:4,derived1:15,see:[9,16,1,10,23,18,14],result:[17,18,19,11,7,4],arg:[6,16,23],close:[6,12,9,13,16],best:2,chose:4,polymorph:[6,15,8],statu:[14,9,16,17,10],said:19,status_message_:17,correctli:17,"_report_abort":16,pointer:[23,16],someth:[9,4,7,16,18],"_body_handl":23,user_info:19,written:[11,17],bridg:15,john:19,simplest:12,progress:6,awai:16,approach:[15,18],across:[23,10],signatur:[23,16],assumpt:9,handler_:6,predefin:9,syntact:[4,7],extend:[18,7,24],"_handler":16,numer:14,ask:[6,13],were:16,hello_world_serv:[20,10],extens:[9,18,7],job:13,preprocessor:[23,14],request_:[6,23],overhaul:14,headers_contain:[4,17],endl:[9,19,10,20,23,12],addit:[15,7,13,19],both:[9,16,17,1,11,21,23],metaprogram:[6,18,2,13],berri:[13,24],cycl:23,response_:[6,23],pertain:4,alon:15,default_wstr:18,against:16,constructor:[9,16,19,10,12,23,14],etc:24,instanc:[9,16,17,18,19,11,23,4],context:[18,7],logic:[9,4,7,16,12],bool:[23,16],mani:[23,24,13,14],com:[6,19,13,20,23],clone:13,among:18,simpli:[9,11,7],publicli:[11,16,17],stream:[23,12,16,14],point:[6,4,18],instanti:16,schedul:16,logic_error:16,dispatch:[15,4,9,18,14],header:[6,9,16,15,18,17,10,11,7,12,23,4,13,14],rpc:20,littl:[15,18],suppli:[9,16,19],comput:[13,16],pod:[4,11],not_found:16,assum:[16,17,11,20,23,4,13],summar:4,trait:[18,17],mailto:19,becom:24,io_servic:[23,16,14],version_major:[23,1,9,11],"_receive_buffer_s":16,handler_inst:16,compos:5,been:[23,16,24],accessor:[4,11,17],compon:[23,4,21,18,19],destructor:15,much:15,treat:11,modif:4,acceptor:16,strategi:[23,15],modern:6,bit:[11,17],immedi:[7,16],basic_uri:[6,9,19,5],clariti:12,target_typ:7,argument:[9,16,10,12,23,4],assert:[9,19],unzip:13,craft:20,understand:16,togeth:[13,24],demand:24,"catch":[20,10],rang:[23,16],repres:16,synchronoushandl:16,present:[6,12],"case":[15,9,16,17,18,10,11,23,4,13],multi:10,therefor:[9,24],look:[6,9,16,15,18,10,20,7,23,4,13,5],gnu:13,plain:15,servic:24,properti:[9,4,7,18],sourceforg:24,aim:8,defin:[15,9,16,18,19,10,7,23,4,13,14],"while":[9,4,24,7,15],smart:[23,16],abov:[9,16,1,19,10,18,23,13],error:[6,12,16,23],thrash:13,aid:3,invoc:16,howev:[18,9],loop:16,pack:[23,16],real:18,layer:[6,24,7,15],would:[9,16,18,10,4,13],remove_head:[4,11,17],almost:16,some_str:23,them:[23,16,17],destin:[4,11,17],"_non_blocking_io":16,itself:[18,7],motiv:[6,24],new_statu:16,boost_network_enable_http:14,pthread:[12,20,10],sever:[16,8],headers_container_typ:[11,17],develop:[6,10,3,12,13,24],welcom:6,author:[23,19],perform:[16,11,20,23,4,24,14],suggest:11,make:[6,9,15,1,10,18,20,12,23,13,14],cross:[6,24],same:[15,9,18,10,7,23,13,24],check:[6,12,13,14],member:[6,9,16,0,15,10,23],fragment:19,complex:[12,13,19],session:23,http_keepalive_8bit_udp_resolv:[23,1,9],come:[15,11,7,13,17],document:[16,0,17,11,20,23,13,14],start:[6,18,16,13,23],higher:[6,13],overal:18,http:[6,9,16,0,15,1,17,24,19,10,21,11,20,2,3,12,23,4,14,13,5],hostnam:16,imagin:20,nest:[9,16,17,18,11,7,4],chainabl:7,upon:16,effect:[23,11,17],user:[9,16,1,19,7,23,13,14],extern:[23,15,14],build:[6,9,10,20,21,12,13,24],respons:[6,9,16,0,17,1,10,20,12,23,14],typic:[4,9,13],bz2:13,http_default_8bit_udp_resolv:[23,1,9,11,17],lower:[24,14],appropri:[23,11,17,13,16],kept:[16,24],equival:18,choos:[23,4,11,13],whole:[12,18,13,17],builder:19,string_typ:[6,11,18,16,17],well:[4,7,16],inherit:18,person:13,client:[6,9,16,0,1,24,10,21,11,20,3,12,23,14,5],reflect:14,thi:[15,9,16,0,17,1,24,19,10,18,11,20,7,12,23,4,14,13,8],service_unavail:16,error_cod:[23,16],everyth:19,latest:[6,13],load:23,construct:[16,17,19,11,23,4],protocol:[6,19,10,11,20,7,3,12,23,4,24,5],entri:24,just:[9,17,18,10,11,20,4,13],object:[6,9,16,15,1,17,10,11,7,12,23,4,24,14],boost_network_no_lib:[23,14],tcp:[23,1,9,15],activ:[23,1,9,24],clear_resolved_cach:23,fact:12,refactor:14,increasingli:24,derived0:15,body_handl:23,yet:[18,16],languag:24,previous:[16,10],web:[13,24],struct:[6,9,16,15,18,10,7,23,4],easi:[6,20,24],snmp:4,makefil:13,except:[15,9,1,10,20,23],dcmake_build_typ:13,add:[12,4,17,11,13],is_valid:19,http_default_8bit_tcp_resolv:[23,1,9],versa:4,overview:[6,19,5],compat:23,ado:12,adl:[4,18],subsequ:[15,17],source_:[11,17],boost_root:[12,20,13,10],headers_:[9,17],dsel:7,applic:[6,16,17,20,3,12,23,24,13,21],torvald:13,mere:4,which:[6,9,16,15,18,19,10,20,7,12,23,4,13,14],format:7,read:[13,16],wstring:[11,18,17],boost_network_http_server_connection_header_buffer_max_s:16,built:[23,12,13,15],asynchronoushandl:16,world:[6,16,10,20,21,3],part:[9,17,19,11,23,4,14],linux:[6,13],if_:18,resid:[12,9],like:[15,9,16,18,10,20,7,23,4,13],specif:[19,10,2,23,4,13],filenam:23,uint16_t:17,signal:12,echo_serv:9,cannot:[23,16],html:9,integ:11,noth:15,collect:24,"boolean":[23,16],necessari:10,either:[4,17,24,11,16],docutil:5,http_async_8bit_tcp_resolv:[23,1,9],http_version_minor:23,mode:14,not_modifi:16,manag:[23,16,14],depend:[9,16,17,11,23,4,13],fulfil:24,encount:[23,16],www:[6,9,19,12],right:[18,16],dean:[13,24],"_linger":16,deal:[15,16,10],simplifi:7,sstream:20,status_:17,interact:13,some:[6,16,15,18,17,19,8,13,14],pipelin:16,resolv:[23,1,9],certain:[9,4,7,16,18],intern:[9,16,18,11,23,14],enumer:10,sampl:[13,16],home:[13,24],indirect:[15,7],server:[6,9,16,0,1,24,19,10,21,11,20,3,12,23,14,5],librari:[6,15,18,17,11,7,3,23,4,24,13,14],tmp:23,basic_serv:9,connectionptr:16,guid:[6,2,13,22],lead:7,abort:16,"_io_servic":[23,16],broad:7,lvalu:[4,16],octet:23,achiev:8,"_receive_low_watermark":16,body_:[11,17],tracker:6,larg:[18,16],slash:19,sequenc:23,moved_temporarili:16,foo:[15,4,18],localhost:20,refer:[6,9,16,0,19,10,7,23,2,4,13,14],msvc:14,peek:6,command:[19,13,20,10],run:[6,16,10,20,21,12,13,14],power:[13,19],"enum":16,usag:[12,20,16,10],fast:6,els:23,http_statu:16,broken:19,step:[12,13],repositori:[6,13],output:19,gatekeep:13,"throw":[23,16],stage:[12,20,10],chapter:8,manual:[6,0],about:[6,16,17,10,11,2,13],central:4,socket:16,linger:16,memori:[23,24,13,16],slightli:18,page:[6,13],delete_:23,stand:19,act:13,commit:24,comp:19,input_rang:16,disabl:16,block:[23,1,9,16],underli:[9,4,7,18],thread_pool:16,own:[23,16,24],erro:23,cosntructor:14,default_str:18,around:[23,16],within:[13,0,16],encod:17,bound:16,two:[9,16,10,11,23,14],down:[9,7,19,15],creativ:15,empti:4,ensur:[4,18,10],default_tag:18,updat:14,next:[12,16],your:[23,9,13,16],merg:13,client_:[6,23],server_:[6,10],span:5,log:6,suffici:13,area:4,transfer:16,support:[6,9,16,15,18,17,19,10,11,7,12,23,4,24,13,14],question:[6,13],transform:[4,7],"long":16,custom:23,avail:[15,16,23,4,24,13,14],stuck:13,reli:[23,14],handler:[6,9,16,15,10,23,14],interfac:[9,16,0,1,11,7,23,14],includ:[16,17,19,10,11,20,7,12,23,14],lot:[15,13],suit:13,forward:9,submiss:6,strictli:14,repetit:14,individu:13,"function":[6,9,16,0,15,18,24,7,23,4,14,5],head:[23,9,12],creation:7,gzip:13,form:[9,4,7,18,19],offer:23,linu:13,basic:[4,7],idea:18,state:[7,16],link:[6,13,23],translat:18,newer:[23,16],line:[6,19,10,20,12,13,14],inlin:[11,7,18,17],"true":[23,16],bug:[13,14],reset:15,pull:13,made:[23,20,16,10],utf:17,input:[15,7],consist:[6,24,19,14],possibl:[6,12,15],"default":[15,9,16,1,12,23,4,18,14],asynchron:[6,14,16,0,23],not_support:16,below:[9,16,17,19,12,23,13],unspecifi:[11,17],those:[17,8],otherwis:[15,11,13,19],problem:15,similar:[9,16,1,18,20,7,23,4,13],impl:10,connect:[6,9,16,15,1,20,12,23],version_:17,featur:[18,13,24],artifact:13,creat:[15,16,17,10,11,20,12,23,13],"int":[6,16,15,17,10,20,12,23],retriev:[4,19,11,17],"abstract":[15,12,10],parser:[9,19,14],ostringstream:20,deep:7,"_openssl_verify_path":23,"char":[6,16,10,20,23,12],bzip:13,implement:[6,9,16,0,15,1,17,19,18,11,7,23,4,14,13,5],"8bit":23,file:[6,16,13,19,23],request:[6,9,16,0,10,11,20,12,23,13,14],exist:[23,13,24],face:[23,16],std:[6,9,16,17,18,19,10,11,20,12,23],fill:23,echo:9,denot:[18,16],readi:[23,14],macro:[23,14],cmake:[6,13],googl:[6,13,14],nonetheless:4,"7zip":13,titl:1,hpp:[16,18,10,20,12,23],when:[15,4,24,16,14],detail:[9,16,17,1,10,11,12,23,4],virtual:15,event:16,finish:[23,16],other:[6,16,18,7,23,2,4,24],lookup:4,futur:[6,9,16,17,1,19,23],branch:13,peopl:6,test:[13,14],you:[6,9,16,15,18,10,20,12,23,13],runtim:15,miss:24,intend:[6,16,13,23],determin:[18,9,16],lend:7,subdivid:19,print_bodi:23,introduc:[23,14],source_typ:4,gcc:13,definit:[18,4,19,11,16],"public":[9,16,0],intent:24,embed:[21,16,10],throughout:14,pool:[16,14],svn:13,moved_perman:16,studio:13,standard:[7,24],vice:4,directori:[23,13],info:[6,19],descript:[9,16,17,1,19,11,23,4],flag:14,notion:[4,7],not_impl:16,basic_request:[11,9],basic_respons:[9,17],ignor:18,invok:[16,13,10],potenti:16,time:[7,16,14],cpp:[0,2,3,4,5,6,7,8,9,10,11,23,13,14,15,16,17,18,19,20,21,12,24],profil:16,inc:14,hello:[6,16,10,20,21,3],legend:[4,17,11,19,16]},objtypes:{},titles:["Reference Manual","<no title>","References","Examples","The message template","An in-depth look at the cpp-netlib","C++ Network Library","Directives","Techniques","HTTP implementation","“Hello world” HTTP server","HTTP Request","HTTP client","Getting Started","What’s New","Static and dynamic polymorphism","HTTP Server API","HTTP Response","Tag metafunctions","The URI template","“Hello world” HTTP client","HTTP examples","Full installation guide","HTTP Client API","Project history"],objnames:{},filenames:["reference","http_client_tags","references","examples","message","in_depth","index","directives","techniques","http","hello_world_server","reference_http_request","http_client","getting_started","whats_new","polymorphism","reference_http_server","reference_http_response","tag_metafunctions","uri","hello_world_client","examples_http","install","reference_http_client","history"]}) \ No newline at end of file +Search.setIndex({objects:{},terms:{directive_typ:7,all:[15,9,16,17,10,11,20,7,12,23,4,13,14],code:[6,9,16,15,18,10,20,7,21,12,23,24,13,14],skeleton:18,chain:7,illustr:18,queri:[11,19],forbidden:16,lack:24,basic_messag:[6,4,19,8],four:17,concept:[6,16,0,17,19,11,7,4,8],follow:[15,9,16,17,18,19,10,11,20,7,3,12,23,4,13,21],lookup:4,synchronushandl:16,ptr:15,abid:[11,7],hierarch:19,whose:18,decid:[15,18,24],"const":[6,9,16,17,10,11,7,12,4],boost_network_http_body_callback:12,range_iter:9,http_client1:23,send:[23,16],rel:19,concret:7,swap:[4,18,19],sens:[9,1,7,12],"_follow_redirect":12,stock_repli:[6,9,16,10],sent:[12,16],liter:8,everi:[4,24],risk:13,straightforward:10,fals:[12,16],"void":[6,9,16,15,18,17,19,10,11,12,4],multi:10,nich:24,netlib:[0,2,3,4,5,6,7,8,9,10,11,23,13,14,15,16,17,18,19,20,21,12,24],endpoint:12,fan:13,veri:16,affect:12,default_:[15,18,9],exact:9,relev:20,look:[6,9,16,15,18,10,20,7,12,4,13,8],span:8,http_async_serv:16,administr:10,level:[6,13,24],michael:[13,24],upload:16,iter:9,factori:[15,4,7],"try":[20,16,10],vector:[18,11,16],verif:12,cooki:12,refer:[6,9,16,0,19,10,7,12,2,4,13,14],impli:4,tel:19,throught:23,peek:6,natur:7,yourself:13,direct:[6,0,17,11,24,7,23,4,8,5],transform:[4,7],handler_typ:16,second:[11,9],cost:14,design:3,pass:[9,16,18,10,20,7,12,23,4],download:[6,13],further:[23,19],port_typ:11,port:[9,16,17,19,10,11,20],append:12,even:[4,7,17],"_cache_resolv":12,what:[6,16,15,18,10,11,20,12,4,14],msysgit:13,barrier:24,repli:10,section:[9,16,17,11,12,4],advanc:5,abl:[13,16],"_linger_timeout":16,overload:[9,16,10],access:[9,16,17,11,20,7,24],delet:[23,9,12],version:[6,16,15,18,17,19,11,12,23,13,14],directori:[12,13],source_wrapp:4,dsel:7,"new":[6,15,18,19,7,13,14],boost:[6,9,16,17,1,19,10,18,11,20,12,23,24,13,14],method:[23,11,9,12,10],xml:20,full:[6,19,13,22,17],deriv:[15,11],absolut:19,usag:[23,20,16,10],gener:[6,16,0,15,19,11,7,12,2,4,24,13,8],never:24,unauthor:16,here:[15,9,16,19,10,12,23],boost_network_http_client_default_tag:14,bodi:[6,9,16,17,18,10,11,20,12,23,4,14],let:[18,20,13,10],argv:[6,23,20,10],address:[9,16,1,10,20,12],path:[11,9,13,19],along:13,rudimentari:7,modifi:[6,0,17,11,12,4,8],sinc:[23,18,20],valu:[15,9,16,17,1,10,11,12,4],wait:[12,16],convert:[4,19,11,17],convers:4,shift:7,anymor:18,larger:21,step:[23,13],cert:12,base:[15,18,19,7,4,13],cerr:[6,20,9,10],behav:12,http_keepalive_8bit_tcp_resolv:[12,1,9],action:16,http_client:[23,9],chang:[9,18,7,12,13,14],narrow:17,portabl:24,semant:[6,4,7,16,15],via:[6,20],repositori:[6,13],appli:[4,7],"while":[9,4,24,7,15],multiple_choic:16,releas:[6,17,13,12,16],unix:[13,19],api:[6,16,0,17,19,11,12,14],famili:18,visibl:9,instal:[6,13,22],gatekeep:13,unit:14,regex:13,argc:[23,20,10],from:[6,9,16,17,18,19,10,11,20,7,12,23,4,13,14],describ:[12,16,3,19,5],zip:13,commun:[6,3,24],distinct:16,doubl:19,upgrad:[12,16,14],subvers:13,websit:23,few:13,program:[15,21,24,19,10],call:[9,16,18,10,7,12,4,13],recommend:13,taken:16,clear_head:[4,11,17],type:[15,9,16,17,18,19,11,7,12,4,24],until:12,minor:[12,11],more:[6,16,4,14,13,24],reachabl:18,said:19,headers_rang:[11,9,17],afford:7,smtp:[4,24],swappabl:[4,18,19],relat:16,notic:[18,9],site:13,warn:[12,17,13,16],visual:13,accept:[7,16],known:[13,19],central:4,hold:[12,1,9],unpack:13,cach:12,content_typ:12,must:[13,14],basic_respons:[9,17],none:16,dcmake_c_compil:13,join:[6,13,16],internal_server_error:16,scalabl:16,alia:[13,17],work:[11,13,17],uniqu:15,histori:[6,24],annoi:24,remain:[15,7],tag:[6,9,16,15,1,17,19,11,12,4,14,18,5],can:[6,9,16,15,18,19,10,20,7,21,12,23,4,13],caveat:13,socket:16,root:[11,18],fetch:12,aliv:[12,1,9,16],proof:16,control:[18,13,16],heart:9,encapsul:[9,1,7,4,12],tar:13,give:16,process:[9,19],lock:16,pthread:[23,20,10],share:[12,1,9,16,10],templat:[6,9,16,15,18,17,19,11,7,12,2,4,24,13,8],high:24,sourc:[6,9,17,10,11,2,4,13,24],want:[15,16,18,20,12,4,13],explos:15,tarbal:13,http_async_8bit_udp_resolv:[12,1,9,14],serial:16,keep:[15,9,1,7,12,18],unsign:[12,11,9,17],occur:[11,17],string:[6,9,16,17,18,19,10,11,20,12,23,4],low:16,alwai:16,differenti:[16,10],multipl:16,goal:24,"_send_buffer_s":16,programmat:14,anoth:[16,19],classifi:19,divis:4,how:[18,19,10,20,21,12,13],scale:16,delete_:12,sever:[16,5],pure:[15,4],subdirectori:23,opt:13,instead:[12,18,16,13,14],simpl:[6,9,16,19,10,20,7,23,4],mpl:[18,14],stock:10,resourc:[13,10],dive:[23,20,21,10],earlier:[15,20],sneak:6,status_messag:17,befor:[12,20,16,14],xzf:13,attent:7,mai:[6,9,16,10,12,4],end:[12,9,24],data:[9,16,19,20,12,4],parallel:13,util:16,github:[6,24,13,12,19],attempt:[16,14],practic:3,third:10,date_tim:13,light:[6,24],author:[12,19],explicit:[12,4],made:[12,20,16,10],element:19,issu:[6,13,14],inform:[6,16,13,14],"switch":[15,11],maintain:[7,13,16],environ:[13,10],allow:[6,16,15,18,7,12,23,4,14],mechan:[18,9],order:[23,7,14],talk:[11,17],oper:[6,9,16,17,10,11,7,12,4,14],composit:18,help:16,xmpp:[4,24],offici:[6,13],move:7,becaus:[15,4,7,16],cross:[6,24],paper:[6,2],through:[11,9,13,16],size_t:16,still:[12,18,17,13,16],vari:[15,4,18],dynam:[6,15,16,12,5],paramet:[9,16,17,18,11,7,12,4,13,14],write:[6,16,20,12,14,24],typedef:[6,9,16,18,10,12,4],group:[6,13,24],fit:16,fix:14,complex:[23,13,19],unsupported_tag:18,better:[16,13,14],platform:[6,24,13,16],window:[6,13],pend:16,whole:[23,18,13,17],mail:[6,13],hidden:[12,7],main:[6,23,13,20,10],might:[18,9],easier:[12,4],non:[4,16,19],multimap:9,"return":[15,9,16,17,1,10,11,20,7,12,23,4,14],greater:[23,10],thei:[9,18,19,12,4,1],handl:[15,16,12,10],smarter:18,safe:[12,10],initi:[12,24,16,14],"break":[15,9,12,14],framework:10,synchron:[6,9,16,0,1,10,12],facilit:15,now:[12,14,17,13,10],discuss:[6,13],nor:4,choic:13,term:[12,4,16],document:[16,0,17,11,20,12,13,14],somewher:12,name:[9,16,17,11,12,4,13,14],realist:3,edit:16,separ:14,easili:[12,24],slide:[6,2],http_server:[6,11,16,17],timeout:16,each:[23,4,13,12,16],debug:13,fulli:[12,24],higher:[6,13],side:[15,10],mean:[12,4,13,16],compil:[12,16,7,13,14],everyth:19,dcmake_cxx_compil:13,weight:[6,24],list:[6,16,17,18,10,13],chunk:[12,16],continu:[16,24],functor:[9,10],realli:20,heavi:[13,14],ensur:[4,18,10],set_statu:16,"static":[6,15,18,7,12,5,14],expect:12,someth:[9,4,7,16,18],our:[18,13,24],happen:12,patch:13,unique_ptr:15,orient:[15,7],special:[6,9,15,18,17,11,7,4],out:[12,13,16],variabl:13,ftp:[19,24],shown:[12,16],safeti:18,network:[6,9,16,17,18,19,10,11,20,3,12,23,4,24],webservic:20,goe:13,tcp_resolv:12,req:16,connection_ptr:16,content:[6,4,16,12],typenam:[18,4,11,17],adapt:4,rational:7,internet:13,print:[23,9],current:[12,16,19],merg:13,correct:[15,4,9],invok:[16,13,10],after:[23,16,19],iostream:[23,20,7,10],linear:16,insid:[9,16],watermark:16,my_io_servic:[12,16],manipul:[4,16],situat:[15,7,16],differ:[6,9,16,0,15,18,17,19,11,7,12,4,14,8],free:[4,16],hello_world_cli:20,standalon:[15,12],reason:13,git:[6,13],latest:[6,13],put:[12,9,16],org:[6,9,19,23],"byte":[12,16],version_minor:[12,1,9,11],bash:19,netib:12,chose:4,your:[12,9,13,16],suffici:13,thread:[9,16,1,10,12,14],question:[6,13],prescrib:13,ask:[6,13],unavoid:15,thing:[23,18,17,13,15],enforc:11,place:16,some_xml_str:20,lifetim:12,assign:[4,16,19],first:[15,9,19,10,11,23,4,13],origin:[18,9],softwar:24,major:[12,11,24],"_openssl_certif":12,directli:[12,16],conform:9,onc:[23,18,13,12,16],independ:[12,7,16],qualiti:24,number:[9,16,1,10,18,11,12,4,13],placehold:18,uri_:9,instruct:13,alreadi:[16,17,11,12,14,24],done:[15,9,16,18,11,4,13],bad_gatewai:16,lboost_system:[23,20,10],stabl:13,"_reuse_address":16,open:24,payload:[4,20],size:16,take:[9,16,19,10,7,12,4,14],given:[6,9,16,15,18,17,19,11,4],"long":16,messag:[6,17,11,24,7,12,23,4,14,8],width:12,profil:16,associ:[18,4,17,11,16],top:[13,24],system:[12,7,13,16],wrapper:[6,9,0,17,11,4,14,8],destination_:[11,17],http_default_8bit_udp_resolv:[12,1,9,11,17],interfac:[9,16,0,1,11,7,12,14],scheme:[11,9,19],zipfil:13,"final":23,boil:7,listen:[16,10],adher:16,udp:[12,1,9],shell:[20,13,10],consol:23,option:[16,24,13,14],especi:16,namespac:[6,9,16,17,18,10,11,20,12,23],tool:[9,13],copi:[12,4,16,19],specifi:[9,16,1,19,12,23,4,13],aptli:9,next:[23,16],appropri:[12,11,17,13,16],pars:[19,9,16,14],mostli:13,than:[18,16],http_version_major:12,serv:18,wide:17,kind:[6,3,15],conveni:12,target:[7,24],provid:[6,9,17,1,19,10,11,12,18,24],hpp:[16,18,10,20,12,23],remov:[4,11,17],lvalu:[4,16],basic_cli:[12,9],structur:[23,18],charact:12,project:[6,13,24],matter:16,reus:7,not_accept:16,store:[12,4,16],str:20,opaqu:[18,19],other:[6,16,18,7,12,2,4,24],html:9,iterator_rang:[12,16],seri:[3,16],pre:[10,8],"function":[6,9,16,0,15,18,24,7,12,4,14,8],fashion:7,comput:[13,16],abov:[9,16,18,19,13,12,10,1],boostcon:[6,2],pertain:4,add_head:[4,11,17],sometim:[4,18],ani:[15,9,16,10,12,23,4,13,14],packag:13,properli:[12,16],manner:[18,11,16,12,17],have:[15,9,16,1,10,18,20,7,12,23,4,13,24],tabl:[12,4,9,16,17],need:[15,16,18,10,3,12,23,13,24],seen:10,dedic:12,incompat:13,well:[4,7,16],repeatedli:24,boost_network_default_tag:14,caus:[12,1,9,18],shared_futur:17,status_t:16,techniqu:[6,18,15,7,5],lib:[23,20,10],callback:[12,16],service_unavail:16,self:7,linger:16,client:[6,9,16,0,1,24,10,21,11,20,3,12,23,14,8],note:[16,17,19,10,20,12,4,13],also:[6,9,16,15,1,17,10,18,11,7,12,4,13,24],without:[23,7],headers_:[9,17],indic:[12,1,9],combin:[15,18],soap:24,singl:[9,16,10,12,23,14],asio:[12,24,16,14],begin:[12,9],sure:10,distribut:[23,24,13,12,16],plenti:24,normal:[12,11],buffer:[18,16,14],conncetionptr:16,compress:23,deleg:9,most:[4,16],wire:7,abus:7,pair:[11,17],"class":[15,9,16,17,18,19,10,11,7,12,4,8],tradit:13,don:[9,1,18,12,23,13],url:[23,20,13],clear:[12,4],later:16,cover:[4,14],uri:[6,9,15,19,11,2,23,14,8],doe:[16,17,19,10,12,4,13],declar:[11,9,17],directive2:7,directive1:7,readcallback:16,usual:[11,7,17],microsoft:13,came:9,show:[21,20,16,19],awar:24,inherit_linearli:18,syntax:[6,9,19,2,23,8],connect:[6,9,16,15,1,20,12,23],session:12,radic:14,protocol:[6,19,10,11,20,7,3,12,23,4,24,8],trivial:[9,7],find:[6,13],foo_direct:4,redirect:12,"_address":16,onli:[15,9,16,1,19,18,7,12,13,14],bind:16,locat:12,explain:23,response_head:[9,16],solut:13,written:[11,17],makefil:13,should:[15,9,16,18,10,12,4,13],prolong:7,configur:[6,14,13,10],hello_world:10,meant:[18,4,17,11,16],set_head:16,contribut:14,variou:12,get:[6,9,17,18,10,20,12,23,13,24],simplest:23,stop:16,fluid:15,soon:16,ssl:[15,12],is_base_of:18,mainten:13,progress:6,report:[6,13,16],metafunct:[6,4,18,5],requir:[15,16,17,19,11,12,4,13,24],embedd:[9,14],receiv:[12,16],enabl:[18,24,13,16],emb:[12,16],ietf:9,applac:16,modern:6,throughout:14,"_port":16,rfc:[9,2,19,23],"default":[15,9,16,1,12,23,4,18,14],common:[23,4,3,24],contain:[16,17,18,10,7,21,4],status_typ:16,where:[15,9,16,18,11,20,7,12,4,24,14],async_serv:16,"_openssl_verify_path":12,certif:12,set:[15,16,17,10,11,7,3,12,4,8],requesthandl:9,truli:7,"_thread_pool":16,assumpt:9,packet:4,increasingli:24,see:[9,16,18,10,12,1,14],result:[17,18,19,11,7,4],arg:[6,16,12],close:[6,16,9,13,23],retriev:[4,19,11,17],best:2,concern:14,polymorph:[6,15,5],statu:[14,9,16,17,10],flexibl:[23,18,7],extend:[18,7,24],correctli:17,"_report_abort":16,pattern:[15,4,7,16,12],review:6,easi:[6,20,24],"_body_handl":12,user_info:19,enough:[7,13],bridg:15,john:19,between:[13,19],"import":[16,14],awai:16,approach:[15,18],across:[12,10],signatur:[12,16],accord:[4,19],handler_:6,predefin:9,syntact:[4,7],status_message_:17,web:[13,24],numer:14,pointer:[12,16],were:16,hello_world_serv:[20,10],extens:[9,18,7],job:13,preprocessor:[12,14],request_:[6,12],overhaul:14,headers_contain:[4,17],endl:[9,19,10,20,12,23],addit:[15,7,13,19],both:[9,16,17,1,11,21,12],metaprogram:[6,18,2,13],berri:[13,24],cycl:12,response_:[6,12],howev:[18,9],alon:15,default_wstr:18,against:16,etc:24,instanc:[9,16,17,18,19,11,12,4],context:[18,7],logic:[9,4,7,16,23],mani:[12,24,13,14],com:[6,20,13,12,19],clone:13,among:18,simpli:[9,11,7],publicli:[11,16,17],stream:[23,16,12,14],point:[6,4,18],instanti:16,schedul:16,logic_error:16,dispatch:[15,4,9,18,14],header:[6,9,16,15,18,17,10,11,7,12,23,4,13,14],rpc:20,dcmake_build_typ:13,suppli:[9,16,19],pod:[4,11],not_found:16,assum:[16,17,11,20,12,4,13],summar:4,mailto:19,becom:24,creat:[15,16,17,10,11,20,12,23,13],version_major:[12,1,9,11],"_receive_buffer_s":16,compos:8,been:[12,16,24],accessor:[4,11,17],compon:[21,4,18,12,19],much:15,treat:11,modif:4,individu:13,acceptor:16,std:[6,9,16,17,18,19,10,11,20,12,23],strategi:[15,12],echo:9,bzip:13,basic_uri:[6,9,19,8],clariti:23,target_typ:7,argument:[9,16,10,12,23,4],assert:[9,19],unzip:13,craft:20,understand:16,togeth:[13,24],demand:24,"catch":[20,10],rang:[12,16],synchronoushandl:16,present:[6,23],"case":[15,9,16,17,18,10,11,12,4,13],inhibit:12,therefor:[9,24],rfc1738:9,gnu:13,plain:15,servic:24,properti:[9,4,7,18],sourceforg:24,act:13,aim:5,defin:[15,9,16,18,19,10,7,12,4,13,14],sln:13,boost_root:[23,20,13,10],behavior:[15,18,9,12],error:[6,16,12,23],thrash:13,aid:3,invoc:16,anchor:11,loop:16,pack:[12,16],real:18,layer:[6,24,7,15],would:[9,16,18,10,4,13],almost:16,them:[12,16,17],destin:[4,11,17],"_non_blocking_io":16,itself:[18,7],motiv:[6,24],new_statu:16,boost_network_enable_http:14,no_cont:16,conn:16,headers_container_typ:[11,17],peopl:6,develop:[6,10,3,23,13,24],welcom:6,minim:14,perform:[16,11,20,12,4,24,14],suggest:11,make:[6,9,15,1,10,18,20,12,23,13,14],intermediari:4,same:[15,9,18,10,7,12,13,24],member:[6,9,16,0,15,10,12],fragment:19,when:[15,4,24,16,14],handler_inst:16,http_keepalive_8bit_udp_resolv:[12,1,9],come:[15,11,7,13,17],eventu:[6,24],start:[6,18,13,12,16],complet:[23,13],overal:18,http:[6,9,16,0,15,1,17,24,19,10,21,11,20,2,3,12,23,4,14,13,8],hostnam:16,imagin:20,ostringstream:20,nest:[9,16,17,18,11,7,4],chainabl:7,upon:16,effect:[12,11,17],user:[9,16,1,19,7,12,13,14],extern:[15,12,14],respons:[6,9,16,0,17,1,10,20,12,23,14],typic:[4,9,13],bz2:13,underneath:[12,14],lower:[24,14],xjf:13,kept:[16,24],equival:18,choos:[12,4,11,13],entri:24,builder:19,string_typ:[6,11,18,16,17],facad:14,inherit:18,person:13,exampl:[6,9,16,18,19,10,20,7,3,12,23,4,13,21],reflect:14,thi:[15,9,16,0,17,1,24,19,10,18,11,20,7,12,23,4,14,13,5],directiven:7,error_cod:[12,16],model:[16,17,11,7,12,4,13],left:[18,7],load:12,construct:[16,17,19,11,12,4],identifi:[4,19],cout:[23,20,9,19,12],just:[9,17,18,10,11,20,4,13],object:[6,9,16,15,1,17,10,11,7,12,23,4,24,14],boost_network_no_lib:[12,14],tcp:[15,1,9,12],activ:[12,1,9,24],clear_resolved_cach:12,virtual:15,part:[9,17,19,11,12,4,14],derived1:15,derived0:15,body_handl:12,yet:[18,16],languag:24,previous:[16,10],"_handler":16,struct:[6,9,16,15,18,10,7,12,4],expos:16,had:24,except:[15,9,1,10,20,12],littl:[15,18],add:[23,4,17,11,13],is_valid:19,http_default_8bit_tcp_resolv:[12,1,9],versa:4,overview:[6,19,8],compat:12,ado:23,adl:[4,18],subsequ:[15,17],source_:[11,17],smart:[12,16],build:[6,9,10,20,21,23,13,24],bin:19,applic:[6,16,17,20,3,12,23,24,13,21],torvald:13,which:[6,9,16,15,18,19,10,20,7,12,23,4,13,14],format:7,read:[13,16],wstring:[11,18,17],distanc:12,built:[23,13,12,15],asynchronoushandl:16,world:[6,16,10,20,21,3],bit:[11,17],linux:[6,13],if_:18,resid:[23,9],like:[15,9,16,18,10,20,7,12,4,13],specif:[19,10,2,12,4,13],filenam:12,docutil:8,signal:23,echo_serv:9,cannot:[12,16],ipp:10,integ:11,noth:15,collect:24,"boolean":[12,16],necessari:10,either:[4,17,24,11,16],mikhailberi:[6,13],http_async_8bit_tcp_resolv:[12,1,9],output:19,not_modifi:16,decis:15,two:[9,16,10,11,12,14],depend:[9,16,17,11,12,4,13],fulfil:24,encount:[12,16],www:[6,9,19,23],right:[18,16],dean:[13,24],"_linger":16,deal:[15,16,10],simplifi:7,sstream:20,status_:17,interact:13,some:[6,16,15,18,17,19,5,13,14],pipelin:16,resolv:[12,1,9],intern:[9,16,18,11,12,14],enumer:10,sampl:[13,16],inlin:[11,7,18,17],home:[13,24],indirect:[15,7],server:[6,9,16,0,1,24,19,10,21,11,20,3,12,23,14,8],titl:1,librari:[6,15,18,17,11,7,3,12,4,24,13,14],tmp:12,googl:[6,13,14],connectionptr:16,guid:[6,2,13,22],lead:7,abort:16,"_io_servic":[12,16],broad:7,though:[23,13,15],octet:12,achiev:5,"_receive_low_watermark":16,body_:[11,17],tracker:6,larg:[18,16],slash:19,sequenc:12,moved_temporarili:16,foo:[15,4,18],localhost:20,mode:14,msvc:14,core:4,who:13,run:[6,16,10,20,21,23,13,14],power:[13,19],"enum":16,migrat:24,fast:6,els:12,http_statu:16,broken:19,host:[11,19,9,13,10],although:[15,4,18,13,16],found:[6,16,10,23,13,24],post:[23,20,9,12],"throw":[12,16],stage:[23,20,10],chapter:5,manual:[6,0],about:[6,16,17,10,11,2,13],actual:16,greatli:15,constraint:24,memori:[12,24,13,16],slightli:18,page:[6,13],basic_serv:9,stand:19,constructor:[9,16,19,10,12,23,14],commit:24,comp:19,input_rang:16,disabl:16,block:[12,1,9,16],underli:[9,4,7,18],thread_pool:16,own:[12,16,24],erro:12,cosntructor:14,default_str:18,around:[12,16],within:[13,0,16],encod:17,bound:16,three:[12,4,9,16,8],down:[9,7,19,15],creativ:15,empti:4,wrap:[15,4,17],default_tag:18,updat:14,destructor:15,mere:4,basic_request:[11,9],manag:[12,16,14],server_:[6,10],string_tag:18,log:6,wai:[12,18,9,16,19],area:4,transfer:16,support:[6,9,16,15,18,17,19,10,11,7,12,23,4,24,13,14],snmp:4,primari:[18,16],submit:[6,13,24],custom:12,avail:[15,16,12,4,24,13,14],stuck:13,reli:[12,14],handler:[6,9,16,15,10,12,14],bad_request:16,includ:[16,17,19,10,11,20,7,12,23,14],lot:[15,13],suit:13,forward:9,submiss:6,strictli:14,repetit:14,remove_head:[4,11,17],fork:13,head:[23,9,12],creation:7,gzip:13,form:[9,4,7,18,19],offer:12,linu:13,basic:[4,7],idea:18,state:[7,16],link:[6,13,12],translat:18,newer:[12,16],line:[6,19,10,20,23,13,14],icmp:4,"true":[12,16],bug:[13,14],reset:15,pull:13,immedi:[7,16],utf:17,input:[15,7],consist:[6,24,19,14],possibl:[6,15,23],whether:[15,16,19,11,12,4,14],vice:4,asynchron:[6,12,16,0,14],not_support:16,below:[9,16,17,19,12,23,13],unspecifi:[11,17],those:[17,5],otherwis:[15,11,13,19],problem:15,similar:[9,16,1,18,20,7,12,4,13],impl:10,significantli:16,version_:17,featur:[18,13,24],artifact:13,io_servic:[12,16,14],"int":[6,16,15,17,10,20,12,23],certain:[9,4,7,16,18],"abstract":[23,15,10],parser:[9,19,14],command:[19,13,20,10],deep:7,repres:16,"char":[6,16,10,20,12,23],uint16_t:17,implement:[6,9,16,0,15,1,17,19,18,11,7,12,4,14,13,8],"8bit":12,file:[6,19,13,12,16],request:[6,9,16,0,10,11,20,12,23,13,14],exist:[12,13,24],face:[12,16],check:[6,14,13,23],fill:12,concurr:16,denot:[18,16],readi:[12,14],macro:[12,14],cmake:[6,13],infosystem:19,nonetheless:4,"7zip":13,todo:7,client_:[6,12],excel:24,detail:[9,16,17,1,10,11,12,23,4],refactor:14,event:16,finish:[12,16],valid:[4,9],bool:[12,16],futur:[6,9,16,17,1,19,12],branch:13,trait:[18,17],test:[13,14],you:[6,9,16,15,18,10,20,12,23,13],runtim:15,miss:24,intend:[6,13,12,16],determin:[18,9,16],lend:7,subdivid:19,print_bodi:12,introduc:[12,14],source_typ:4,gcc:13,definit:[18,4,19,11,16],"public":[9,16,0],intent:24,embed:[21,16,10],boost_network_http_server_connection_header_buffer_max_s:16,pool:[16,14],svn:13,moved_perman:16,studio:13,standard:[7,24],http_version_minor:12,argpack:[12,16],info:[6,19],descript:[9,16,17,1,19,11,12,4],flag:14,notion:[4,7],not_impl:16,some_str:12,depth:[6,8],ignor:18,fact:23,potenti:16,time:[7,16,14],cpp:[0,2,3,4,5,6,7,8,9,10,11,23,13,14,15,16,17,18,19,20,21,12,24],invari:18,inc:14,hello:[6,16,10,20,21,3],legend:[4,17,11,19,16]},objtypes:{},titles:["Reference Manual","<no title>","References","Examples","The message template","Techniques","C++ Network Library","Directives","An in-depth look at the cpp-netlib","HTTP implementation","“Hello world” HTTP server","HTTP Request","HTTP Client API","Getting Started","What’s New","Static and dynamic polymorphism","HTTP Server API","HTTP Response","Tag metafunctions","The URI template","“Hello world” HTTP client","HTTP examples","Full installation guide","HTTP client","Project history"],objnames:{},filenames:["reference","http_client_tags","references","examples","message","techniques","index","directives","in_depth","http","hello_world_server","reference_http_request","reference_http_client","getting_started","whats_new","polymorphism","reference_http_server","reference_http_response","tag_metafunctions","uri","hello_world_client","examples_http","install","http_client","history"]}) \ No newline at end of file diff --git a/libs/network/doc/reference_http_client.rst b/libs/network/doc/reference_http_client.rst index 9b63c5e6d..12b1389e2 100644 --- a/libs/network/doc/reference_http_client.rst +++ b/libs/network/doc/reference_http_client.rst @@ -295,7 +295,7 @@ Streaming Body Handler As of v0.9.1 the library now offers a way to support a streaming body callback function in all HTTP requests that expect a body part (GET, PUT, POST, DELETE). A convenience macro is also provided to make callback handlers easier to write. -This macro is called `BOOST_NETWORK_HTTP_BODY_CALLBACK` which allows users to +This macro is called ``BOOST_NETWORK_HTTP_BODY_CALLBACK`` which allows users to write the following code to easily create functions or function objects that are compatible with the callback function requirements. @@ -339,5 +339,5 @@ to create a function object. response_ = client_.get(request("http://cpp-netlib.github.com/"), _body_handler=print_body); -The `BOOST_NETWORK_HTTP_BODY_CALLBACK` macro is defined in -`boost/network/protocol/http/client/macros.hpp`. +The ``BOOST_NETWORK_HTTP_BODY_CALLBACK`` macro is defined in +``boost/network/protocol/http/client/macros.hpp``. From 9956721fd5d6405625b11fdce199a4e16aea81c2 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 5 Aug 2011 16:43:05 +1000 Subject: [PATCH 127/768] Fixes #56 -- caches asynchronously fetched headers. --- boost/network/protocol/http/message/async_message.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/boost/network/protocol/http/message/async_message.hpp b/boost/network/protocol/http/message/async_message.hpp index 3e2849018..1c52986cb 100644 --- a/boost/network/protocol/http/message/async_message.hpp +++ b/boost/network/protocol/http/message/async_message.hpp @@ -91,13 +91,15 @@ namespace boost { namespace network { namespace http { destination_ = future; } - headers_container_type const headers() const { + headers_container_type const & headers() const { + if (retrieved_headers_) return *retrieved_headers_; headers_container_type raw_headers = headers_.get(); raw_headers.insert(added_headers.begin(), added_headers.end()); BOOST_FOREACH(string_type const & key, removed_headers) { raw_headers.erase(key); } - return raw_headers; + retrieved_headers_ = raw_headers; + return *retrieved_headers_; } void headers(boost::shared_future const & future) const { @@ -144,6 +146,7 @@ namespace boost { namespace network { namespace http { mutable headers_container_type added_headers; mutable std::set removed_headers; mutable boost::shared_future body_; + mutable boost::optional retrieved_headers_; friend struct boost::network::http::impl::ready_wrapper; }; From 86435370f8642cd917bae9c5fdd3f2d23904fc22 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 5 Aug 2011 16:43:45 +1000 Subject: [PATCH 128/768] Removing localhost tests. --- libs/network/test/http/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index a129d3adf..408c58abf 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -23,12 +23,14 @@ if (Boost_FOUND) client_get_test client_get_different_port_test client_get_timeout_test - client_localhost_normal_test + # TODO: refactor these so that local servers are no longer necessary + # client_localhost_normal_test client_get_streaming_test ) - if (OPENSSL_FOUND) - set ( TESTS ${TESTS} client_localhost_ssl_test ) - endif (OPENSSL_FOUND) + # TODO: refactor these so that local servers are no longer necessary + #if (OPENSSL_FOUND) + # set ( TESTS ${TESTS} client_localhost_ssl_test ) + #endif (OPENSSL_FOUND) foreach ( test ${TESTS} ) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) set_source_files_properties(${test}.cpp @@ -42,12 +44,13 @@ if (Boost_FOUND) endif() set_target_properties(cpp-netlib-http-${test} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) - add_test(cpp-netlib-http-${test} + add_test(cpp-netlib-http-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) endforeach (test) set ( SERVER_API_TESTS server_constructor_test + server_async_run_stop_concurrency ) foreach ( test ${SERVER_API_TESTS} ) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) @@ -67,7 +70,6 @@ if (Boost_FOUND) server_hello_world server_async server_async_less_copy - server_async_run_stop_concurrency ) set ( PORT 8000 ) foreach ( test ${SERVER_TESTS} ) From 922dcc1b14462be8dbf450feabd9844ecf9fb285 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 5 Aug 2011 17:48:15 +1000 Subject: [PATCH 129/768] Adding copyright notices. --- boost/network/protocol/http/message/async_message.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/boost/network/protocol/http/message/async_message.hpp b/boost/network/protocol/http/message/async_message.hpp index 1c52986cb..493b474ba 100644 --- a/boost/network/protocol/http/message/async_message.hpp +++ b/boost/network/protocol/http/message/async_message.hpp @@ -3,6 +3,8 @@ // Copyright 2010 (c) Dean Michael Berris // Copyright 2010 (c) Sinefunc, Inc. +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) From 15f1ba9b7339bf5b42ee1523b48afac60c8b00af Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 12 Aug 2011 15:44:30 +1000 Subject: [PATCH 130/768] Fixes #59 -- Handling body data properly in the streaming case. --- .../protocol/http/client/async_impl.hpp | 150 ++-- .../http/client/connection/async_normal.hpp | 677 ++++++++++-------- .../connection/async_protocol_handler.hpp | 671 ++++++++--------- 3 files changed, 782 insertions(+), 716 deletions(-) diff --git a/boost/network/protocol/http/client/async_impl.hpp b/boost/network/protocol/http/client/async_impl.hpp index 66844b271..a7e178d16 100644 --- a/boost/network/protocol/http/client/async_impl.hpp +++ b/boost/network/protocol/http/client/async_impl.hpp @@ -2,6 +2,8 @@ #define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623 // Copyright Dean Michael Berris 2010. +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -13,87 +15,87 @@ namespace boost { namespace network { namespace http { - template - struct basic_client_impl; + template + struct basic_client_impl; - namespace impl { - template - struct async_client : - connection_policy::type - { - typedef - typename connection_policy::type - connection_base; - typedef - typename resolver::type - resolver_type; - typedef - typename string::type - string_type; + namespace impl { + template + struct async_client : + connection_policy::type + { + typedef + typename connection_policy::type + connection_base; + typedef + typename resolver::type + resolver_type; + typedef + typename string::type + string_type; - typedef - function const &, system::error_code const &)> - body_callback_function_type; + typedef + function const &, system::error_code const &)> + body_callback_function_type; - async_client(bool cache_resolved, bool follow_redirect, optional const & certificate_filename, optional const & verify_path) - : connection_base(cache_resolved, follow_redirect), - service_ptr(new boost::asio::io_service), - service_(*service_ptr), - resolver_(service_), - sentinel_(new boost::asio::io_service::work(service_)), - certificate_filename_(certificate_filename), - verify_path_(verify_path) - { - connection_base::resolver_strand_.reset(new - boost::asio::io_service::strand(service_)); - lifetime_thread_.reset(new boost::thread( - boost::bind( - &boost::asio::io_service::run, - &service_ - ))); - } + async_client(bool cache_resolved, bool follow_redirect, optional const & certificate_filename, optional const & verify_path) + : connection_base(cache_resolved, follow_redirect), + service_ptr(new boost::asio::io_service), + service_(*service_ptr), + resolver_(service_), + sentinel_(new boost::asio::io_service::work(service_)), + certificate_filename_(certificate_filename), + verify_path_(verify_path) + { + connection_base::resolver_strand_.reset(new + boost::asio::io_service::strand(service_)); + lifetime_thread_.reset(new boost::thread( + boost::bind( + &boost::asio::io_service::run, + &service_ + ))); + } - async_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service, optional const & certificate_filename, optional const & verify_path) - : connection_base(cache_resolved, follow_redirect), - service_ptr(0), - service_(service), - resolver_(service_), - sentinel_(new boost::asio::io_service::work(service_)), - certificate_filename_(certificate_filename), - verify_path_(verify_path) - { - } + async_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service, optional const & certificate_filename, optional const & verify_path) + : connection_base(cache_resolved, follow_redirect), + service_ptr(0), + service_(service), + resolver_(service_), + sentinel_(new boost::asio::io_service::work(service_)), + certificate_filename_(certificate_filename), + verify_path_(verify_path) + { + } - ~async_client() throw () - { - sentinel_.reset(); - if (lifetime_thread_.get()) { - lifetime_thread_->join(); - lifetime_thread_.reset(); - } - delete service_ptr; - } + ~async_client() throw () + { + sentinel_.reset(); + if (lifetime_thread_.get()) { + lifetime_thread_->join(); + lifetime_thread_.reset(); + } + delete service_ptr; + } - basic_response const request_skeleton( - basic_request const & request_, - string_type const & method, - bool get_body, - body_callback_function_type callback - ) - { - typename connection_base::connection_ptr connection_; - connection_ = connection_base::get_connection(resolver_, request_, certificate_filename_, verify_path_); - return connection_->send_request(method, request_, get_body, callback); - } + basic_response const request_skeleton( + basic_request const & request_, + string_type const & method, + bool get_body, + body_callback_function_type callback + ) + { + typename connection_base::connection_ptr connection_; + connection_ = connection_base::get_connection(resolver_, request_, certificate_filename_, verify_path_); + return connection_->send_request(method, request_, get_body, callback); + } - boost::asio::io_service * service_ptr; - boost::asio::io_service & service_; - resolver_type resolver_; - boost::shared_ptr sentinel_; - boost::shared_ptr lifetime_thread_; - optional certificate_filename_, verify_path_; - }; - } // namespace impl + boost::asio::io_service * service_ptr; + boost::asio::io_service & service_; + resolver_type resolver_; + boost::shared_ptr sentinel_; + boost::shared_ptr lifetime_thread_; + optional certificate_filename_, verify_path_; + }; + } // namespace impl } // namespace http diff --git a/boost/network/protocol/http/client/connection/async_normal.hpp b/boost/network/protocol/http/client/connection/async_normal.hpp index b3b106a0a..3d6fb0817 100644 --- a/boost/network/protocol/http/client/connection/async_normal.hpp +++ b/boost/network/protocol/http/client/connection/async_normal.hpp @@ -29,335 +29,396 @@ namespace boost { namespace network { namespace http { namespace impl { - template - struct async_connection_base; + template + struct async_connection_base; - template - struct http_async_connection - : async_connection_base, - protected http_async_protocol_handler, - boost::enable_shared_from_this > - { - typedef async_connection_base base; - typedef http_async_protocol_handler protocol_base; - typedef typename base::resolver_type resolver_type; - typedef typename base::resolver_base::resolver_iterator resolver_iterator; - typedef typename base::resolver_base::resolver_iterator_pair resolver_iterator_pair; - typedef typename base::response response; - typedef typename base::string_type string_type; - typedef typename base::request request; - typedef typename base::resolver_base::resolve_function resolve_function; - typedef typename base::body_callback_function_type body_callback_function_type; + namespace placeholders = boost::asio::placeholders; - http_async_connection( - resolver_type & resolver, - resolve_function resolve, - bool follow_redirect - ) : - follow_redirect_(follow_redirect), - resolver_(resolver), - resolve_(resolve), - request_strand_(resolver.get_io_service()) - {} + template + struct http_async_connection + : async_connection_base, + protected http_async_protocol_handler, + boost::enable_shared_from_this > + { + typedef async_connection_base base; + typedef http_async_protocol_handler protocol_base; + typedef typename base::resolver_type resolver_type; + typedef typename base::resolver_base::resolver_iterator resolver_iterator; + typedef typename base::resolver_base::resolver_iterator_pair resolver_iterator_pair; + typedef typename base::response response; + typedef typename base::string_type string_type; + typedef typename base::request request; + typedef typename base::resolver_base::resolve_function resolve_function; + typedef typename base::body_callback_function_type body_callback_function_type; + typedef http_async_connection this_type; + http_async_connection(resolver_type & resolver, + resolve_function resolve, + bool follow_redirect) + : + follow_redirect_(follow_redirect), + resolver_(resolver), + resolve_(resolve), + request_strand_(resolver.get_io_service()) {} - virtual response start(request const & request, string_type const & method, bool get_body, body_callback_function_type callback) { - response response_; - this->init_response(response_, get_body); - linearize(request, method, version_major, version_minor, - std::ostreambuf_iterator::type>(&command_streambuf)); - this->method = method; - boost::uint16_t port_ = port(request); - resolve_(resolver_, host(request), - port_, - request_strand_.wrap( - boost::bind( - &http_async_connection::handle_resolved, - http_async_connection::shared_from_this(), - port_, get_body, callback, - _1, _2))); - return response_; - } - private: + // This is the main entry point for the connection/request pipeline. We're + // overriding async_connection_base<...>::start(...) here which is called + // by the client. + virtual response start(request const & request, + string_type const & method, + bool get_body, + body_callback_function_type callback) { + response response_; + this->init_response(response_, get_body); + linearize(request, method, version_major, version_minor, + std::ostreambuf_iterator::type>(&command_streambuf)); + this->method = method; + boost::uint16_t port_ = port(request); + resolve_(resolver_, host(request), + port_, + request_strand_.wrap( + boost::bind( + &this_type::handle_resolved, + this_type::shared_from_this(), + port_, get_body, callback, + _1, _2))); + return response_; + } - http_async_connection(http_async_connection const &); // = delete + private: - void set_errors(boost::system::error_code const & ec) { - boost::system::system_error error(ec); - this->version_promise.set_exception(boost::copy_exception(error)); - this->status_promise.set_exception(boost::copy_exception(error)); - this->status_message_promise.set_exception(boost::copy_exception(error)); - this->headers_promise.set_exception(boost::copy_exception(error)); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - this->body_promise.set_exception(boost::copy_exception(error)); + http_async_connection(http_async_connection const &); // = delete + + void set_errors(boost::system::error_code const & ec) { + boost::system::system_error error(ec); + this->version_promise.set_exception(boost::copy_exception(error)); + this->status_promise.set_exception(boost::copy_exception(error)); + this->status_message_promise.set_exception(boost::copy_exception(error)); + this->headers_promise.set_exception(boost::copy_exception(error)); + this->source_promise.set_exception(boost::copy_exception(error)); + this->destination_promise.set_exception(boost::copy_exception(error)); + this->body_promise.set_exception(boost::copy_exception(error)); + } + + void handle_resolved(boost::uint16_t port, + bool get_body, + body_callback_function_type callback, + boost::system::error_code const & ec, + resolver_iterator_pair endpoint_range) { + resolver_iterator iter = boost::begin(endpoint_range); + if (!ec && !boost::empty(endpoint_range)) { + // Here we deal with the case that there was an error encountered and + // that there's still more endpoints to try connecting to. + boost::asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), + port); + socket_.reset( + new boost::asio::ip::tcp::socket( + resolver_.get_io_service())); + socket_->async_connect(endpoint, + request_strand_.wrap( + boost::bind( + &this_type::handle_connected, + this_type::shared_from_this(), + port, + get_body, + callback, + std::make_pair(++iter, + resolver_iterator()), + placeholders::error))); + } else { + set_errors(ec ? ec : boost::asio::error::host_not_found); + } + } + + void handle_connected(boost::uint16_t port, + bool get_body, + body_callback_function_type callback, + resolver_iterator_pair endpoint_range, + boost::system::error_code const & ec) { + if (!ec) { + boost::asio::async_write( + *socket_ + , command_streambuf + , request_strand_.wrap( + boost::bind( + &this_type::handle_sent_request, + this_type::shared_from_this(), + get_body, callback, + placeholders::error, + placeholders::bytes_transferred + ))); + } else { + if (!boost::empty(endpoint_range)) { + resolver_iterator iter = boost::begin(endpoint_range); + boost::asio::ip::tcp::endpoint endpoint( + iter->endpoint().address(), + port + ); + socket_.reset(new boost::asio::ip::tcp::socket( + resolver_.get_io_service())); + socket_->async_connect( + endpoint, + request_strand_.wrap( + boost::bind( + &this_type::handle_connected, + this_type::shared_from_this(), + port, get_body, callback, std::make_pair(++iter, resolver_iterator()), + placeholders::error + ))); + } else { + set_errors(ec ? ec : boost::asio::error::host_not_found); } + } + } - void handle_resolved(boost::uint16_t port, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, resolver_iterator_pair endpoint_range) { - resolver_iterator iter = boost::begin(endpoint_range); - if (!ec && !boost::empty(endpoint_range)) { - boost::asio::ip::tcp::endpoint endpoint( - iter->endpoint().address(), - port - ); - socket_.reset(new boost::asio::ip::tcp::socket( - resolver_.get_io_service())); - socket_->async_connect( - endpoint, - request_strand_.wrap( - boost::bind( - &http_async_connection::handle_connected, - http_async_connection::shared_from_this(), - port, get_body, callback, - std::make_pair(++iter, resolver_iterator()), - boost::asio::placeholders::error - ))); - } else { - set_errors(ec ? ec : boost::asio::error::host_not_found); + enum state_t { + version, status, status_message, headers, body + }; + + void handle_sent_request(bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { + if (!ec) { + socket_->async_read_some( + boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), + request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + version, get_body, callback, + placeholders::error, + placeholders::bytes_transferred))); + } else { + set_errors(ec); + } + } + + void handle_received_data(state_t state, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { + if (!ec || ec == boost::asio::error::eof) { + logic::tribool parsed_ok; + size_t remainder; + switch(state) { + case version: + parsed_ok = + this->parse_version(*socket_, + request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + version, get_body, callback, + placeholders::error, + placeholders::bytes_transferred)), + bytes_transferred); + if (!parsed_ok || indeterminate(parsed_ok)) return; + case status: + parsed_ok = + this->parse_status(*socket_, + request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + status, get_body, callback, + placeholders::error, + placeholders::bytes_transferred)), + bytes_transferred); + if (!parsed_ok || indeterminate(parsed_ok)) return; + case status_message: + parsed_ok = + this->parse_status_message(*socket_, + request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + status_message, get_body, callback, + placeholders::error, placeholders::bytes_transferred + ) + ), + bytes_transferred + ); + if (!parsed_ok || indeterminate(parsed_ok)) return; + case headers: + // In the following, remainder is the number of bytes that remain + // in the buffer. We need this in the body processing to make sure + // that the data remaining in the buffer is dealt with before + // another call to get more data for the body is scheduled. + fusion::tie(parsed_ok, remainder) = + this->parse_headers(*socket_, + request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + headers, get_body, callback, + placeholders::error, placeholders::bytes_transferred + ) + ), + bytes_transferred + ); + + if (!parsed_ok || indeterminate(parsed_ok)) return; + + if (!get_body) { + // We short-circuit here because the user does not + // want to get the body (in the case of a HEAD + // request). + this->body_promise.set_value(""); + this->destination_promise.set_value(""); + this->source_promise.set_value(""); + this->part.assign('\0'); + this->response_parser_.reset(); + return; } - } - void handle_connected(boost::uint16_t port, bool get_body, body_callback_function_type callback, resolver_iterator_pair endpoint_range, boost::system::error_code const & ec) { - if (!ec) { - boost::asio::async_write( - *socket_ - , command_streambuf - , request_strand_.wrap( - boost::bind( - &http_async_connection::handle_sent_request, - http_async_connection::shared_from_this(), - get_body, callback, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred - ))); + if (callback) { + // Here we deal with the spill-over data from the + // headers processing. This means the headers data + // has already been parsed appropriately and we're + // looking to treat everything that remains in the + // buffer. + typename protocol_base::buffer_type::const_iterator begin = this->part_begin; + typename protocol_base::buffer_type::const_iterator end = begin; + std::advance(end, remainder); + + // We're setting the body promise here to an empty string because + // this can be used as a signaling mechanism for the user to + // determine that the body is now ready for processing, even + // though the callback is already provided. + this->body_promise.set_value(""); + + // The invocation of the callback is synchronous to allow us to + // wait before scheduling another read. + callback(make_iterator_range(begin, end), ec); + + socket_->async_read_some( + boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), + request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + body, get_body, callback, + placeholders::error, placeholders::bytes_transferred) + ) + ); } else { - if (!boost::empty(endpoint_range)) { - resolver_iterator iter = boost::begin(endpoint_range); - boost::asio::ip::tcp::endpoint endpoint( - iter->endpoint().address(), - port - ); - socket_.reset(new boost::asio::ip::tcp::socket( - resolver_.get_io_service())); - socket_->async_connect( - endpoint, - request_strand_.wrap( - boost::bind( - &http_async_connection::handle_connected, - http_async_connection::shared_from_this(), - port, get_body, callback, std::make_pair(++iter, resolver_iterator()), - boost::asio::placeholders::error - ))); - } else { - set_errors(ec ? ec : boost::asio::error::host_not_found); - } + // Here we handle the body data ourself and append to an + // ever-growing string buffer. + this->parse_body( + *socket_, + request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + body, get_body, callback, + placeholders::error, placeholders::bytes_transferred + ) + ), + remainder); } - } - - enum state_t { - version, status, status_message, headers, body - }; + return; + case body: + if (ec == boost::asio::error::eof) { + // Here we're handling the case when the connection has been + // closed from the server side, or at least that the end of file + // has been reached while reading the socket. This signals the end + // of the body processing chain. + if (callback) { + typename protocol_base::buffer_type::const_iterator begin = + this->part.begin(), + end = begin; + std::advance(end, bytes_transferred); - void handle_sent_request(bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { - if (!ec) { + // We call the callback function synchronously passing the error + // condition (in this case, end of file) so that it can handle + // it appropriately. + callback(make_iterator_range(begin, end), ec); + } else { + string_type body_string; + std::swap(body_string, this->partial_parsed); + body_string.append( + this->part.begin() + , bytes_transferred + ); + this->body_promise.set_value(body_string); + } + // TODO set the destination value somewhere! + this->destination_promise.set_value(""); + this->source_promise.set_value(""); + this->part.assign('\0'); + this->response_parser_.reset(); + } else { + // This means the connection has not been closed yet and we want to get more + // data. + if (callback) { + // Here we have a body_handler callback. Let's invoke the + // callback from here and make sure we're getting more data + // right after. + typename protocol_base::buffer_type::const_iterator begin = this->part.begin(); + typename protocol_base::buffer_type::const_iterator end = begin; + std::advance(end, bytes_transferred); + callback(make_iterator_range(begin, end), ec); socket_->async_read_some( - boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), + boost::asio::mutable_buffers_1( + this->part.c_array(), + this->part.size()), request_strand_.wrap( boost::bind( - &http_async_connection::handle_received_data, - http_async_connection::shared_from_this(), - version, get_body, callback, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred))); - } else { - set_errors(ec); + &this_type::handle_received_data, + this_type::shared_from_this(), + body, + get_body, + callback, + placeholders::error, + placeholders::bytes_transferred))); + } else { + // Here we don't have a body callback. Let's + // make sure that we deal with the remainder + // from the headers part in case we do have data + // that's still in the buffer. + this->parse_body(*socket_, + request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + body, + get_body, + callback, + placeholders::error, + placeholders::bytes_transferred)), + bytes_transferred); + } } + return; + default: + BOOST_ASSERT(false && "Bug, report this to the developers!"); } - - void handle_received_data(state_t state, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { - if (!ec || ec == boost::asio::error::eof) { - // Sanity check - if (ec == boost::asio::error::eof && state < headers) { - return; - } - logic::tribool parsed_ok; - size_t remainder; - switch(state) { - case version: - parsed_ok = - this->parse_version(*socket_, - request_strand_.wrap( - boost::bind( - &http_async_connection::handle_received_data, - http_async_connection::shared_from_this(), - version, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred - ); - if (parsed_ok != true) return; - case status: - parsed_ok = - this->parse_status(*socket_, - request_strand_.wrap( - boost::bind( - &http_async_connection::handle_received_data, - http_async_connection::shared_from_this(), - status, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred - ); - if (parsed_ok != true) return; - case status_message: - parsed_ok = - this->parse_status_message(*socket_, - request_strand_.wrap( - boost::bind( - &http_async_connection::handle_received_data, - http_async_connection::shared_from_this(), - status_message, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred - ); - if (parsed_ok != true) return; - case headers: - fusion::tie(parsed_ok, remainder) = - this->parse_headers(*socket_, - request_strand_.wrap( - boost::bind( - &http_async_connection::handle_received_data, - http_async_connection::shared_from_this(), - headers, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred - ); - if (parsed_ok != true) return; - if (!get_body) { - this->body_promise.set_value(""); - return; - } - if (callback) { - typename protocol_base::buffer_type::const_iterator begin = this->part.begin(); - std::advance(begin, remainder); - typename protocol_base::buffer_type::const_iterator end = begin; - std::advance(end, this->part.size() - remainder); - this->body_promise.set_value(""); - callback(make_iterator_range(begin, end), ec); - socket_->async_read_some( - boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), - request_strand_.wrap( - boost::bind( - &http_async_connection::handle_received_data, - http_async_connection::shared_from_this(), - body, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred) - ) - ); - } else { - this->parse_body( - *socket_, - request_strand_.wrap( - boost::bind( - &http_async_connection::handle_received_data, - http_async_connection::shared_from_this(), - body, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - remainder); - } - return; - case body: - if (ec == boost::asio::error::eof) { - if (callback) { - typename protocol_base::buffer_type::const_iterator begin = this->part.begin(), end = begin; - std::advance(end, bytes_transferred); - callback(make_iterator_range(begin, end), ec); - } else { - string_type body_string; - std::swap(body_string, this->partial_parsed); - body_string.append( - this->part.begin() - , bytes_transferred - ); - this->body_promise.set_value(body_string); - } - // TODO set the destination value somewhere! - this->destination_promise.set_value(""); - this->source_promise.set_value(""); - this->part.assign('\0'); - this->response_parser_.reset(); - } else { - if (callback) { - typename protocol_base::buffer_type::const_iterator begin = this->part.begin(), end = begin; - std::advance(end, bytes_transferred); - callback(make_iterator_range(begin, end), ec); - socket_->async_read_some( - boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), - request_strand_.wrap( - boost::bind( - &http_async_connection::handle_received_data, - http_async_connection::shared_from_this(), - body, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred) - ) - ); - } else { - this->parse_body( - *socket_, - request_strand_.wrap( - boost::bind( - &http_async_connection::handle_received_data, - http_async_connection::shared_from_this(), - body, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred); - } - } - return; - default: - BOOST_ASSERT(false && "Bug, report this to the developers!"); - } - } else { - boost::system::system_error error(ec); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - switch (state) { - case version: - this->version_promise.set_exception(boost::copy_exception(error)); - case status: - this->status_promise.set_exception(boost::copy_exception(error)); - case status_message: - this->status_message_promise.set_exception(boost::copy_exception(error)); - case headers: - this->headers_promise.set_exception(boost::copy_exception(error)); - case body: - this->body_promise.set_exception(boost::copy_exception(error)); - break; - default: - BOOST_ASSERT(false && "Bug, report this to the developers!"); - } - } + } else { + boost::system::system_error error(ec); + this->source_promise.set_exception(boost::copy_exception(error)); + this->destination_promise.set_exception(boost::copy_exception(error)); + switch (state) { + case version: + this->version_promise.set_exception(boost::copy_exception(error)); + case status: + this->status_promise.set_exception(boost::copy_exception(error)); + case status_message: + this->status_message_promise.set_exception(boost::copy_exception(error)); + case headers: + this->headers_promise.set_exception(boost::copy_exception(error)); + case body: + this->body_promise.set_exception(boost::copy_exception(error)); + break; + default: + BOOST_ASSERT(false && "Bug, report this to the developers!"); } + } + } - bool follow_redirect_; - resolver_type & resolver_; - boost::shared_ptr socket_; - resolve_function resolve_; - boost::asio::io_service::strand request_strand_; - boost::asio::streambuf command_streambuf; - string_type method; - }; + bool follow_redirect_; + resolver_type & resolver_; + boost::shared_ptr socket_; + resolve_function resolve_; + boost::asio::io_service::strand request_strand_; + boost::asio::streambuf command_streambuf; + string_type method; + }; } // namespace impl diff --git a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp index f9dc0aa87..66b510585 100644 --- a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp +++ b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp @@ -13,364 +13,367 @@ namespace boost { namespace network { namespace http { namespace impl { - template - struct http_async_protocol_handler { - protected: + template + struct http_async_protocol_handler { + protected: - typedef typename string::type string_type; + typedef typename string::type string_type; #ifdef BOOST_NETWORK_DEBUG - struct debug_escaper { - string_type & string; - explicit debug_escaper(string_type & string_) - : string(string_) {} - debug_escaper(debug_escaper const & other) - : string(other.string) {} - void operator()(typename string_type::value_type input) { - if (!algorithm::is_print()(input)) { - typename ostringstream::type escaped_stream; - if (input == '\r') { - string.append("\\r"); - } else if (input == '\n') { - string.append("\\n"); - } else { - escaped_stream << "\\x" << static_cast(input); - string.append(escaped_stream.str()); - } - } else { - string.push_back(input); - } - } - }; + struct debug_escaper { + string_type & string; + explicit debug_escaper(string_type & string_) + : string(string_) {} + debug_escaper(debug_escaper const & other) + : string(other.string) {} + void operator()(typename string_type::value_type input) { + if (!algorithm::is_print()(input)) { + typename ostringstream::type escaped_stream; + if (input == '\r') { + string.append("\\r"); + } else if (input == '\n') { + string.append("\\n"); + } else { + escaped_stream << "\\x" << static_cast(input); + string.append(escaped_stream.str()); + } + } else { + string.push_back(input); + } + } + }; #endif - template - void init_response(ResponseType & response_, bool get_body) { - boost::shared_future source_future( - source_promise.get_future()); - source(response_, source_future); - boost::shared_future destination_future( - destination_promise.get_future()); - destination(response_, destination_future); - boost::shared_future::type> - headers_future(headers_promise.get_future()); - headers(response_, headers_future); - boost::shared_future body_future( - body_promise.get_future()); - body(response_, body_future); - boost::shared_future version_future( - version_promise.get_future()); - version(response_, version_future); - boost::shared_future status_future( - status_promise.get_future()); - status(response_, status_future); - boost::shared_future status_message_future( - status_message_promise.get_future()); - status_message(response_, status_message_future); - } + template + void init_response(ResponseType & response_, bool get_body) { + boost::shared_future source_future( + source_promise.get_future()); + source(response_, source_future); + boost::shared_future destination_future( + destination_promise.get_future()); + destination(response_, destination_future); + boost::shared_future::type> + headers_future(headers_promise.get_future()); + headers(response_, headers_future); + boost::shared_future body_future( + body_promise.get_future()); + body(response_, body_future); + boost::shared_future version_future( + version_promise.get_future()); + version(response_, version_future); + boost::shared_future status_future( + status_promise.get_future()); + status(response_, status_future); + boost::shared_future status_message_future( + status_message_promise.get_future()); + status_message(response_, status_message_future); + } - struct to_http_headers { - typedef typename string::type string_type; - template - string_type const operator() (U const & pair) const { - typedef typename ostringstream::type ostringstream_type; - typedef constants constants; - ostringstream_type header_line; - header_line << pair.first - << constants::colon() - << constants::space() - << pair.second - << constants::crlf(); - return header_line.str(); - } - }; + struct to_http_headers { + typedef typename string::type string_type; + template + string_type const operator() (U const & pair) const { + typedef typename ostringstream::type ostringstream_type; + typedef constants constants; + ostringstream_type header_line; + header_line << pair.first + << constants::colon() + << constants::space() + << pair.second + << constants::crlf(); + return header_line.str(); + } + }; - template - logic::tribool parse_version(Socket & socket_, - Callback callback, - size_t bytes) { - logic::tribool parsed_ok; - part_begin = part.begin(); - typename buffer_type::const_iterator part_end = part.begin(); - std::advance(part_end, bytes); - typename boost::iterator_range - result_range, - input_range = boost::make_iterator_range(part_begin, part_end); - fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( - response_parser_type::http_version_done, - input_range); - if (parsed_ok == true) { - string_type version; - std::swap(version, partial_parsed); - version.append(boost::begin(result_range), - boost::end(result_range)); - algorithm::trim(version); - version_promise.set_value(version); - part_begin = boost::end(result_range); - } else if (parsed_ok == false) { + template + logic::tribool parse_version(Socket & socket_, + Callback callback, + size_t bytes) { + logic::tribool parsed_ok; + part_begin = part.begin(); + typename buffer_type::const_iterator part_end = part.begin(); + std::advance(part_end, bytes); + typename boost::iterator_range + result_range, + input_range = boost::make_iterator_range(part_begin, part_end); + fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( + response_parser_type::http_version_done, + input_range); + if (parsed_ok == true) { + string_type version; + std::swap(version, partial_parsed); + version.append(boost::begin(result_range), + boost::end(result_range)); + algorithm::trim(version); + version_promise.set_value(version); + part_begin = boost::end(result_range); + } else if (parsed_ok == false) { #ifdef BOOST_NETWORK_DEBUG - string_type escaped; - debug_escaper escaper(escaped); - std::for_each(part_begin, part_end, escaper); - BOOST_NETWORK_MESSAGE("[parser:" - << response_parser_.state() - << "] buffer contents: \"" - << escaped - << "\""); + string_type escaped; + debug_escaper escaper(escaped); + std::for_each(part_begin, part_end, escaper); + BOOST_NETWORK_MESSAGE("[parser:" + << response_parser_.state() + << "] buffer contents: \"" + << escaped + << "\""); #endif - std::runtime_error error("Invalid Version Part."); - version_promise.set_exception(boost::copy_exception(error)); - status_promise.set_exception(boost::copy_exception(error)); - status_message_promise.set_exception( - boost::copy_exception(error)); - headers_promise.set_exception(boost::copy_exception(error)); - source_promise.set_exception(boost::copy_exception(error)); - destination_promise.set_exception(boost::copy_exception(error)); - body_promise.set_exception(boost::copy_exception(error)); - } else { - partial_parsed.append( - boost::begin(result_range), - boost::end(result_range) - ); - part_begin = part.begin(); - socket_.async_read_some( - boost::asio::mutable_buffers_1(part.c_array(), part.size()), - callback - ); - } - return parsed_ok; - } + std::runtime_error error("Invalid Version Part."); + version_promise.set_exception(boost::copy_exception(error)); + status_promise.set_exception(boost::copy_exception(error)); + status_message_promise.set_exception( + boost::copy_exception(error)); + headers_promise.set_exception(boost::copy_exception(error)); + source_promise.set_exception(boost::copy_exception(error)); + destination_promise.set_exception(boost::copy_exception(error)); + body_promise.set_exception(boost::copy_exception(error)); + } else { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range) + ); + part_begin = part.begin(); + socket_.async_read_some( + boost::asio::mutable_buffers_1(part.c_array(), part.size()), + callback + ); + } + return parsed_ok; + } - template - logic::tribool parse_status(Socket & socket_, - Callback callback, - size_t bytes) { - logic::tribool parsed_ok; - typename buffer_type::const_iterator part_end = part.begin(); - std::advance(part_end, bytes); - typename boost::iterator_range - result_range, - input_range = boost::make_iterator_range(part_begin, part_end); - fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( - response_parser_type::http_status_done, - input_range); - if (parsed_ok == true) { - string_type status; - std::swap(status, partial_parsed); - status.append(boost::begin(result_range), - boost::end(result_range)); - trim(status); - boost::uint16_t status_int = - lexical_cast(status); - status_promise.set_value(status_int); - part_begin = boost::end(result_range); - } else if (parsed_ok == false) { + template + logic::tribool parse_status(Socket & socket_, + Callback callback, + size_t bytes) { + logic::tribool parsed_ok; + typename buffer_type::const_iterator part_end = part.begin(); + std::advance(part_end, bytes); + typename boost::iterator_range + result_range, + input_range = boost::make_iterator_range(part_begin, part_end); + fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( + response_parser_type::http_status_done, + input_range); + if (parsed_ok == true) { + string_type status; + std::swap(status, partial_parsed); + status.append(boost::begin(result_range), + boost::end(result_range)); + trim(status); + boost::uint16_t status_int = + lexical_cast(status); + status_promise.set_value(status_int); + part_begin = boost::end(result_range); + } else if (parsed_ok == false) { #ifdef BOOST_NETWORK_DEBUG - string_type escaped; - debug_escaper escaper(escaped); - std::for_each(part_begin, part_end, escaper); - BOOST_NETWORK_MESSAGE("[parser:" - << response_parser_.state() - << "] buffer contents: \"" - << escaped - << "\""); + string_type escaped; + debug_escaper escaper(escaped); + std::for_each(part_begin, part_end, escaper); + BOOST_NETWORK_MESSAGE("[parser:" + << response_parser_.state() + << "] buffer contents: \"" + << escaped + << "\""); #endif - std::runtime_error error("Invalid status part."); - status_promise.set_exception(boost::copy_exception(error)); - status_message_promise.set_exception( - boost::copy_exception(error)); - headers_promise.set_exception(boost::copy_exception(error)); - source_promise.set_exception(boost::copy_exception(error)); - destination_promise.set_exception(boost::copy_exception(error)); - body_promise.set_exception(boost::copy_exception(error)); - } else { - partial_parsed.append( - boost::begin(result_range), - boost::end(result_range) - ); - part_begin = part.begin(); - socket_.async_read_some( - boost::asio::mutable_buffers_1(part.c_array(), part.size()), - callback - ); - } - return parsed_ok; - } + std::runtime_error error("Invalid status part."); + status_promise.set_exception(boost::copy_exception(error)); + status_message_promise.set_exception( + boost::copy_exception(error)); + headers_promise.set_exception(boost::copy_exception(error)); + source_promise.set_exception(boost::copy_exception(error)); + destination_promise.set_exception(boost::copy_exception(error)); + body_promise.set_exception(boost::copy_exception(error)); + } else { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range) + ); + part_begin = part.begin(); + socket_.async_read_some( + boost::asio::mutable_buffers_1(part.c_array(), part.size()), + callback + ); + } + return parsed_ok; + } - template - logic::tribool parse_status_message(Socket & socket_, - Callback callback, - size_t bytes) { - logic::tribool parsed_ok; - typename buffer_type::const_iterator part_end = part.begin(); - std::advance(part_end, bytes); - typename boost::iterator_range - result_range, - input_range = boost::make_iterator_range(part_begin, part_end); - fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( - response_parser_type::http_status_message_done, - input_range); - if (parsed_ok == true) { - string_type status_message; - std::swap(status_message, partial_parsed); - status_message.append(boost::begin(result_range), - boost::end(result_range)); - algorithm::trim(status_message); - status_message_promise.set_value(status_message); - part_begin = boost::end(result_range); - } else if (parsed_ok == false) { + template + logic::tribool parse_status_message(Socket & socket_, + Callback callback, + size_t bytes) { + logic::tribool parsed_ok; + typename buffer_type::const_iterator part_end = part.begin(); + std::advance(part_end, bytes); + typename boost::iterator_range + result_range, + input_range = boost::make_iterator_range(part_begin, part_end); + fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( + response_parser_type::http_status_message_done, + input_range); + if (parsed_ok == true) { + string_type status_message; + std::swap(status_message, partial_parsed); + status_message.append(boost::begin(result_range), + boost::end(result_range)); + algorithm::trim(status_message); + status_message_promise.set_value(status_message); + part_begin = boost::end(result_range); + } else if (parsed_ok == false) { #ifdef BOOST_NETWORK_DEBUG - string_type escaped; - debug_escaper escaper(escaped); - std::for_each(part_begin, part_end, escaper); - BOOST_NETWORK_MESSAGE("[parser:" - << response_parser_.state() - << "] buffer contents: \"" - << escaped - << "\""); + string_type escaped; + debug_escaper escaper(escaped); + std::for_each(part_begin, part_end, escaper); + BOOST_NETWORK_MESSAGE("[parser:" + << response_parser_.state() + << "] buffer contents: \"" + << escaped + << "\""); #endif - std::runtime_error error("Invalid status message part."); - status_message_promise.set_exception( - boost::copy_exception(error)); - headers_promise.set_exception(boost::copy_exception(error)); - source_promise.set_exception(boost::copy_exception(error)); - destination_promise.set_exception(boost::copy_exception(error)); - body_promise.set_exception(boost::copy_exception(error)); - } else { - partial_parsed.append( - boost::begin(result_range), - boost::end(result_range)); - part_begin = part.begin(); - socket_.async_read_some( - boost::asio::mutable_buffers_1(part.c_array(), part.size()), - callback - ); - } - return parsed_ok; - } + std::runtime_error error("Invalid status message part."); + status_message_promise.set_exception( + boost::copy_exception(error)); + headers_promise.set_exception(boost::copy_exception(error)); + source_promise.set_exception(boost::copy_exception(error)); + destination_promise.set_exception(boost::copy_exception(error)); + body_promise.set_exception(boost::copy_exception(error)); + } else { + partial_parsed.append( + boost::begin(result_range), + boost::end(result_range)); + part_begin = part.begin(); + socket_.async_read_some( + boost::asio::mutable_buffers_1(part.c_array(), part.size()), + callback + ); + } + return parsed_ok; + } - void parse_headers_real(string_type & headers_part) { - typename boost::iterator_range - input_range = boost::make_iterator_range(headers_part) - , result_range; - logic::tribool parsed_ok; - response_parser_type headers_parser( - response_parser_type::http_header_line_done); - typename headers_container::type headers; - std::pair header_pair; - while (!boost::empty(input_range)) { - fusion::tie(parsed_ok, result_range) = - headers_parser.parse_until( - response_parser_type::http_header_colon, - input_range); - if (headers_parser.state() - != response_parser_type::http_header_colon) - break; - header_pair.first = string_type(boost::begin(result_range), - boost::end(result_range)); - input_range.advance_begin(boost::distance(result_range)); - fusion::tie(parsed_ok, result_range) = - headers_parser.parse_until( - response_parser_type::http_header_line_done, - input_range); - header_pair.second = string_type(boost::begin(result_range), - boost::end(result_range)); - input_range.advance_begin(boost::distance(result_range)); + void parse_headers_real(string_type & headers_part) { + typename boost::iterator_range + input_range = boost::make_iterator_range(headers_part) + , result_range; + logic::tribool parsed_ok; + response_parser_type headers_parser( + response_parser_type::http_header_line_done); + typename headers_container::type headers; + std::pair header_pair; + while (!boost::empty(input_range)) { + fusion::tie(parsed_ok, result_range) = + headers_parser.parse_until( + response_parser_type::http_header_colon, + input_range); + if (headers_parser.state() + != response_parser_type::http_header_colon) + break; + header_pair.first = string_type(boost::begin(result_range), + boost::end(result_range)); + input_range.advance_begin(boost::distance(result_range)); + fusion::tie(parsed_ok, result_range) = + headers_parser.parse_until( + response_parser_type::http_header_line_done, + input_range); + header_pair.second = string_type(boost::begin(result_range), + boost::end(result_range)); + input_range.advance_begin(boost::distance(result_range)); - trim(header_pair.first); - if (header_pair.first.size() > 1) { - header_pair.first.erase( - header_pair.first.size() - 1 - ); - } - trim(header_pair.second); - headers.insert(header_pair); - } - headers_promise.set_value(headers); + trim(header_pair.first); + if (header_pair.first.size() > 1) { + header_pair.first.erase( + header_pair.first.size() - 1 + ); } + trim(header_pair.second); + headers.insert(header_pair); + } + headers_promise.set_value(headers); + } - template - fusion::tuple parse_headers(Socket & socket_, - Callback callback, - size_t bytes) { - logic::tribool parsed_ok; - typename buffer_type::const_iterator part_end = part.begin(); - std::advance(part_end, bytes); - typename boost::iterator_range - result_range, - input_range = boost::make_iterator_range(part_begin, part_end); - fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( - response_parser_type::http_headers_done, - input_range); - if (parsed_ok == true) { - string_type headers_string; - std::swap(headers_string, partial_parsed); - headers_string.append(boost::begin(result_range), - boost::end(result_range)); - part_begin = boost::end(result_range); - this->parse_headers_real(headers_string); - } else if (parsed_ok == false) { - // We want to output the contents of the buffer that caused - // the error in debug builds. + template + fusion::tuple parse_headers(Socket & socket_, + Callback callback, + size_t bytes) { + logic::tribool parsed_ok; + typename buffer_type::const_iterator part_end = part.begin(); + std::advance(part_end, bytes); + typename boost::iterator_range + result_range, + input_range = boost::make_iterator_range(part_begin, part_end); + fusion::tie(parsed_ok, result_range) = response_parser_.parse_until( + response_parser_type::http_headers_done, + input_range); + if (parsed_ok == true) { + string_type headers_string; + std::swap(headers_string, partial_parsed); + headers_string.append(boost::begin(result_range), + boost::end(result_range)); + part_begin = boost::end(result_range); + this->parse_headers_real(headers_string); + } else if (parsed_ok == false) { + // We want to output the contents of the buffer that caused + // the error in debug builds. #ifdef BOOST_NETWORK_DEBUG - string_type escaped; - debug_escaper escaper(escaped); - std::for_each(part_begin, part_end, escaper); - BOOST_NETWORK_MESSAGE("[parser:" - << response_parser_.state() - << "] buffer contents: \"" - << escaped - << "\" consumed length: " - << boost::distance(result_range)); + string_type escaped; + debug_escaper escaper(escaped); + std::for_each(part_begin, part_end, escaper); + BOOST_NETWORK_MESSAGE("[parser:" + << response_parser_.state() + << "] buffer contents: \"" + << escaped + << "\" consumed length: " + << boost::distance(result_range)); #endif - std::runtime_error error("Invalid header part."); - headers_promise.set_exception(boost::copy_exception(error)); - body_promise.set_exception(boost::copy_exception(error)); - source_promise.set_exception(boost::copy_exception(error)); - destination_promise.set_exception(boost::copy_exception(error)); - } else { - partial_parsed.append(boost::begin(result_range), - boost::end(result_range)); - part_begin = part.begin(); - socket_.async_read_some( - boost::asio::mutable_buffers_1(part.c_array(), part.size()), - callback - ); - } - return fusion::make_tuple( - parsed_ok, - std::distance( - boost::end(result_range) - , part_end - ) - ); - } + std::runtime_error error("Invalid header part."); + headers_promise.set_exception(boost::copy_exception(error)); + body_promise.set_exception(boost::copy_exception(error)); + source_promise.set_exception(boost::copy_exception(error)); + destination_promise.set_exception(boost::copy_exception(error)); + } else { + partial_parsed.append(boost::begin(result_range), + boost::end(result_range)); + part_begin = part.begin(); + socket_.async_read_some( + boost::asio::mutable_buffers_1(part.c_array(), part.size()), + callback + ); + } + return fusion::make_tuple( + parsed_ok, + std::distance( + boost::end(result_range) + , part_end + ) + ); + } - template - void parse_body(Socket & socket_, Callback callback, size_t bytes) { - partial_parsed.append(part_begin, bytes); - part_begin = part.begin(); - socket_.async_read_some( - boost::asio::mutable_buffers_1(part.c_array(), part.size()), - callback - ); - } + template + void parse_body(Socket & socket_, Callback callback, size_t bytes) { + // TODO: we should really not use a string for the partial body + // buffer. + partial_parsed.append(part_begin, bytes); + part_begin = part.begin(); + socket_.async_read_some( + boost::asio::mutable_buffers_1(part.c_array(), part.size()), + callback + ); + } - typedef response_parser response_parser_type; - typedef boost::array::type, 1024> buffer_type; + typedef response_parser response_parser_type; + // TODO: make 1024 go away and become a configurable value. + typedef boost::array::type, 1024> buffer_type; - response_parser_type response_parser_; - boost::promise version_promise; - boost::promise status_promise; - boost::promise status_message_promise; - boost::promise::type> headers_promise; - boost::promise source_promise; - boost::promise destination_promise; - boost::promise body_promise; - buffer_type part; - typename buffer_type::const_iterator part_begin; - string_type partial_parsed; - }; + response_parser_type response_parser_; + boost::promise version_promise; + boost::promise status_promise; + boost::promise status_message_promise; + boost::promise::type> headers_promise; + boost::promise source_promise; + boost::promise destination_promise; + boost::promise body_promise; + buffer_type part; + typename buffer_type::const_iterator part_begin; + string_type partial_parsed; + }; } /* impl */ From 12822aa695a83e68fbc91efa8cd391bf41b27827 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Fri, 12 Aug 2011 15:46:49 +1000 Subject: [PATCH 131/768] Adding copyright headers. --- boost/network/protocol/http/client/connection/async_normal.hpp | 2 ++ boost/network/protocol/http/policies/async_connection.hpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/boost/network/protocol/http/client/connection/async_normal.hpp b/boost/network/protocol/http/client/connection/async_normal.hpp index 3d6fb0817..aaa7d85b0 100644 --- a/boost/network/protocol/http/client/connection/async_normal.hpp +++ b/boost/network/protocol/http/client/connection/async_normal.hpp @@ -3,6 +3,8 @@ // Copyright 2010 (C) Dean Michael Berris // Copyright 2010 (C) Sinefunc, Inc. +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google,Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) diff --git a/boost/network/protocol/http/policies/async_connection.hpp b/boost/network/protocol/http/policies/async_connection.hpp index bfbd7d446..ea8638d6b 100644 --- a/boost/network/protocol/http/policies/async_connection.hpp +++ b/boost/network/protocol/http/policies/async_connection.hpp @@ -3,6 +3,8 @@ // Copyright 2010 (C) Dean Michael Berris // Copyright 2010 (C) Sinefunc, Inc. +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) From 0eda3d9216b90e4da333bade62498d5a2e4ad5e7 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Thu, 12 May 2011 21:20:12 +0200 Subject: [PATCH 132/768] Refactored URI interface. The implementation parser won't do anything now, this will be the next step. --- boost/network/uri.hpp | 19 +- boost/network/uri/basic_uri.hpp | 242 ---------- boost/network/uri/basic_uri_fwd.hpp | 19 - boost/network/uri/detail/impl/parse_uri.ipp | 10 +- .../uri/http/detail/parse_specific.hpp | 49 -- boost/network/uri/http/detail/uri_parts.hpp | 52 --- boost/network/uri/http/uri.hpp | 43 -- boost/network/uri/uri.hpp | 442 +++++++++++++++++- boost/network/uri/uri_concept.hpp | 48 -- libs/network/test/CMakeLists.txt | 5 +- libs/network/test/url_test.cpp | 13 +- 11 files changed, 462 insertions(+), 480 deletions(-) delete mode 100644 boost/network/uri/basic_uri.hpp delete mode 100644 boost/network/uri/basic_uri_fwd.hpp delete mode 100644 boost/network/uri/http/detail/parse_specific.hpp delete mode 100644 boost/network/uri/http/detail/uri_parts.hpp delete mode 100644 boost/network/uri/http/uri.hpp delete mode 100644 boost/network/uri/uri_concept.hpp diff --git a/boost/network/uri.hpp b/boost/network/uri.hpp index bcf63dcb1..49bb0877f 100644 --- a/boost/network/uri.hpp +++ b/boost/network/uri.hpp @@ -6,20 +6,19 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include #include -#include -#include +#include -namespace boost { namespace network { namespace uri { - - typedef basic_uri uri; - typedef basic_uri wuri; - namespace http { - typedef basic_uri uri; - } +namespace boost { namespace network { namespace uri { +typedef basic_uri uri; +typedef basic_uri wuri; +// +// namespace http { +// typedef basic_uri uri; +// } +// } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/basic_uri.hpp b/boost/network/uri/basic_uri.hpp deleted file mode 100644 index 9a2d0bee2..000000000 --- a/boost/network/uri/basic_uri.hpp +++ /dev/null @@ -1,242 +0,0 @@ -#ifndef BOOST_NETWORK_URL_BASIC_URL_ -#define BOOST_NETWORK_URL_BASIC_URL_ - -// Copyright 2009 Dean Michael Berris, Jeroen Habraken. -// Copyright 2010 Glyn Matthews. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#include -#include -#include -#include - -namespace boost { namespace network { namespace uri { - -template -struct uri_base { - typedef typename string::type string_type; - - uri_base(string_type const & uri = string_type()) - : - raw_(uri), - parts_(), - valid_(false) - { - valid_ = parse_uri(raw_, parts_); - } - - uri_base(const uri_base & other) - : - raw_(other.raw_), - parts_(other.parts_), - valid_(other.valid_) - { } - - uri_base & operator=(uri_base other) { - other.swap(*this); - return *this; - } - - uri_base & operator=(string_type const & uri) { - return *this = uri_base(uri); - } - - void swap(uri_base & other) { - using std::swap; - - swap(other.raw_, raw_); - swap(other.parts_, parts_); - swap(other.valid_, valid_); - } - - string_type scheme() const { - return parts_.scheme; - } - - string_type user_info() const { - return parts_.user_info ? *parts_.user_info : string_type(); - } - - string_type host() const { - return parts_.host ? *parts_.host : string_type(); - } - - uint16_t port() const { - return parts_.port ? *parts_.port : 0; - } - - string_type path() const { - return parts_.path; - } - - string_type query() const { - return parts_.query ? *parts_.query : string_type(); - } - - string_type fragment() const { - return parts_.fragment ? *parts_.fragment : string_type(); - } - - string_type raw() const { - return raw_; - } - - string_type string() const { - return raw_; - } - - bool valid() const { - return is_valid(); - } - - bool is_valid() const { - return valid_; - } - - bool operator == (uri_base const & other) const { - return (raw_ == other.raw_) && (parts_ == other.parts_) && (valid_ == other.valid_); - } - - bool operator != (uri_base const & other) const { - return !(*this == other); - } - -protected: - - string_type raw_; - detail::uri_parts parts_; - bool valid_; -}; - -template -class basic_uri : public uri_base { - -public: - - basic_uri() : uri_base() {} - basic_uri(typename uri_base::string_type const & uri) : uri_base(uri) {} - basic_uri(basic_uri const & other) : uri_base(other) {} - - basic_uri & operator= (basic_uri rhs) { - rhs.swap(*this); - return *this; - } - - void swap(basic_uri & other) { - uri_base::swap(other); - } - - using uri_base::operator==; - using uri_base::operator!=; - -}; - -template -inline -void swap(basic_uri & left, basic_uri & right) { - right.swap(left); -} - -template -inline -typename string::type -scheme(basic_uri const & uri) { - return uri.scheme(); -} - -template -inline -typename string::type -user_info(basic_uri const & uri) { - return uri.user_info(); -} - -template -inline -typename string::type -host(basic_uri const & uri) { - return uri.host(); -} - -template -struct port_wrapper { - basic_uri const & uri; - explicit port_wrapper(basic_uri const & uri) - : uri(uri) - {} - - operator boost::optional() const { - return uri.port(); - } - - operator boost::uint16_t() const { - boost::optional const & port_ = uri.port(); - typedef typename string::type string_type; - typedef constants consts; - if (port_) return *port_; - return boost::iequals(uri.scheme(), string_type(consts::https())) ? 443 : 80; - } -}; - -template -inline -port_wrapper const -port(basic_uri const & uri) { - return port_wrapper(uri); -} - -template -inline -typename string::type -path(basic_uri const & uri) { - return uri.path(); -} - -template -inline -typename string::type -query(basic_uri const & uri) { - return uri.query(); -} - -template -inline -typename string::type -fragment(basic_uri const & uri) { - return uri.fragment(); -} - -template -inline -bool -valid(basic_uri const & uri) { - return uri.valid(); -} - -template -inline -bool -is_valid(basic_uri const & uri) { - return uri.is_valid(); -} -} // namespace uri -} // namespace network -} // namespace boost - -#ifdef BOOST_NETWORK_DEBUG -// Check that the URI concept is met by the basic_uri type. -#include -#include -namespace boost { namespace network { namespace uri { -BOOST_CONCEPT_ASSERT((URI >)); -BOOST_CONCEPT_ASSERT((URI >)); -} // namespace uri -} // namespace network -} // namespace boost -#endif // BOOST_NETWORK_DEBUG - -#endif - diff --git a/boost/network/uri/basic_uri_fwd.hpp b/boost/network/uri/basic_uri_fwd.hpp deleted file mode 100644 index bbcac611b..000000000 --- a/boost/network/uri/basic_uri_fwd.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef BOOST_NETWORK_URL_BASIC_URL_FWD_HPP_ -#define BOOST_NETWORK_URL_BASIC_URL_FWD_HPP_ - -// Copyright 2009 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -namespace boost { namespace network { namespace uri { -template < - class Tag - > -class basic_uri; -} // namespace uri -} // namespace network -} // namespace boost - -#endif - diff --git a/boost/network/uri/detail/impl/parse_uri.ipp b/boost/network/uri/detail/impl/parse_uri.ipp index d8c1d888a..ff8700a41 100644 --- a/boost/network/uri/detail/impl/parse_uri.ipp +++ b/boost/network/uri/detail/impl/parse_uri.ipp @@ -1,5 +1,5 @@ -// Copyright 2010-2011 Dean Michael Berris. +// Copyright 2010-2011 Dean Michael Berris. // Copyright 2009 Jeroen Habraken. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -220,7 +220,7 @@ struct choose_uri_base { typedef uri_parts_wide_base type; }; - + namespace qi = boost::spirit::qi; template @@ -398,11 +398,11 @@ BOOST_NETWORK_INLINE bool parse_uri_impl(boost::iterator_range -#include -#include -#include -#include - -namespace boost { namespace network { namespace uri { - - namespace detail { - - template <> - inline bool parse_specific - (uri_parts & parts) - { - if ((parts.scheme.size() < 4) || (parts.scheme.size() > 5)) - return false; - - if (parts.scheme.size() == 4) { - if (not boost::iequals(parts.scheme, "http")) - return false; - } else { // size is 5 - if (not boost::iequals(parts.scheme, "https")) - return false; - } - - if ((not parts.host) || parts.host->empty()) - return false; - - return true; - } - - } // namespace detail - -} // namespace uri - -} // namespace network - -} // namespace boost - -#endif - diff --git a/boost/network/uri/http/detail/uri_parts.hpp b/boost/network/uri/http/detail/uri_parts.hpp deleted file mode 100644 index b61367f42..000000000 --- a/boost/network/uri/http/detail/uri_parts.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef BOOST_NETWORK_URL_HTTP_DETAIL_URL_PARTS_HPP_ -#define BOOST_NETWORK_URL_HTTP_DETAIL_URL_PARTS_HPP_ - -// Copyright 2009 Dean Michael Berris, Jeroen Habraken. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt of copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include - -namespace boost { namespace network { namespace uri { - - namespace detail { - - template <> struct uri_parts { - typedef string::type string_type; - string_type scheme; - string_type scheme_specific_part; - optional user_info; - string_type host; - optional port; - optional path; - optional query; - optional fragment; - }; - - template <> - inline void swap(uri_parts & l, uri_parts & r) { - using std::swap; - swap(l.scheme, r.scheme); - swap(l.scheme_specific_part, r.scheme_specific_part); - swap(l.user_info, r.user_info); - swap(l.host, r.host); - swap(l.port, r.port); - swap(l.path, r.path); - swap(l.query, r.query); - swap(l.fragment, r.fragment); - } - - } // namespace detail - -} // namespace uri - -} // namespace network - -} // namespace boost - -#endif - diff --git a/boost/network/uri/http/uri.hpp b/boost/network/uri/http/uri.hpp deleted file mode 100644 index 9b8ffcd65..000000000 --- a/boost/network/uri/http/uri.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef BOOST_NETWORK_URL_HTTP_URL_HPP_ -#define BOOST_NETWORK_URL_HTTP_URL_HPP_ - -// Copyright 2009 Dean Michael Berris, Jeroen Habraken. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include - - -namespace boost { namespace network { namespace uri { - -template <> -class basic_uri - : public uri_base { - -public: - basic_uri() : uri_base() {} - basic_uri(uri_base::string_type const & uri) : uri_base(uri) {} - - boost::optional port() const { - return parts_.port; - return parts_.port ? *(parts_.port) : - (boost::iequals(parts_.scheme, string_type("https")) ? 443 : 80); - } - - string_type path() const { - return (parts_.path == "") ? string_type("/") : parts_.path; - } -}; - -} // namespace uri -} // namespace network -} // namespace boost - -#endif - diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 0f69a33d5..1bab6f345 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -1,14 +1,446 @@ -// Copyright (c) Glyn Matthews 2010. +// Copyright 2009, 2010, 2011 Dean Michael Berris, Jeroen Habraken, Glyn Matthews. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#ifndef __BOOST_NETWORK_URI_URI_INC__ -# define __BOOST_NETWORK_URI_URI_INC__ +#ifndef __BOOST_NETWORK_URI_INC__ +# define __BOOST_NETWORK_URI_INC__ -# include +# include +# include +# include +# include +# include +# include +# include -#endif // __BOOST_NETWORK_URI_URI_INC__ +namespace boost { +namespace network { +namespace uri { +namespace details { +template < + class Tag + > +struct iterator_range + : boost::fusion::vector< + typename string::type::const_iterator + , typename string::type::const_iterator + > +{ }; + + +template < + class Tag + > +struct uri_parts + : boost::fusion::vector< + iterator_range + , iterator_range + , iterator_range + , iterator_range + , iterator_range + , iterator_range + , iterator_range + > +{ }; +} // namespace details + +template < + class Tag + > +class basic_uri + : public boost::equality_comparable > { + +public: + + typedef typename string::type string_type; + typedef typename string_type::iterator iterator_type; + typedef boost::iterator_range range_type; + typedef typename string_type::const_iterator const_iterator_type; + typedef boost::iterator_range const_range_type; + + basic_uri() : is_valid_(false) { + + } + + explicit basic_uri(const string_type &uri) + : uri_(uri), is_valid_(false) { + parse(); + } + + basic_uri(const basic_uri &other) + : uri_(other.uri_), + uri_parts_(other.uri_parts_), + is_valid_(other.is_valid_) { + + } + + basic_uri &operator = (const basic_uri &other) { + basic_uri(other).swap(*this); + return *this; + } + + ~basic_uri() { + + } + + void swap(basic_uri &other) { + boost::swap(uri_, other.uri_); + boost::swap(uri_parts_, other.uri_parts_); + boost::swap(is_valid_, other.is_valid_); + } + + const_range_type scheme_range() const { + using boost::fusion::at_c; + return const_range_type(at_c<0>(at_c<0>(uri_parts_)), + at_c<1>(at_c<0>(uri_parts_))); + } + + const_range_type user_info_range() const { + using boost::fusion::at_c; + return const_range_type(at_c<0>(at_c<1>(uri_parts_)), + at_c<1>(at_c<1>(uri_parts_))); + } + + const_range_type host_range() const { + using boost::fusion::at_c; + return const_range_type(at_c<0>(at_c<2>(uri_parts_)), + at_c<1>(at_c<2>(uri_parts_))); + } + + const_range_type port_range() const { + using boost::fusion::at_c; + return const_range_type(at_c<0>(at_c<3>(uri_parts_)), + at_c<1>(at_c<3>(uri_parts_))); + } + + const_range_type path_range() const { + using boost::fusion::at_c; + return const_range_type(at_c<0>(at_c<4>(uri_parts_)), + at_c<1>(at_c<4>(uri_parts_))); + } + + const_range_type query_range() const { + using boost::fusion::at_c; + return const_range_type(at_c<0>(at_c<5>(uri_parts_)), + at_c<1>(at_c<5>(uri_parts_))); + } + + const_range_type fragment_range() const { + using boost::fusion::at_c; + return const_range_type(at_c<0>(at_c<6>(uri_parts_)), + at_c<1>(at_c<6>(uri_parts_))); + } + + string_type scheme() const { + const_range_type range = scheme_range(); + return string_type(boost::begin(range), boost::end(range)); + } + + string_type user_info() const { + const_range_type range = user_info_range(); + return string_type(boost::begin(range), boost::end(range)); + } + + string_type host() const { + const_range_type range = host_range(); + return string_type(boost::begin(range), boost::end(range)); + } + + string_type port() const { + const_range_type range = port_range(); + return string_type(boost::begin(range), boost::end(range)); + } + + string_type path() const { + const_range_type range = path_range(); + return string_type(boost::begin(range), boost::end(range)); + } + + string_type query() const { + const_range_type range = query_range(); + return string_type(boost::begin(range), boost::end(range)); + } + + string_type fragment() const { + const_range_type range = fragment_range(); + return string_type(boost::begin(range), boost::end(range)); + } + + string_type to_string() const { + return uri_; + } + + bool is_valid() const { + return is_valid_; + } + +private: + + void parse(); + + string_type uri_; + details::uri_parts uri_parts_; + bool is_valid_; + +}; +} // namespace uri +} // namespace network +} // namespace boost + + +# include +# include +# include +# include +# include + + +namespace boost { +namespace network { +namespace uri { +namespace details { +namespace qi = boost::spirit::qi; + +template < + class Tag, + typename Iterator + > +struct uri_grammar : qi::grammar()> { + + uri_grammar() : uri_grammar::base_type(start, "uri") { + using boost::spirit::repository::qi::iter_pos; + + // // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" + // gen_delims %= qi::char_(":/?#[]@"); + // // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + // sub_delims %= qi::char_("!$&'()*+,;="); + // // reserved = gen-delims / sub-delims + // reserved %= gen_delims | sub_delims; + // // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + // unreserved %= qi::alnum | qi::char_("-._~"); + // // pct-encoded = "%" HEXDIG HEXDIG + // pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; + + // // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + // pchar %= qi::raw[ + // unreserved | pct_encoded | sub_delims | qi::char_(":@") + // ]; + + // // segment = *pchar + // segment %= qi::raw[*pchar]; + // // segment-nz = 1*pchar + // segment_nz %= qi::raw[+pchar]; + // // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) + // segment_nz_nc %= qi::raw[ + // +(unreserved | pct_encoded | sub_delims | qi::char_("@")) + // ]; + // // path-abempty = *( "/" segment ) + // path_abempty %= qi::raw[*(qi::char_("/") >> segment)]; + // // path-absolute = "/" [ segment-nz *( "/" segment ) ] + // path_absolute %= qi::raw[ + // qi::char_("/") + // >> -(segment_nz >> *(qi::char_("/") >> segment)) + // ]; + // // path-rootless = segment-nz *( "/" segment ) + // path_rootless %= qi::raw[ + // segment_nz >> *(qi::char_("/") >> segment) + // ]; + // // path-empty = 0 + // path_empty %= qi::eps; + + // // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + // scheme %= qi::alpha >> *(qi::alnum | qi::char_("+.-")); + + // // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) + // user_info %= qi::raw[ + // *(unreserved | pct_encoded | sub_delims | qi::char_(":")) + // ]; + + // // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 + // dec_octet %= + // !(qi::lit('0') >> qi::digit) + // >> qi::raw[ + // qi::uint_parser() + // ]; + // // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet + // ipv4address %= qi::raw[ + // dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] + // ]; + // // reg-name = *( unreserved / pct-encoded / sub-delims ) + // reg_name %= qi::raw[ + // *(unreserved | pct_encoded | sub_delims) + // ]; + // // TODO, host = IP-literal / IPv4address / reg-name + // host %= ipv4address | reg_name; + + // // port %= qi::ushort_; + + // // query = *( pchar / "/" / "?" ) + // query %= qi::raw[*(pchar | qi::char_("/?"))]; + // // fragment = *( pchar / "/" / "?" ) + // fragment %= qi::raw[*(pchar | qi::char_("/?"))]; + + // // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty + // // authority = [ userinfo "@" ] host [ ":" port ] + // hier_part %= + // ( + // "//" + // >> -(user_info >> '@') + // >> host + // >> -(':' >> port) + // // >> -(':' >> qi::ushort_) + // >> path_abempty + // ) + // | + // ( + // qi::attr(std::string()) + // >> qi::attr(std::string()) + // >> qi::attr(std::string()) + // >> ( + // path_absolute + // | path_rootless + // | path_empty + // ) + // ); + + // start %= + // iter_pos + // >> iter_pos + // >> iter_pos + // >> iter_pos + // >> iter_pos + // >> iter_pos + // >> qi::omit[scheme] >> ':' + // >> hier_part + // // >> -('?' >> qi::omit[query]) + // // >> -('#' >> qi::omit[fragment]) + // ; + } + + qi::rule + gen_delims, sub_delims, reserved, unreserved; + qi::rule + pct_encoded, pchar; + + qi::rule + segment, segment_nz, segment_nz_nc; + qi::rule + path_abempty, path_absolute, path_rootless, path_empty; + + qi::rule + dec_octet, ipv4address, reg_name, host, port; + + qi::rule + scheme, user_info, query, fragment; + + qi::rule + hier_part; + + // actual uri parser + qi::rule()> start; + +}; +} // namespace details + + +template < + class Tag + > +void basic_uri::parse() { + namespace qi = boost::spirit::qi; + static details::uri_grammar grammar; + const_iterator_type first(boost::begin(uri_)), last(boost::end(uri_)); + is_valid_ = qi::parse(first, last, grammar, uri_parts_); + is_valid_ = is_valid_ && (first == last); +} + + +template < + class Tag + > +inline +void swap(basic_uri &lhs, basic_uri &rhs) { + lhs.swap(rhs); +} + +template < + class Tag + > +inline +typename basic_uri::string_type scheme(const basic_uri &uri) { + return uri.scheme(); +} + +template < + class Tag + > +inline +typename basic_uri::string_type user_info(const basic_uri &uri) { + return uri.user_info(); +} + +template < + class Tag + > +inline +typename basic_uri::string_type host(const basic_uri &uri) { + return uri.host(); +} + +template < + class Tag + > +inline +typename basic_uri::string_type port(const basic_uri &uri) { + return uri.port(); +} + +template < + class Tag + > +inline +typename basic_uri::string_type path(const basic_uri &uri) { + return uri.path(); +} + +template < + class Tag + > +inline +typename basic_uri::string_type query(const basic_uri &uri) { + return uri.query(); +} + +template < + class Tag + > +inline +typename basic_uri::string_type fragment(const basic_uri &uri) { + return uri.fragment(); +} + +template < + class Tag + > +inline +bool is_valid(const basic_uri &uri) { + return uri.is_valid(); +} + +template < + class Tag + > +inline +bool operator == (const basic_uri &lhs, const basic_uri &rhs) { + return lhs.to_string() == rhs.to_string(); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_INC__ diff --git a/boost/network/uri/uri_concept.hpp b/boost/network/uri/uri_concept.hpp deleted file mode 100644 index 08abf28e8..000000000 --- a/boost/network/uri/uri_concept.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef BOOST_NETWORK_URL_URL_CONCEPT_HPP_ -#define BOOST_NETWORK_URL_URL_CONCEPT_HPP_ - -// Copyright 2009 Dean Michael Berris, Jeroen Habraken. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include - -namespace boost { namespace network { namespace uri { - - template - struct URI : DefaultConstructible, EqualityComparable { - typedef typename U::string_type string_type; - - BOOST_CONCEPT_USAGE(URI) - { - U uri_(uri); // copy constructable - - U temp; - swap(temp, uri_); // swappable - - string_type scheme_ = scheme(uri); // support functions - string_type user_info_ = user_info(uri); - string_type host_ = host(uri); - uint16_t port_ = port(uri); - port_ = 0; - string_type path_ = path(uri); - string_type query_ = query(uri); - string_type fragment_ = fragment(uri); - - bool valid_ = is_valid(uri); - valid_ = false; - } - - private: - U uri; - }; - -} // namespace uri - -} // namespace network - -} // namespace boost - -#endif - diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index 5ed915509..ea7efaba2 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -24,8 +24,9 @@ if (Boost_FOUND) set_source_files_properties(${test}.cpp PROPERTIES COMPILE_FLAGS "-Wall") add_executable(cpp-netlib-${test} ${test}.cpp) - add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + # add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) + # target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) endif() diff --git a/libs/network/test/url_test.cpp b/libs/network/test/url_test.cpp index db0463bef..62c23f08f 100644 --- a/libs/network/test/url_test.cpp +++ b/libs/network/test/url_test.cpp @@ -8,7 +8,7 @@ #define BOOST_TEST_MODULE URL Test #include #include -#include +#include #include #include #include @@ -17,7 +17,7 @@ using namespace boost::network; typedef boost::mpl::list< tags::default_string - , tags::default_wstring + // , tags::default_wstring > tag_types; @@ -45,7 +45,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, tag_types) { const std::string scheme("http"); const std::string user_info("user:password"); const std::string host("www.boost.org"); - boost::uint16_t port = 8000; + // boost::uint16_t port = 8000; + const std::string port = "8000"; const std::string path("/path"); const std::string query("query"); const std::string fragment("fragment"); @@ -55,7 +56,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK_EQUAL(uri::port(instance), port); + // BOOST_CHECK_EQUAL(uri::port(instance), port); + BOOST_CHECK(boost::equal(uri::port(instance), port)); BOOST_CHECK(boost::equal(uri::path(instance), path)); BOOST_CHECK(boost::equal(uri::query(instance), query)); BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); @@ -212,6 +214,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, tag_types) { uri_type instance(string_type(boost::begin(url), boost::end(url))); uri_type copy; copy = instance; - BOOST_CHECK(instance.raw() == copy.raw()); + // BOOST_CHECK(instance.raw() == copy.raw()); + BOOST_CHECK(instance.to_string() == copy.to_string()); BOOST_CHECK(instance == copy); } From aab4f7288512cc0acbeb7fa7239407dd0b88880d Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Fri, 13 May 2011 19:09:46 +0200 Subject: [PATCH 133/768] Refactored URI, all unit tests pass. --- boost/network/uri/uri.hpp | 318 +++++++++++++++++++++++--------------- 1 file changed, 192 insertions(+), 126 deletions(-) diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 1bab6f345..14dd39481 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -38,10 +38,12 @@ template < struct uri_parts : boost::fusion::vector< iterator_range - , iterator_range - , iterator_range - , iterator_range - , iterator_range + , boost::fusion::vector< + iterator_range + , iterator_range + , iterator_range + , iterator_range + > , iterator_range , iterator_range > @@ -101,38 +103,62 @@ class basic_uri const_range_type user_info_range() const { using boost::fusion::at_c; - return const_range_type(at_c<0>(at_c<1>(uri_parts_)), - at_c<1>(at_c<1>(uri_parts_))); + const boost::fusion::vector< + details::iterator_range + , details::iterator_range + , details::iterator_range + , details::iterator_range > &hier_part = at_c<1>(uri_parts_); + + return const_range_type(at_c<0>(at_c<0>(hier_part)), + at_c<1>(at_c<0>(hier_part))); } const_range_type host_range() const { using boost::fusion::at_c; - return const_range_type(at_c<0>(at_c<2>(uri_parts_)), - at_c<1>(at_c<2>(uri_parts_))); + const boost::fusion::vector< + details::iterator_range + , details::iterator_range + , details::iterator_range + , details::iterator_range > &hier_part = at_c<1>(uri_parts_); + + return const_range_type(at_c<0>(at_c<1>(hier_part)), + at_c<1>(at_c<1>(hier_part))); } const_range_type port_range() const { using boost::fusion::at_c; - return const_range_type(at_c<0>(at_c<3>(uri_parts_)), - at_c<1>(at_c<3>(uri_parts_))); + const boost::fusion::vector< + details::iterator_range + , details::iterator_range + , details::iterator_range + , details::iterator_range > &hier_part = at_c<1>(uri_parts_); + + return const_range_type(at_c<0>(at_c<2>(hier_part)), + at_c<1>(at_c<2>(hier_part))); } const_range_type path_range() const { using boost::fusion::at_c; - return const_range_type(at_c<0>(at_c<4>(uri_parts_)), - at_c<1>(at_c<4>(uri_parts_))); + const boost::fusion::vector< + details::iterator_range + , details::iterator_range + , details::iterator_range + , details::iterator_range > &hier_part = at_c<1>(uri_parts_); + + return const_range_type(at_c<0>(at_c<3>(hier_part)), + at_c<1>(at_c<3>(hier_part))); } const_range_type query_range() const { using boost::fusion::at_c; - return const_range_type(at_c<0>(at_c<5>(uri_parts_)), - at_c<1>(at_c<5>(uri_parts_))); + return const_range_type(at_c<0>(at_c<2>(uri_parts_)), + at_c<1>(at_c<2>(uri_parts_))); } const_range_type fragment_range() const { using boost::fusion::at_c; - return const_range_type(at_c<0>(at_c<6>(uri_parts_)), - at_c<1>(at_c<6>(uri_parts_))); + return const_range_type(at_c<0>(at_c<3>(uri_parts_)), + at_c<1>(at_c<3>(uri_parts_))); } string_type scheme() const { @@ -214,130 +240,170 @@ struct uri_grammar : qi::grammar()> { uri_grammar() : uri_grammar::base_type(start, "uri") { using boost::spirit::repository::qi::iter_pos; - // // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" - // gen_delims %= qi::char_(":/?#[]@"); - // // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" - // sub_delims %= qi::char_("!$&'()*+,;="); - // // reserved = gen-delims / sub-delims - // reserved %= gen_delims | sub_delims; - // // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - // unreserved %= qi::alnum | qi::char_("-._~"); - // // pct-encoded = "%" HEXDIG HEXDIG - // pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; - - // // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - // pchar %= qi::raw[ - // unreserved | pct_encoded | sub_delims | qi::char_(":@") - // ]; - - // // segment = *pchar - // segment %= qi::raw[*pchar]; - // // segment-nz = 1*pchar - // segment_nz %= qi::raw[+pchar]; - // // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) - // segment_nz_nc %= qi::raw[ - // +(unreserved | pct_encoded | sub_delims | qi::char_("@")) - // ]; - // // path-abempty = *( "/" segment ) - // path_abempty %= qi::raw[*(qi::char_("/") >> segment)]; - // // path-absolute = "/" [ segment-nz *( "/" segment ) ] - // path_absolute %= qi::raw[ - // qi::char_("/") - // >> -(segment_nz >> *(qi::char_("/") >> segment)) - // ]; - // // path-rootless = segment-nz *( "/" segment ) - // path_rootless %= qi::raw[ - // segment_nz >> *(qi::char_("/") >> segment) - // ]; - // // path-empty = 0 - // path_empty %= qi::eps; - - // // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) - // scheme %= qi::alpha >> *(qi::alnum | qi::char_("+.-")); - - // // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) - // user_info %= qi::raw[ - // *(unreserved | pct_encoded | sub_delims | qi::char_(":")) - // ]; - - // // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 - // dec_octet %= - // !(qi::lit('0') >> qi::digit) - // >> qi::raw[ - // qi::uint_parser() - // ]; - // // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet - // ipv4address %= qi::raw[ - // dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] - // ]; - // // reg-name = *( unreserved / pct-encoded / sub-delims ) - // reg_name %= qi::raw[ - // *(unreserved | pct_encoded | sub_delims) - // ]; - // // TODO, host = IP-literal / IPv4address / reg-name - // host %= ipv4address | reg_name; - - // // port %= qi::ushort_; - - // // query = *( pchar / "/" / "?" ) - // query %= qi::raw[*(pchar | qi::char_("/?"))]; - // // fragment = *( pchar / "/" / "?" ) - // fragment %= qi::raw[*(pchar | qi::char_("/?"))]; - - // // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty - // // authority = [ userinfo "@" ] host [ ":" port ] - // hier_part %= - // ( - // "//" - // >> -(user_info >> '@') - // >> host - // >> -(':' >> port) - // // >> -(':' >> qi::ushort_) - // >> path_abempty - // ) - // | - // ( - // qi::attr(std::string()) - // >> qi::attr(std::string()) - // >> qi::attr(std::string()) - // >> ( - // path_absolute - // | path_rootless - // | path_empty - // ) - // ); - - // start %= - // iter_pos - // >> iter_pos - // >> iter_pos - // >> iter_pos - // >> iter_pos - // >> iter_pos - // >> qi::omit[scheme] >> ':' - // >> hier_part - // // >> -('?' >> qi::omit[query]) - // // >> -('#' >> qi::omit[fragment]) - // ; + // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" + gen_delims %= qi::char_(":/?#[]@"); + // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + sub_delims %= qi::char_("!$&'()*+,;="); + // reserved = gen-delims / sub-delims + reserved %= gen_delims | sub_delims; + // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + unreserved %= qi::alnum | qi::char_("-._~"); + // pct-encoded = "%" HEXDIG HEXDIG + pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; + + // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + pchar %= qi::raw[ + unreserved | pct_encoded | sub_delims | qi::char_(":@") + ]; + + // segment = *pchar + segment %= qi::raw[*pchar]; + // segment-nz = 1*pchar + segment_nz %= qi::raw[+pchar]; + // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) + segment_nz_nc %= qi::raw[ + +(unreserved | pct_encoded | sub_delims | qi::char_("@")) + ]; + // path-abempty = *( "/" segment ) + path_abempty %= + iter_pos + >> qi::omit[qi::raw[*(qi::char_("/") >> segment)]] + >> iter_pos + ; + // path-absolute = "/" [ segment-nz *( "/" segment ) ] + path_absolute %= + iter_pos + >> qi::omit[qi::raw[ + qi::char_("/") + >> -(segment_nz >> *(qi::char_("/") >> segment)) + ]] + >> iter_pos + ; + // path-rootless = segment-nz *( "/" segment ) + path_rootless %= + iter_pos + >> qi::omit[qi::raw[ + segment_nz >> *(qi::char_("/") >> segment) + ]] + >> iter_pos + ; + // path-empty = 0 + path_empty %= + iter_pos + >> qi::omit[qi::eps] + >> iter_pos + ; + + // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + scheme %= + iter_pos + >> qi::omit[qi::alpha >> *(qi::alnum | qi::char_("+.-"))] + >> iter_pos + ; + + // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) + user_info %= + iter_pos + >> qi::omit[qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))]] + >> iter_pos + ; + + // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 + dec_octet %= + !(qi::lit('0') >> qi::digit) + >> qi::raw[ + qi::uint_parser() + ]; + // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet + ipv4address %= qi::raw[ + dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] + ]; + // reg-name = *( unreserved / pct-encoded / sub-delims ) + reg_name %= qi::raw[ + *(unreserved | pct_encoded | sub_delims) + ]; + // TODO, host = IP-literal / IPv4address / reg-name + host %= + iter_pos + >> qi::omit[ipv4address | reg_name] + >> iter_pos + ; + + // port %= qi::ushort_; + port %= + iter_pos + >> qi::omit[*qi::digit] + >> iter_pos + ; + + // query = *( pchar / "/" / "?" ) + query %= + iter_pos + >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] + >> iter_pos + ; + // fragment = *( pchar / "/" / "?" ) + fragment %= + iter_pos + >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] + >> iter_pos + ; + + // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty + // authority = [ userinfo "@" ] host [ ":" port ] + hier_part %= + ( + "//" + >> -(user_info >> '@') + >> host + >> -(':' >> port) + >> path_abempty + ) + | + ( + qi::attr(iterator_range()) + >> qi::attr(iterator_range()) + >> qi::attr(iterator_range()) + >> ( + path_absolute + | path_rootless + | path_empty + ) + ) + ; + + start %= + scheme >> ':' + >> hier_part + >> -('?' >> query) + >> -('#' >> fragment) + ; } - qi::rule + qi::rule::type::value_type()> gen_delims, sub_delims, reserved, unreserved; + //qi::rule()> qi::rule pct_encoded, pchar; qi::rule segment, segment_nz, segment_nz_nc; - qi::rule + qi::rule()> path_abempty, path_absolute, path_rootless, path_empty; qi::rule - dec_octet, ipv4address, reg_name, host, port; + dec_octet, ipv4address, reg_name; - qi::rule + qi::rule()> + host, port; + + qi::rule()> scheme, user_info, query, fragment; - qi::rule + qi::rule, + iterator_range, + iterator_range, + iterator_range >()> hier_part; // actual uri parser From d2882cdcadab4ebff0151cc1bf09a5b3eebb2df5 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Fri, 13 May 2011 19:13:54 +0200 Subject: [PATCH 134/768] Works with std::wstring too. --- boost/network/uri/uri.hpp | 6 +++--- libs/network/test/url_test.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 14dd39481..32a73b75d 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -383,15 +383,15 @@ struct uri_grammar : qi::grammar()> { qi::rule::type::value_type()> gen_delims, sub_delims, reserved, unreserved; //qi::rule()> - qi::rule + qi::rule::type()> pct_encoded, pchar; - qi::rule + qi::rule::type()> segment, segment_nz, segment_nz_nc; qi::rule()> path_abempty, path_absolute, path_rootless, path_empty; - qi::rule + qi::rule::type()> dec_octet, ipv4address, reg_name; qi::rule()> diff --git a/libs/network/test/url_test.cpp b/libs/network/test/url_test.cpp index 62c23f08f..d97a21f9b 100644 --- a/libs/network/test/url_test.cpp +++ b/libs/network/test/url_test.cpp @@ -17,7 +17,7 @@ using namespace boost::network; typedef boost::mpl::list< tags::default_string - // , tags::default_wstring + , tags::default_wstring > tag_types; From 7edad2e0c2e726c9765fd94cea125a5a102ed989 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 14 May 2011 09:46:09 +0200 Subject: [PATCH 135/768] Refactored library for changes to URI. --- CMakeLists.txt | 2 +- boost/network/protocol/http/impl/request.hpp | 8 +- .../protocol/http/message/wrappers/port.hpp | 2 +- .../protocol/http/policies/sync_resolver.hpp | 1 + boost/network/uri.hpp | 1 + boost/network/uri/detail/impl/parse_uri.ipp | 408 ------------------ boost/network/uri/detail/parse_uri.hpp | 261 +++++++++-- boost/network/uri/detail/uri_parts.hpp | 196 ++------- boost/network/uri/http/uri.hpp | 72 ++++ boost/network/uri/uri.hpp | 325 ++++---------- libs/network/example/uri.cpp | 4 +- libs/network/src/CMakeLists.txt | 13 + libs/network/src/uri/parse.cpp | 12 + libs/network/test/CMakeLists.txt | 4 +- libs/network/test/http/CMakeLists.txt | 10 +- 15 files changed, 452 insertions(+), 867 deletions(-) delete mode 100644 boost/network/uri/detail/impl/parse_uri.ipp create mode 100644 boost/network/uri/http/uri.hpp create mode 100644 libs/network/src/CMakeLists.txt create mode 100644 libs/network/src/uri/parse.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4aedc4e6f..1475321ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ if (Boost_FOUND) include_directories(${Boost_INCLUDE_DIRS}) endif() enable_testing() -add_subdirectory(libs/network/build) +add_subdirectory(libs/network/src) add_subdirectory(libs/network/test) add_subdirectory(libs/mime/test) add_subdirectory(libs/network/example) diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index cfe5bddfc..e54ba1cb7 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -24,8 +24,8 @@ #include -namespace boost { namespace network { - +namespace boost { namespace network { + /** Specialize the traits for the http_server tag. */ template <> struct headers_container : @@ -92,7 +92,7 @@ namespace http { } port_type port() const { - return uri::port(uri_); + return uri::port_us(uri_); } string_type const path() const { @@ -162,7 +162,7 @@ namespace http { }; template <> - struct basic_request + struct basic_request : not_quite_pod_request_base {}; diff --git a/boost/network/protocol/http/message/wrappers/port.hpp b/boost/network/protocol/http/message/wrappers/port.hpp index 4da1f6eda..9777ac277 100644 --- a/boost/network/protocol/http/message/wrappers/port.hpp +++ b/boost/network/protocol/http/message/wrappers/port.hpp @@ -30,7 +30,7 @@ namespace boost { namespace network { namespace http { } operator boost::optional () { - return port(message_.uri()); + return port_us(message_.uri()); } }; diff --git a/boost/network/protocol/http/policies/sync_resolver.hpp b/boost/network/protocol/http/policies/sync_resolver.hpp index ca6c93e5a..9702425e9 100644 --- a/boost/network/protocol/http/policies/sync_resolver.hpp +++ b/boost/network/protocol/http/policies/sync_resolver.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/boost/network/uri.hpp b/boost/network/uri.hpp index 49bb0877f..741ac48e5 100644 --- a/boost/network/uri.hpp +++ b/boost/network/uri.hpp @@ -8,6 +8,7 @@ #include #include +#include namespace boost { namespace network { namespace uri { diff --git a/boost/network/uri/detail/impl/parse_uri.ipp b/boost/network/uri/detail/impl/parse_uri.ipp deleted file mode 100644 index ff8700a41..000000000 --- a/boost/network/uri/detail/impl/parse_uri.ipp +++ /dev/null @@ -1,408 +0,0 @@ - -// Copyright 2010-2011 Dean Michael Berris. -// Copyright 2009 Jeroen Habraken. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef PARSE_URI_IMPL_AQAWWXWT -#define PARSE_URI_IMPL_AQAWWXWT - -#ifdef BOOST_NETWORK_NO_LIB -#define BOOST_NETWORK_INLINE inline -#else -#define BOOST_NETWORK_INLINE -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -BOOST_FUSION_ADAPT_STRUCT(boost::network::uri::detail::uri_parts_default_base, - (std::string, scheme) - (optional, user_info) - (optional, host) - (optional, port) - (optional, path) - (optional, query) - (optional, fragment) -) - -BOOST_FUSION_ADAPT_STRUCT(boost::network::uri::detail::uri_parts_wide_base, - (std::wstring, scheme) - (optional, user_info) - (optional, host) - (optional, port) - (optional, path) - (optional, query) - (optional, fragment) -) - -namespace boost { namespace spirit { namespace traits { -template <> -struct transform_attribute< - boost::network::uri::detail::uri_parts_default_base, - boost::fusion::tuple< - std::string &, - boost::fusion::tuple< - boost::optional&, - boost::optional&, - boost::optional &, - std::string & - >, - optional&, - optional& - > -#if SPIRIT_VERSION >= 0x2030 - , boost::spirit::qi::domain -#endif - > -{ - typedef - boost::fusion::tuple< - std::string &, - boost::fusion::tuple< - boost::optional&, - boost::optional&, - boost::optional &, - std::string & - >, - optional&, - optional& - > type; - - static type pre(boost::network::uri::detail::uri_parts_default_base & parts) { - boost::fusion::tuple< - boost::optional &, - boost::optional &, - boost::optional &, - std::string & - > hier_part = - boost::fusion::tie( - parts.user_info, - parts.host, - parts.port, - parts.path - ); - - return boost::fusion::tie( - parts.scheme, - hier_part, - parts.query, - parts.fragment - ); -} - -static void post(boost::network::uri::detail::uri_parts_default_base &, type const &) { } - -#if SPIRIT_VERSION >= 0x2030 -static void fail(boost::network::uri::detail::uri_parts_default_base & val) { } -#endif -}; - -#if SPIRIT_VERSION < 0x2030 -template -struct transform_attribute< - optional, - Transformed, - typename disable_if, Transformed> >::type - > -{ - typedef Transformed & type; - - static Transformed & pre(optional & val) { - if (!val) - val = Transformed(); - return boost::get(val); - } - - static void post(optional &, Transformed const &) { } -}; -#endif - -template <> -struct transform_attribute< - boost::network::uri::detail::uri_parts_wide_base, - boost::fusion::tuple< - std::wstring &, - boost::fusion::tuple< - boost::optional&, - boost::optional&, - boost::optional &, - std::wstring & - >, - optional&, - optional& - > -#if SPIRIT_VERSION >= 0x2030 - , boost::spirit::qi::domain -#endif - > -{ - typedef - boost::fusion::tuple< - std::wstring &, - boost::fusion::tuple< - boost::optional&, - boost::optional&, - boost::optional &, - std::wstring & - >, - optional&, - optional& - > type; - - static type pre(boost::network::uri::detail::uri_parts_wide_base & parts) { - boost::fusion::tuple< - boost::optional &, - boost::optional &, - boost::optional &, - std::wstring & - > hier_part = - boost::fusion::tie( - parts.user_info, - parts.host, - parts.port, - parts.path - ); - - return boost::fusion::tie( - parts.scheme, - hier_part, - parts.query, - parts.fragment - ); -} - -static void post(boost::network::uri::detail::uri_parts_wide_base &, type const &) { } - -#if SPIRIT_VERSION >= 0x2030 -static void fail(boost::network::uri::detail::uri_parts_wide_base & val) { } -#endif -}; - -} // namespace traits -} // namespace spirit -} // namespace boost - - -namespace boost { namespace network { namespace uri { namespace detail { - -template -struct unsupported_string; - -template -struct choose_uri_base -{ - typedef unsupported_string type; -}; - -template -struct choose_uri_base -{ - typedef uri_parts_default_base type; -}; - -template -struct choose_uri_base -{ - typedef uri_parts_wide_base type; -}; - -namespace qi = boost::spirit::qi; - -template -struct uri_grammar_default : qi::grammar::type()> { - uri_grammar_default() : uri_grammar_default::base_type(start, "uri") { - // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" - gen_delims %= qi::char_(":/?#[]@"); - // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" - sub_delims %= qi::char_("!$&'()*+,;="); - // reserved = gen-delims / sub-delims - reserved %= gen_delims | sub_delims; - // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - unreserved %= qi::alnum | qi::char_("-._~"); - // pct-encoded = "%" HEXDIG HEXDIG - pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; - - // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - pchar %= qi::raw[ - unreserved | pct_encoded | sub_delims | qi::char_(":@") - ]; - - // segment = *pchar - segment %= qi::raw[*pchar]; - // segment-nz = 1*pchar - segment_nz %= qi::raw[+pchar]; - // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) - segment_nz_nc %= qi::raw[ - +(unreserved | pct_encoded | sub_delims | qi::char_("@")) - ]; - // path-abempty = *( "/" segment ) - path_abempty %= qi::raw[*(qi::char_("/") >> segment)]; - // path-absolute = "/" [ segment-nz *( "/" segment ) ] - path_absolute %= qi::raw[ - qi::char_("/") - >> -(segment_nz >> *(qi::char_("/") >> segment)) - ]; - // path-rootless = segment-nz *( "/" segment ) - path_rootless %= qi::raw[ - segment_nz >> *(qi::char_("/") >> segment) - ]; - // path-empty = 0 - path_empty %= qi::eps; - - // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) - scheme %= qi::alpha >> *(qi::alnum | qi::char_("+.-")); - - // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) - user_info %= qi::raw[ - *(unreserved | pct_encoded | sub_delims | qi::char_(":")) - ]; - - // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 - dec_octet %= - !(qi::lit('0') >> qi::digit) - >> qi::raw[ - qi::uint_parser() - ]; - // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet - ipv4address %= qi::raw[ - dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] - ]; - // reg-name = *( unreserved / pct-encoded / sub-delims ) - reg_name %= qi::raw[ - *(unreserved | pct_encoded | sub_delims) - ]; - // TODO, host = IP-literal / IPv4address / reg-name - host %= ipv4address | reg_name; - - // query = *( pchar / "/" / "?" ) - query %= qi::raw[*(pchar | qi::char_("/?"))]; - // fragment = *( pchar / "/" / "?" ) - fragment %= qi::raw[*(pchar | qi::char_("/?"))]; - - // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty - // authority = [ userinfo "@" ] host [ ":" port ] - hier_part %= - ( - "//" - >> -(user_info >> '@') - >> host - >> -(':' >> qi::ushort_) - >> path_abempty - ) - | - ( - qi::attr(optional()) - >> qi::attr(optional()) - >> qi::attr(optional()) - >> ( - path_absolute - | path_rootless - | path_empty - ) - ); - - uri %= - scheme >> ':' - >> hier_part - >> -('?' >> query) - >> -('#' >> fragment); - - start %= uri.alias(); - } - - typedef String string_type; - - qi::rule - gen_delims, sub_delims, reserved, unreserved; - qi::rule - pct_encoded, pchar; - - qi::rule - segment, segment_nz, segment_nz_nc; - qi::rule - path_abempty, path_absolute, path_rootless, path_empty; - - qi::rule - dec_octet, ipv4address, reg_name, host; - - qi::rule - scheme, user_info, query, fragment; - - qi::rule&, - optional&, - optional&, - string_type & - >()> hier_part; - - // start rule of grammar - qi::rule::type()> start; - - // actual uri parser - qi::rule< - Iterator, - boost::fusion::tuple< - string_type&, - boost::fusion::tuple< - optional&, - optional&, - optional&, - string_type & - >, - optional&, - optional& - >() - > uri; - -}; - -BOOST_NETWORK_INLINE bool parse_uri_impl(boost::iterator_range & range, uri_parts_default_base & parts, boost::network::tags::default_string) { - // Qualified boost::begin and boost::end because MSVC complains - // of ambiguity on call to begin(range) and end(range). - std::string::const_iterator start_ = boost::begin(range); - std::string::const_iterator end_ = boost::end(range); - - static uri_grammar_default grammar; - - bool ok = qi::parse(start_, end_, grammar, parts); - - return ok && start_ == end_; -} - -BOOST_NETWORK_INLINE bool parse_uri_impl(boost::iterator_range & range, uri_parts_wide_base & parts, boost::network::tags::default_wstring) { - // Qualified boost::begin and boost::end because MSVC complains - // of ambiguity on call to begin(range) and end(range). - std::wstring::const_iterator start_ = boost::begin(range); - std::wstring::const_iterator end_ = boost::end(range); - - static uri_grammar_default grammar; - - bool ok = qi::parse(start_, end_, grammar, parts); - - return ok && start_ == end_; -} - -} /* detail */ - -} /* uri */ - -} /* network */ - -} /* boost */ - -#endif /* PARSE_URI_IMPL_AQAWWXWT */ diff --git a/boost/network/uri/detail/parse_uri.hpp b/boost/network/uri/detail/parse_uri.hpp index 0c7cb9b70..2c92ace79 100644 --- a/boost/network/uri/detail/parse_uri.hpp +++ b/boost/network/uri/detail/parse_uri.hpp @@ -1,53 +1,238 @@ +// Copyright 2009, 2010, 2011 Dean Michael Berris, Jeroen Habraken, Glyn Matthews. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + #ifndef BOOST_NETWORK_URL_DETAIL_PARSE_URL_HPP_ -#define BOOST_NETWORK_URL_DETAIL_PARSE_URL_HPP_ +# define BOOST_NETWORK_URL_DETAIL_PARSE_URL_HPP_ + + +# ifdef BOOST_NETWORK_NO_LIB +# define BOOST_NETWORK_INLINE inline +# else +# define BOOST_NETWORK_INLINE +# endif // BOOST_NETWORK_NO_LIB -// Copyright 2009 Dean Michael Berris, Jeroen Habraken. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) #include -#include -#include -#ifdef BOOST_NETWORK_NO_LIB -#include -#endif +#include +#include +#include +#include +#include -namespace boost { namespace network { namespace uri { namespace detail { -template -inline bool parse_specific(uri_parts & parts) { - return true; -} +namespace boost { +namespace network { +namespace uri { +namespace detail { +namespace qi = boost::spirit::qi; + +template < + class String, + typename Iterator + > +struct uri_grammar : qi::grammar()> { + + uri_grammar() : uri_grammar::base_type(start, "uri") { + using boost::spirit::repository::qi::iter_pos; + + // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" + gen_delims %= qi::char_(":/?#[]@"); + // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + sub_delims %= qi::char_("!$&'()*+,;="); + // reserved = gen-delims / sub-delims + reserved %= gen_delims | sub_delims; + // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + unreserved %= qi::alnum | qi::char_("-._~"); + // pct-encoded = "%" HEXDIG HEXDIG + pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; + + // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + pchar %= qi::raw[ + unreserved | pct_encoded | sub_delims | qi::char_(":@") + ]; + + // segment = *pchar + segment %= qi::raw[*pchar]; + // segment-nz = 1*pchar + segment_nz %= qi::raw[+pchar]; + // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) + segment_nz_nc %= qi::raw[ + +(unreserved | pct_encoded | sub_delims | qi::char_("@")) + ]; + // path-abempty = *( "/" segment ) + path_abempty %= + iter_pos + >> qi::omit[qi::raw[*(qi::char_("/") >> segment)]] + >> iter_pos + ; + // path-absolute = "/" [ segment-nz *( "/" segment ) ] + path_absolute %= + iter_pos + >> qi::omit[qi::raw[ + qi::char_("/") + >> -(segment_nz >> *(qi::char_("/") >> segment)) + ]] + >> iter_pos + ; + // path-rootless = segment-nz *( "/" segment ) + path_rootless %= + iter_pos + >> qi::omit[qi::raw[ + segment_nz >> *(qi::char_("/") >> segment) + ]] + >> iter_pos + ; + // path-empty = 0 + path_empty %= + iter_pos + >> qi::omit[qi::eps] + >> iter_pos + ; + + // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + scheme %= + iter_pos + >> qi::omit[qi::alpha >> *(qi::alnum | qi::char_("+.-"))] + >> iter_pos + ; + + // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) + user_info %= + iter_pos + >> qi::omit[qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))]] + >> iter_pos + ; + + // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 + dec_octet %= + !(qi::lit('0') >> qi::digit) + >> qi::raw[ + qi::uint_parser() + ]; + // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet + ipv4address %= qi::raw[ + dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] + ]; + // reg-name = *( unreserved / pct-encoded / sub-delims ) + reg_name %= qi::raw[ + *(unreserved | pct_encoded | sub_delims) + ]; + // TODO, host = IP-literal / IPv4address / reg-name + host %= + iter_pos + >> qi::omit[ipv4address | reg_name] + >> iter_pos + ; -#ifndef BOOST_NETWORK_NO_LIB -extern bool parse_uri_impl(boost::iterator_range & range, uri_parts_default_base & parts, tags::default_string); -extern bool parse_uri_impl(boost::iterator_range & range, uri_parts_wide_base & parts, tags::default_wstring); -#endif - -template -struct unsupported_tag; - -template -inline bool parse_uri(Range & range, uri_parts & parts) { - typedef typename range_iterator::type iterator; - boost::iterator_range local_range = boost::make_iterator_range(range); - return parse_uri_impl(local_range, parts, - typename mpl::if_< - is_default_string, - tags::default_string, - typename mpl::if_< - is_default_wstring, - tags::default_wstring, - unsupported_tag - >::type - >::type()); + // port %= qi::ushort_; + port %= + iter_pos + >> qi::omit[*qi::digit] + >> iter_pos + ; + + // query = *( pchar / "/" / "?" ) + query %= + iter_pos + >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] + >> iter_pos + ; + // fragment = *( pchar / "/" / "?" ) + fragment %= + iter_pos + >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] + >> iter_pos + ; + + // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty + // authority = [ userinfo "@" ] host [ ":" port ] + hier_part %= + ( + "//" + >> -(user_info >> '@') + >> host + >> -(':' >> port) + >> path_abempty + ) + | + ( + qi::attr(iterator_range()) + >> qi::attr(iterator_range()) + >> qi::attr(iterator_range()) + >> ( + path_absolute + | path_rootless + | path_empty + ) + ) + ; + + start %= + scheme >> ':' + >> hier_part + >> -('?' >> query) + >> -('#' >> fragment) + ; + } + + qi::rule + gen_delims, sub_delims, reserved, unreserved; + qi::rule + pct_encoded, pchar; + + qi::rule + segment, segment_nz, segment_nz_nc; + qi::rule()> + path_abempty, path_absolute, path_rootless, path_empty; + + qi::rule + dec_octet, ipv4address, reg_name; + + qi::rule()> + host, port; + + qi::rule()> + scheme, user_info, query, fragment; + + qi::rule, + iterator_range, + iterator_range, + iterator_range >()> + hier_part; + + // actual uri parser + qi::rule()> start; + +}; + + +BOOST_NETWORK_INLINE +bool parse(std::string::const_iterator first, + std::string::const_iterator last, + uri_parts &parts) { + namespace qi = boost::spirit::qi; + static detail::uri_grammar grammar; + bool is_valid = qi::parse(first, last, grammar, parts); + return is_valid && (first == last); } +BOOST_NETWORK_INLINE +bool parse(std::wstring::const_iterator first, + std::wstring::const_iterator last, + uri_parts &parts) { + namespace qi = boost::spirit::qi; + static uri_grammar grammar; + bool is_valid = qi::parse(first, last, grammar, parts); + return is_valid && (first == last); +} } // namespace detail } // namespace uri } // namespace network } // namespace boost -#endif + +#endif // BOOST_NETWORK_URL_DETAIL_PARSE_URL_HPP_ diff --git a/boost/network/uri/detail/uri_parts.hpp b/boost/network/uri/detail/uri_parts.hpp index 3bf238acf..a2647e1ec 100644 --- a/boost/network/uri/detail/uri_parts.hpp +++ b/boost/network/uri/detail/uri_parts.hpp @@ -1,169 +1,51 @@ -#ifndef BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ -#define BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ - -// Copyright 2009 Dean Michael Berris, Jeroen Habraken. +// Copyright 2009, 2010, 2011 Dean Michael Berris, Jeroen Habraken, Glyn Matthews. // Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt of copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) -#include -#include - -namespace boost { namespace network { namespace uri { - -namespace detail { - - struct uri_parts_default_base { - typedef std::string string_type; - string_type scheme; - optional user_info; - optional host; - optional port; - string_type path; - optional query; - optional fragment; - - uri_parts_default_base(uri_parts_default_base const & other) - : scheme(other.scheme) - , user_info(other.user_info) - , host(other.host) - , port(other.port) - , path(other.path) - , query(other.query) - , fragment(other.fragment) - {} - - uri_parts_default_base() - {} - - uri_parts_default_base & operator=(uri_parts_default_base rhs) - { - rhs.swap(*this); - return *this; - } - - void swap(uri_parts_default_base & rhs) - { - std::swap(scheme, rhs.scheme); - std::swap(user_info, rhs.user_info); - std::swap(host, rhs.host); - std::swap(port, rhs.port); - std::swap(path, rhs.path); - std::swap(query, rhs.query); - std::swap(fragment, rhs.fragment); - } - }; - - struct uri_parts_wide_base { - typedef std::wstring string_type; - string_type scheme; - optional user_info; - optional host; - optional port; - string_type path; - optional query; - optional fragment; - - uri_parts_wide_base(uri_parts_wide_base const & other) - : scheme(other.scheme) - , user_info(other.user_info) - , host(other.host) - , port(other.port) - , path(other.path) - , query(other.query) - , fragment(other.fragment) - {} - - uri_parts_wide_base() - {} - - uri_parts_wide_base & operator=(uri_parts_wide_base rhs) - { - rhs.swap(*this); - return *this; - } - - void swap(uri_parts_wide_base & rhs) - { - std::swap(this->scheme, rhs.scheme); - std::swap(this->user_info, rhs.user_info); - std::swap(this->host, rhs.host); - std::swap(this->port, rhs.port); - std::swap(this->path, rhs.path); - std::swap(this->query, rhs.query); - std::swap(this->fragment, rhs.fragment); - } - }; - -template -struct uri_parts : - mpl::if_< - is_default_string - , uri_parts_default_base - , uri_parts_wide_base - >::type -{ - typedef typename mpl::if_< - is_default_string - , uri_parts_default_base - , uri_parts_wide_base - >::type base_type; - uri_parts() : base_type() {} - uri_parts(uri_parts const & other) - : base_type(other) - {} - uri_parts & operator=(uri_parts rhs) - { - swap(*this, rhs); - return *this; - } -}; - -template -inline void swap(uri_parts & l, uri_parts & r) { - using std::swap; +#ifndef BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ +# define BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ - swap(l.scheme, r.scheme); - swap(l.user_info, r.user_info); - swap(l.host, r.host); - swap(l.port, r.port); - swap(l.path, r.path); - swap(l.query, r.query); - swap(l.fragment, r.fragment); -} -template -inline -bool operator==(uri_parts const & l, uri_parts const & r) { - return (l.scheme == r.scheme) && - (l.user_info == r.user_info) && - (l.host == r.host) && - (l.port == r.port) && - (l.path == r.path) && - (l.query == r.query) && - (l.fragment == r.fragment); -} +# include +# include -template -inline -bool operator!=(uri_parts const & l, uri_parts const & r) { - return (l.scheme != r.scheme) && - (l.user_info != r.user_info) && - (l.host != r.host) && - (l.port != r.port) && - (l.path != r.path) && - (l.query != r.query) && - (l.fragment != r.fragment); -} +namespace boost { +namespace network { +namespace uri { +namespace detail { +template < + class String + > +struct iterator_range + : boost::fusion::vector< + typename String::const_iterator + , typename String::const_iterator + > +{ }; + + +template < + class String + > +struct uri_parts + : boost::fusion::vector< + iterator_range // scheme + , boost::fusion::vector< + iterator_range // user_info + , iterator_range // host + , iterator_range // port + , iterator_range // path + > + , iterator_range // query + , iterator_range // fragment + > +{ }; } // namespace detail } // namespace uri } // namespace network } // namespace boost -#endif +#endif // BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ diff --git a/boost/network/uri/http/uri.hpp b/boost/network/uri/http/uri.hpp new file mode 100644 index 000000000..ea7ccb38f --- /dev/null +++ b/boost/network/uri/http/uri.hpp @@ -0,0 +1,72 @@ +#ifndef __BOOST_NETWORK_URI_HTTP_URI_INC__ +# define __BOOST_NETWORK_URI_HTTP_URI_INC__ + + +# include + + +namespace boost { +namespace network { +namespace uri { +namespace http { +template < + class Tag + > +class basic_uri + : public boost::network::uri::basic_uri { + + typedef boost::network::uri::basic_uri base_type; + +public: + + basic_uri() { + + } + + basic_uri(const typename base_type::string_type &uri) : base_type(uri) { + + } + + basic_uri &operator = (const typename base_type::string_type &uri) { + basic_uri(uri).swap(*this); + return *this; + } + +}; + + +template < + class Tag + > +inline +typename basic_uri::string_type port(const basic_uri &uri) { + typedef typename basic_uri::range_type range_type; + typedef typename basic_uri::string_type string_type; + + static const char default_http_port[] = "80"; + static const char default_https_port[] = "443"; + + range_type port = uri.port_range(); + string_type scheme = uri.scheme(); + + if (boost::empty(port)) { + if (scheme == "http") { + return string_type(boost::begin(default_http_port), + boost::end(default_http_port)); + } + else if (scheme == "https") { + return string_type(boost::begin(default_https_port), + boost::end(default_https_port)); + } + } + return string_type(boost::begin(port), boost::end(port)); +} + +typedef basic_uri uri; +} // namespace http +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_HTTP_URI_INC__ diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 32a73b75d..141672102 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -10,45 +10,31 @@ # include # include +# include +# include +# include +# include # include # include -# include -# include +# include +# include +# include # include namespace boost { namespace network { namespace uri { -namespace details { -template < - class Tag - > -struct iterator_range - : boost::fusion::vector< - typename string::type::const_iterator - , typename string::type::const_iterator - > -{ }; +namespace detail { +bool parse(std::string::const_iterator first, + std::string::const_iterator last, + uri_parts &parts); +bool parse(std::wstring::const_iterator first, + std::wstring::const_iterator last, + uri_parts &parts); +} // namespace detail -template < - class Tag - > -struct uri_parts - : boost::fusion::vector< - iterator_range - , boost::fusion::vector< - iterator_range - , iterator_range - , iterator_range - , iterator_range - > - , iterator_range - , iterator_range - > -{ }; -} // namespace details template < class Tag @@ -68,7 +54,7 @@ class basic_uri } - explicit basic_uri(const string_type &uri) + basic_uri(const string_type &uri) : uri_(uri), is_valid_(false) { parse(); } @@ -85,6 +71,11 @@ class basic_uri return *this; } + basic_uri &operator = (const string_type &uri) { + basic_uri(uri).swap(*this); + return *this; + } + ~basic_uri() { } @@ -104,10 +95,10 @@ class basic_uri const_range_type user_info_range() const { using boost::fusion::at_c; const boost::fusion::vector< - details::iterator_range - , details::iterator_range - , details::iterator_range - , details::iterator_range > &hier_part = at_c<1>(uri_parts_); + detail::iterator_range::type> + , detail::iterator_range::type> + , detail::iterator_range::type> + , detail::iterator_range::type> > &hier_part = at_c<1>(uri_parts_); return const_range_type(at_c<0>(at_c<0>(hier_part)), at_c<1>(at_c<0>(hier_part))); @@ -116,10 +107,10 @@ class basic_uri const_range_type host_range() const { using boost::fusion::at_c; const boost::fusion::vector< - details::iterator_range - , details::iterator_range - , details::iterator_range - , details::iterator_range > &hier_part = at_c<1>(uri_parts_); + detail::iterator_range::type> + , detail::iterator_range::type> + , detail::iterator_range::type> + , detail::iterator_range::type> > &hier_part = at_c<1>(uri_parts_); return const_range_type(at_c<0>(at_c<1>(hier_part)), at_c<1>(at_c<1>(hier_part))); @@ -128,10 +119,10 @@ class basic_uri const_range_type port_range() const { using boost::fusion::at_c; const boost::fusion::vector< - details::iterator_range - , details::iterator_range - , details::iterator_range - , details::iterator_range > &hier_part = at_c<1>(uri_parts_); + detail::iterator_range::type> + , detail::iterator_range::type> + , detail::iterator_range::type> + , detail::iterator_range::type> > &hier_part = at_c<1>(uri_parts_); return const_range_type(at_c<0>(at_c<2>(hier_part)), at_c<1>(at_c<2>(hier_part))); @@ -140,10 +131,10 @@ class basic_uri const_range_type path_range() const { using boost::fusion::at_c; const boost::fusion::vector< - details::iterator_range - , details::iterator_range - , details::iterator_range - , details::iterator_range > &hier_part = at_c<1>(uri_parts_); + detail::iterator_range::type> + , detail::iterator_range::type> + , detail::iterator_range::type> + , detail::iterator_range::type> > &hier_part = at_c<1>(uri_parts_); return const_range_type(at_c<0>(at_c<3>(hier_part)), at_c<1>(at_c<3>(hier_part))); @@ -209,222 +200,20 @@ class basic_uri void parse(); string_type uri_; - details::uri_parts uri_parts_; + detail::uri_parts::type> uri_parts_; bool is_valid_; }; -} // namespace uri -} // namespace network -} // namespace boost - - -# include -# include -# include -# include -# include - - -namespace boost { -namespace network { -namespace uri { -namespace details { -namespace qi = boost::spirit::qi; - -template < - class Tag, - typename Iterator - > -struct uri_grammar : qi::grammar()> { - - uri_grammar() : uri_grammar::base_type(start, "uri") { - using boost::spirit::repository::qi::iter_pos; - - // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" - gen_delims %= qi::char_(":/?#[]@"); - // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" - sub_delims %= qi::char_("!$&'()*+,;="); - // reserved = gen-delims / sub-delims - reserved %= gen_delims | sub_delims; - // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - unreserved %= qi::alnum | qi::char_("-._~"); - // pct-encoded = "%" HEXDIG HEXDIG - pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; - - // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - pchar %= qi::raw[ - unreserved | pct_encoded | sub_delims | qi::char_(":@") - ]; - - // segment = *pchar - segment %= qi::raw[*pchar]; - // segment-nz = 1*pchar - segment_nz %= qi::raw[+pchar]; - // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) - segment_nz_nc %= qi::raw[ - +(unreserved | pct_encoded | sub_delims | qi::char_("@")) - ]; - // path-abempty = *( "/" segment ) - path_abempty %= - iter_pos - >> qi::omit[qi::raw[*(qi::char_("/") >> segment)]] - >> iter_pos - ; - // path-absolute = "/" [ segment-nz *( "/" segment ) ] - path_absolute %= - iter_pos - >> qi::omit[qi::raw[ - qi::char_("/") - >> -(segment_nz >> *(qi::char_("/") >> segment)) - ]] - >> iter_pos - ; - // path-rootless = segment-nz *( "/" segment ) - path_rootless %= - iter_pos - >> qi::omit[qi::raw[ - segment_nz >> *(qi::char_("/") >> segment) - ]] - >> iter_pos - ; - // path-empty = 0 - path_empty %= - iter_pos - >> qi::omit[qi::eps] - >> iter_pos - ; - - // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) - scheme %= - iter_pos - >> qi::omit[qi::alpha >> *(qi::alnum | qi::char_("+.-"))] - >> iter_pos - ; - - // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) - user_info %= - iter_pos - >> qi::omit[qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))]] - >> iter_pos - ; - - // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 - dec_octet %= - !(qi::lit('0') >> qi::digit) - >> qi::raw[ - qi::uint_parser() - ]; - // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet - ipv4address %= qi::raw[ - dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] - ]; - // reg-name = *( unreserved / pct-encoded / sub-delims ) - reg_name %= qi::raw[ - *(unreserved | pct_encoded | sub_delims) - ]; - // TODO, host = IP-literal / IPv4address / reg-name - host %= - iter_pos - >> qi::omit[ipv4address | reg_name] - >> iter_pos - ; - - // port %= qi::ushort_; - port %= - iter_pos - >> qi::omit[*qi::digit] - >> iter_pos - ; - - // query = *( pchar / "/" / "?" ) - query %= - iter_pos - >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] - >> iter_pos - ; - // fragment = *( pchar / "/" / "?" ) - fragment %= - iter_pos - >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] - >> iter_pos - ; - - // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty - // authority = [ userinfo "@" ] host [ ":" port ] - hier_part %= - ( - "//" - >> -(user_info >> '@') - >> host - >> -(':' >> port) - >> path_abempty - ) - | - ( - qi::attr(iterator_range()) - >> qi::attr(iterator_range()) - >> qi::attr(iterator_range()) - >> ( - path_absolute - | path_rootless - | path_empty - ) - ) - ; - - start %= - scheme >> ':' - >> hier_part - >> -('?' >> query) - >> -('#' >> fragment) - ; - } - - qi::rule::type::value_type()> - gen_delims, sub_delims, reserved, unreserved; - //qi::rule()> - qi::rule::type()> - pct_encoded, pchar; - - qi::rule::type()> - segment, segment_nz, segment_nz_nc; - qi::rule()> - path_abempty, path_absolute, path_rootless, path_empty; - - qi::rule::type()> - dec_octet, ipv4address, reg_name; - - qi::rule()> - host, port; - - qi::rule()> - scheme, user_info, query, fragment; - - qi::rule, - iterator_range, - iterator_range, - iterator_range >()> - hier_part; - - // actual uri parser - qi::rule()> start; - -}; -} // namespace details template < class Tag > void basic_uri::parse() { - namespace qi = boost::spirit::qi; - static details::uri_grammar grammar; const_iterator_type first(boost::begin(uri_)), last(boost::end(uri_)); - is_valid_ = qi::parse(first, last, grammar, uri_parts_); - is_valid_ = is_valid_ && (first == last); + is_valid_ = detail::parse(first, last, uri_parts_); } - template < class Tag > @@ -465,6 +254,42 @@ typename basic_uri::string_type port(const basic_uri &uri) { return uri.port(); } +template < + class Tag + > +struct port_wrapper { + const basic_uri &uri; + + port_wrapper(const basic_uri &uri) : uri(uri) { + + } + + operator boost::optional () const { + typename basic_uri::string_type port = uri.port(); + return (port.empty())? + boost::optional() : + boost::optional(boost::lexical_cast(port)); + } + + operator unsigned short () const { + const boost::optional &port = + static_cast >(*this); + typedef typename string::type string_type; + typedef constants consts; + if (port) return *port; + return boost::iequals(uri.scheme_range(), string_type(consts::https())) ? 443 : 80; + } +}; + + +template < + class Tag + > +inline +port_wrapper port_us(const basic_uri &uri) { + return port_wrapper(uri); +} + template < class Tag > diff --git a/libs/network/example/uri.cpp b/libs/network/example/uri.cpp index b89cc6b60..e4f798321 100644 --- a/libs/network/example/uri.cpp +++ b/libs/network/example/uri.cpp @@ -24,7 +24,7 @@ int main(int argc, char * argv[]) { boost::network::uri::uri uri_(input); /*<< Check if it's a valid URI. >>*/ std::cout << "You've entered " - << (boost::network::uri::valid(uri_)? + << (boost::network::uri::is_valid(uri_)? std::string("a valid") : std::string("an invalid")) << " URI!" << std::endl; @@ -32,7 +32,7 @@ int main(int argc, char * argv[]) { boost::network::uri::http::uri http_uri_(input); /*<< Check if it's a valid HTTP URI. >>*/ std::cout << "It's also " - << (boost::network::uri::valid(http_uri_)? + << (boost::network::uri::is_valid(http_uri_)? std::string("a valid HTTP URI") : std::string("an invalid HTTP URI.")) << "!" << std::endl; diff --git a/libs/network/src/CMakeLists.txt b/libs/network/src/CMakeLists.txt new file mode 100644 index 000000000..dae683daf --- /dev/null +++ b/libs/network/src/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (c) Glyn Matthews 2011. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + + +# boost_network_uri +include_directories(${CPP-NETLIB_SOURCE_DIR}) +set(CPP-NETLIB_URI_SRCS uri/parse.cpp) +add_library(cppnetlib-uri-parsers ${CPP-NETLIB_URI_SRCS}) + +set(CPP-NETLIB_HTTP_SERVER_SRCS server_request_parsers_impl.cpp) +add_library(cppnetlib-server-parsers ${CPP-NETLIB_HTTP_SERVER_SRCS}) diff --git a/libs/network/src/uri/parse.cpp b/libs/network/src/uri/parse.cpp new file mode 100644 index 000000000..4aadb2628 --- /dev/null +++ b/libs/network/src/uri/parse.cpp @@ -0,0 +1,12 @@ +// Copyright 2009, 2010, 2011 Dean Michael Berris, Jeroen Habraken, Glyn Matthews. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifdef BOOST_NETWORK_NO_LIB +# undef BOOST_NETWORK_NO_LIB +#endif // BOOST_NETWORK_NO_LIB + + +#include diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index ea7efaba2..8a94a28d2 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -24,9 +24,11 @@ if (Boost_FOUND) set_source_files_properties(${test}.cpp PROPERTIES COMPILE_FLAGS "-Wall") add_executable(cpp-netlib-${test} ${test}.cpp) + add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) + # add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) # target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) endif() diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 408c58abf..018993729 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright 2010 Dean Michael Berris. +# Copyright 2010 Dean Michael Berris. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) @@ -81,11 +81,11 @@ if (Boost_FOUND) add_dependencies(cpp-netlib-http-${test} cppnetlib-server-parsers) target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) set_target_properties(cpp-netlib-http-${test} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) - add_test(cpp-netlib-${test} - python - ${CPP-NETLIB_SOURCE_DIR}/libs/network/test/httplib_acceptance.py + add_test(cpp-netlib-${test} + python + ${CPP-NETLIB_SOURCE_DIR}/libs/network/test/httplib_acceptance.py ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test} ${PORT} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}.passed) From a47e86416b2116981961989ee02c25f43b11a949 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 6 Aug 2011 09:30:26 +0200 Subject: [PATCH 136/768] Removing the include for parse_uri.hpp reduces the compile time dramatically. --- boost/network/uri/uri.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 141672102..600b64a33 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -12,7 +12,6 @@ # include # include # include -# include # include # include # include From 2c2cf86651ca3acdb91f20709d2323136d8f2927 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 6 Aug 2011 09:49:57 +0200 Subject: [PATCH 137/768] Updated test for port as an unsigned short. --- boost/network/uri/uri.hpp | 9 ++++++--- libs/network/test/url_test.cpp | 3 +-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 600b64a33..af02530b9 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -263,18 +263,21 @@ struct port_wrapper { } - operator boost::optional () const { + boost::optional to_optional() const { typename basic_uri::string_type port = uri.port(); return (port.empty())? boost::optional() : boost::optional(boost::lexical_cast(port)); } + operator boost::optional () const { + return to_optional(); + } + operator unsigned short () const { - const boost::optional &port = - static_cast >(*this); typedef typename string::type string_type; typedef constants consts; + const boost::optional &port = to_optional(); if (port) return *port; return boost::iequals(uri.scheme_range(), string_type(consts::https())) ? 443 : 80; } diff --git a/libs/network/test/url_test.cpp b/libs/network/test/url_test.cpp index d97a21f9b..6ec4f882f 100644 --- a/libs/network/test/url_test.cpp +++ b/libs/network/test/url_test.cpp @@ -56,7 +56,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); BOOST_CHECK(boost::equal(uri::host(instance), host)); - // BOOST_CHECK_EQUAL(uri::port(instance), port); + BOOST_CHECK_EQUAL(static_cast(uri::port_us(instance)), 8000); BOOST_CHECK(boost::equal(uri::port(instance), port)); BOOST_CHECK(boost::equal(uri::path(instance), path)); BOOST_CHECK(boost::equal(uri::query(instance), query)); @@ -214,7 +214,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, tag_types) { uri_type instance(string_type(boost::begin(url), boost::end(url))); uri_type copy; copy = instance; - // BOOST_CHECK(instance.raw() == copy.raw()); BOOST_CHECK(instance.to_string() == copy.to_string()); BOOST_CHECK(instance == copy); } From a411abd187ef156bfceec43f08880d962a8a7f16 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 6 Aug 2011 10:57:06 +0200 Subject: [PATCH 138/768] Updated some of the URI tests. Added begin/end accessors to make the URI a valid forward range. --- boost/network/uri/uri.hpp | 19 ++++ libs/network/test/CMakeLists.txt | 2 +- libs/network/test/http/url_test.cpp | 89 ------------------- libs/network/test/mailto_url_test.cpp | 13 --- libs/network/test/uri/CMakeLists.txt | 34 ++++++++ libs/network/test/uri/url_http_test.cpp | 106 +++++++++++++++++++++++ libs/network/test/{ => uri}/url_test.cpp | 4 +- 7 files changed, 161 insertions(+), 106 deletions(-) delete mode 100644 libs/network/test/http/url_test.cpp delete mode 100644 libs/network/test/mailto_url_test.cpp create mode 100644 libs/network/test/uri/CMakeLists.txt create mode 100644 libs/network/test/uri/url_http_test.cpp rename libs/network/test/{ => uri}/url_test.cpp (98%) diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index af02530b9..37a88ca21 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -12,6 +12,9 @@ # include # include # include +# ifdef BOOST_NETWORK_NO_LIB +# include +# endif // #ifdef BOOST_NETWORK_NO_LIB # include # include # include @@ -85,6 +88,22 @@ class basic_uri boost::swap(is_valid_, other.is_valid_); } + iterator_type begin() { + return uri_.begin(); + } + + const_iterator_type begin() const { + return uri_.begin(); + } + + iterator_type end() { + return uri_.end(); + } + + const_iterator_type end() const { + return uri_.end(); + } + const_range_type scheme_range() const { using boost::fusion::at_c; return const_range_type(at_c<0>(at_c<0>(uri_parts_)), diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index 8a94a28d2..190affb4a 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -10,6 +10,7 @@ find_package( Threads ) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) +add_subdirectory(uri) add_subdirectory(http) if (Boost_FOUND) @@ -17,7 +18,6 @@ if (Boost_FOUND) TESTS message_test message_transform_test - url_test utils_thread_pool ) foreach (test ${TESTS}) diff --git a/libs/network/test/http/url_test.cpp b/libs/network/test/http/url_test.cpp deleted file mode 100644 index 20714fd78..000000000 --- a/libs/network/test/http/url_test.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) Glyn Matthews 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#define BOOST_TEST_MODULE HTTP URL Test -#include -#include -#include -#include -#include - -using namespace boost::network; - -BOOST_AUTO_TEST_CASE(http_url_test) { - typedef uri::basic_uri uri_type; - typedef uri_type::string_type string_type; - - const std::string url("http://www.boost.org/"); - const std::string scheme("http"); - const std::string host("www.boost.org"); - const std::string path("/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); - boost::optional host_ = uri::host(instance); - boost::optional port_ = uri::port(instance); - - BOOST_REQUIRE(uri::is_valid(instance)); - BOOST_CHECK_EQUAL(instance.raw(), url); - BOOST_CHECK( !port_ ); - string_type scheme_ = uri::scheme(instance); - BOOST_CHECK_EQUAL(scheme_, scheme); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); -} - -BOOST_AUTO_TEST_CASE(full_http_url_test) { - typedef uri::basic_uri uri_type; - typedef uri_type::string_type string_type; - - const std::string url("http://user:password@www.boost.org:8000/path?query#fragment"); - const std::string scheme("http"); - const std::string user_info("user:password"); - const std::string host("www.boost.org"); - const boost::uint16_t port = 8000; - const std::string path("/path"); - const std::string query("query"); - const std::string fragment("fragment"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK_EQUAL(uri::port(instance), port); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::query(instance), query)); - BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); -} - -BOOST_AUTO_TEST_CASE(https_url_test) { - typedef uri::basic_uri uri_type; - typedef uri_type::string_type string_type; - - const std::string url("https://www.boost.org/"); - const std::string scheme("https"); - const std::string host("www.boost.org"); - const boost::uint16_t port = 443; - const std::string path("/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK_EQUAL(uri::port(instance), port); - BOOST_CHECK(boost::equal(uri::path(instance), path)); -} - -//BOOST_AUTO_TEST_CASE(invalid_http_url_test) { -// typedef uri::basic_uri uri_type; -// typedef uri_type::string_type string_type; - -// const std::string url("/service/ftp://www.boost.org/"); - -// uri_type instance(string_type(boost::begin(url), boost::end(url))); -// BOOST_CHECK(!uri::is_valid(instance)); -//} diff --git a/libs/network/test/mailto_url_test.cpp b/libs/network/test/mailto_url_test.cpp deleted file mode 100644 index 2be437839..000000000 --- a/libs/network/test/mailto_url_test.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Glyn Matthews 2010. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - - -#define BOOST_TEST_MODULE HTTP URL Test -#include -#include -#include -#include -#include diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt new file mode 100644 index 000000000..4a610d4cb --- /dev/null +++ b/libs/network/test/uri/CMakeLists.txt @@ -0,0 +1,34 @@ +# Copyright (c) Dean Michael Berris 2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +include_directories(${CPP-NETLIB_SOURCE_DIR}) +find_package( Boost 1.41.0 COMPONENTS unit_test_framework system regex date_time filesystem ) +find_package( OpenSSL ) +find_package( Threads ) +set(Boost_USE_STATIC_LIBS ON) +set(Boost_USE_MULTITHREADED ON) + + +if (Boost_FOUND) + set( + TESTS + url_test + url_http_test + ) + foreach (test ${TESTS}) + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") + add_executable(cpp-netlib-${test} ${test}.cpp) + add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) + target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + if (OPENSSL_FOUND) + target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) + endif() + set_target_properties(cpp-netlib-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) + endforeach (test) + +endif() diff --git a/libs/network/test/uri/url_http_test.cpp b/libs/network/test/uri/url_http_test.cpp new file mode 100644 index 000000000..6cc8cac94 --- /dev/null +++ b/libs/network/test/uri/url_http_test.cpp @@ -0,0 +1,106 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + + +#define BOOST_TEST_MODULE HTTP URL Test +#include +#include +#include +#include +#include + +using namespace boost::network; + +typedef boost::mpl::list< + tags::default_string + , tags::default_wstring + > tag_types; + + +BOOST_AUTO_TEST_CASE_TEMPLATE(not_http, T, tag_types) +{ + typedef uri::http::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + const std::string url("/service/mailto:john.doe@example.com"); + uri_type instance(string_type(boost::begin(url), boost::end(url))); + std::copy(instance.begin(), instance.end(), + std::ostream_iterator(std::cout)); + std::cout << std::endl; + //BOOST_CHECK(!uri::is_valid(instance)); +} + +// BOOST_AUTO_TEST_CASE(http_url_test) { +// typedef uri::basic_uri uri_type; +// typedef uri_type::string_type string_type; +// +// const std::string url("http://www.boost.org/"); +// const std::string scheme("http"); +// const std::string host("www.boost.org"); +// const std::string path("/"); +// +// uri_type instance(string_type(boost::begin(url), boost::end(url))); +// boost::optional host_ = uri::host(instance); +// boost::optional port_ = uri::port(instance); +// +// BOOST_REQUIRE(uri::is_valid(instance)); +// BOOST_CHECK_EQUAL(instance.raw(), url); +// BOOST_CHECK( !port_ ); +// string_type scheme_ = uri::scheme(instance); +// BOOST_CHECK_EQUAL(scheme_, scheme); +// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); +// BOOST_CHECK(boost::equal(uri::host(instance), host)); +// BOOST_CHECK(boost::equal(uri::path(instance), path)); +// } +// +// BOOST_AUTO_TEST_CASE(full_http_url_test) { +// typedef uri::basic_uri uri_type; +// typedef uri_type::string_type string_type; +// +// const std::string url("http://user:password@www.boost.org:8000/path?query#fragment"); +// const std::string scheme("http"); +// const std::string user_info("user:password"); +// const std::string host("www.boost.org"); +// const boost::uint16_t port = 8000; +// const std::string path("/path"); +// const std::string query("query"); +// const std::string fragment("fragment"); +// +// uri_type instance(string_type(boost::begin(url), boost::end(url))); +// BOOST_REQUIRE(uri::is_valid(instance)); +// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); +// BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); +// BOOST_CHECK(boost::equal(uri::host(instance), host)); +// BOOST_CHECK_EQUAL(uri::port(instance), port); +// BOOST_CHECK(boost::equal(uri::path(instance), path)); +// BOOST_CHECK(boost::equal(uri::query(instance), query)); +// BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); +// } +// +// BOOST_AUTO_TEST_CASE(https_url_test) { +// typedef uri::basic_uri uri_type; +// typedef uri_type::string_type string_type; +// +// const std::string url("https://www.boost.org/"); +// const std::string scheme("https"); +// const std::string host("www.boost.org"); +// const boost::uint16_t port = 443; +// const std::string path("/"); +// +// uri_type instance(string_type(boost::begin(url), boost::end(url))); +// BOOST_REQUIRE(uri::is_valid(instance)); +// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); +// BOOST_CHECK(boost::equal(uri::host(instance), host)); +// BOOST_CHECK_EQUAL(uri::port(instance), port); +// BOOST_CHECK(boost::equal(uri::path(instance), path)); +// } +// +//BOOST_AUTO_TEST_CASE(invalid_http_url_test) { +// typedef uri::basic_uri uri_type; +// typedef uri_type::string_type string_type; +// const std::string url("/service/ftp://www.boost.org/"); +// uri_type instance(string_type(boost::begin(url), boost::end(url))); +// BOOST_CHECK(!uri::is_valid(instance)); +//} diff --git a/libs/network/test/url_test.cpp b/libs/network/test/uri/url_test.cpp similarity index 98% rename from libs/network/test/url_test.cpp rename to libs/network/test/uri/url_test.cpp index 6ec4f882f..fa28c4404 100644 --- a/libs/network/test/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -1,6 +1,4 @@ - -// Copyright 2009 Dean Michael Berris, Jeroen Habraken. -// Copyright 2010 Glyn Matthews. +// Copyright 2009, 2010, 2011 Dean Michael Berris, Jeroen Habraken, Glyn Matthews. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt of copy at // http://www.boost.org/LICENSE_1_0.txt) From add64a9e0ac28eb5649a9c7e8c0966a23ba6b8ba Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 7 Aug 2011 08:36:57 +0200 Subject: [PATCH 139/768] The URI is parsed in the swap function now in order to update the internal ranges. --- boost/network/uri/uri.hpp | 3 +-- libs/network/test/uri/url_http_test.cpp | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 37a88ca21..2f3bf80d7 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -84,8 +84,7 @@ class basic_uri void swap(basic_uri &other) { boost::swap(uri_, other.uri_); - boost::swap(uri_parts_, other.uri_parts_); - boost::swap(is_valid_, other.is_valid_); + parse(); } iterator_type begin() { diff --git a/libs/network/test/uri/url_http_test.cpp b/libs/network/test/uri/url_http_test.cpp index 6cc8cac94..a458e9d72 100644 --- a/libs/network/test/uri/url_http_test.cpp +++ b/libs/network/test/uri/url_http_test.cpp @@ -26,9 +26,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(not_http, T, tag_types) typedef typename uri_type::string_type string_type; const std::string url("/service/mailto:john.doe@example.com"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - std::copy(instance.begin(), instance.end(), - std::ostream_iterator(std::cout)); - std::cout << std::endl; //BOOST_CHECK(!uri::is_valid(instance)); } From 5bc6c29b02a9ca1b4df791cdac8dd73e24dbd853 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Tue, 16 Aug 2011 18:54:36 +0200 Subject: [PATCH 140/768] Updated some tests and examples that use the HTTP URI. Conflicts: libs/network/test/xmpp/xmpp_client_tests.cpp --- boost/network/protocol/http/impl/request.hpp | 6 +- boost/network/uri.hpp | 11 +- boost/network/uri/detail/parse_uri.hpp | 4 + boost/network/uri/http/uri.hpp | 33 +++++- boost/network/uri/uri.hpp | 10 ++ libs/network/example/simple_wget.cpp | 2 +- libs/network/example/uri.cpp | 1 - libs/network/test/uri/url_http_test.cpp | 108 ++++++------------- libs/network/test/uri/url_test.cpp | 56 ++++++---- 9 files changed, 119 insertions(+), 112 deletions(-) diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index e54ba1cb7..ca5a2c26a 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include @@ -50,7 +50,7 @@ namespace http { struct basic_request : public basic_message { - mutable boost::network::uri::http::uri uri_; + mutable boost::network::uri::http::basic_uri uri_; typedef basic_message base_type; public: @@ -115,7 +115,7 @@ namespace http { uri_ = new_uri; } - boost::network::uri::http::uri const uri() const { + boost::network::uri::http::basic_uri const & uri() const { return uri_; } diff --git a/boost/network/uri.hpp b/boost/network/uri.hpp index 741ac48e5..7472e8cbc 100644 --- a/boost/network/uri.hpp +++ b/boost/network/uri.hpp @@ -8,6 +8,7 @@ #include #include +#include #include @@ -15,11 +16,11 @@ namespace boost { namespace network { namespace uri { typedef basic_uri uri; typedef basic_uri wuri; -// -// namespace http { -// typedef basic_uri uri; -// } -// + +namespace http { +typedef basic_uri uri; +} + } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/detail/parse_uri.hpp b/boost/network/uri/detail/parse_uri.hpp index 2c92ace79..dc9e1cb96 100644 --- a/boost/network/uri/detail/parse_uri.hpp +++ b/boost/network/uri/detail/parse_uri.hpp @@ -112,14 +112,17 @@ struct uri_grammar : qi::grammar()> { >> qi::raw[ qi::uint_parser() ]; + // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet ipv4address %= qi::raw[ dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] ]; + // reg-name = *( unreserved / pct-encoded / sub-delims ) reg_name %= qi::raw[ *(unreserved | pct_encoded | sub_delims) ]; + // TODO, host = IP-literal / IPv4address / reg-name host %= iter_pos @@ -140,6 +143,7 @@ struct uri_grammar : qi::grammar()> { >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] >> iter_pos ; + // fragment = *( pchar / "/" / "?" ) fragment %= iter_pos diff --git a/boost/network/uri/http/uri.hpp b/boost/network/uri/http/uri.hpp index ea7ccb38f..d4c859031 100644 --- a/boost/network/uri/http/uri.hpp +++ b/boost/network/uri/http/uri.hpp @@ -33,28 +33,52 @@ class basic_uri } }; +} // namespace http +template < + class Tag + > +bool is_http(const http::basic_uri &uri) { + static const char scheme_http[] = {'h', 't', 't', 'p'}; + return boost::equal(uri.scheme_range(), scheme_http); +} + +template < + class Tag + > +bool is_https(const http::basic_uri &uri) { + static const char scheme_https[] = {'h', 't', 't', 'p', 's'}; + return boost::equal(uri.scheme_range(), scheme_https); +} + +template < + class Tag + > +inline +bool is_valid(const http::basic_uri &uri) { + return is_http(uri) || is_https(uri); +} template < class Tag > inline -typename basic_uri::string_type port(const basic_uri &uri) { +typename basic_uri::string_type port(const http::basic_uri &uri) { typedef typename basic_uri::range_type range_type; typedef typename basic_uri::string_type string_type; static const char default_http_port[] = "80"; static const char default_https_port[] = "443"; + range_type scheme = uri.scheme_range(); range_type port = uri.port_range(); - string_type scheme = uri.scheme(); if (boost::empty(port)) { - if (scheme == "http") { + if (is_http(uri)) { return string_type(boost::begin(default_http_port), boost::end(default_http_port)); } - else if (scheme == "https") { + else if (is_https(uri)) { return string_type(boost::begin(default_https_port), boost::end(default_https_port)); } @@ -63,7 +87,6 @@ typename basic_uri::string_type port(const basic_uri &uri) { } typedef basic_uri uri; -} // namespace http } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 2f3bf80d7..338f327b1 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -334,6 +334,16 @@ typename basic_uri::string_type fragment(const basic_uri &uri) { return uri.fragment(); } +template < + class Tag + > +inline +typename basic_uri::string_type authority(const basic_uri &uri) { + typename basic_uri::const_range_type user_info(uri.user_info_range()); + typename basic_uri::const_range_type port(uri.port_range()); + return typename basic_uri::string_type(user_info.begin(), port.end()); +} + template < class Tag > diff --git a/libs/network/example/simple_wget.cpp b/libs/network/example/simple_wget.cpp index 557876045..cc3909544 100644 --- a/libs/network/example/simple_wget.cpp +++ b/libs/network/example/simple_wget.cpp @@ -15,7 +15,7 @@ #include -#include +#include #include #include #include diff --git a/libs/network/example/uri.cpp b/libs/network/example/uri.cpp index e4f798321..72c46e205 100644 --- a/libs/network/example/uri.cpp +++ b/libs/network/example/uri.cpp @@ -10,7 +10,6 @@ This is a simple program that validates a URI. */ #include -#include #include #include diff --git a/libs/network/test/uri/url_http_test.cpp b/libs/network/test/uri/url_http_test.cpp index a458e9d72..ed162df89 100644 --- a/libs/network/test/uri/url_http_test.cpp +++ b/libs/network/test/uri/url_http_test.cpp @@ -4,7 +4,6 @@ // http://www.boost.org/LICENSE_1_0.txt) - #define BOOST_TEST_MODULE HTTP URL Test #include #include @@ -20,84 +19,43 @@ typedef boost::mpl::list< > tag_types; +BOOST_AUTO_TEST_CASE_TEMPLATE(valid_http, T, tag_types) +{ + typedef uri::http::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + const std::string url("http://example.com/"); + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_http(instance)); + BOOST_REQUIRE(uri::is_valid(instance)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(valid_https, T, tag_types) +{ + typedef uri::http::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + const std::string url("https://example.com/"); + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_https(instance)); + BOOST_REQUIRE(uri::is_valid(instance)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(invalid_https, T, tag_types) +{ + typedef uri::http::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + const std::string url("http://example.com/"); + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(!uri::is_https(instance)); + BOOST_REQUIRE(uri::is_valid(instance)); +} + BOOST_AUTO_TEST_CASE_TEMPLATE(not_http, T, tag_types) { typedef uri::http::basic_uri uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/mailto:john.doe@example.com"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - //BOOST_CHECK(!uri::is_valid(instance)); + BOOST_REQUIRE(!uri::is_http(instance)); + BOOST_REQUIRE(!uri::is_https(instance)); + BOOST_REQUIRE(!uri::is_valid(instance)); } - -// BOOST_AUTO_TEST_CASE(http_url_test) { -// typedef uri::basic_uri uri_type; -// typedef uri_type::string_type string_type; -// -// const std::string url("http://www.boost.org/"); -// const std::string scheme("http"); -// const std::string host("www.boost.org"); -// const std::string path("/"); -// -// uri_type instance(string_type(boost::begin(url), boost::end(url))); -// boost::optional host_ = uri::host(instance); -// boost::optional port_ = uri::port(instance); -// -// BOOST_REQUIRE(uri::is_valid(instance)); -// BOOST_CHECK_EQUAL(instance.raw(), url); -// BOOST_CHECK( !port_ ); -// string_type scheme_ = uri::scheme(instance); -// BOOST_CHECK_EQUAL(scheme_, scheme); -// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); -// BOOST_CHECK(boost::equal(uri::host(instance), host)); -// BOOST_CHECK(boost::equal(uri::path(instance), path)); -// } -// -// BOOST_AUTO_TEST_CASE(full_http_url_test) { -// typedef uri::basic_uri uri_type; -// typedef uri_type::string_type string_type; -// -// const std::string url("http://user:password@www.boost.org:8000/path?query#fragment"); -// const std::string scheme("http"); -// const std::string user_info("user:password"); -// const std::string host("www.boost.org"); -// const boost::uint16_t port = 8000; -// const std::string path("/path"); -// const std::string query("query"); -// const std::string fragment("fragment"); -// -// uri_type instance(string_type(boost::begin(url), boost::end(url))); -// BOOST_REQUIRE(uri::is_valid(instance)); -// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); -// BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); -// BOOST_CHECK(boost::equal(uri::host(instance), host)); -// BOOST_CHECK_EQUAL(uri::port(instance), port); -// BOOST_CHECK(boost::equal(uri::path(instance), path)); -// BOOST_CHECK(boost::equal(uri::query(instance), query)); -// BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); -// } -// -// BOOST_AUTO_TEST_CASE(https_url_test) { -// typedef uri::basic_uri uri_type; -// typedef uri_type::string_type string_type; -// -// const std::string url("https://www.boost.org/"); -// const std::string scheme("https"); -// const std::string host("www.boost.org"); -// const boost::uint16_t port = 443; -// const std::string path("/"); -// -// uri_type instance(string_type(boost::begin(url), boost::end(url))); -// BOOST_REQUIRE(uri::is_valid(instance)); -// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); -// BOOST_CHECK(boost::equal(uri::host(instance), host)); -// BOOST_CHECK_EQUAL(uri::port(instance), port); -// BOOST_CHECK(boost::equal(uri::path(instance), path)); -// } -// -//BOOST_AUTO_TEST_CASE(invalid_http_url_test) { -// typedef uri::basic_uri uri_type; -// typedef uri_type::string_type string_type; -// const std::string url("/service/ftp://www.boost.org/"); -// uri_type instance(string_type(boost::begin(url), boost::end(url))); -// BOOST_CHECK(!uri::is_valid(instance)); -//} diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index fa28c4404..b230efab0 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -10,6 +10,7 @@ #include #include #include +#include using namespace boost::network; @@ -43,7 +44,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, tag_types) { const std::string scheme("http"); const std::string user_info("user:password"); const std::string host("www.boost.org"); - // boost::uint16_t port = 8000; const std::string port = "8000"; const std::string path("/path"); const std::string query("query"); @@ -106,29 +106,29 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -// IPv6 is not yet supported by the parser -// BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test, T, tag_types) { -// typedef uri::basic_uri uri_type; -// typedef typename uri_type::string_type string_type; +//// IPv6 is not yet supported by the parser +//BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test, T, tag_types) { +// typedef uri::basic_uri uri_type; +// typedef typename uri_type::string_type string_type; // -// const std::string url("http://1080:0:0:0:8:800:200C:417A/"); -// const std::string scheme("http"); -// const std::string host("1080:0:0:8:800:200C:417A"); -// const std::string path("/"); +// const std::string url("http://1080:0:0:0:8:800:200C:417A/"); +// const std::string scheme("http"); +// const std::string host("1080:0:0:8:800:200C:417A"); +// const std::string path("/"); // -// uri_type instance(string_type(boost::begin(url), boost::end(url))); -// BOOST_REQUIRE(uri::is_valid(instance)); -// std::cout << uri::scheme(instance) << std::endl; -// std::cout << uri::user_info(instance) << std::endl; -// std::cout << uri::host(instance) << std::endl; -// std::cout << uri::port(instance) << std::endl; -// std::cout << uri::path(instance) << std::endl; -// std::cout << uri::query(instance) << std::endl; -// std::cout << uri::fragment(instance) << std::endl; -// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); -// BOOST_CHECK(boost::equal(uri::host(instance), host)); -// BOOST_CHECK(boost::equal(uri::path(instance), path)); -// } +// uri_type instance(string_type(boost::begin(url), boost::end(url))); +// std::cout << uri::scheme(instance) << std::endl; +// std::cout << uri::user_info(instance) << std::endl; +// std::cout << uri::host(instance) << std::endl; +// std::cout << uri::port(instance) << std::endl; +// std::cout << uri::path(instance) << std::endl; +// std::cout << uri::query(instance) << std::endl; +// std::cout << uri::fragment(instance) << std::endl; +// BOOST_REQUIRE(uri::is_valid(instance)); +// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); +// BOOST_CHECK(boost::equal(uri::host(instance), host)); +// BOOST_CHECK(boost::equal(uri::path(instance), path)); +//} BOOST_AUTO_TEST_CASE_TEMPLATE(ftp_test, T, tag_types) { typedef uri::basic_uri uri_type; @@ -215,3 +215,15 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, tag_types) { BOOST_CHECK(instance.to_string() == copy.to_string()); BOOST_CHECK(instance == copy); } + +BOOST_AUTO_TEST_CASE_TEMPLATE(authority_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://user:password@www.boost.org:8000/path?query#fragment"); + const std::string authority("user:password@www.boost.org:8000"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::authority(instance), authority)); +} From b17a4f3d09ef5e374cba62aa887172df45a464e6 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 14 Aug 2011 21:52:41 +0200 Subject: [PATCH 141/768] Added accessor to fill a map with the key-value pairs in the URI query; added accessors to get the username and password individually; added a class that will eventually become an e-mail address. --- boost/network/uri/mailto/uri.hpp | 74 +++++++++++++++++ boost/network/uri/uri.hpp | 48 ++++------- boost/network/uri/uri_accessors.hpp | 82 +++++++++++++++++++ libs/network/test/uri/CMakeLists.txt | 1 + libs/network/test/uri/url_mailto_test.cpp | 30 +++++++ libs/network/test/uri/url_test.cpp | 99 ++++++++++++++++++++--- 6 files changed, 288 insertions(+), 46 deletions(-) create mode 100644 boost/network/uri/mailto/uri.hpp create mode 100644 boost/network/uri/uri_accessors.hpp create mode 100644 libs/network/test/uri/url_mailto_test.cpp diff --git a/boost/network/uri/mailto/uri.hpp b/boost/network/uri/mailto/uri.hpp new file mode 100644 index 000000000..aff33c275 --- /dev/null +++ b/boost/network/uri/mailto/uri.hpp @@ -0,0 +1,74 @@ +#ifndef __BOOST_NETWORK_URI_MAILTO_URI_INC__ +# define __BOOST_NETWORK_URI_MAILTO_URI_INC__ + + +# include + + +namespace boost { +namespace network { +namespace uri { +namespace mailto { +namespace details { +template < + class String + > +struct uri_parts + : boost::fusion::vector< + iterator_range // to + // headers + > +{ }; +} // namespace details +} // namespace mailto +} // namespace uri +} // namespace network +} // namespace boost + + +namespace boost { +namespace network { +namespace uri { +namespace mailto { + +template < + class Tag + > +class basic_uri + : public boost::network::uri::basic_uri { + + typedef boost::network::uri::basic_uri base_type; + +public: + + basic_uri() { + + } + + basic_uri(const typename base_type::string_type &uri) : base_type(uri) { + + } + + basic_uri &operator = (const typename base_type::string_type &uri) { + basic_uri(uri).swap(*this); + return *this; + } + + + +}; +} // namespace mailto + +template < + class Tag + > +bool is_mailto(const mailto::basic_uri &uri) { + static const char scheme_mailto[] = {'m', 'a', 'i', 'l', 't', 'o'}; + return boost::equal(uri.scheme_range(), scheme_mailto); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_MAILTO_URI_INC__ diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 338f327b1..2e7ffff41 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -15,6 +15,7 @@ # ifdef BOOST_NETWORK_NO_LIB # include # endif // #ifdef BOOST_NETWORK_NO_LIB +# include # include # include # include @@ -111,50 +112,26 @@ class basic_uri const_range_type user_info_range() const { using boost::fusion::at_c; - const boost::fusion::vector< - detail::iterator_range::type> - , detail::iterator_range::type> - , detail::iterator_range::type> - , detail::iterator_range::type> > &hier_part = at_c<1>(uri_parts_); - - return const_range_type(at_c<0>(at_c<0>(hier_part)), - at_c<1>(at_c<0>(hier_part))); + return const_range_type(at_c<0>(at_c<0>(at_c<1>(uri_parts_))), + at_c<1>(at_c<0>(at_c<1>(uri_parts_)))); } const_range_type host_range() const { using boost::fusion::at_c; - const boost::fusion::vector< - detail::iterator_range::type> - , detail::iterator_range::type> - , detail::iterator_range::type> - , detail::iterator_range::type> > &hier_part = at_c<1>(uri_parts_); - - return const_range_type(at_c<0>(at_c<1>(hier_part)), - at_c<1>(at_c<1>(hier_part))); + return const_range_type(at_c<0>(at_c<1>(at_c<1>(uri_parts_))), + at_c<1>(at_c<1>(at_c<1>(uri_parts_)))); } const_range_type port_range() const { using boost::fusion::at_c; - const boost::fusion::vector< - detail::iterator_range::type> - , detail::iterator_range::type> - , detail::iterator_range::type> - , detail::iterator_range::type> > &hier_part = at_c<1>(uri_parts_); - - return const_range_type(at_c<0>(at_c<2>(hier_part)), - at_c<1>(at_c<2>(hier_part))); + return const_range_type(at_c<0>(at_c<2>(at_c<1>(uri_parts_))), + at_c<1>(at_c<2>(at_c<1>(uri_parts_)))); } const_range_type path_range() const { using boost::fusion::at_c; - const boost::fusion::vector< - detail::iterator_range::type> - , detail::iterator_range::type> - , detail::iterator_range::type> - , detail::iterator_range::type> > &hier_part = at_c<1>(uri_parts_); - - return const_range_type(at_c<0>(at_c<3>(hier_part)), - at_c<1>(at_c<3>(hier_part))); + return const_range_type(at_c<0>(at_c<3>(at_c<1>(uri_parts_))), + at_c<1>(at_c<3>(at_c<1>(uri_parts_)))); } const_range_type query_range() const { @@ -208,6 +185,10 @@ class basic_uri return uri_; } + string_type raw() const { + return to_string(); + } + bool is_valid() const { return is_valid_; } @@ -222,10 +203,10 @@ class basic_uri }; - template < class Tag > +inline void basic_uri::parse() { const_iterator_type first(boost::begin(uri_)), last(boost::end(uri_)); is_valid_ = detail::parse(first, last, uri_parts_); @@ -301,7 +282,6 @@ struct port_wrapper { } }; - template < class Tag > diff --git a/boost/network/uri/uri_accessors.hpp b/boost/network/uri/uri_accessors.hpp new file mode 100644 index 000000000..30f61fa1b --- /dev/null +++ b/boost/network/uri/uri_accessors.hpp @@ -0,0 +1,82 @@ +#ifndef __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ +# define __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ + + +# include +# include + + +namespace boost { +namespace network { +namespace uri { +namespace details { +template < + typename Uri, + typename Map + > +struct key_value_sequence + : spirit::qi::grammar +{ + typedef typename Uri::const_iterator_type const_iterator_type; + + key_value_sequence() + : key_value_sequence::base_type(query) + { + query = pair >> *((spirit::qi::lit(';') | '&') >> pair); + pair = key >> -('=' >> value); + key = spirit::qi::char_("a-zA-Z_") >> *spirit::qi::char_("a-zA-Z_0-9%"); + value = +spirit::qi::char_("a-zA-Z_0-9%"); + } + + spirit::qi::rule query; + spirit::qi::rule()> pair; + spirit::qi::rule key, value; +}; +} // namespace details + +template < + class Tag, + class Map + > +inline +Map &query_map(const basic_uri &uri, Map &map) { + typename basic_uri::const_range_type range = uri.query_range(); + details::key_value_sequence, Map> parser; + spirit::qi::parse(boost::begin(range), boost::end(range), parser, map); + return map; +} + +template < + class Tag + > +typename basic_uri::string_type username(const basic_uri &uri) { + typename basic_uri::const_range_type user_info_range = uri.user_info_range(); + typename basic_uri::const_iterator_type it(boost::begin(user_info_range)), end(boost::end(user_info_range)); + for (; it != end; ++it) { + if (*it == ':') { + break; + } + } + return typename string::type(boost::begin(user_info_range), it); +} + +template < + class Tag + > +typename basic_uri::string_type password(const basic_uri &uri) { + typename basic_uri::const_range_type user_info_range = uri.user_info_range(); + typename basic_uri::const_iterator_type it(boost::begin(user_info_range)), end(boost::end(user_info_range)); + for (; it != end; ++it) { + if (*it == ':') { + ++it; + break; + } + } + return typename string::type(it, boost::end(user_info_range)); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index 4a610d4cb..0c1e48a5a 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -16,6 +16,7 @@ if (Boost_FOUND) TESTS url_test url_http_test + url_mailto_test ) foreach (test ${TESTS}) set_source_files_properties(${test}.cpp diff --git a/libs/network/test/uri/url_mailto_test.cpp b/libs/network/test/uri/url_mailto_test.cpp new file mode 100644 index 000000000..d3c931f15 --- /dev/null +++ b/libs/network/test/uri/url_mailto_test.cpp @@ -0,0 +1,30 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#define BOOST_TEST_MODULE mailto URL Test +#include +#include +#include +#include +#include + +using namespace boost::network; + +typedef boost::mpl::list< + tags::default_string +// , tags::default_wstring + > tag_types; + + +BOOST_AUTO_TEST_CASE_TEMPLATE(valid_mailto, T, tag_types) +{ + typedef uri::mailto::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + const std::string url("/service/mailto:john.doe@example.com"); + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_mailto(instance)); + BOOST_REQUIRE(uri::is_valid(instance)); +} diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index b230efab0..20531923a 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -7,10 +7,14 @@ #include #include #include +#include #include #include #include +#include #include +#include + using namespace boost::network; @@ -24,9 +28,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(uri_test, T, tag_types) { typedef uri::basic_uri uri_type; typedef typename uri_type::string_type string_type; - const std::string url("http://www.boost.org/"); + const std::string url("http://www.example.com/"); const std::string scheme("http"); - const std::string host("www.boost.org"); + const std::string host("www.example.com"); const std::string path("/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); @@ -40,11 +44,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, tag_types) { typedef uri::basic_uri uri_type; typedef typename uri_type::string_type string_type; - const std::string url("http://user:password@www.boost.org:8000/path?query#fragment"); + const std::string url("http://user:password@www.example.com/path?query#fragment"); const std::string scheme("http"); const std::string user_info("user:password"); - const std::string host("www.boost.org"); - const std::string port = "8000"; + const std::string host("www.example.com"); + const std::string port = "80"; const std::string path("/path"); const std::string query("query"); const std::string fragment("fragment"); @@ -54,7 +58,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK_EQUAL(static_cast(uri::port_us(instance)), 8000); + BOOST_CHECK_EQUAL(static_cast(uri::port_us(instance)), 80); BOOST_CHECK(boost::equal(uri::port(instance), port)); BOOST_CHECK(boost::equal(uri::path(instance), path)); BOOST_CHECK(boost::equal(uri::query(instance), query)); @@ -90,6 +94,23 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(file_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } +BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("/service/xmpp:example-node@example.com?message;subject=Hello%20World"); + const std::string scheme("xmpp"); + // RFC 3986 interprets this as the path + const std::string path("example-node@example.com"); + const std::string query("message;subject=Hello%20World"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::query(instance), query)); +} + BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, tag_types) { typedef uri::basic_uri uri_type; typedef typename uri_type::string_type string_type; @@ -180,9 +201,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_uri_test, T, tag_types) { typedef uri::basic_uri uri_type; typedef typename uri_type::string_type string_type; - const std::string url("http://www.boost.org/"); + const std::string url("http://www.example.com/"); const std::string scheme("http"); - const std::string host("www.boost.org"); + const std::string host("www.example.com"); const std::string path("/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); @@ -196,7 +217,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(copy_constructor_test, T, tag_types) { typedef uri::basic_uri uri_type; typedef typename uri_type::string_type string_type; - const std::string url("http://www.boost.org/"); + const std::string url("http://www.example.com/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); uri_type copy = instance; @@ -207,7 +228,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, tag_types) { typedef uri::basic_uri uri_type; typedef typename uri_type::string_type string_type; - const std::string url("http://www.boost.org/"); + const std::string url("http://www.example.com/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); uri_type copy; @@ -216,14 +237,68 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, tag_types) { BOOST_CHECK(instance == copy); } +BOOST_AUTO_TEST_CASE_TEMPLATE(username_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("/service/ftp://john.doe:password@ftp.example.com/"); + const std::string scheme("http"); + const std::string username("john.doe"); + const std::string password("password"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::username(instance), username)); + BOOST_CHECK(boost::equal(uri::password(instance), password)); +} + BOOST_AUTO_TEST_CASE_TEMPLATE(authority_test, T, tag_types) { typedef uri::basic_uri uri_type; typedef typename uri_type::string_type string_type; - const std::string url("http://user:password@www.boost.org:8000/path?query#fragment"); - const std::string authority("user:password@www.boost.org:8000"); + const std::string url("http://user:password@www.example.com/path?query#fragment"); + const std::string authority("user:password@www.example.com:80"); uri_type instance(string_type(boost::begin(url), boost::end(url))); BOOST_REQUIRE(uri::is_valid(instance)); BOOST_CHECK(boost::equal(uri::authority(instance), authority)); } + +BOOST_AUTO_TEST_CASE_TEMPLATE(http_query_map_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://user:password@www.example.com/path?query#fragment"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + const std::string key("query"); + const std::string value; + + std::map queries; + uri::query_map(instance, queries); + BOOST_CHECK_EQUAL(queries.size(), std::size_t(1)); + BOOST_CHECK(boost::equal(queries.begin()->first, key)); + BOOST_CHECK(boost::equal(queries.begin()->second, value)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("/service/xmpp:example-node@example.com?message;subject=Hello%20World"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + const std::string key_1("message"), key_2("subject"); + const std::string value_1, value_2("Hello%20World"); + + std::map queries; + uri::query_map(instance, queries); + BOOST_CHECK_EQUAL(queries.size(), std::size_t(2)); + BOOST_CHECK(boost::equal(queries.begin()->first, key_1)); + BOOST_CHECK(boost::equal(queries.begin()->second, value_1)); + BOOST_CHECK(boost::equal((++queries.begin())->first, key_2)); + //BOOST_CHECK(boost::equal((++queries.begin())->second, value_2)); + //BOOST_CHECK_EQUAL((++queries.begin())->second, value_2); +} From 380e55284a10cd8d63cdd882d1c2e3f0bdd33b2f Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 14 Aug 2011 22:11:42 +0200 Subject: [PATCH 142/768] Fixed test for query map. --- libs/network/test/uri/url_test.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index 20531923a..0f2e90513 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -299,6 +299,5 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, tag_types) { BOOST_CHECK(boost::equal(queries.begin()->first, key_1)); BOOST_CHECK(boost::equal(queries.begin()->second, value_1)); BOOST_CHECK(boost::equal((++queries.begin())->first, key_2)); - //BOOST_CHECK(boost::equal((++queries.begin())->second, value_2)); - //BOOST_CHECK_EQUAL((++queries.begin())->second, value_2); + BOOST_CHECK(boost::equal((++queries.begin())->second, value_2)); } From 9b169579b6d3edd9f0154f928351a236e926fa62 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Mon, 15 Aug 2011 08:50:13 +0200 Subject: [PATCH 143/768] Some minor changes to the URI interface. --- boost/network/uri/uri.hpp | 8 ++++---- boost/network/uri/uri_accessors.hpp | 4 ++-- libs/network/test/uri/url_test.cpp | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 2e7ffff41..dd28af535 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -181,12 +181,12 @@ class basic_uri return string_type(boost::begin(range), boost::end(range)); } - string_type to_string() const { + string_type string() const { return uri_; } string_type raw() const { - return to_string(); + return string(); } bool is_valid() const { @@ -198,7 +198,7 @@ class basic_uri void parse(); string_type uri_; - detail::uri_parts::type> uri_parts_; + detail::uri_parts::type> uri_parts_; bool is_valid_; }; @@ -337,7 +337,7 @@ template < > inline bool operator == (const basic_uri &lhs, const basic_uri &rhs) { - return lhs.to_string() == rhs.to_string(); + return std::equal(lhs.begin(), lhs.end(), rhs.begin()); } } // namespace uri } // namespace network diff --git a/boost/network/uri/uri_accessors.hpp b/boost/network/uri/uri_accessors.hpp index 30f61fa1b..74f40cc21 100644 --- a/boost/network/uri/uri_accessors.hpp +++ b/boost/network/uri/uri_accessors.hpp @@ -24,8 +24,8 @@ struct key_value_sequence { query = pair >> *((spirit::qi::lit(';') | '&') >> pair); pair = key >> -('=' >> value); - key = spirit::qi::char_("a-zA-Z_") >> *spirit::qi::char_("a-zA-Z_0-9%"); - value = +spirit::qi::char_("a-zA-Z_0-9%"); + key = spirit::qi::char_("a-zA-Z_") >> *spirit::qi::char_("a-zA-Z_0-9/%"); + value = +spirit::qi::char_("a-zA-Z_0-9/%"); } spirit::qi::rule query; diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index 0f2e90513..b63607d96 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -233,7 +233,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, tag_types) { uri_type instance(string_type(boost::begin(url), boost::end(url))); uri_type copy; copy = instance; - BOOST_CHECK(instance.to_string() == copy.to_string()); + BOOST_CHECK(instance.string() == copy.string()); BOOST_CHECK(instance == copy); } @@ -277,7 +277,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_query_map_test, T, tag_types) { std::map queries; uri::query_map(instance, queries); - BOOST_CHECK_EQUAL(queries.size(), std::size_t(1)); + BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(1)); BOOST_CHECK(boost::equal(queries.begin()->first, key)); BOOST_CHECK(boost::equal(queries.begin()->second, value)); } @@ -295,7 +295,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, tag_types) { std::map queries; uri::query_map(instance, queries); - BOOST_CHECK_EQUAL(queries.size(), std::size_t(2)); + BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(2)); BOOST_CHECK(boost::equal(queries.begin()->first, key_1)); BOOST_CHECK(boost::equal(queries.begin()->second, value_1)); BOOST_CHECK(boost::equal((++queries.begin())->first, key_2)); From 32c6970babf5d460abd378629e17a0e54b17090a Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Tue, 16 Aug 2011 19:08:04 +0200 Subject: [PATCH 144/768] Small fix to compile simple_wget with updated URI code. --- libs/network/example/simple_wget.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libs/network/example/simple_wget.cpp b/libs/network/example/simple_wget.cpp index cc3909544..464652016 100644 --- a/libs/network/example/simple_wget.cpp +++ b/libs/network/example/simple_wget.cpp @@ -26,7 +26,10 @@ namespace uri = boost::network::uri; namespace { -std::string get_filename(const uri::http::uri &url) { +template < + class Tag + > +std::string get_filename(const uri::http::basic_uri &url) { std::string path = uri::path(url); std::size_t index = path.find_last_of('/'); std::string filename = path.substr(index + 1); From d6c255a70d606a4b54c220bb103e6f1f5a6dc7d8 Mon Sep 17 00:00:00 2001 From: Matt Leisinger Date: Tue, 16 Aug 2011 19:37:48 -0500 Subject: [PATCH 145/768] Added a Boost.Log example #14 --- .../example/http/hello_world_server_log.cpp | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 libs/network/example/http/hello_world_server_log.cpp diff --git a/libs/network/example/http/hello_world_server_log.cpp b/libs/network/example/http/hello_world_server_log.cpp new file mode 100644 index 000000000..4a0eef780 --- /dev/null +++ b/libs/network/example/http/hello_world_server_log.cpp @@ -0,0 +1,117 @@ +// Copyright 2009 (c) Tarro, Inc. +// Copyright 2009 (c) Dean Michael Berris +// Copyright 2011 (c) Matt Leisinger +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +//[ hello_world_server_main +/*` + This is a part of the 'Hello World' example. It's used to + demonstrate how easy it is to set up an HTTP server. All we do in + this example is create a request handler and run the server. This + version of the server simply adds logging + */ +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace http = boost::network::http; +namespace logging = boost::log; +namespace fmt = boost::log::formatters; +namespace flt = boost::log::filters; +namespace sinks = boost::log::sinks; +namespace attrs = boost::log::attributes; +namespace src = boost::log::sources; +namespace keywords = boost::log::keywords; + +/*<< Defines the server. >>*/ +struct hello_world; +typedef http::server server; + +/*<< Defines the request handler. It's a class that defines two + functions, `operator()` and `log()` >>*/ +struct hello_world { + /*<< This is the function that handles the incoming request. >>*/ + void operator() (server::request const &request, + server::response &response) { + server::string_type ip = source(request); + std::ostringstream data; + data << "Hello, " << ip << "!"; + response = server::response::stock_reply( + server::response::ok, data.str()); + } + /*<< Using Boost.Log we'll simply log the number of errors >>*/ + void log(const char *error) { + BOOST_LOG(lg) << "Error occured (" << error << "). Total number of errors reported is " << ++numErrors; + } + + /*<< Catch all for any other errors >>*/ + void log(...) { + BOOST_LOG(lg) << "Unknown error occured. Total number of error reported is " << ++numErrors; + } + private: + src::logger_mt lg; + uint32_t numErrors; + +}; + +/*<< Sets up two logger sinks, one to the console and the other to a file >>*/ +void init_logging() +{ + /*<< Setup the console logger >>*/ + logging::init_log_to_console(std::clog, keywords::format = "%TimeStamp%: %_%"); + + /*<< Setup the file logger >>*/ + logging::init_log_to_file + ( + "hello_world_server.log", + keywords::format = fmt::format("[%1%] %2%") + % fmt::date_time("TimeStamp", std::nothrow) + % fmt::message(), + keywords::auto_flush = true + ); + + logging::add_common_attributes(); +} + +int main(int argc, char * argv[]) { + + if (argc != 3) { + std::cerr << "Usage: " << argv[0] << " address port" << std::endl; + return 1; + } + + init_logging(); + src::logger_mt lg; + + try { + /*<< Creates the request handler. >>*/ + hello_world handler; + /*<< Creates the server. >>*/ + server server_(argv[1], argv[2], handler); + /*<< Write to the log source >>*/ + BOOST_LOG(lg) << "Starting HTTP Hello World Server..."; + /*<< Runs the server. >>*/ + server_.run(); + } + catch (std::exception &e) { + std::cerr << e.what() << std::endl; + return 1; + } + + return 0; +} +//] From 235cdab2bdd14c233787bdbb352ea788f75a7547 Mon Sep 17 00:00:00 2001 From: Matt Leisinger Date: Wed, 17 Aug 2011 05:07:12 -0500 Subject: [PATCH 146/768] Adding build changes for hello_world_server_log example --- libs/network/example/CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 293a6ad30..f2f43e9f2 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -4,7 +4,7 @@ # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) -find_package( Boost 1.41.0 COMPONENTS program_options system regex date_time thread filesystem ) +find_package( Boost 1.41.0 COMPONENTS program_options system regex date_time thread filesystem log log_setup) find_package( OpenSSL ) include_directories(${OPENSSL_INCLUDE_DIR}) find_package( Threads ) @@ -14,20 +14,27 @@ set(Boost_USE_MULTITHREADED ON) if (Boost_FOUND) add_executable(http_client http_client.cpp) add_executable(simple_wget simple_wget.cpp) + add_executable(hello_world_client http/hello_world_client.cpp) add_executable(hello_world_server http/hello_world_server.cpp) + add_executable(hello_world_server_log http/hello_world_server_log.cpp) add_executable(fileserver http/fileserver.cpp) add_executable(uri uri.cpp) add_dependencies(http_client cppnetlib-uri-parsers) + add_dependencies(hello_world_client cppnetlib-uri-parsers) add_dependencies(simple_wget cppnetlib-uri-parsers) add_dependencies(uri cppnetlib-uri-parsers) target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers) target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers) + target_link_libraries(hello_world_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers) target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} ) + target_link_libraries(hello_world_server_log ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} ) target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) target_link_libraries(uri cppnetlib-uri-parsers) set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + set_target_properties(hello_world_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + set_target_properties(hello_world_server_log PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) endif() From 5a5cff3faf83f9db0787060d0d0de177214c4af4 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 20 Aug 2011 11:48:14 +1000 Subject: [PATCH 147/768] Squashed commit of the following: commit e84929c5985440503b90a70aa8baf61e2cdc628f Author: Dean Michael Berris Date: Fri Aug 19 19:04:54 2011 +1000 Adding Copyright information. commit 50b9c226a5c2aa7a9baed82e5021c14dd3ae9d9b Author: Dean Michael Berris Date: Fri Aug 19 19:01:14 2011 +1000 Internal refactor complete, now testing can start to happen. commit 4e7349ad1fb4946b916150d5b09d2ee1748c82fb Author: Dean Michael Berris Date: Fri Aug 19 17:49:13 2011 +1000 WIP: broken build because Boost 1.45 asio seems to not have support for wide strings in API. --- CMakeLists.txt | 8 +- .../http/client/connection/async_base.hpp | 89 ++-- .../http/client/connection/async_normal.hpp | 169 ++++---- .../connection/async_protocol_handler.hpp | 30 +- .../http/client/connection/async_ssl.hpp | 410 ------------------ .../client/connection/connection_delegate.hpp | 30 ++ .../connection_delegate_factory.hpp | 56 +++ .../client/connection/normal_delegate.hpp | 45 ++ .../client/connection/normal_delegate.ipp | 42 ++ .../http/client/connection/ssl_delegate.hpp | 58 +++ .../http/client/connection/ssl_delegate.ipp | 64 +++ .../protocol/http/traits/delegate_factory.hpp | 39 ++ boost/network/traits/char.hpp | 7 +- libs/network/example/CMakeLists.txt | 8 +- libs/network/src/CMakeLists.txt | 8 +- libs/network/test/CMakeLists.txt | 2 - libs/network/test/http/CMakeLists.txt | 8 +- .../server_async_run_stop_concurrency.cpp | 226 +++++----- 18 files changed, 623 insertions(+), 676 deletions(-) delete mode 100644 boost/network/protocol/http/client/connection/async_ssl.hpp create mode 100644 boost/network/protocol/http/client/connection/connection_delegate.hpp create mode 100644 boost/network/protocol/http/client/connection/connection_delegate_factory.hpp create mode 100644 boost/network/protocol/http/client/connection/normal_delegate.hpp create mode 100644 boost/network/protocol/http/client/connection/normal_delegate.ipp create mode 100644 boost/network/protocol/http/client/connection/ssl_delegate.hpp create mode 100644 boost/network/protocol/http/client/connection/ssl_delegate.ipp create mode 100644 boost/network/protocol/http/traits/delegate_factory.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1475321ce..eba49491b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,18 +6,24 @@ cmake_minimum_required(VERSION 2.6) project(CPP-NETLIB) find_package( Boost 1.41.0 ) +find_package( OpenSSL ) +find_package( Threads ) set(CMAKE_VERBOSE_MAKEFILE true) if (CMAKE_BUILD_TYPE MATCHES Debug) add_definitions(-DBOOST_NETWORK_DEBUG) endif() - if (Boost_FOUND) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTI_THREADED ON) include_directories(${Boost_INCLUDE_DIRS}) endif() enable_testing() + +if (OPENSSL_FOUND) + add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) +endif() + add_subdirectory(libs/network/src) add_subdirectory(libs/network/test) add_subdirectory(libs/mime/test) diff --git a/boost/network/protocol/http/client/connection/async_base.hpp b/boost/network/protocol/http/client/connection/async_base.hpp index 8916fedc2..943ca2106 100644 --- a/boost/network/protocol/http/client/connection/async_base.hpp +++ b/boost/network/protocol/http/client/connection/async_base.hpp @@ -8,45 +8,64 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#include +#include #include -#ifdef BOOST_NETWORK_ENABLE_HTTPS -#include -#endif namespace boost { namespace network { namespace http { namespace impl { - template - struct async_connection_base { - typedef typename resolver_policy::type resolver_base; - typedef typename resolver_base::resolver_type resolver_type; - typedef typename resolver_base::resolve_function resolve_function; - typedef typename string::type string_type; - typedef basic_request request; - typedef basic_response response; - typedef - function const &, system::error_code const &)> - body_callback_function_type; - - static boost::shared_ptr > new_connection(resolve_function resolve, resolver_type & resolver, bool follow_redirect, bool https, optional certificate_filename=optional(), optional const & verify_path=optional()) { - boost::shared_ptr > temp; - if (https) { -#ifdef BOOST_NETWORK_ENABLE_HTTPS - temp.reset(new https_async_connection(resolver, resolve, follow_redirect, certificate_filename, verify_path)); - return temp; -#else - throw std::runtime_error("HTTPS not supported."); -#endif - } - temp.reset(new http_async_connection(resolver, resolve, follow_redirect)); - assert(temp.get() != 0); - return temp; - } - - virtual response start(request const & request, string_type const & method, bool get_body, body_callback_function_type callback) = 0; - - virtual ~async_connection_base() {} - - }; + template + struct async_connection_base { + typedef async_connection_base this_type; + typedef typename resolver_policy::type resolver_base; + typedef typename resolver_base::resolver_type resolver_type; + typedef typename resolver_base::resolve_function resolve_function; + typedef typename string::type string_type; + typedef basic_request request; + typedef basic_response response; + typedef iterator_range char_const_range; + typedef function + body_callback_function_type; + typedef shared_ptr connection_ptr; + + // This is the factory function which constructs the appropriate async + // connection implementation with the correct delegate chosen based on the + // tag. + static connection_ptr new_connection( + resolve_function resolve, + resolver_type & resolver, + bool follow_redirect, + bool https, + optional certificate_filename=optional(), + optional const & verify_path=optional()) { + typedef http_async_connection + async_connection; + typedef typename delegate_factory::type delegate_factory_type; + connection_ptr temp; + temp.reset( + new async_connection( + resolver, + resolve, + follow_redirect, + delegate_factory_type::new_connection_delegate( + resolver.get_io_service(), + https, + certificate_filename, + verify_path))); + BOOST_ASSERT(temp.get() != 0); + return temp; + } + + // This is the pure virtual entry-point for all asynchronous connections. + virtual response start( + request const & request, + string_type const & method, + bool get_body, + body_callback_function_type callback) = 0; + + virtual ~async_connection_base() {} + + }; } // namespace impl diff --git a/boost/network/protocol/http/client/connection/async_normal.hpp b/boost/network/protocol/http/client/connection/async_normal.hpp index aaa7d85b0..f1d0e9e3b 100644 --- a/boost/network/protocol/http/client/connection/async_normal.hpp +++ b/boost/network/protocol/http/client/connection/async_normal.hpp @@ -29,6 +29,8 @@ #include #include +#include + namespace boost { namespace network { namespace http { namespace impl { template @@ -53,16 +55,20 @@ namespace boost { namespace network { namespace http { namespace impl { typedef typename base::resolver_base::resolve_function resolve_function; typedef typename base::body_callback_function_type body_callback_function_type; typedef http_async_connection this_type; + typedef typename delegate_factory::type delegate_factory_type; + typedef typename delegate_factory_type::connection_delegate_ptr + connection_delegate_ptr; http_async_connection(resolver_type & resolver, resolve_function resolve, - bool follow_redirect) + bool follow_redirect, + connection_delegate_ptr delegate) : follow_redirect_(follow_redirect), resolver_(resolver), resolve_(resolve), - request_strand_(resolver.get_io_service()) {} - + request_strand_(resolver.get_io_service()), + delegate_(delegate) {} // This is the main entry point for the connection/request pipeline. We're // overriding async_connection_base<...>::start(...) here which is called @@ -77,14 +83,17 @@ namespace boost { namespace network { namespace http { namespace impl { std::ostreambuf_iterator::type>(&command_streambuf)); this->method = method; boost::uint16_t port_ = port(request); - resolve_(resolver_, host(request), - port_, - request_strand_.wrap( - boost::bind( - &this_type::handle_resolved, - this_type::shared_from_this(), - port_, get_body, callback, - _1, _2))); + resolve_(resolver_, + host(request), + port_, + request_strand_.wrap( + boost::bind(&this_type::handle_resolved, + this_type::shared_from_this(), + port_, + get_body, + callback, + _1, + _2))); return response_; } @@ -108,26 +117,22 @@ namespace boost { namespace network { namespace http { namespace impl { body_callback_function_type callback, boost::system::error_code const & ec, resolver_iterator_pair endpoint_range) { - resolver_iterator iter = boost::begin(endpoint_range); if (!ec && !boost::empty(endpoint_range)) { // Here we deal with the case that there was an error encountered and // that there's still more endpoints to try connecting to. - boost::asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), - port); - socket_.reset( - new boost::asio::ip::tcp::socket( - resolver_.get_io_service())); - socket_->async_connect(endpoint, - request_strand_.wrap( - boost::bind( - &this_type::handle_connected, - this_type::shared_from_this(), - port, - get_body, - callback, - std::make_pair(++iter, - resolver_iterator()), - placeholders::error))); + resolver_iterator iter = boost::begin(endpoint_range); + asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); + delegate_->connect(endpoint, + request_strand_.wrap( + boost::bind( + &this_type::handle_connected, + this_type::shared_from_this(), + port, + get_body, + callback, + std::make_pair(++iter, + resolver_iterator()), + placeholders::error))); } else { set_errors(ec ? ec : boost::asio::error::host_not_found); } @@ -139,35 +144,31 @@ namespace boost { namespace network { namespace http { namespace impl { resolver_iterator_pair endpoint_range, boost::system::error_code const & ec) { if (!ec) { - boost::asio::async_write( - *socket_ - , command_streambuf - , request_strand_.wrap( - boost::bind( - &this_type::handle_sent_request, - this_type::shared_from_this(), - get_body, callback, - placeholders::error, - placeholders::bytes_transferred - ))); + BOOST_ASSERT(delegate_.get() != 0); + delegate_->write(command_streambuf, + request_strand_.wrap( + boost::bind( + &this_type::handle_sent_request, + this_type::shared_from_this(), + get_body, + callback, + placeholders::error, + placeholders::bytes_transferred))); } else { if (!boost::empty(endpoint_range)) { resolver_iterator iter = boost::begin(endpoint_range); - boost::asio::ip::tcp::endpoint endpoint( - iter->endpoint().address(), - port - ); - socket_.reset(new boost::asio::ip::tcp::socket( - resolver_.get_io_service())); - socket_->async_connect( - endpoint, - request_strand_.wrap( - boost::bind( - &this_type::handle_connected, - this_type::shared_from_this(), - port, get_body, callback, std::make_pair(++iter, resolver_iterator()), - placeholders::error - ))); + asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); + delegate_->connect(endpoint, + request_strand_.wrap( + boost::bind( + &this_type::handle_connected, + this_type::shared_from_this(), + port, + get_body, + callback, + std::make_pair(++iter, + resolver_iterator()), + placeholders::error))); } else { set_errors(ec ? ec : boost::asio::error::host_not_found); } @@ -178,17 +179,20 @@ namespace boost { namespace network { namespace http { namespace impl { version, status, status_message, headers, body }; - void handle_sent_request(bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { + void handle_sent_request(bool get_body, + body_callback_function_type callback, + boost::system::error_code const & ec, + std::size_t bytes_transferred) { if (!ec) { - socket_->async_read_some( - boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), - request_strand_.wrap( - boost::bind( - &this_type::handle_received_data, - this_type::shared_from_this(), - version, get_body, callback, - placeholders::error, - placeholders::bytes_transferred))); + delegate_->read_some( + boost::asio::mutable_buffers_1(this->part.c_array(), + this->part.size()), + request_strand_.wrap( + boost::bind(&this_type::handle_received_data, + this_type::shared_from_this(), + version, get_body, callback, + placeholders::error, + placeholders::bytes_transferred))); } else { set_errors(ec); } @@ -201,7 +205,7 @@ namespace boost { namespace network { namespace http { namespace impl { switch(state) { case version: parsed_ok = - this->parse_version(*socket_, + this->parse_version(delegate_, request_strand_.wrap( boost::bind( &this_type::handle_received_data, @@ -213,7 +217,7 @@ namespace boost { namespace network { namespace http { namespace impl { if (!parsed_ok || indeterminate(parsed_ok)) return; case status: parsed_ok = - this->parse_status(*socket_, + this->parse_status(delegate_, request_strand_.wrap( boost::bind( &this_type::handle_received_data, @@ -225,7 +229,7 @@ namespace boost { namespace network { namespace http { namespace impl { if (!parsed_ok || indeterminate(parsed_ok)) return; case status_message: parsed_ok = - this->parse_status_message(*socket_, + this->parse_status_message(delegate_, request_strand_.wrap( boost::bind( &this_type::handle_received_data, @@ -243,7 +247,7 @@ namespace boost { namespace network { namespace http { namespace impl { // that the data remaining in the buffer is dealt with before // another call to get more data for the body is scheduled. fusion::tie(parsed_ok, remainder) = - this->parse_headers(*socket_, + this->parse_headers(delegate_, request_strand_.wrap( boost::bind( &this_type::handle_received_data, @@ -289,21 +293,22 @@ namespace boost { namespace network { namespace http { namespace impl { // wait before scheduling another read. callback(make_iterator_range(begin, end), ec); - socket_->async_read_some( - boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), - request_strand_.wrap( - boost::bind( - &this_type::handle_received_data, - this_type::shared_from_this(), - body, get_body, callback, - placeholders::error, placeholders::bytes_transferred) - ) - ); + delegate_->read_some( + boost::asio::mutable_buffers_1(this->part.c_array(), + this->part.size()), + request_strand_.wrap( + boost::bind(&this_type::handle_received_data, + this_type::shared_from_this(), + body, + get_body, + callback, + placeholders::error, + placeholders::bytes_transferred))); } else { // Here we handle the body data ourself and append to an // ever-growing string buffer. this->parse_body( - *socket_, + delegate_, request_strand_.wrap( boost::bind( &this_type::handle_received_data, @@ -356,7 +361,7 @@ namespace boost { namespace network { namespace http { namespace impl { typename protocol_base::buffer_type::const_iterator end = begin; std::advance(end, bytes_transferred); callback(make_iterator_range(begin, end), ec); - socket_->async_read_some( + delegate_->read_some( boost::asio::mutable_buffers_1( this->part.c_array(), this->part.size()), @@ -374,7 +379,7 @@ namespace boost { namespace network { namespace http { namespace impl { // make sure that we deal with the remainder // from the headers part in case we do have data // that's still in the buffer. - this->parse_body(*socket_, + this->parse_body(delegate_, request_strand_.wrap( boost::bind( &this_type::handle_received_data, @@ -415,9 +420,9 @@ namespace boost { namespace network { namespace http { namespace impl { bool follow_redirect_; resolver_type & resolver_; - boost::shared_ptr socket_; resolve_function resolve_; boost::asio::io_service::strand request_strand_; + connection_delegate_ptr delegate_; boost::asio::streambuf command_streambuf; string_type method; }; diff --git a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp index 66b510585..f0368c0e1 100644 --- a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp +++ b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp @@ -85,8 +85,8 @@ namespace boost { namespace network { namespace http { namespace impl { } }; - template - logic::tribool parse_version(Socket & socket_, + template + logic::tribool parse_version(Delegate & delegate_, Callback callback, size_t bytes) { logic::tribool parsed_ok; @@ -133,7 +133,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::end(result_range) ); part_begin = part.begin(); - socket_.async_read_some( + delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); @@ -141,8 +141,8 @@ namespace boost { namespace network { namespace http { namespace impl { return parsed_ok; } - template - logic::tribool parse_status(Socket & socket_, + template + logic::tribool parse_status(Delegate & delegate_, Callback callback, size_t bytes) { logic::tribool parsed_ok; @@ -189,7 +189,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::end(result_range) ); part_begin = part.begin(); - socket_.async_read_some( + delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); @@ -197,8 +197,8 @@ namespace boost { namespace network { namespace http { namespace impl { return parsed_ok; } - template - logic::tribool parse_status_message(Socket & socket_, + template + logic::tribool parse_status_message(Delegate & delegate_, Callback callback, size_t bytes) { logic::tribool parsed_ok; @@ -241,7 +241,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::begin(result_range), boost::end(result_range)); part_begin = part.begin(); - socket_.async_read_some( + delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); @@ -289,8 +289,8 @@ namespace boost { namespace network { namespace http { namespace impl { headers_promise.set_value(headers); } - template - fusion::tuple parse_headers(Socket & socket_, + template + fusion::tuple parse_headers(Delegate & delegate_, Callback callback, size_t bytes) { logic::tribool parsed_ok; @@ -332,7 +332,7 @@ namespace boost { namespace network { namespace http { namespace impl { partial_parsed.append(boost::begin(result_range), boost::end(result_range)); part_begin = part.begin(); - socket_.async_read_some( + delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); @@ -346,13 +346,13 @@ namespace boost { namespace network { namespace http { namespace impl { ); } - template - void parse_body(Socket & socket_, Callback callback, size_t bytes) { + template + void parse_body(Delegate & delegate_, Callback callback, size_t bytes) { // TODO: we should really not use a string for the partial body // buffer. partial_parsed.append(part_begin, bytes); part_begin = part.begin(); - socket_.async_read_some( + delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); diff --git a/boost/network/protocol/http/client/connection/async_ssl.hpp b/boost/network/protocol/http/client/connection/async_ssl.hpp deleted file mode 100644 index 1b2af32f1..000000000 --- a/boost/network/protocol/http/client/connection/async_ssl.hpp +++ /dev/null @@ -1,410 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_ASYNC_CONNECTION_HPP_20100601 -#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_ASYNC_CONNECTION_HPP_20100601 - -// Copyright 2010 (C) Dean Michael Berris -// Copyright 2010 (C) Sinefunc, Inc. -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { namespace impl { - - template - struct async_connection_base; - - template - struct https_async_connection - : async_connection_base, - protected http_async_protocol_handler, - boost::enable_shared_from_this > - { - typedef async_connection_base base; - typedef http_async_protocol_handler protocol_base; - typedef typename base::resolver_type resolver_type; - typedef typename base::resolver_base::resolver_iterator resolver_iterator; - typedef typename base::resolver_base::resolver_iterator_pair resolver_iterator_pair; - typedef typename base::response response; - typedef typename base::string_type string_type; - typedef typename base::request request; - typedef typename base::resolver_base::resolve_function resolve_function; - typedef typename base::body_callback_function_type body_callback_function_type; - - https_async_connection( - resolver_type & resolver, - resolve_function resolve, - bool follow_redirect, - optional const & certificate_filename = optional(), - optional const & verify_path = optional() - ) : - follow_redirect_(follow_redirect), - resolver_(resolver), - certificate_filename_(certificate_filename), - verify_path_(verify_path), - resolve_(resolve), - request_strand_(resolver.get_io_service()) - {} - - - virtual response start(request const & request, string_type const & method, bool get_body, body_callback_function_type callback) { - response response_; - this->init_response(response_, get_body); - linearize(request, method, version_major, version_minor, - std::ostreambuf_iterator::type>(&command_streambuf)); - this->method = method; - boost::uint16_t port_ = port(request); - resolve_(resolver_, host(request), - port_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_resolved, - https_async_connection::shared_from_this(), - port_, get_body, callback, - _1, _2))); - return response_; - } - - private: - void handle_resolved(boost::uint16_t port, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, resolver_iterator_pair endpoint_range) { - resolver_iterator iter = boost::begin(endpoint_range); - if (!ec && !boost::empty(endpoint_range)) { - boost::asio::ip::tcp::endpoint endpoint( - iter->endpoint().address(), - port - ); - context_.reset(new boost::asio::ssl::context( - resolver_.get_io_service(), - boost::asio::ssl::context::sslv23_client - ) - ); - if (certificate_filename_ || verify_path_) { - context_->set_verify_mode(boost::asio::ssl::context::verify_peer); - if (certificate_filename_) context_->load_verify_file(*certificate_filename_); - if (verify_path_) context_->add_verify_path(*verify_path_); - } else { - context_->set_verify_mode(boost::asio::ssl::context::verify_none); - } - socket_.reset(new boost::asio::ssl::stream( - resolver_.get_io_service(), - *context_ - ) - ); - socket_->lowest_layer().async_connect( - endpoint, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_connected, - https_async_connection::shared_from_this(), - port, get_body, callback, std::make_pair(++iter, resolver_iterator()), - boost::asio::placeholders::error - ))); - } else { - boost::system::system_error error(ec ? ec : boost::asio::error::host_not_found); - this->version_promise.set_exception(boost::copy_exception(error)); - this->status_promise.set_exception(boost::copy_exception(error)); - this->status_message_promise.set_exception(boost::copy_exception(error)); - this->headers_promise.set_exception(boost::copy_exception(error)); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - this->body_promise.set_exception(boost::copy_exception(error)); - } - } - - void handle_connected(boost::uint16_t port, bool get_body, body_callback_function_type callback, resolver_iterator_pair endpoint_range, boost::system::error_code const & ec) { - if (!ec) { - socket_->async_handshake(boost::asio::ssl::stream_base::client, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_handshake, - https_async_connection::shared_from_this(), - port, get_body, callback, - boost::asio::placeholders::error - ) - ) - ); - } else { - if (!boost::empty(endpoint_range)) { - resolver_iterator iter = boost::begin(endpoint_range); - boost::asio::ip::tcp::endpoint endpoint( - iter->endpoint().address(), - port - ); - socket_.reset(new boost::asio::ssl::stream( - resolver_.get_io_service() - , *context_ - ) - ); - socket_->lowest_layer().async_connect( - endpoint, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_connected, - https_async_connection::shared_from_this(), - port, get_body, callback, std::make_pair(++iter, resolver_iterator()), - boost::asio::placeholders::error - ))); - } else { - boost::system::system_error error( - ec ? ec : boost::asio::error::host_not_found - ); - this->version_promise.set_exception(boost::copy_exception(error)); - this->status_promise.set_exception(boost::copy_exception(error)); - this->status_message_promise.set_exception(boost::copy_exception(error)); - this->headers_promise.set_exception(boost::copy_exception(error)); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - this->body_promise.set_exception(boost::copy_exception(error)); - } - } - } - - void handle_handshake(boost::uint16_t port, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec) { - if (!ec) { - boost::asio::async_write( - *socket_ - , command_streambuf - , request_strand_.wrap( - boost::bind( - &https_async_connection::handle_sent_request, - https_async_connection::shared_from_this(), - get_body, callback, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred - ))); - } else { - boost::system::system_error error( - ec ? ec : boost::asio::error::host_not_found - ); - this->version_promise.set_exception(boost::copy_exception(error)); - this->status_promise.set_exception(boost::copy_exception(error)); - this->status_message_promise.set_exception(boost::copy_exception(error)); - this->headers_promise.set_exception(boost::copy_exception(error)); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - this->body_promise.set_exception(boost::copy_exception(error)); - } - } - - enum state_t { - version, status, status_message, headers, body - }; - - void handle_sent_request(bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { - if (!ec) { - socket_->async_read_some( - boost::asio::mutable_buffers_1( - this->part.c_array(), - this->part.size()), - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - version, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); - } else { - boost::system::system_error error( - ec ? ec : boost::asio::error::host_not_found - ); - this->version_promise.set_exception(boost::copy_exception(error)); - this->status_promise.set_exception(boost::copy_exception(error)); - this->status_message_promise.set_exception(boost::copy_exception(error)); - this->headers_promise.set_exception(boost::copy_exception(error)); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - this->body_promise.set_exception(boost::copy_exception(error)); - } - } - - void handle_received_data(state_t state, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { - if (!ec || ec == boost::asio::error::eof) { - logic::tribool parsed_ok; - size_t remainder; - switch(state) { - case version: - parsed_ok = - this->parse_version( - *socket_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - status, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred - ); - if (parsed_ok != true) return; - case status: - parsed_ok = - this->parse_status(*socket_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - status_message, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred - ); - if (parsed_ok != true) return; - case status_message: - parsed_ok = - this->parse_status_message(*socket_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - headers, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred - ); - if (parsed_ok != true) return; - case headers: - fusion::tie(parsed_ok, remainder) = - this->parse_headers(*socket_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - headers, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred - ); - if (parsed_ok != true) return; - if (!get_body) { - this->body_promise.set_value(""); - return; - } - if (callback) { - typename protocol_base::buffer_type::const_iterator begin = this->part.begin(); - std::advance(begin, remainder); - typename protocol_base::buffer_type::const_iterator end = begin; - std::advance(end, this->part.size() - remainder); - callback(make_iterator_range(begin, end), ec); - socket_->async_read_some( - boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - body, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); - this->body_promise.set_value(""); - } else { - this->parse_body( - *socket_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - body, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - remainder); - } - break; - case body: - if (ec == boost::asio::error::eof) { - if (callback) { - typename protocol_base::buffer_type::const_iterator begin = this->part.begin(), end = begin; - std::advance(end, bytes_transferred); - callback(make_iterator_range(begin, end), ec); - } else { - string_type body; - std::swap(body, this->partial_parsed); - body.append( - this->part.begin() - , bytes_transferred - ); - this->body_promise.set_value(body); - } - // TODO set the destination value somewhere! - this->destination_promise.set_value(""); - this->source_promise.set_value(""); - this->part.assign('\0'); - this->response_parser_.reset(); - } else { - if (callback) { - typename protocol_base::buffer_type::const_iterator begin = this->part.begin(), end = begin; - std::advance(end, bytes_transferred); - callback(make_iterator_range(begin, end), ec); - socket_->async_read_some( - boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - body, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); - } else { - this->parse_body( - *socket_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - body, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred); - } - } - break; - default: - BOOST_ASSERT(false && "Bug, report this to the developers!"); - } - } else { - boost::system::system_error error(ec); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - switch (state) { - case version: - this->version_promise.set_exception(boost::copy_exception(error)); - case status: - this->status_promise.set_exception(boost::copy_exception(error)); - case status_message: - this->status_message_promise.set_exception(boost::copy_exception(error)); - case headers: - this->headers_promise.set_exception(boost::copy_exception(error)); - case body: - if (get_body) this->body_promise.set_exception(boost::copy_exception(error)); - break; - default: - BOOST_ASSERT(false && "Bug, report this to the developers!"); - } - } - } - - bool follow_redirect_; - resolver_type & resolver_; - optional certificate_filename_, verify_path_; - resolve_function resolve_; - boost::shared_ptr context_; - boost::shared_ptr > socket_; - boost::asio::io_service::strand request_strand_; - boost::asio::streambuf command_streambuf; - string_type method; - }; - -} // namespace impl - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_ASYNC_CONNECTION_HPP_20100601 diff --git a/boost/network/protocol/http/client/connection/connection_delegate.hpp b/boost/network/protocol/http/client/connection/connection_delegate.hpp new file mode 100644 index 000000000..0e18b231c --- /dev/null +++ b/boost/network/protocol/http/client/connection/connection_delegate.hpp @@ -0,0 +1,30 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ +#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +namespace boost { namespace network { namespace http { namespace impl { + +struct connection_delegate { + virtual void connect(asio::ip::tcp::endpoint & endpoint, + function handler) = 0; + virtual void write(asio::streambuf & command_streambuf, + function handler) = 0; + virtual void read_some(asio::mutable_buffers_1 const & read_buffer, + function handler) = 0; + virtual ~connection_delegate() {} +}; + +} /* impl */ + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ */ diff --git a/boost/network/protocol/http/client/connection/connection_delegate_factory.hpp b/boost/network/protocol/http/client/connection/connection_delegate_factory.hpp new file mode 100644 index 000000000..eca673666 --- /dev/null +++ b/boost/network/protocol/http/client/connection/connection_delegate_factory.hpp @@ -0,0 +1,56 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 +#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#ifdef BOOST_NETWORK_ENABLE_HTTPS +#include +#endif /* BOOST_NETWORK_ENABLE_HTTPS */ + +namespace boost { namespace network { namespace http { namespace impl { + +struct ssl_delegate; + +struct normal_delegate; + +template +struct connection_delegate_factory { + typedef shared_ptr connection_delegate_ptr; + typedef typename string::type string_type; + + // This is the factory method that actually returns the delegate instance. + // TODO Support passing in proxy settings when crafting connections. + static connection_delegate_ptr new_connection_delegate( + asio::io_service & service, + bool https, + optional certificate_filename, + optional verify_path) { + connection_delegate_ptr delegate; + if (https) { +#ifdef BOOST_NETWORK_ENABLE_HTTPS + delegate.reset(new ssl_delegate(service, + certificate_filename, + verify_path)); +#else + BOOST_THROW_EXCEPTION(std::runtime_error("HTTPS not supported.")); +#endif /* BOOST_NETWORK_ENABLE_HTTPS */ + } else { + delegate.reset(new normal_delegate(service)); + } + return delegate; + } +}; + +} /* impl */ +} /* http */ +} /* network */ +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 */ diff --git a/boost/network/protocol/http/client/connection/normal_delegate.hpp b/boost/network/protocol/http/client/connection/normal_delegate.hpp new file mode 100644 index 000000000..8b3d79c51 --- /dev/null +++ b/boost/network/protocol/http/client/connection/normal_delegate.hpp @@ -0,0 +1,45 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 +#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +namespace boost { namespace network { namespace http { namespace impl { + +struct normal_delegate : connection_delegate { + normal_delegate(asio::io_service & service); + + virtual void connect(asio::ip::tcp::endpoint & endpoint, + function handler); + virtual void write(asio::streambuf & command_streambuf, + function handler); + virtual void read_some(asio::mutable_buffers_1 const & read_buffer, + function handler); + ~normal_delegate(); + + private: + asio::io_service & service_; + scoped_ptr socket_; + + normal_delegate(normal_delegate const &); // = delete + normal_delegate& operator=(normal_delegate); // = delete +}; + +} /* impl */ + +} /* http */ + +} /* network */ + +} /* boost */ + +#ifdef BOOST_NETWORK_NO_LIB +#include +#endif /* BOOST_NETWORK_NO_LIB */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 */ diff --git a/boost/network/protocol/http/client/connection/normal_delegate.ipp b/boost/network/protocol/http/client/connection/normal_delegate.ipp new file mode 100644 index 000000000..f084dc163 --- /dev/null +++ b/boost/network/protocol/http/client/connection/normal_delegate.ipp @@ -0,0 +1,42 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 +#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include + +boost::network::http::impl::normal_delegate::normal_delegate(asio::io_service & service) + : service_(service) +{} + +void boost::network::http::impl::normal_delegate::connect( + asio::ip::tcp::endpoint & endpoint, + function handler) { + socket_.reset(new asio::ip::tcp::socket(service_)); + socket_->async_connect(endpoint, handler); +} + +void boost::network::http::impl::normal_delegate::write( + asio::streambuf & command_streambuf, + function handler) { + asio::async_write(*socket_, command_streambuf, handler); +} + +void boost::network::http::impl::normal_delegate::read_some( + asio::mutable_buffers_1 const & read_buffer, + function handler) { + socket_->async_read_some(read_buffer, handler); +} + +boost::network::http::impl::normal_delegate::~normal_delegate() {} + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 */ diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.hpp b/boost/network/protocol/http/client/connection/ssl_delegate.hpp new file mode 100644 index 000000000..a1cb9a0c6 --- /dev/null +++ b/boost/network/protocol/http/client/connection/ssl_delegate.hpp @@ -0,0 +1,58 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 +#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace network { namespace http { namespace impl { + +struct ssl_delegate : connection_delegate, enable_shared_from_this { + ssl_delegate(asio::io_service & service, + optional certificate_filename, + optional verify_path); + + virtual void connect(asio::ip::tcp::endpoint & endpoint, + function handler); + virtual void write(asio::streambuf & command_streambuf, + function handler); + virtual void read_some(asio::mutable_buffers_1 const & read_buffer, + function handler); + ~ssl_delegate(); + + private: + asio::io_service & service_; + optional certificate_filename_, verify_path_; + scoped_ptr context_; + scoped_ptr > socket_; + + ssl_delegate(ssl_delegate const &); // = delete + ssl_delegate& operator=(ssl_delegate); // = delete + + void handle_connected(system::error_code const & ec, + function handler); +}; + +} /* impl */ + +} /* http */ + +} /* network */ + +} /* boost */ + +#ifdef BOOST_NETWORK_NO_LIB +#include +#endif /* BOOST_NETWORK_NO_LIB */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 */ diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.ipp b/boost/network/protocol/http/client/connection/ssl_delegate.ipp new file mode 100644 index 000000000..ed8531e31 --- /dev/null +++ b/boost/network/protocol/http/client/connection/ssl_delegate.ipp @@ -0,0 +1,64 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 +#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +boost::network::http::impl::ssl_delegate::ssl_delegate(asio::io_service & service, + optional certificate_filename, + optional verify_path) : + service_(service), + certificate_filename_(certificate_filename), + verify_path_(verify_path) {} + +void boost::network::http::impl::ssl_delegate::connect( + asio::ip::tcp::endpoint & endpoint, + function handler) { + context_.reset(new asio::ssl::context( + service_, + asio::ssl::context::sslv23_client)); + if (certificate_filename_ || verify_path_) { + context_->set_verify_mode(asio::ssl::context::verify_peer); + if (certificate_filename_) context_->load_verify_file(*certificate_filename_); + if (verify_path_) context_->add_verify_path(*verify_path_); + } else { + context_->set_verify_mode(asio::ssl::context::verify_none); + } + socket_.reset(new asio::ssl::stream(service_, *context_)); + socket_->lowest_layer().async_connect( + endpoint, + bind(&boost::network::http::impl::ssl_delegate::handle_connected, + boost::network::http::impl::ssl_delegate::shared_from_this(), + asio::placeholders::error, + handler)); +} + +void boost::network::http::impl::ssl_delegate::handle_connected(system::error_code const & ec, + function handler) { + if (!ec) { + socket_->async_handshake(asio::ssl::stream_base::client, handler); + } else { + handler(ec); + } +} + +void boost::network::http::impl::ssl_delegate::write( + asio::streambuf & command_streambuf, + function handler) { + asio::async_write(*socket_, command_streambuf, handler); +} + +void boost::network::http::impl::ssl_delegate::read_some( + asio::mutable_buffers_1 const & read_buffer, + function handler) { + socket_->async_read_some(read_buffer, handler); +} + +boost::network::http::impl::ssl_delegate::~ssl_delegate() {} + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 */ diff --git a/boost/network/protocol/http/traits/delegate_factory.hpp b/boost/network/protocol/http/traits/delegate_factory.hpp new file mode 100644 index 000000000..714fc590e --- /dev/null +++ b/boost/network/protocol/http/traits/delegate_factory.hpp @@ -0,0 +1,39 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_DELEGATE_FACTORY_HPP_20110819 +#define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_DELEGATE_FACTORY_HPP_20110819 + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +namespace boost { namespace network { namespace http { + +namespace impl { + +template +struct connection_delegate_factory; + +} /* impl */ + +template struct unsupported_tag; + +template +struct delegate_factory { + typedef unsupported_tag type; +}; + +template +struct delegate_factory >::type> { + typedef impl::connection_delegate_factory type; +}; + +} /* http */ +} /* network */ +} /* boost */ + + + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_DELEGATE_FACTORY_HPP_20110819 */ diff --git a/boost/network/traits/char.hpp b/boost/network/traits/char.hpp index 66e7dbbeb..79e73441d 100644 --- a/boost/network/traits/char.hpp +++ b/boost/network/traits/char.hpp @@ -6,10 +6,8 @@ #ifndef BOOST_NETWORK_TRAITS_CHAR_HPP #define BOOST_NETWORK_TRAITS_CHAR_HPP -#include #include #include -#include namespace boost { namespace network { @@ -21,13 +19,13 @@ namespace boost { namespace network { { typedef unsupported_tag type; }; - + template struct char_ >::type> { typedef char type; }; - + template struct char_ >::type> { @@ -39,4 +37,3 @@ namespace boost { namespace network { } // namespace boost #endif // BOOST_NETWORK_TRAITS_CHAR_HPP - diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 293a6ad30..2eccb3c3e 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -17,11 +17,11 @@ if (Boost_FOUND) add_executable(hello_world_server http/hello_world_server.cpp) add_executable(fileserver http/fileserver.cpp) add_executable(uri uri.cpp) - add_dependencies(http_client cppnetlib-uri-parsers) - add_dependencies(simple_wget cppnetlib-uri-parsers) + add_dependencies(http_client cppnetlib-uri-parsers cppnetlib-client-connections) + add_dependencies(simple_wget cppnetlib-uri-parsers cppnetlib-client-connections) add_dependencies(uri cppnetlib-uri-parsers) - target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers) - target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers) + target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers cppnetlib-client-connections) + target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers cppnetlib-client-connections) target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} ) target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) target_link_libraries(uri cppnetlib-uri-parsers) diff --git a/libs/network/src/CMakeLists.txt b/libs/network/src/CMakeLists.txt index dae683daf..e06a58d1c 100644 --- a/libs/network/src/CMakeLists.txt +++ b/libs/network/src/CMakeLists.txt @@ -1,13 +1,17 @@ -# Copyright (c) Glyn Matthews 2011. +# Copyright (c) Glyn Matthews 2011. +# Copyright 2011 Dean Michael Berris (dberris@google.com) +# Copyright 2011 Google, Inc. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) -# boost_network_uri include_directories(${CPP-NETLIB_SOURCE_DIR}) set(CPP-NETLIB_URI_SRCS uri/parse.cpp) add_library(cppnetlib-uri-parsers ${CPP-NETLIB_URI_SRCS}) set(CPP-NETLIB_HTTP_SERVER_SRCS server_request_parsers_impl.cpp) add_library(cppnetlib-server-parsers ${CPP-NETLIB_HTTP_SERVER_SRCS}) + +set(CPP-NETLIB_HTTP_CLIENT_SRCS client.cpp) +add_library(cppnetlib-client-connections ${CPP-NETLIB_HTTP_CLIENT_SRCS}) diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index 190affb4a..092499b5a 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -5,8 +5,6 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) find_package( Boost 1.41.0 COMPONENTS unit_test_framework system regex date_time thread filesystem ) -find_package( OpenSSL ) -find_package( Threads ) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 018993729..aa20424ba 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -23,14 +23,8 @@ if (Boost_FOUND) client_get_test client_get_different_port_test client_get_timeout_test - # TODO: refactor these so that local servers are no longer necessary - # client_localhost_normal_test client_get_streaming_test ) - # TODO: refactor these so that local servers are no longer necessary - #if (OPENSSL_FOUND) - # set ( TESTS ${TESTS} client_localhost_ssl_test ) - #endif (OPENSSL_FOUND) foreach ( test ${TESTS} ) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) set_source_files_properties(${test}.cpp @@ -38,7 +32,7 @@ if (Boost_FOUND) endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) add_dependencies(cpp-netlib-http-${test} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers cppnetlib-client-connections) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) endif() diff --git a/libs/network/test/http/server_async_run_stop_concurrency.cpp b/libs/network/test/http/server_async_run_stop_concurrency.cpp index d85e0dfb7..e9a4e25ac 100644 --- a/libs/network/test/http/server_async_run_stop_concurrency.cpp +++ b/libs/network/test/http/server_async_run_stop_concurrency.cpp @@ -22,118 +22,118 @@ struct dummy_async_handler { int main(int argc, char * argv[]) { dummy_async_handler async_handler; -#define ASYNC_SERVER_TEST_CONFIG \ - http::_address = "127.0.0.1", \ - http::_port = "80", \ - http::_handler = async_handler, \ - http::_thread_pool = pool, \ - http::_reuse_address = true - -#define ASYNC_SERVER_SLEEP_TIME \ - boost::posix_time::milliseconds(100) - - // stop from main thread - { - BOOST_NETWORK_MESSAGE("TEST: stop without running"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - server_instance.stop(); - } - - // run-stop from main thread - { - BOOST_NETWORK_MESSAGE("TEST: stop from main thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - server_instance.stop(); - running_thread.join(); - } - - // run-stop from another thread - { - BOOST_NETWORK_MESSAGE("TEST: stop from another thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - stopping_thread.join(); - running_thread.join(); - } - - // run-stop-run-stop from another thread - { - BOOST_NETWORK_MESSAGE("TEST: run-stop-run-stop from another thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - stopping_thread.join(); - running_thread.join(); - second_stopping_thread.join(); - second_running_thread.join(); - } - - // run-run-stop from another thread - { - BOOST_NETWORK_MESSAGE("TEST: run-run-stop from another thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - stopping_thread.join(); - running_thread.join(); - second_running_thread.join(); - } - - // run-stop-stop from another thread - { - BOOST_NETWORK_MESSAGE("TEST: run-stop-stop from another thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - stopping_thread.join(); - second_stopping_thread.join(); - running_thread.join(); - } - +#define ASYNC_SERVER_TEST_CONFIG \ + http::_address = "127.0.0.1", \ + http::_port = "8007", \ + http::_handler = async_handler, \ + http::_thread_pool = pool, \ + http::_reuse_address = true + +#define ASYNC_SERVER_SLEEP_TIME \ + boost::posix_time::milliseconds(100) + + // stop from main thread + { + BOOST_NETWORK_MESSAGE("TEST: stop without running"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + server_instance.stop(); + } + + // run-stop from main thread + { + BOOST_NETWORK_MESSAGE("TEST: stop from main thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + server_instance.stop(); + running_thread.join(); + } + + // run-stop from another thread + { + BOOST_NETWORK_MESSAGE("TEST: stop from another thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + stopping_thread.join(); + running_thread.join(); + } + + // run-stop-run-stop from another thread + { + BOOST_NETWORK_MESSAGE("TEST: run-stop-run-stop from another thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + stopping_thread.join(); + running_thread.join(); + second_stopping_thread.join(); + second_running_thread.join(); + } + + // run-run-stop from another thread + { + BOOST_NETWORK_MESSAGE("TEST: run-run-stop from another thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + stopping_thread.join(); + running_thread.join(); + second_running_thread.join(); + } + + // run-stop-stop from another thread + { + BOOST_NETWORK_MESSAGE("TEST: run-stop-stop from another thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + stopping_thread.join(); + second_stopping_thread.join(); + running_thread.join(); + } + #undef ASYNC_SERVER_TEST_CONFIG - - return 0; + + return 0; } From fc7ce3b118388a605a71bb30f0e06a974d7314ca Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 21 Aug 2011 00:17:08 +1000 Subject: [PATCH 148/768] Adding missing client.cpp --- libs/network/src/client.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 libs/network/src/client.cpp diff --git a/libs/network/src/client.cpp b/libs/network/src/client.cpp new file mode 100644 index 000000000..3ce8c1f19 --- /dev/null +++ b/libs/network/src/client.cpp @@ -0,0 +1,17 @@ + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef BOOST_NETWORK_NO_LIB +#warn Building the library even with BOOST_NETWORK_NO_LIB defined. +#undef BOOST_NETWORK_NO_LIB +#endif + +#include + +#ifdef BOOST_NETWORK_ENABLE_HTTPS +#include +#endif From ced0a508dbdfc89970bf65c945a239933f031f8b Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 21 Aug 2011 15:10:52 +0200 Subject: [PATCH 149/768] Added some missing headers. --- .../protocol/http/client/connection/normal_delegate.hpp | 2 ++ .../network/protocol/http/client/connection/ssl_delegate.ipp | 1 + libs/network/test/http/client_get_streaming_test.cpp | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/boost/network/protocol/http/client/connection/normal_delegate.hpp b/boost/network/protocol/http/client/connection/normal_delegate.hpp index 8b3d79c51..d18f1461a 100644 --- a/boost/network/protocol/http/client/connection/normal_delegate.hpp +++ b/boost/network/protocol/http/client/connection/normal_delegate.hpp @@ -8,6 +8,8 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#include +#include namespace boost { namespace network { namespace http { namespace impl { diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.ipp b/boost/network/protocol/http/client/connection/ssl_delegate.ipp index ed8531e31..c7ee5e573 100644 --- a/boost/network/protocol/http/client/connection/ssl_delegate.ipp +++ b/boost/network/protocol/http/client/connection/ssl_delegate.ipp @@ -8,6 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#include boost::network::http::impl::ssl_delegate::ssl_delegate(asio::io_service & service, optional certificate_filename, diff --git a/libs/network/test/http/client_get_streaming_test.cpp b/libs/network/test/http/client_get_streaming_test.cpp index 19009fa23..aa1bdd902 100644 --- a/libs/network/test/http/client_get_streaming_test.cpp +++ b/libs/network/test/http/client_get_streaming_test.cpp @@ -1,4 +1,4 @@ -// Copyright 2011 Dean Michael Berris <mikhailberis@gmail.com>. +// Copyright 2011 Dean Michael Berris <mikhailberis@gmail.com>. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -43,6 +43,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_streaming_test, client, async_only BOOST_CHECK_EQUAL ( response.status_message(), std::string("OK") ); dummy_body = body(response); } - BOOST_CHECK ( dummy_body == typename client::string_type() ); + BOOST_CHECK ( dummy_body == typename client::string_type() ); } From 8eb6bd041910633602e2976cf710ad59f5c0222d Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 20 Aug 2011 08:58:47 +0200 Subject: [PATCH 150/768] Added first unit test for a URI builder. --- boost/network/uri/builder.hpp | 141 +++++++++++++++++++++++++ boost/network/uri/http/uri.hpp | 6 ++ boost/network/uri/mailto/uri.hpp | 8 +- boost/network/uri/uri_accessors.hpp | 6 ++ libs/network/test/uri/CMakeLists.txt | 1 + libs/network/test/uri/builder_test.cpp | 47 +++++++++ 6 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 boost/network/uri/builder.hpp create mode 100644 libs/network/test/uri/builder_test.cpp diff --git a/boost/network/uri/builder.hpp b/boost/network/uri/builder.hpp new file mode 100644 index 000000000..ef20749ee --- /dev/null +++ b/boost/network/uri/builder.hpp @@ -0,0 +1,141 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef __BOOST_NETWORK_URI_BUILDER_INC__ +# define __BOOST_NETWORK_URI_BUILDER_INC__ + + +# include + + +namespace boost { +namespace network { +namespace uri { +namespace builder { +template < + class T + > +struct scheme_t { + scheme_t(const T &scheme) + : scheme(scheme) { + + } + + const T &scheme; +}; + +template < + class T + > +inline +scheme_t scheme(const T &scheme) { + return scheme_t(scheme); +} + +template < + class T + > +struct host_t { + host_t(const T &host) + : host(host) { + + } + + const T &host; +}; + +template < + class T + > +inline +host_t host(const T &host) { + return host_t(host); +} + +template < + class T + > +struct path_t { + path_t(const T &path) + : path(path) { + + } + + const T &path; +}; + +template < + class T + > +inline +path_t path(const T &path) { + return path_t(path); +} +} // namespace builder + +template < + class Tag + > +class basic_builder { + +public: + +public: + + basic_builder(basic_uri &uri) + : uri_(uri) { + + } + + const basic_uri &uri() const { + return uri_; + } + +private: + basic_uri &uri_; +}; + +template < + class Tag + > +inline +basic_builder operator << (basic_uri &uri, const builder::scheme_t::type> &scheme) { + // uri.set_scheme( + return basic_builder(uri); +} + +template < + class Tag + > +inline +basic_builder &operator << (basic_builder &builder, const builder::scheme_t::type> &scheme) { + // uri.set_scheme( + return builder; +} + +template < + class Tag + > +inline +basic_builder &operator << (basic_builder &builder, const builder::host_t::type> &host) { + // uri.set_host( + return builder; +} + +template < + class Tag + > +inline +basic_builder &operator << (basic_builder &builder, const builder::path_t::type> &path) { + // uri.set_path( + return builder; +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_BUILDER_INC__ diff --git a/boost/network/uri/http/uri.hpp b/boost/network/uri/http/uri.hpp index d4c859031..ecee3f491 100644 --- a/boost/network/uri/http/uri.hpp +++ b/boost/network/uri/http/uri.hpp @@ -1,3 +1,9 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + #ifndef __BOOST_NETWORK_URI_HTTP_URI_INC__ # define __BOOST_NETWORK_URI_HTTP_URI_INC__ diff --git a/boost/network/uri/mailto/uri.hpp b/boost/network/uri/mailto/uri.hpp index aff33c275..87490a502 100644 --- a/boost/network/uri/mailto/uri.hpp +++ b/boost/network/uri/mailto/uri.hpp @@ -1,3 +1,9 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + #ifndef __BOOST_NETWORK_URI_MAILTO_URI_INC__ # define __BOOST_NETWORK_URI_MAILTO_URI_INC__ @@ -54,7 +60,7 @@ class basic_uri return *this; } - + }; } // namespace mailto diff --git a/boost/network/uri/uri_accessors.hpp b/boost/network/uri/uri_accessors.hpp index 74f40cc21..93052f640 100644 --- a/boost/network/uri/uri_accessors.hpp +++ b/boost/network/uri/uri_accessors.hpp @@ -1,3 +1,9 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + #ifndef __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ # define __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index 0c1e48a5a..c41614b35 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -17,6 +17,7 @@ if (Boost_FOUND) url_test url_http_test url_mailto_test + builder_test ) foreach (test ${TESTS}) set_source_files_properties(${test}.cpp diff --git a/libs/network/test/uri/builder_test.cpp b/libs/network/test/uri/builder_test.cpp new file mode 100644 index 000000000..c7dfebdc2 --- /dev/null +++ b/libs/network/test/uri/builder_test.cpp @@ -0,0 +1,47 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE URI builder test +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace boost::network; + +typedef boost::mpl::list< + tags::default_string +// , tags::default_wstring + > tag_types; + + +BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + + uri_type instance; + uri::basic_builder builder(instance); + builder << uri::builder::scheme(string_type(boost::begin(scheme), + boost::end(scheme))) + << uri::builder::host(string_type(boost::begin(host), + boost::end(host))) + << uri::builder::path(string_type(boost::begin(path), + boost::end(path))) + ; + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} From 7f8e36b9bf4f92c6f14b21cf1f65fb52195f6e42 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Mon, 22 Aug 2011 23:21:07 +0200 Subject: [PATCH 151/768] Added some functions that allow encoding and decoding of URI strings. --- boost/network/uri/decode.hpp | 98 +++++++++++ boost/network/uri/encode.hpp | 164 ++++++++++++++++++ boost/network/uri/uri.hpp | 8 + .../test/http/server_async_less_copy.cpp | 5 +- libs/network/test/uri/CMakeLists.txt | 1 + libs/network/test/uri/builder_test.cpp | 10 +- libs/network/test/uri/url_encoding_test.cpp | 48 +++++ 7 files changed, 325 insertions(+), 9 deletions(-) create mode 100644 boost/network/uri/decode.hpp create mode 100644 boost/network/uri/encode.hpp create mode 100644 libs/network/test/uri/url_encoding_test.cpp diff --git a/boost/network/uri/decode.hpp b/boost/network/uri/decode.hpp new file mode 100644 index 000000000..e56e3f6e8 --- /dev/null +++ b/boost/network/uri/decode.hpp @@ -0,0 +1,98 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef __BOOST_NETWORK_URI_DECODE_INC__ +# define __BOOST_NETWORK_URI_DECODE_INC__ + + +# include +# include +# include +# include + + +namespace boost { +namespace network { +namespace uri { +namespace detail { +template < + typename CharT + > +CharT letter_to_hex(CharT in) +{ + switch (in) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return in - '0'; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + return in + 10 - 'a'; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + return in + 10 - 'A'; + } + return CharT(); +} +} // namespace detail + +template < + class InputIterator, + class OutputIterator + > +OutputIterator decode(const InputIterator &in_begin, const InputIterator &in_end, const OutputIterator &out_begin) { + typedef typename boost::iterator_value::type value_type; + + InputIterator it = in_begin; + OutputIterator out = out_begin; + while (it != in_end) { + if (*it == '%') + { + ++it; + value_type v0 = detail::letter_to_hex(*it); + ++it; + value_type v1 = detail::letter_to_hex(*it); + ++it; + *out++ = 0x10 * v0 + v1; + } + else + { + *out++ = *it++; + } + } + return out; +} + +template < + class SinglePassRange, + class OutputIterator + > +inline +OutputIterator decode(const SinglePassRange &range, const OutputIterator &out) { + return decode(boost::begin(range), boost::end(range), out); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DECODE_INC__ diff --git a/boost/network/uri/encode.hpp b/boost/network/uri/encode.hpp new file mode 100644 index 000000000..18b344ee5 --- /dev/null +++ b/boost/network/uri/encode.hpp @@ -0,0 +1,164 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef __BOOST_NETWORK_URI_ENCODE_INC__ +# define __BOOST_NETWORK_URI_ENCODE_INC__ + + +# include +# include +# include +# include + + +namespace boost { +namespace network { +namespace uri { +namespace detail { +template < + typename CharT + > +inline +CharT hex_to_letter(CharT in) { + switch (in) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + return in + '0'; + case 10: + case 11: + case 12: + case 13: + case 14: + default: + return in - 10 + 'A'; + } + return CharT(); +} + + +template < + typename CharT, + class OutputIterator + > +void encode_char(CharT in, OutputIterator &out) { + switch (in) + { + case 'a': + case 'A': + case 'b': + case 'B': + case 'c': + case 'C': + case 'd': + case 'D': + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + case 'h': + case 'H': + case 'i': + case 'I': + case 'j': + case 'J': + case 'k': + case 'K': + case 'l': + case 'L': + case 'm': + case 'M': + case 'n': + case 'N': + case 'o': + case 'O': + case 'p': + case 'P': + case 'q': + case 'Q': + case 'r': + case 'R': + case 's': + case 'S': + case 't': + case 'T': + case 'u': + case 'U': + case 'v': + case 'V': + case 'w': + case 'W': + case 'x': + case 'X': + case 'y': + case 'Y': + case 'z': + case 'Z': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + case '.': + case '_': + case '~': + out++ = in; + break; + default: + out++ = '%'; + out++ = hex_to_letter(in >> 4); + out++ = hex_to_letter(in & 0x0f); + ; + } +} +} // namespace detail + +template < + class InputIterator, + class OutputIterator + > +OutputIterator encode(const InputIterator &in_begin, const InputIterator &in_end, const OutputIterator &out_begin) { + typedef typename boost::iterator_value::type value_type; + + InputIterator it = in_begin; + OutputIterator out = out_begin; + while (it != in_end) { + detail::encode_char(*it, out); + ++it; + } + return out; +} + +template < + class SinglePassRange, + class OutputIterator + > +inline +OutputIterator encode(const SinglePassRange &range, const OutputIterator &out) { + return encode(boost::begin(range), boost::end(range), out); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_ENCODE_INC__ diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index dd28af535..4ccb4e19c 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -324,6 +324,14 @@ typename basic_uri::string_type authority(const basic_uri &uri) { return typename basic_uri::string_type(user_info.begin(), port.end()); } +template < + class Tag + > +inline +typename basic_uri::string_type netloc(const basic_uri &uri) { + return authority(uri); +} + template < class Tag > diff --git a/libs/network/test/http/server_async_less_copy.cpp b/libs/network/test/http/server_async_less_copy.cpp index 73d8aa5f3..c1ca4786b 100644 --- a/libs/network/test/http/server_async_less_copy.cpp +++ b/libs/network/test/http/server_async_less_copy.cpp @@ -1,5 +1,5 @@ -// Copyright 2010 Dean Michael Berris. +// Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -51,11 +51,10 @@ struct async_hello_world { }; int main(int argc, char * argv[]) { - utils::thread_pool thread_pool(2); + utils::thread_pool thread_pool(2); async_hello_world handler; std::string port = "8000"; if (argc > 1) port = argv[1]; - std::cerr << "Configuration: port = " << port << std::endl; server instance("127.0.0.1", port, handler, thread_pool, http::_reuse_address=true); instance.run(); return 0; diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index c41614b35..fb0e9bcb0 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -17,6 +17,7 @@ if (Boost_FOUND) url_test url_http_test url_mailto_test + url_encoding_test builder_test ) foreach (test ${TESTS}) diff --git a/libs/network/test/uri/builder_test.cpp b/libs/network/test/uri/builder_test.cpp index c7dfebdc2..862d89f87 100644 --- a/libs/network/test/uri/builder_test.cpp +++ b/libs/network/test/uri/builder_test.cpp @@ -26,6 +26,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) { typedef uri::basic_uri uri_type; typedef typename uri_type::string_type string_type; + namespace urib = uri::builder; const std::string scheme("http"); const std::string host("www.example.com"); @@ -33,12 +34,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) uri_type instance; uri::basic_builder builder(instance); - builder << uri::builder::scheme(string_type(boost::begin(scheme), - boost::end(scheme))) - << uri::builder::host(string_type(boost::begin(host), - boost::end(host))) - << uri::builder::path(string_type(boost::begin(path), - boost::end(path))) + builder << urib::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << urib::host(string_type(boost::begin(host), boost::end(host))) + << urib::path(string_type(boost::begin(path), boost::end(path))) ; BOOST_REQUIRE(uri::is_valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); diff --git a/libs/network/test/uri/url_encoding_test.cpp b/libs/network/test/uri/url_encoding_test.cpp new file mode 100644 index 000000000..bc08f8c1c --- /dev/null +++ b/libs/network/test/uri/url_encoding_test.cpp @@ -0,0 +1,48 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE URL encoding test +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace boost::network; + +typedef boost::mpl::list< + tags::default_string + , tags::default_wstring + > tag_types; + + +BOOST_AUTO_TEST_CASE_TEMPLATE(encoding_test, T, tag_types) { + typedef typename string::type string_type; + + const std::string unencoded(" !\"#$%&\'()*"); + const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A"); + + string_type instance; + uri::encode(unencoded, std::back_inserter(instance)); + BOOST_CHECK(boost::equal(instance, encoded)); +} + + +BOOST_AUTO_TEST_CASE_TEMPLATE(decoding_test, T, tag_types) { + typedef typename string::type string_type; + + const std::string unencoded(" !\"#$%&\'()*"); + const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A"); + + string_type instance; + uri::decode(encoded, std::back_inserter(instance)); + BOOST_CHECK(boost::equal(instance, unencoded)); +} From 80c416fc729aa9ed530f750b92e1dc2811240256 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Tue, 23 Aug 2011 07:59:01 +0200 Subject: [PATCH 152/768] Added unit tests for encoded strings in URL. --- boost/network/uri/uri_accessors.hpp | 12 ++++++++++++ libs/network/test/uri/url_test.cpp | 8 +++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/boost/network/uri/uri_accessors.hpp b/boost/network/uri/uri_accessors.hpp index 93052f640..337a1addf 100644 --- a/boost/network/uri/uri_accessors.hpp +++ b/boost/network/uri/uri_accessors.hpp @@ -9,6 +9,8 @@ # include +# include +# include # include @@ -80,6 +82,16 @@ typename basic_uri::string_type password(const basic_uri &uri) { } return typename string::type(it, boost::end(user_info_range)); } + +template < + class Tag + > +typename basic_uri::string_type decoded_path(const basic_uri &uri) { + typename basic_uri::const_range_type path_range = uri.path_range(); + typename basic_uri::string_type decoded_path; + decode(path_range, std::back_inserter(decoded_path)); + return decoded_path; +} } // namespace uri } // namespace network } // namespace boost diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index b63607d96..ce6185ebe 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -201,16 +201,18 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_uri_test, T, tag_types) { typedef uri::basic_uri uri_type; typedef typename uri_type::string_type string_type; - const std::string url("http://www.example.com/"); + const std::string url("http://www.example.com/Path%20With%20%28Some%29%20Encoded%20Characters%21"); const std::string scheme("http"); const std::string host("www.example.com"); - const std::string path("/"); + const std::string encoded_path("/Path%20With%20%28Some%29%20Encoded%20Characters%21"); + const std::string decoded_path("/Path With (Some) Encoded Characters!"); uri_type instance(string_type(boost::begin(url), boost::end(url))); BOOST_REQUIRE(uri::is_valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::path(instance), encoded_path)); + BOOST_CHECK(boost::equal(uri::decoded_path(instance), decoded_path)); } BOOST_AUTO_TEST_CASE_TEMPLATE(copy_constructor_test, T, tag_types) { From 11a11abcdc10fec0c5ee2a54352ed9a0a5fa8197 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Thu, 25 Aug 2011 20:11:24 +0200 Subject: [PATCH 153/768] Added a first draft of IPv6 support; initial unit tests succeed. --- boost/network/uri/detail/parse_uri.hpp | 37 +++++++++++++++++- boost/network/uri/uri_accessors.hpp | 20 ++++++++++ libs/network/test/uri/url_test.cpp | 54 +++++++++++++++----------- 3 files changed, 86 insertions(+), 25 deletions(-) diff --git a/boost/network/uri/detail/parse_uri.hpp b/boost/network/uri/detail/parse_uri.hpp index dc9e1cb96..424bafd52 100644 --- a/boost/network/uri/detail/parse_uri.hpp +++ b/boost/network/uri/detail/parse_uri.hpp @@ -106,6 +106,36 @@ struct uri_grammar : qi::grammar()> { >> iter_pos ; + ip_literal %= + qi::lit('[') >> (ipv6address | ipvfuture) >> ']' + ; + + ipvfuture %= + qi::lit('v') >> +qi::xdigit >> '.' >> +( unreserved | sub_delims | ':') + ; + + ipv6address %= qi::raw[ + //qi::lit("1080:0:0:0:8:800:200C:417A") + qi::repeat(6)[h16 >> ':'] >> ls32 + | "::" >> qi::repeat(5)[h16 >> ':'] >> ls32 + | qi::raw[ h16] >> "::" >> qi::repeat(4)[h16 >> ':'] >> ls32 + | qi::raw[+(*(h16 >> ':')) >> h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 + | qi::raw[qi::repeat(2)[*(h16 >> ':')] >> h16] >> "::" >> qi::repeat(2)[h16 >> ':'] >> ls32 + | qi::raw[qi::repeat(3)[*(h16 >> ':')] >> h16] >> "::" >> h16 >> ':' >> ls32 + | qi::raw[qi::repeat(4)[*(h16 >> ':')] >> h16] >> "::" >> ls32 + | qi::raw[qi::repeat(5)[*(h16 >> ':')] >> h16] >> "::" >> h16 + | qi::raw[qi::repeat(6)[*(h16 >> ':')] >> h16] >> "::" + + ]; + + // ls32 = ( h16 ":" h16 ) / IPv4address + ls32 %= (h16 >> ':' >> h16) | ipv4address + ; + + // h16 = 1*4HEXDIG + h16 %= qi::repeat(1, 4)[qi::xdigit] + ; + // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 dec_octet %= !(qi::lit('0') >> qi::digit) @@ -126,7 +156,7 @@ struct uri_grammar : qi::grammar()> { // TODO, host = IP-literal / IPv4address / reg-name host %= iter_pos - >> qi::omit[ipv4address | reg_name] + >> qi::omit[ip_literal | ipv4address | reg_name] >> iter_pos ; @@ -193,7 +223,10 @@ struct uri_grammar : qi::grammar()> { path_abempty, path_absolute, path_rootless, path_empty; qi::rule - dec_octet, ipv4address, reg_name; + dec_octet, ipv4address, reg_name, ipv6address, ipvfuture, ip_literal; + + qi::rule + h16, ls32; qi::rule()> host, port; diff --git a/boost/network/uri/uri_accessors.hpp b/boost/network/uri/uri_accessors.hpp index 337a1addf..88ed97e16 100644 --- a/boost/network/uri/uri_accessors.hpp +++ b/boost/network/uri/uri_accessors.hpp @@ -92,6 +92,26 @@ typename basic_uri::string_type decoded_path(const basic_uri &uri) { decode(path_range, std::back_inserter(decoded_path)); return decoded_path; } + +template < + class Tag + > +typename basic_uri::string_type decoded_query(const basic_uri &uri) { + typename basic_uri::const_range_type query_range = uri.query_range(); + typename basic_uri::string_type decoded_query; + decode(query_range, std::back_inserter(decoded_query)); + return decoded_query; +} + +template < + class Tag + > +typename basic_uri::string_type decoded_fragment(const basic_uri &uri) { + typename basic_uri::const_range_type fragment_range = uri.fragment_range(); + typename basic_uri::string_type decoded_fragment; + decode(fragment_range, std::back_inserter(decoded_fragment)); + return decoded_fragment; +} } // namespace uri } // namespace network } // namespace boost diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index ce6185ebe..a5ba2af51 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -127,29 +127,37 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -//// IPv6 is not yet supported by the parser -//BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test, T, tag_types) { -// typedef uri::basic_uri uri_type; -// typedef typename uri_type::string_type string_type; -// -// const std::string url("http://1080:0:0:0:8:800:200C:417A/"); -// const std::string scheme("http"); -// const std::string host("1080:0:0:8:800:200C:417A"); -// const std::string path("/"); -// -// uri_type instance(string_type(boost::begin(url), boost::end(url))); -// std::cout << uri::scheme(instance) << std::endl; -// std::cout << uri::user_info(instance) << std::endl; -// std::cout << uri::host(instance) << std::endl; -// std::cout << uri::port(instance) << std::endl; -// std::cout << uri::path(instance) << std::endl; -// std::cout << uri::query(instance) << std::endl; -// std::cout << uri::fragment(instance) << std::endl; -// BOOST_REQUIRE(uri::is_valid(instance)); -// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); -// BOOST_CHECK(boost::equal(uri::host(instance), host)); -// BOOST_CHECK(boost::equal(uri::path(instance), path)); -//} +BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_1, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://[1080::8:800:200c:417a]/"); + const std::string scheme("http"); + const std::string host("[1080:0:0:0:8:800:200C:417A]"); + const std::string path("/"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_2, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/"); + const std::string scheme("http"); + const std::string host("[2001:db8:85a3:8d3:1319:8a2e:370:7348]"); + const std::string path("/"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} BOOST_AUTO_TEST_CASE_TEMPLATE(ftp_test, T, tag_types) { typedef uri::basic_uri uri_type; From c20d1d3222e83d4dc0969a079f404ba5f622d111 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Fri, 26 Aug 2011 08:08:19 +0200 Subject: [PATCH 154/768] First (and limited) draft of URI builder syntax. --- boost/network/uri/builder.hpp | 141 ------------------ boost/network/uri/detail/parse_uri.hpp | 3 +- boost/network/uri/directives.hpp | 37 +++++ boost/network/uri/directives/authority.hpp | 14 ++ boost/network/uri/directives/fragment.hpp | 14 ++ boost/network/uri/directives/host.hpp | 51 +++++++ boost/network/uri/directives/path.hpp | 51 +++++++ boost/network/uri/directives/port.hpp | 14 ++ boost/network/uri/directives/query.hpp | 14 ++ boost/network/uri/directives/scheme.hpp | 55 +++++++ boost/network/uri/directives/user_info.hpp | 14 ++ boost/network/uri/uri.hpp | 13 ++ libs/network/test/uri/CMakeLists.txt | 2 +- ...{builder_test.cpp => url_builder_test.cpp} | 16 +- libs/network/test/uri/url_mailto_test.cpp | 2 +- 15 files changed, 289 insertions(+), 152 deletions(-) delete mode 100644 boost/network/uri/builder.hpp create mode 100644 boost/network/uri/directives.hpp create mode 100644 boost/network/uri/directives/authority.hpp create mode 100644 boost/network/uri/directives/fragment.hpp create mode 100644 boost/network/uri/directives/host.hpp create mode 100644 boost/network/uri/directives/path.hpp create mode 100644 boost/network/uri/directives/port.hpp create mode 100644 boost/network/uri/directives/query.hpp create mode 100644 boost/network/uri/directives/scheme.hpp create mode 100644 boost/network/uri/directives/user_info.hpp rename libs/network/test/uri/{builder_test.cpp => url_builder_test.cpp} (76%) diff --git a/boost/network/uri/builder.hpp b/boost/network/uri/builder.hpp deleted file mode 100644 index ef20749ee..000000000 --- a/boost/network/uri/builder.hpp +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_BUILDER_INC__ -# define __BOOST_NETWORK_URI_BUILDER_INC__ - - -# include - - -namespace boost { -namespace network { -namespace uri { -namespace builder { -template < - class T - > -struct scheme_t { - scheme_t(const T &scheme) - : scheme(scheme) { - - } - - const T &scheme; -}; - -template < - class T - > -inline -scheme_t scheme(const T &scheme) { - return scheme_t(scheme); -} - -template < - class T - > -struct host_t { - host_t(const T &host) - : host(host) { - - } - - const T &host; -}; - -template < - class T - > -inline -host_t host(const T &host) { - return host_t(host); -} - -template < - class T - > -struct path_t { - path_t(const T &path) - : path(path) { - - } - - const T &path; -}; - -template < - class T - > -inline -path_t path(const T &path) { - return path_t(path); -} -} // namespace builder - -template < - class Tag - > -class basic_builder { - -public: - -public: - - basic_builder(basic_uri &uri) - : uri_(uri) { - - } - - const basic_uri &uri() const { - return uri_; - } - -private: - basic_uri &uri_; -}; - -template < - class Tag - > -inline -basic_builder operator << (basic_uri &uri, const builder::scheme_t::type> &scheme) { - // uri.set_scheme( - return basic_builder(uri); -} - -template < - class Tag - > -inline -basic_builder &operator << (basic_builder &builder, const builder::scheme_t::type> &scheme) { - // uri.set_scheme( - return builder; -} - -template < - class Tag - > -inline -basic_builder &operator << (basic_builder &builder, const builder::host_t::type> &host) { - // uri.set_host( - return builder; -} - -template < - class Tag - > -inline -basic_builder &operator << (basic_builder &builder, const builder::path_t::type> &path) { - // uri.set_path( - return builder; -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_BUILDER_INC__ diff --git a/boost/network/uri/detail/parse_uri.hpp b/boost/network/uri/detail/parse_uri.hpp index 424bafd52..a4fa0969a 100644 --- a/boost/network/uri/detail/parse_uri.hpp +++ b/boost/network/uri/detail/parse_uri.hpp @@ -115,11 +115,10 @@ struct uri_grammar : qi::grammar()> { ; ipv6address %= qi::raw[ - //qi::lit("1080:0:0:0:8:800:200C:417A") qi::repeat(6)[h16 >> ':'] >> ls32 | "::" >> qi::repeat(5)[h16 >> ':'] >> ls32 | qi::raw[ h16] >> "::" >> qi::repeat(4)[h16 >> ':'] >> ls32 - | qi::raw[+(*(h16 >> ':')) >> h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 + | qi::raw[ +(*(h16 >> ':')) >> h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 | qi::raw[qi::repeat(2)[*(h16 >> ':')] >> h16] >> "::" >> qi::repeat(2)[h16 >> ':'] >> ls32 | qi::raw[qi::repeat(3)[*(h16 >> ':')] >> h16] >> "::" >> h16 >> ':' >> ls32 | qi::raw[qi::repeat(4)[*(h16 >> ':')] >> h16] >> "::" >> ls32 diff --git a/boost/network/uri/directives.hpp b/boost/network/uri/directives.hpp new file mode 100644 index 000000000..a389ac744 --- /dev/null +++ b/boost/network/uri/directives.hpp @@ -0,0 +1,37 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_INC__ + + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + + +namespace boost { +namespace network { +namespace uri { +template < + class Tag + , class Directive + > +inline +basic_uri &operator << (basic_uri &uri, const Directive &directive) { + directive(uri); + return uri; +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_INC__ diff --git a/boost/network/uri/directives/authority.hpp b/boost/network/uri/directives/authority.hpp new file mode 100644 index 000000000..78bc5aaf4 --- /dev/null +++ b/boost/network/uri/directives/authority.hpp @@ -0,0 +1,14 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ + + +namespace boost { +namespace network { +namespace uri { + +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ diff --git a/boost/network/uri/directives/fragment.hpp b/boost/network/uri/directives/fragment.hpp new file mode 100644 index 000000000..94b2b3cfd --- /dev/null +++ b/boost/network/uri/directives/fragment.hpp @@ -0,0 +1,14 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ + + +namespace boost { +namespace network { +namespace uri { + +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ diff --git a/boost/network/uri/directives/host.hpp b/boost/network/uri/directives/host.hpp new file mode 100644 index 000000000..360c584d7 --- /dev/null +++ b/boost/network/uri/directives/host.hpp @@ -0,0 +1,51 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ + + +namespace boost { +namespace network { +namespace uri { +template < + class ValueType + > +struct host_directive { + + explicit host_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + uri.append(value); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + uri.append(value); + } + + const ValueType &value; + +}; + +template < + class T + > +inline +host_directive host(const T &value) { + return host_directive(value); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ diff --git a/boost/network/uri/directives/path.hpp b/boost/network/uri/directives/path.hpp new file mode 100644 index 000000000..7d48092c3 --- /dev/null +++ b/boost/network/uri/directives/path.hpp @@ -0,0 +1,51 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_PATH_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_PATH_INC__ + + +namespace boost { +namespace network { +namespace uri { +template < + class ValueType + > +struct path_directive { + + explicit path_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + uri.append(value); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + uri.append(value); + } + + const ValueType &value; + +}; + +template < + class T + > +inline +path_directive path(const T &value) { + return path_directive(value); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_PATH_INC__ diff --git a/boost/network/uri/directives/port.hpp b/boost/network/uri/directives/port.hpp new file mode 100644 index 000000000..06eab0ba8 --- /dev/null +++ b/boost/network/uri/directives/port.hpp @@ -0,0 +1,14 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ + + +namespace boost { +namespace network { +namespace uri { + +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp new file mode 100644 index 000000000..c9f803a58 --- /dev/null +++ b/boost/network/uri/directives/query.hpp @@ -0,0 +1,14 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ + + +namespace boost { +namespace network { +namespace uri { + +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ diff --git a/boost/network/uri/directives/scheme.hpp b/boost/network/uri/directives/scheme.hpp new file mode 100644 index 000000000..ec07b103b --- /dev/null +++ b/boost/network/uri/directives/scheme.hpp @@ -0,0 +1,55 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ + + +namespace boost { +namespace network { +namespace uri { +template < + class ValueType + > +struct scheme_directive { + + explicit scheme_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + char separator[] = {':', '/', '/'}; + uri.append(value); + uri.append(boost::begin(separator), boost::end(separator)); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + char separator[] = {':', '/', '/'}; + uri.append(value); + uri.append(boost::begin(separator), boost::end(separator)); + } + + const ValueType &value; + +}; + +template < + class T + > +inline +scheme_directive scheme(const T &value) { + return scheme_directive(value); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ diff --git a/boost/network/uri/directives/user_info.hpp b/boost/network/uri/directives/user_info.hpp new file mode 100644 index 000000000..e4c6bd21d --- /dev/null +++ b/boost/network/uri/directives/user_info.hpp @@ -0,0 +1,14 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ + + +namespace boost { +namespace network { +namespace uri { + +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 4ccb4e19c..c6c95992b 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -193,6 +193,19 @@ class basic_uri return is_valid_; } + void append(const string_type &data) { + uri_.append(data); + parse(); + } + + template < + class Iterator + > + void append(Iterator first, Iterator last) { + uri_.append(first, last); + parse(); + } + private: void parse(); diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index fb0e9bcb0..3d6c147cf 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -18,7 +18,7 @@ if (Boost_FOUND) url_http_test url_mailto_test url_encoding_test - builder_test + url_builder_test ) foreach (test ${TESTS}) set_source_files_properties(${test}.cpp diff --git a/libs/network/test/uri/builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp similarity index 76% rename from libs/network/test/uri/builder_test.cpp rename to libs/network/test/uri/url_builder_test.cpp index 862d89f87..deb77d59e 100644 --- a/libs/network/test/uri/builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -7,18 +7,21 @@ #include #include #include -#include +#include #include #include #include #include +#include + + using namespace boost::network; typedef boost::mpl::list< tags::default_string -// , tags::default_wstring + , tags::default_wstring > tag_types; @@ -26,17 +29,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) { typedef uri::basic_uri uri_type; typedef typename uri_type::string_type string_type; - namespace urib = uri::builder; const std::string scheme("http"); const std::string host("www.example.com"); const std::string path("/"); uri_type instance; - uri::basic_builder builder(instance); - builder << urib::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << urib::host(string_type(boost::begin(host), boost::end(host))) - << urib::path(string_type(boost::begin(path), boost::end(path))) + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::path(string_type(boost::begin(path), boost::end(path))) ; BOOST_REQUIRE(uri::is_valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); diff --git a/libs/network/test/uri/url_mailto_test.cpp b/libs/network/test/uri/url_mailto_test.cpp index d3c931f15..8765748fe 100644 --- a/libs/network/test/uri/url_mailto_test.cpp +++ b/libs/network/test/uri/url_mailto_test.cpp @@ -15,7 +15,7 @@ using namespace boost::network; typedef boost::mpl::list< tags::default_string -// , tags::default_wstring + , tags::default_wstring > tag_types; From a1242bf20f8d1d0ce53ea49a7af6c4ef77d6df08 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Fri, 26 Aug 2011 22:49:12 +0200 Subject: [PATCH 155/768] Added more URI builder tests. --- .../uri/{uri_accessors.hpp => accessors.hpp} | 0 boost/network/uri/directives.hpp | 4 - boost/network/uri/directives/authority.hpp | 43 +++++ boost/network/uri/directives/fragment.hpp | 47 +++++ boost/network/uri/directives/host.hpp | 6 + boost/network/uri/directives/path.hpp | 15 +- boost/network/uri/directives/port.hpp | 78 +++++++++ boost/network/uri/directives/query.hpp | 117 +++++++++++++ boost/network/uri/directives/scheme.hpp | 10 +- boost/network/uri/directives/user_info.hpp | 47 +++++ boost/network/uri/encode.hpp | 1 + boost/network/uri/uri.hpp | 4 - boost/network/uri/uri_io.hpp | 23 +++ libs/network/example/simple_wget.cpp | 2 +- libs/network/test/uri/CMakeLists.txt | 50 +++--- libs/network/test/uri/url_builder_test.cpp | 164 +++++++++++++++++- libs/network/test/uri/url_test.cpp | 3 +- 17 files changed, 571 insertions(+), 43 deletions(-) rename boost/network/uri/{uri_accessors.hpp => accessors.hpp} (100%) create mode 100644 boost/network/uri/uri_io.hpp diff --git a/boost/network/uri/uri_accessors.hpp b/boost/network/uri/accessors.hpp similarity index 100% rename from boost/network/uri/uri_accessors.hpp rename to boost/network/uri/accessors.hpp diff --git a/boost/network/uri/directives.hpp b/boost/network/uri/directives.hpp index a389ac744..233c630ca 100644 --- a/boost/network/uri/directives.hpp +++ b/boost/network/uri/directives.hpp @@ -11,10 +11,6 @@ # include # include # include -# include -# include -# include -# include namespace boost { diff --git a/boost/network/uri/directives/authority.hpp b/boost/network/uri/directives/authority.hpp index 78bc5aaf4..e7d135f92 100644 --- a/boost/network/uri/directives/authority.hpp +++ b/boost/network/uri/directives/authority.hpp @@ -2,10 +2,53 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { +template < + class ValueType + > +struct authority_directive { + + explicit authority_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + uri.append(value); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + uri.append(value); + } + + const ValueType &value; + +}; +template < + class T + > +inline +authority_directive authority(const T &value) { + return authority_directive(value); +} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/fragment.hpp b/boost/network/uri/directives/fragment.hpp index 94b2b3cfd..ef7a01c21 100644 --- a/boost/network/uri/directives/fragment.hpp +++ b/boost/network/uri/directives/fragment.hpp @@ -2,10 +2,57 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { +template < + class ValueType + > +struct fragment_directive { + + explicit fragment_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + static const char separator[] = {'#'}; + uri.append(boost::begin(separator), boost::end(separator)); + uri.append(value); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + static const char separator[] = {'#'}; + uri.append(boost::begin(separator), boost::end(separator)); + uri.append(value); + } + + const ValueType &value; + +}; +template < + class T + > +inline +fragment_directive fragment(const T &value) { + return fragment_directive(value); +} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/host.hpp b/boost/network/uri/directives/host.hpp index 360c584d7..d82d17489 100644 --- a/boost/network/uri/directives/host.hpp +++ b/boost/network/uri/directives/host.hpp @@ -2,6 +2,12 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { diff --git a/boost/network/uri/directives/path.hpp b/boost/network/uri/directives/path.hpp index 7d48092c3..697c1d423 100644 --- a/boost/network/uri/directives/path.hpp +++ b/boost/network/uri/directives/path.hpp @@ -2,6 +2,13 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_PATH_INC__ +# include +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { @@ -20,7 +27,9 @@ struct path_directive { > typename enable_if, void>::type operator () (Uri &uri) const { - uri.append(value); + typename string::type encoded_value; + encode(boost::begin(value), boost::end(value), std::back_inserter(encoded_value)); + uri.append(encoded_value); } template < @@ -29,7 +38,9 @@ struct path_directive { > typename enable_if >, void>::type operator () (Uri &uri) const { - uri.append(value); + typename string::type encoded_value; + encode(boost::begin(value), boost::end(value), std::back_inserter(encoded_value)); + uri.append(encoded_value); } const ValueType &value; diff --git a/boost/network/uri/directives/port.hpp b/boost/network/uri/directives/port.hpp index 06eab0ba8..59e2d9a4c 100644 --- a/boost/network/uri/directives/port.hpp +++ b/boost/network/uri/directives/port.hpp @@ -2,10 +2,88 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ +# include +# include +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { +template < + class ValueType + > +struct port_directive { + + explicit port_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + static const char separator[] = {':'}; + uri.append(boost::begin(separator), boost::end(separator)); + uri.append(value); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + static const char separator[] = {':'}; + uri.append(boost::begin(separator), boost::end(separator)); + uri.append(value); + } + + const ValueType &value; + +}; + + +struct port_directive_us { + + explicit port_directive_us(boost::uint16_t value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + void operator () (Uri &uri) const { + static const char separator[] = {':'}; + uri.append(boost::begin(separator), boost::end(separator)); + typename string::type port = boost::lexical_cast::type>(value); + uri.append(port); + } + + boost::uint16_t value; + +}; + + +template < + class T + > +inline +port_directive port(const T &value, + typename boost::disable_if::type>::type * = 0) { + return port_directive(value); +} +inline +port_directive_us port(boost::uint16_t value) { + return port_directive_us(value); +} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp index c9f803a58..3908c8820 100644 --- a/boost/network/uri/directives/query.hpp +++ b/boost/network/uri/directives/query.hpp @@ -2,10 +2,127 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { +template < + class ValueType + > +struct query_directive { + + explicit query_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + static const char separator[] = {'?'}; + uri.append(boost::begin(separator), boost::end(separator)); + uri.append(value); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + static const char separator[] = {'?'}; + uri.append(boost::begin(separator), boost::end(separator)); + uri.append(value); + } + + const ValueType &value; + +}; + +template < + class T + > +inline +query_directive query(const T &value) { + return query_directive(value); +} + +template < + class KeyType + , class ValueType + > +struct query_key_value_directive { + + query_key_value_directive(const KeyType &key, const ValueType &value) + : key(key), value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + static const char separator_1[] = {'?'}; + static const char separator_2[] = {'='}; + static const char separator_3[] = {';'}; + if (!uri.query_range()) + { + uri.append(boost::begin(separator_1), boost::end(separator_1)); + } + else + { + uri.append(boost::begin(separator_3), boost::end(separator_3)); + } + uri.append(key); + uri.append(boost::begin(separator_2), boost::end(separator_2)); + typename string::type encoded_value; + encode(boost::begin(value), boost::end(value), std::back_inserter(encoded_value)); + uri.append(encoded_value); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + static const char separator_1[] = {'?'}; + static const char separator_2[] = {'='}; + static const char separator_3[] = {';'}; + if (!uri.query_range()) + { + uri.append(boost::begin(separator_1), boost::end(separator_1)); + } + else + { + uri.append(boost::begin(separator_3), boost::end(separator_3)); + } + uri.append(key); + uri.append(boost::begin(separator_2), boost::end(separator_2)); + uri.append(value); + } + + const KeyType &key; + const ValueType &value; + +}; +template < + class Key + , class Value + > +inline +query_key_value_directive query(const Key &key, const Value &value) { + return query_key_value_directive(key, value); +} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/scheme.hpp b/boost/network/uri/directives/scheme.hpp index ec07b103b..3ac337704 100644 --- a/boost/network/uri/directives/scheme.hpp +++ b/boost/network/uri/directives/scheme.hpp @@ -2,6 +2,12 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { @@ -20,7 +26,7 @@ struct scheme_directive { > typename enable_if, void>::type operator () (Uri &uri) const { - char separator[] = {':', '/', '/'}; + static const char separator[] = {':', '/', '/'}; uri.append(value); uri.append(boost::begin(separator), boost::end(separator)); } @@ -31,7 +37,7 @@ struct scheme_directive { > typename enable_if >, void>::type operator () (Uri &uri) const { - char separator[] = {':', '/', '/'}; + static const char separator[] = {':', '/', '/'}; uri.append(value); uri.append(boost::begin(separator), boost::end(separator)); } diff --git a/boost/network/uri/directives/user_info.hpp b/boost/network/uri/directives/user_info.hpp index e4c6bd21d..871123ffd 100644 --- a/boost/network/uri/directives/user_info.hpp +++ b/boost/network/uri/directives/user_info.hpp @@ -2,10 +2,57 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { +template < + class ValueType + > +struct user_info_directive { + + explicit user_info_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + static const char separator[] = {'@'}; + uri.append(value); + uri.append(boost::begin(separator), boost::end(separator)); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + static const char separator[] = {'@'}; + uri.append(value); + uri.append(boost::begin(separator), boost::end(separator)); + } + + const ValueType &value; + +}; +template < + class T + > +inline +user_info_directive user_info(const T &value) { + return user_info_directive(value); +} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/encode.hpp b/boost/network/uri/encode.hpp index 18b344ee5..39d3da47f 100644 --- a/boost/network/uri/encode.hpp +++ b/boost/network/uri/encode.hpp @@ -121,6 +121,7 @@ void encode_char(CharT in, OutputIterator &out) { case '.': case '_': case '~': + case '/': out++ = in; break; default: diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index c6c95992b..2e3d916e2 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -185,10 +185,6 @@ class basic_uri return uri_; } - string_type raw() const { - return string(); - } - bool is_valid() const { return is_valid_; } diff --git a/boost/network/uri/uri_io.hpp b/boost/network/uri/uri_io.hpp new file mode 100644 index 000000000..efff221f4 --- /dev/null +++ b/boost/network/uri/uri_io.hpp @@ -0,0 +1,23 @@ +#ifndef __BOOST_NETWORK_URI_URI_IO_INC__ +# define __BOOST_NETWORK_URI_URI_IO_INC__ + + +# include + + +namespace boost { +namespace network { +namespace uri { +template < + class Tag + > +inline +std::ostream &operator << (std::ostream &os, const basic_uri &uri) { + return os << uri.string(); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_URI_IO_INC__ diff --git a/libs/network/example/simple_wget.cpp b/libs/network/example/simple_wget.cpp index 464652016..45821f447 100644 --- a/libs/network/example/simple_wget.cpp +++ b/libs/network/example/simple_wget.cpp @@ -29,7 +29,7 @@ namespace { template < class Tag > -std::string get_filename(const uri::http::basic_uri &url) { +std::string get_filename(const uri::basic_uri &url) { std::string path = uri::path(url); std::size_t index = path.find_last_of('/'); std::string filename = path.substr(index + 1); diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index 3d6c147cf..5ca9fb1de 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -7,31 +7,29 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) find_package( Boost 1.41.0 COMPONENTS unit_test_framework system regex date_time filesystem ) find_package( OpenSSL ) find_package( Threads ) -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_MULTITHREADED ON) - if (Boost_FOUND) - set( - TESTS - url_test - url_http_test - url_mailto_test - url_encoding_test - url_builder_test - ) - foreach (test ${TESTS}) - set_source_files_properties(${test}.cpp - PROPERTIES COMPILE_FLAGS "-Wall") - add_executable(cpp-netlib-${test} ${test}.cpp) - add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) - if (OPENSSL_FOUND) - target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) - endif() - set_target_properties(cpp-netlib-${test} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) - add_test(cpp-netlib-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) - endforeach (test) - -endif() + set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_MULTITHREADED ON) + set( + TESTS + url_test + url_http_test + url_mailto_test + url_encoding_test + url_builder_test + ) + foreach (test ${TESTS}) + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") + add_executable(cpp-netlib-${test} ${test}.cpp) + add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) + target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + if (OPENSSL_FOUND) + target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) + endif() + set_target_properties(cpp-netlib-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) + endforeach (test) +endif(Boost_FOUND) diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index deb77d59e..d1d666d7b 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -8,15 +8,14 @@ #include #include #include +#include +#include #include #include #include #include -#include - - using namespace boost::network; typedef boost::mpl::list< @@ -45,3 +44,162 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); } + +BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_builder_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string user_info("user:password"); + const std::string host("www.example.com"); + const std::string port("80"); + const std::string path("/path"); + const std::string query("query"); + const std::string fragment("fragment"); + + uri_type instance; + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::user_info(string_type(boost::begin(user_info), boost::end(user_info))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::port(string_type(boost::begin(port), boost::end(port))) + << uri::path(string_type(boost::begin(path), boost::end(path))) + << uri::query(string_type(boost::begin(query), boost::end(query))) + << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))) + ; + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK_EQUAL(static_cast(uri::port_us(instance)), 80); + BOOST_CHECK(boost::equal(uri::port(instance), port)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::query(instance), query)); + BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(port_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string port("8000"); + const std::string path("/"); + + uri_type instance; + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::port(8000) << uri::path("/"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::port(8000) + << uri::path(string_type(boost::begin(path), boost::end(path))) + ; + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::port(instance), port)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string port("8000"); + const std::string encoded_path("/Path%20With%20%28Some%29%20Encoded%20Characters%21"); + const std::string decoded_path("/Path With (Some) Encoded Characters!"); + + uri_type instance; + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::port(8000) + << uri::path(string_type(boost::begin(decoded_path), boost::end(decoded_path))) + ; + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::port(instance), port)); + BOOST_CHECK(boost::equal(uri::path(instance), encoded_path)); + BOOST_CHECK(boost::equal(uri::decoded_path(instance), decoded_path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(query_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + const std::string query("key=value"); + const std::string query_key("key"); + const std::string query_value("value"); + + uri_type instance; + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::path(string_type(boost::begin(path), boost::end(path))) + << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), + string_type(boost::begin(query_value), boost::end(query_value))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::query(instance), query)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(query_2_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + const std::string query("key=value;key=value"); + const std::string query_key("key"); + const std::string query_value("value"); + + uri_type instance; + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::path(string_type(boost::begin(path), boost::end(path))) + << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), + string_type(boost::begin(query_value), boost::end(query_value))) + << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), + string_type(boost::begin(query_value), boost::end(query_value))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::query(instance), query)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + const std::string fragment("fragment"); + + uri_type instance; + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") << uri::fragment("fragment"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::path(string_type(boost::begin(path), boost::end(path))) + << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); +} diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index a5ba2af51..b0a313168 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -18,6 +18,7 @@ using namespace boost::network; + typedef boost::mpl::list< tags::default_string , tags::default_wstring From 21015f7f8a1e868975079335b22947f0523086fc Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 27 Aug 2011 22:16:16 +0200 Subject: [PATCH 156/768] Updated the builder directives & tests; added a very short example. --- boost/network/uri/decode.hpp | 7 ++- boost/network/uri/directives/authority.hpp | 18 +----- boost/network/uri/directives/fragment.hpp | 25 +++----- boost/network/uri/directives/host.hpp | 18 +----- boost/network/uri/directives/path.hpp | 47 +++++++++++---- boost/network/uri/directives/port.hpp | 19 +------ boost/network/uri/directives/query.hpp | 66 ++++++---------------- boost/network/uri/directives/scheme.hpp | 48 ++++++++++------ boost/network/uri/directives/user_info.hpp | 20 +------ boost/network/uri/encode.hpp | 8 ++- boost/network/uri/uri.hpp | 4 ++ libs/network/example/CMakeLists.txt | 3 + libs/network/example/uri_builder.cpp | 25 ++++++++ libs/network/test/uri/url_builder_test.cpp | 46 ++++++++++++++- 14 files changed, 189 insertions(+), 165 deletions(-) create mode 100644 libs/network/example/uri_builder.cpp diff --git a/boost/network/uri/decode.hpp b/boost/network/uri/decode.hpp index e56e3f6e8..7f1441f26 100644 --- a/boost/network/uri/decode.hpp +++ b/boost/network/uri/decode.hpp @@ -59,7 +59,9 @@ template < class InputIterator, class OutputIterator > -OutputIterator decode(const InputIterator &in_begin, const InputIterator &in_end, const OutputIterator &out_begin) { +OutputIterator decode(const InputIterator &in_begin, + const InputIterator &in_end, + const OutputIterator &out_begin) { typedef typename boost::iterator_value::type value_type; InputIterator it = in_begin; @@ -87,7 +89,8 @@ template < class OutputIterator > inline -OutputIterator decode(const SinglePassRange &range, const OutputIterator &out) { +OutputIterator decode(const SinglePassRange &range, + const OutputIterator &out) { return decode(boost::begin(range), boost::end(range), out); } } // namespace uri diff --git a/boost/network/uri/directives/authority.hpp b/boost/network/uri/directives/authority.hpp index e7d135f92..6e723cfe8 100644 --- a/boost/network/uri/directives/authority.hpp +++ b/boost/network/uri/directives/authority.hpp @@ -2,10 +2,8 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ -# include -# include -# include -# include +# include + namespace boost { @@ -24,17 +22,7 @@ struct authority_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - uri.append(value); - } - - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { uri.append(value); } diff --git a/boost/network/uri/directives/fragment.hpp b/boost/network/uri/directives/fragment.hpp index ef7a01c21..809f1f8a7 100644 --- a/boost/network/uri/directives/fragment.hpp +++ b/boost/network/uri/directives/fragment.hpp @@ -2,10 +2,9 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ -# include -# include -# include -# include +# include +# include +# include namespace boost { @@ -24,22 +23,12 @@ struct fragment_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { + typename string::type encoded_value; static const char separator[] = {'#'}; uri.append(boost::begin(separator), boost::end(separator)); - uri.append(value); - } - - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { - static const char separator[] = {'#'}; - uri.append(boost::begin(separator), boost::end(separator)); - uri.append(value); + encode(boost::as_literal(value), std::back_inserter(encoded_value)); + uri.append(encoded_value); } const ValueType &value; diff --git a/boost/network/uri/directives/host.hpp b/boost/network/uri/directives/host.hpp index d82d17489..e251edb84 100644 --- a/boost/network/uri/directives/host.hpp +++ b/boost/network/uri/directives/host.hpp @@ -2,10 +2,8 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ -# include -# include -# include -# include +# include +# include namespace boost { @@ -24,17 +22,7 @@ struct host_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - uri.append(value); - } - - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { uri.append(value); } diff --git a/boost/network/uri/directives/path.hpp b/boost/network/uri/directives/path.hpp index 697c1d423..d2b1afd5a 100644 --- a/boost/network/uri/directives/path.hpp +++ b/boost/network/uri/directives/path.hpp @@ -3,10 +3,7 @@ # include -# include -# include -# include -# include +# include namespace boost { @@ -25,21 +22,39 @@ struct path_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - typename string::type encoded_value; - encode(boost::begin(value), boost::end(value), std::back_inserter(encoded_value)); - uri.append(encoded_value); + void operator () (Uri &uri) const { + (*this)(boost::as_literal(value), uri); + } + + template < + class Rng + , class Tag + , template class Uri + > + void operator () (const Rng &rng, Uri &uri) const { + uri.append(boost::begin(rng), boost::end(rng)); } + const ValueType &value; + +}; + +template < + class ValueType + > +struct encoded_path_directive { + + explicit encoded_path_directive(const ValueType &value) + : value(value) + {} + template < class Tag , template class Uri > - typename enable_if >, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { typename string::type encoded_value; - encode(boost::begin(value), boost::end(value), std::back_inserter(encoded_value)); + encode(boost::as_literal(value), std::back_inserter(encoded_value)); uri.append(encoded_value); } @@ -54,6 +69,14 @@ inline path_directive path(const T &value) { return path_directive(value); } + +template < + class T + > +inline +encoded_path_directive encoded_path(const T &value) { + return encoded_path_directive(value); +} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/port.hpp b/boost/network/uri/directives/port.hpp index 59e2d9a4c..ae3a9bb88 100644 --- a/boost/network/uri/directives/port.hpp +++ b/boost/network/uri/directives/port.hpp @@ -2,12 +2,11 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ -# include # include -# include -# include # include # include +# include +# include namespace boost { @@ -26,19 +25,7 @@ struct port_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - static const char separator[] = {':'}; - uri.append(boost::begin(separator), boost::end(separator)); - uri.append(value); - } - - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { static const char separator[] = {':'}; uri.append(boost::begin(separator), boost::end(separator)); uri.append(value); diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp index 3908c8820..59eb2ea06 100644 --- a/boost/network/uri/directives/query.hpp +++ b/boost/network/uri/directives/query.hpp @@ -2,10 +2,9 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ -# include -# include -# include -# include +# include +# include +# include namespace boost { @@ -24,19 +23,8 @@ struct query_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - static const char separator[] = {'?'}; - uri.append(boost::begin(separator), boost::end(separator)); - uri.append(value); - } - - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { + typename string::type encoded_value; static const char separator[] = {'?'}; uri.append(boost::begin(separator), boost::end(separator)); uri.append(value); @@ -68,48 +56,26 @@ struct query_key_value_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - static const char separator_1[] = {'?'}; - static const char separator_2[] = {'='}; - static const char separator_3[] = {';'}; + void operator () (Uri &uri) const { + typename string::type encoded_key, encoded_value; + static const char qmark[] = {'?'}; + static const char equal[] = {'='}; + static const char scolon[] = {';'}; if (!uri.query_range()) { - uri.append(boost::begin(separator_1), boost::end(separator_1)); + uri.append(boost::begin(qmark), boost::end(qmark)); } else { - uri.append(boost::begin(separator_3), boost::end(separator_3)); + uri.append(boost::begin(scolon), boost::end(scolon)); } - uri.append(key); - uri.append(boost::begin(separator_2), boost::end(separator_2)); - typename string::type encoded_value; - encode(boost::begin(value), boost::end(value), std::back_inserter(encoded_value)); + encode(boost::as_literal(key), std::back_inserter(encoded_key)); + uri.append(encoded_key); + uri.append(boost::begin(equal), boost::end(equal)); + encode(boost::as_literal(value), std::back_inserter(encoded_value)); uri.append(encoded_value); } - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { - static const char separator_1[] = {'?'}; - static const char separator_2[] = {'='}; - static const char separator_3[] = {';'}; - if (!uri.query_range()) - { - uri.append(boost::begin(separator_1), boost::end(separator_1)); - } - else - { - uri.append(boost::begin(separator_3), boost::end(separator_3)); - } - uri.append(key); - uri.append(boost::begin(separator_2), boost::end(separator_2)); - uri.append(value); - } - const KeyType &key; const ValueType &value; diff --git a/boost/network/uri/directives/scheme.hpp b/boost/network/uri/directives/scheme.hpp index 3ac337704..27726ac30 100644 --- a/boost/network/uri/directives/scheme.hpp +++ b/boost/network/uri/directives/scheme.hpp @@ -2,10 +2,8 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ -# include -# include -# include -# include +# include +# include namespace boost { @@ -24,19 +22,7 @@ struct scheme_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - static const char separator[] = {':', '/', '/'}; - uri.append(value); - uri.append(boost::begin(separator), boost::end(separator)); - } - - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { static const char separator[] = {':', '/', '/'}; uri.append(value); uri.append(boost::begin(separator), boost::end(separator)); @@ -53,6 +39,34 @@ inline scheme_directive scheme(const T &value) { return scheme_directive(value); } + +namespace schemes { +struct scheme_helper { + + scheme_helper(const char *scheme) + : scheme(scheme) { + + } + + template < + class Tag + , template class Uri + > + void operator () (Uri &uri) const { + static const char separator[] = {':', '/', '/'}; + uri.append(boost::begin(scheme), boost::end(scheme)); + uri.append(boost::begin(separator), boost::end(separator)); + } + + std::string scheme; + +}; + +//static scheme_helper http("http"); +//static scheme_helper https("https"); +//static scheme_helper ftp("ftp"); +//static scheme_helper mailto("mailto"); +} // namespace schemes } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/user_info.hpp b/boost/network/uri/directives/user_info.hpp index 871123ffd..881700a6a 100644 --- a/boost/network/uri/directives/user_info.hpp +++ b/boost/network/uri/directives/user_info.hpp @@ -2,10 +2,8 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ -# include -# include -# include -# include +# include +# include namespace boost { @@ -24,19 +22,7 @@ struct user_info_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - static const char separator[] = {'@'}; - uri.append(value); - uri.append(boost::begin(separator), boost::end(separator)); - } - - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { static const char separator[] = {'@'}; uri.append(value); uri.append(boost::begin(separator), boost::end(separator)); diff --git a/boost/network/uri/encode.hpp b/boost/network/uri/encode.hpp index 39d3da47f..4c1d2fcee 100644 --- a/boost/network/uri/encode.hpp +++ b/boost/network/uri/encode.hpp @@ -9,6 +9,7 @@ # include +# include # include # include # include @@ -137,7 +138,9 @@ template < class InputIterator, class OutputIterator > -OutputIterator encode(const InputIterator &in_begin, const InputIterator &in_end, const OutputIterator &out_begin) { +OutputIterator encode(const InputIterator &in_begin, + const InputIterator &in_end, + const OutputIterator &out_begin) { typedef typename boost::iterator_value::type value_type; InputIterator it = in_begin; @@ -154,7 +157,8 @@ template < class OutputIterator > inline -OutputIterator encode(const SinglePassRange &range, const OutputIterator &out) { +OutputIterator encode(const SinglePassRange &range, + const OutputIterator &out) { return encode(boost::begin(range), boost::end(range), out); } } // namespace uri diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 2e3d916e2..fe7c8e264 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -361,4 +361,8 @@ bool operator == (const basic_uri &lhs, const basic_uri &rhs) { } // namespace boost +# include +# include + + #endif // __BOOST_NETWORK_URI_INC__ diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 2eccb3c3e..5bf5d4510 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -17,6 +17,7 @@ if (Boost_FOUND) add_executable(hello_world_server http/hello_world_server.cpp) add_executable(fileserver http/fileserver.cpp) add_executable(uri uri.cpp) + add_executable(uri_builder uri_builder.cpp) add_dependencies(http_client cppnetlib-uri-parsers cppnetlib-client-connections) add_dependencies(simple_wget cppnetlib-uri-parsers cppnetlib-client-connections) add_dependencies(uri cppnetlib-uri-parsers) @@ -25,9 +26,11 @@ if (Boost_FOUND) target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} ) target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) target_link_libraries(uri cppnetlib-uri-parsers) + target_link_libraries(uri_builder cppnetlib-uri-parsers) set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + set_target_properties(uri_builder PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) endif() diff --git a/libs/network/example/uri_builder.cpp b/libs/network/example/uri_builder.cpp new file mode 100644 index 000000000..e37160d0b --- /dev/null +++ b/libs/network/example/uri_builder.cpp @@ -0,0 +1,25 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include +#include +#include + + +using namespace boost::network; + + +int +main(int argc, char *argv[]) { + + uri::uri url; + url << uri::scheme("http") + << uri::host("www.github.com") + << uri::path("/cpp-netlib"); + std::cout << url << std::endl; + + return 0; +} diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index d1d666d7b..6135cc0b3 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -117,7 +117,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, tag_types) instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) << uri::host(string_type(boost::begin(host), boost::end(host))) << uri::port(8000) - << uri::path(string_type(boost::begin(decoded_path), boost::end(decoded_path))) + << uri::encoded_path(string_type(boost::begin(decoded_path), boost::end(decoded_path))) + //<< uri::path(uri::encoded(string_type(boost::begin(decoded_path), boost::end(decoded_path)))) ; BOOST_REQUIRE(uri::is_valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); @@ -203,3 +204,46 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, tag_types) BOOST_CHECK(boost::equal(uri::path(instance), path)); BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); } + +//BOOST_AUTO_TEST_CASE_TEMPLATE(scheme_test, T, tag_types) +//{ +// typedef uri::basic_uri uri_type; +// typedef typename uri_type::string_type string_type; +// +// const std::string scheme("http"); +// const std::string host("www.example.com"); +// const std::string path("/"); +// +// uri_type instance; +// //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); +// instance << uri::schemes::http +// << uri::host(string_type(boost::begin(host), boost::end(host))) +// << uri::path(string_type(boost::begin(path), boost::end(path))) +// ; +// BOOST_REQUIRE(uri::is_valid(instance)); +// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); +// BOOST_CHECK(boost::equal(uri::host(instance), host)); +// BOOST_CHECK(boost::equal(uri::path(instance), path)); +//} + +BOOST_AUTO_TEST_CASE(encoded_null_char_test) +{ + typedef uri::basic_uri uri_type; + typedef uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + + uri_type instance; + // there is a potential bug in the way we process ranges if the + // strings are null terminated. + instance << uri::scheme("http") + << uri::host("www.example.com") + << uri::encoded_path("/") + ; + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK_EQUAL(uri::scheme(instance), scheme); + BOOST_CHECK_EQUAL(uri::host(instance), host); + BOOST_CHECK_EQUAL(uri::path(instance), path); +} From c76a1fc4b363ebb452254ce19f5001637a7ba1ab Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Wed, 17 Aug 2011 22:11:14 +0200 Subject: [PATCH 157/768] Cleaned up example build file so that it can build on MSVC. --- .../protocol/http/message/async_message.hpp | 1 + libs/network/example/CMakeLists.txt | 54 ++++++++++--------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/boost/network/protocol/http/message/async_message.hpp b/boost/network/protocol/http/message/async_message.hpp index 493b474ba..f7580b1f7 100644 --- a/boost/network/protocol/http/message/async_message.hpp +++ b/boost/network/protocol/http/message/async_message.hpp @@ -11,6 +11,7 @@ #include #include +#include //FIXME move this out to a trait #include diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 5bf5d4510..a5693b2d2 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -6,31 +6,35 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) find_package( Boost 1.41.0 COMPONENTS program_options system regex date_time thread filesystem ) find_package( OpenSSL ) -include_directories(${OPENSSL_INCLUDE_DIR}) find_package( Threads ) -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_MULTITHREADED ON) if (Boost_FOUND) - add_executable(http_client http_client.cpp) - add_executable(simple_wget simple_wget.cpp) - add_executable(hello_world_server http/hello_world_server.cpp) - add_executable(fileserver http/fileserver.cpp) - add_executable(uri uri.cpp) - add_executable(uri_builder uri_builder.cpp) - add_dependencies(http_client cppnetlib-uri-parsers cppnetlib-client-connections) - add_dependencies(simple_wget cppnetlib-uri-parsers cppnetlib-client-connections) - add_dependencies(uri cppnetlib-uri-parsers) - target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers cppnetlib-client-connections) - target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers cppnetlib-client-connections) - target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} ) - target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) - target_link_libraries(uri cppnetlib-uri-parsers) - target_link_libraries(uri_builder cppnetlib-uri-parsers) - set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) - set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) - set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) - set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) - set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) - set_target_properties(uri_builder PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -endif() + set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_MULTITHREADED ON) +endif (Boost_FOUND) + +if (OPENSSL_FOUND) + include_directories(${OPENSSL_INCLUDE_DIR}) +endif (OPENSSL_FOUND) + +add_executable(http_client http_client.cpp) +add_executable(simple_wget simple_wget.cpp) +add_executable(hello_world_server http/hello_world_server.cpp) +add_executable(fileserver http/fileserver.cpp) +add_executable(uri uri.cpp) +add_executable(uri_builder uri_builder.cpp) +add_dependencies(http_client cppnetlib-uri-parsers) +add_dependencies(simple_wget cppnetlib-uri-parsers) +add_dependencies(uri cppnetlib-uri-parsers) +target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) +target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) +target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) +target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) +target_link_libraries(uri cppnetlib-uri-parsers) +target_link_libraries(uri_builder cppnetlib-uri-parsers) +set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(uri_builder PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) From 1247c76d0fba77edfeb3a7fd800abbec548fceb2 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 6 Aug 2011 18:40:42 +0200 Subject: [PATCH 158/768] Modified some code to get as much working on MSVC 10 as possible. There is still a compiler error in protocol/http/algorithms/linearize.hpp. --- CMakeLists.txt | 12 +++- .../http/policies/simple_connection.hpp | 8 +-- libs/network/example/CMakeLists.txt | 59 +++++++++++-------- libs/network/test/http/http_test_server.hpp | 24 ++++---- 4 files changed, 61 insertions(+), 42 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eba49491b..cde6f5ef8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,13 @@ if (Boost_FOUND) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTI_THREADED ON) include_directories(${Boost_INCLUDE_DIRS}) -endif() +endif(Boost_FOUND) +if (MSVC) + add_definitions(-D_SCL_SECURE_NO_WARNINGS) +endif(MSVC) +if (WIN32) + add_definitions(-D_WIN32_WINNT=0x0501) +endif(WIN32) enable_testing() if (OPENSSL_FOUND) @@ -26,6 +32,8 @@ endif() add_subdirectory(libs/network/src) add_subdirectory(libs/network/test) -add_subdirectory(libs/mime/test) +if (NOT MSVC) + add_subdirectory(libs/mime/test) +endif(NOT_MSVC) add_subdirectory(libs/network/example) diff --git a/boost/network/protocol/http/policies/simple_connection.hpp b/boost/network/protocol/http/policies/simple_connection.hpp index 72f6a6974..16d9fd1a8 100644 --- a/boost/network/protocol/http/policies/simple_connection.hpp +++ b/boost/network/protocol/http/policies/simple_connection.hpp @@ -30,9 +30,9 @@ namespace boost { namespace network { namespace http { typedef function const &, system::error_code const &)> body_callback_function_type; struct connection_impl { - connection_impl(resolver_type & resolver, bool follow_redirect, string_type const & hostname, string_type const & port, resolver_function_type resolve, bool https, optional const & certificate_filename = optional(), optional const & verify_path = optional()) + connection_impl(resolver_type & resolver, bool follow_redirect, string_type const & hostname, string_type const & port, resolver_function_type resolve, bool https, optional const & certificate_filename = optional(), optional const & verify_path = optional()) : pimpl() - , follow_redirect_(follow_redirect) + , follow_redirect_(follow_redirect) { pimpl.reset(impl::sync_connection_base::new_connection(resolver, resolve, https, certificate_filename, verify_path)); } @@ -55,7 +55,7 @@ namespace boost { namespace network { namespace http { boost::uint16_t status = response_.status(); if (status >= 300 && status <= 307) { typename headers_range >::type location_range = headers(response_)["Location"]; - typename range_iterator >::type>::type location_header = boost::begin(location_range); + typename range_iterator >::type>::type location_header = boost::begin(location_range); if (location_header != boost::end(location_range)) { request_.uri(location_header->second); } else throw std::runtime_error("Location header not defined in redirect response."); @@ -98,7 +98,7 @@ namespace boost { namespace network { namespace http { void cleanup() { } - simple_connection_policy(bool cache_resolved, bool follow_redirect) + simple_connection_policy(bool cache_resolved, bool follow_redirect) : resolver_base(cache_resolved), follow_redirect_(follow_redirect) {} // member variables diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index a5693b2d2..e975c9902 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -9,32 +9,43 @@ find_package( OpenSSL ) find_package( Threads ) if (Boost_FOUND) - set(Boost_USE_STATIC_LIBS ON) - set(Boost_USE_MULTITHREADED ON) + set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_MULTITHREADED ON) endif (Boost_FOUND) if (OPENSSL_FOUND) - include_directories(${OPENSSL_INCLUDE_DIR}) + include_directories(${OPENSSL_INCLUDE_DIR}) endif (OPENSSL_FOUND) -add_executable(http_client http_client.cpp) -add_executable(simple_wget simple_wget.cpp) -add_executable(hello_world_server http/hello_world_server.cpp) -add_executable(fileserver http/fileserver.cpp) -add_executable(uri uri.cpp) -add_executable(uri_builder uri_builder.cpp) -add_dependencies(http_client cppnetlib-uri-parsers) -add_dependencies(simple_wget cppnetlib-uri-parsers) -add_dependencies(uri cppnetlib-uri-parsers) -target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) -target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) -target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) -target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) -target_link_libraries(uri cppnetlib-uri-parsers) -target_link_libraries(uri_builder cppnetlib-uri-parsers) -set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(uri_builder PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +if (Boost_FOUND) + add_executable(http_client http_client.cpp) + add_dependencies(http_client cppnetlib-uri-parsers) + target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + + add_executable(simple_wget simple_wget.cpp) + add_dependencies(simple_wget cppnetlib-uri-parsers) + target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + + add_executable(hello_world_server http/hello_world_server.cpp) + target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) + set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + + if (UNIX) + add_executable(fileserver http/fileserver.cpp) + target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) + set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + endif (UNIX) + + add_executable(uri uri.cpp) + add_dependencies(uri cppnetlib-uri-parsers) + target_link_libraries(uri cppnetlib-uri-parsers) + set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + + add_executable(uri_builder uri_builder.cpp) + add_dependencies(uri_builder cppnetlib-uri-parsers) + target_link_libraries(uri_builder cppnetlib-uri-parsers) + set_target_properties(uri_builder PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + +endif() diff --git a/libs/network/test/http/http_test_server.hpp b/libs/network/test/http/http_test_server.hpp index 0f19ce95c..293c9d9d8 100644 --- a/libs/network/test/http/http_test_server.hpp +++ b/libs/network/test/http/http_test_server.hpp @@ -1,4 +1,4 @@ -// +// // Copyright Kim Grasman 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -16,14 +16,14 @@ #include // ShellExecuteEx - #include + #include #pragma comment( lib, "shell32" ) #else #include // fork, execlp etc. #include #include // for waitpid #include // for chmod - #include // for kill + #include // for kill #endif struct http_test_server @@ -61,7 +61,7 @@ struct http_test_server boost::filesystem::path get_server_path(const boost::filesystem::path& base_path) { using namespace boost::filesystem; - const path script_name = + const path script_name = #if defined(HTTPS_SERVER_TEST) "https_test_server.py" #else @@ -84,8 +84,8 @@ struct http_test_server script_handle_t launch_python_script(const boost::filesystem::path& python_script_path) { using namespace boost::filesystem; - path::string_type script_name = python_script_path.filename().string(); - path::string_type script_dir = python_script_path.parent_path().string(); + path::string_type script_name = python_script_path.filename().native(); + path::string_type script_dir = python_script_path.parent_path().native(); #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) SHELLEXECUTEINFOA sei = {0}; @@ -93,8 +93,8 @@ struct http_test_server sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI; sei.lpVerb = "open"; sei.lpFile = "python.exe"; - sei.lpParameters = script_name.c_str(); - sei.lpDirectory = script_dir.c_str(); + sei.lpParameters = reinterpret_cast(script_name.c_str()); + sei.lpDirectory = reinterpret_cast(script_dir.c_str()); sei.nShow = SW_SHOWNOACTIVATE; if (!ShellExecuteExA(&sei)) @@ -107,16 +107,16 @@ struct http_test_server if (child_process < 0) return false; - if (child_process == 0) { + if (child_process == 0) { // child process - + // cd into script dir and launch python script current_path(script_dir); if (execlp("python", "python", script_name.c_str(), (char*)NULL) == -1) return 0; - } - else { + } + else { // parent sleep(1); } From 161d6cd773662858dd267837b952eb8a96983855 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 6 Aug 2011 19:34:32 +0200 Subject: [PATCH 159/768] Minor fix in build script. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cde6f5ef8..e6449449e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,6 @@ add_subdirectory(libs/network/src) add_subdirectory(libs/network/test) if (NOT MSVC) add_subdirectory(libs/mime/test) -endif(NOT_MSVC) +endif(NOT MSVC) add_subdirectory(libs/network/example) From afb49277ab22ffc1e67af1d3ecae6cba2f4893a5 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 7 Aug 2011 08:38:08 +0200 Subject: [PATCH 160/768] I added a couple of fixes to ensure compilation on MSVC 10. --- .../protocol/http/client/connection/sync_base.hpp | 6 +++--- .../protocol/http/policies/pooled_connection.hpp | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/boost/network/protocol/http/client/connection/sync_base.hpp b/boost/network/protocol/http/client/connection/sync_base.hpp index 8314363b8..290cf372f 100644 --- a/boost/network/protocol/http/client/connection/sync_base.hpp +++ b/boost/network/protocol/http/client/connection/sync_base.hpp @@ -130,7 +130,7 @@ namespace boost { namespace network { namespace http { namespace impl { } if (boost::iequals(boost::begin(transfer_encoding_range)->second, "chunked")) { bool stopping = false; - do { + do { std::size_t chunk_size_line = read_until(socket_, response_buffer, "\r\n", error); if ((chunk_size_line == 0) && (error != boost::asio::error::eof)) throw boost::system::system_error(error); std::size_t chunk_size = 0; @@ -163,7 +163,7 @@ namespace boost { namespace network { namespace http { namespace impl { if (chunk_size != 0) throw std::runtime_error("Size mismatch between tranfer encoding chunk data size and declared chunk size."); - } + } } while (!stopping); } else throw std::runtime_error("Unsupported Transfer-Encoding."); } else { @@ -177,7 +177,7 @@ namespace boost { namespace network { namespace http { namespace impl { while ((bytes_read = boost::asio::read(socket_, response_buffer, boost::asio::transfer_at_least(1), error))) { body_stream << &response_buffer; length -= bytes_read; - if ((length <= 0) or error) + if ((length <= 0) || error) break; } } diff --git a/boost/network/protocol/http/policies/pooled_connection.hpp b/boost/network/protocol/http/policies/pooled_connection.hpp index c90289e6f..31be06f8e 100644 --- a/boost/network/protocol/http/policies/pooled_connection.hpp +++ b/boost/network/protocol/http/policies/pooled_connection.hpp @@ -30,7 +30,7 @@ namespace boost { namespace network { namespace http { typedef typename resolver_base::resolver_type resolver_type; typedef function resolver_function_type; typedef function const &, system::error_code const &)> body_callback_function_type; - + void cleanup() { host_connection_map().swap(host_connections); } @@ -85,9 +85,9 @@ namespace boost { namespace network { namespace http { pimpl->read_headers(response_, response_buffer); if ( - get_body && response_.status() != 304 + get_body && response_.status() != 304 && (response_.status() != 204) - && not (response_.status() >= 100 && response_.status() <= 199) + && !(response_.status() >= 100 && response_.status() <= 199) ) { pimpl->read_body(response_, response_buffer); } @@ -125,7 +125,7 @@ namespace boost { namespace network { namespace http { }; typedef shared_ptr connection_ptr; - + typedef unordered_map host_connection_map; host_connection_map host_connections; bool follow_redirect_; @@ -164,7 +164,7 @@ namespace boost { namespace network { namespace http { pooled_connection_policy(bool cache_resolved, bool follow_redirect) : resolver_base(cache_resolved), host_connections(), follow_redirect_(follow_redirect) {} - + }; } // namespace http From 994bca721e4b1780f8bc6a4874abb9e631e3cc50 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Mon, 29 Aug 2011 23:00:48 +0200 Subject: [PATCH 161/768] Added a couple of extra tests to construct a URI from an existing root URI. --- boost/network/uri/accessors.hpp | 14 ++-- boost/network/uri/directives.hpp | 11 +++ boost/network/uri/directives/authority.hpp | 2 +- boost/network/uri/uri.hpp | 81 ++++++++++++++++------ libs/network/test/uri/url_builder_test.cpp | 24 +++++++ libs/network/test/uri/url_test.cpp | 12 ++++ 6 files changed, 116 insertions(+), 28 deletions(-) diff --git a/boost/network/uri/accessors.hpp b/boost/network/uri/accessors.hpp index 88ed97e16..6123ab898 100644 --- a/boost/network/uri/accessors.hpp +++ b/boost/network/uri/accessors.hpp @@ -23,9 +23,9 @@ template < typename Map > struct key_value_sequence - : spirit::qi::grammar + : spirit::qi::grammar { - typedef typename Uri::const_iterator_type const_iterator_type; + typedef typename Uri::const_iterator const_iterator; key_value_sequence() : key_value_sequence::base_type(query) @@ -36,9 +36,9 @@ struct key_value_sequence value = +spirit::qi::char_("a-zA-Z_0-9/%"); } - spirit::qi::rule query; - spirit::qi::rule()> pair; - spirit::qi::rule key, value; + spirit::qi::rule query; + spirit::qi::rule()> pair; + spirit::qi::rule key, value; }; } // namespace details @@ -59,7 +59,7 @@ template < > typename basic_uri::string_type username(const basic_uri &uri) { typename basic_uri::const_range_type user_info_range = uri.user_info_range(); - typename basic_uri::const_iterator_type it(boost::begin(user_info_range)), end(boost::end(user_info_range)); + typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); for (; it != end; ++it) { if (*it == ':') { break; @@ -73,7 +73,7 @@ template < > typename basic_uri::string_type password(const basic_uri &uri) { typename basic_uri::const_range_type user_info_range = uri.user_info_range(); - typename basic_uri::const_iterator_type it(boost::begin(user_info_range)), end(boost::end(user_info_range)); + typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); for (; it != end; ++it) { if (*it == ':') { ++it; diff --git a/boost/network/uri/directives.hpp b/boost/network/uri/directives.hpp index 233c630ca..6b47e77c3 100644 --- a/boost/network/uri/directives.hpp +++ b/boost/network/uri/directives.hpp @@ -16,6 +16,17 @@ namespace boost { namespace network { namespace uri { +template < + class Tag + > +inline +basic_uri &operator << (basic_uri &uri, const basic_uri &root_uri) { + if (root_uri.is_valid()) { + uri.append(boost::begin(root_uri), boost::end(root_uri)); + } + return uri; +} + template < class Tag , class Directive diff --git a/boost/network/uri/directives/authority.hpp b/boost/network/uri/directives/authority.hpp index 6e723cfe8..7d0830a0f 100644 --- a/boost/network/uri/directives/authority.hpp +++ b/boost/network/uri/directives/authority.hpp @@ -34,7 +34,7 @@ template < class T > inline -authority_directive authority(const T &value) { +authority_directive authority(const T &value) { return authority_directive(value); } } // namespace uri diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index fe7c8e264..ef1fc58c3 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -48,15 +48,24 @@ class basic_uri public: typedef typename string::type string_type; - typedef typename string_type::iterator iterator_type; - typedef boost::iterator_range range_type; - typedef typename string_type::const_iterator const_iterator_type; - typedef boost::iterator_range const_range_type; + typedef typename string_type::iterator iterator; + typedef boost::iterator_range range_type; + typedef typename string_type::const_iterator const_iterator; + typedef boost::iterator_range const_range_type; - basic_uri() : is_valid_(false) { + basic_uri() + : is_valid_(false) { } + template < + class FwdIter + > + basic_uri(const FwdIter &first, const FwdIter &last) + : uri_(first, last), is_valid_(false) { + parse(); + } + basic_uri(const string_type &uri) : uri_(uri), is_valid_(false) { parse(); @@ -88,19 +97,19 @@ class basic_uri parse(); } - iterator_type begin() { + iterator begin() { return uri_.begin(); } - const_iterator_type begin() const { + const_iterator begin() const { return uri_.begin(); } - iterator_type end() { + iterator end() { return uri_.end(); } - const_iterator_type end() const { + const_iterator end() const { return uri_.end(); } @@ -195,9 +204,9 @@ class basic_uri } template < - class Iterator + class FwdIter > - void append(Iterator first, Iterator last) { + void append(const FwdIter &first, const FwdIter &last) { uri_.append(first, last); parse(); } @@ -217,18 +226,10 @@ template < > inline void basic_uri::parse() { - const_iterator_type first(boost::begin(uri_)), last(boost::end(uri_)); + const_iterator first(boost::begin(uri_)), last(boost::end(uri_)); is_valid_ = detail::parse(first, last, uri_parts_); } -template < - class Tag - > -inline -void swap(basic_uri &lhs, basic_uri &rhs) { - lhs.swap(rhs); -} - template < class Tag > @@ -358,6 +359,46 @@ bool operator == (const basic_uri &lhs, const basic_uri &rhs) { } } // namespace uri } // namespace network + +template < + class Tag + > +inline +typename network::uri::basic_uri::iterator begin(network::uri::basic_uri &uri) { + return uri.begin(); +} + +template < + class Tag + > +inline +typename network::uri::basic_uri::iterator end(network::uri::basic_uri &uri) { + return uri.end(); +} + +template < + class Tag + > +inline +typename network::uri::basic_uri::const_iterator begin(const network::uri::basic_uri &uri) { + return uri.begin(); +} + +template < + class Tag + > +inline +typename network::uri::basic_uri::const_iterator end(const network::uri::basic_uri &uri) { + return uri.end(); +} + +template < + class Tag + > +inline +void swap(network::uri::basic_uri &lhs, network::uri::basic_uri &rhs) { + lhs.swap(rhs); +} } // namespace boost diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index 6135cc0b3..f6d7a138b 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -205,6 +205,30 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, tag_types) BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); } +BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string root("http://www.example.com/"); + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + const std::string fragment("fragment"); + + uri_type root_uri(boost::begin(root), boost::end(root)); + uri_type instance; + //instance << uri::uri("http://www.example.com/") << uri::path("/") << uri::fragment("fragment"); + instance << root_uri + << uri::path(string_type(boost::begin(path), boost::end(path))) + << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); +} + //BOOST_AUTO_TEST_CASE_TEMPLATE(scheme_test, T, tag_types) //{ // typedef uri::basic_uri uri_type; diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index b0a313168..10373428c 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -312,3 +312,15 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, tag_types) { BOOST_CHECK(boost::equal((++queries.begin())->first, key_2)); BOOST_CHECK(boost::equal((++queries.begin())->second, value_2)); } + +BOOST_AUTO_TEST_CASE_TEMPLATE(range_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://www.example.com/"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(instance, url)); +} From 73a0486ec129bf56e8195631beb79164ed1da32d Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Thu, 1 Sep 2011 19:36:53 +0200 Subject: [PATCH 162/768] Refactored unit tests in order to prepare for the new URI interface. --- libs/network/test/uri/url_builder_test.cpp | 45 ++++++------ libs/network/test/uri/url_test.cpp | 85 +++++++++++----------- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index f6d7a138b..d98dd893c 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -6,6 +6,7 @@ #define BOOST_TEST_MODULE URI builder test #include #include +#include #include #include #include @@ -19,14 +20,14 @@ using namespace boost::network; typedef boost::mpl::list< - tags::default_string - , tags::default_wstring - > tag_types; + uri::uri + , uri::wuri + > uri_types; -BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string scheme("http"); @@ -45,9 +46,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_builder_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_builder_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string scheme("http"); @@ -78,9 +79,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_builder_test, T, tag_types) BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(port_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(port_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string scheme("http"); @@ -102,9 +103,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(port_test, T, tag_types) BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string scheme("http"); @@ -128,9 +129,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, tag_types) BOOST_CHECK(boost::equal(uri::decoded_path(instance), decoded_path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(query_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(query_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string scheme("http"); @@ -154,9 +155,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(query_test, T, tag_types) BOOST_CHECK(boost::equal(uri::query(instance), query)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(query_2_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(query_2_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string scheme("http"); @@ -182,9 +183,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(query_2_test, T, tag_types) BOOST_CHECK(boost::equal(uri::query(instance), query)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string scheme("http"); @@ -205,9 +206,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, tag_types) BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string root("http://www.example.com/"); @@ -229,9 +230,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, tag_types) BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); } -//BOOST_AUTO_TEST_CASE_TEMPLATE(scheme_test, T, tag_types) +//BOOST_AUTO_TEST_CASE_TEMPLATE(scheme_test, T, uri_types) //{ -// typedef uri::basic_uri uri_type; +// typedef T uri_type; // typedef typename uri_type::string_type string_type; // // const std::string scheme("http"); @@ -252,7 +253,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, tag_types) BOOST_AUTO_TEST_CASE(encoded_null_char_test) { - typedef uri::basic_uri uri_type; + typedef uri::uri uri_type; typedef uri_type::string_type string_type; const std::string scheme("http"); diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index 10373428c..48e56556d 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -6,9 +6,9 @@ #define BOOST_TEST_MODULE URL Test #include #include +#include #include #include -#include #include #include #include @@ -18,15 +18,14 @@ using namespace boost::network; - typedef boost::mpl::list< - tags::default_string - , tags::default_wstring - > tag_types; + uri::uri + , uri::wuri + > uri_types; -BOOST_AUTO_TEST_CASE_TEMPLATE(uri_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(uri_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://www.example.com/"); @@ -41,8 +40,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(uri_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://user:password@www.example.com/path?query#fragment"); @@ -66,8 +65,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(mailto_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(mailto_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/mailto:john.doe@example.com"); @@ -81,8 +80,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(mailto_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(file_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(file_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/file:///bin/bash"); @@ -95,8 +94,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(file_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/xmpp:example-node@example.com?message;subject=Hello%20World"); @@ -112,8 +111,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::query(instance), query)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://129.79.245.252/"); @@ -128,8 +127,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_1, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_1, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://[1080::8:800:200c:417a]/"); @@ -144,8 +143,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_1, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_2, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_2, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/"); @@ -160,8 +159,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_2, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ftp_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(ftp_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/ftp://john.doe@ftp.example.com/"); @@ -178,8 +177,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ftp_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(news_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(news_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/news:comp.infosystems.www.servers.unix"); @@ -192,8 +191,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(news_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(tel_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(tel_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/tel:+1-816-555-1212"); @@ -206,8 +205,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(tel_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_uri_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_uri_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://www.example.com/Path%20With%20%28Some%29%20Encoded%20Characters%21"); @@ -224,8 +223,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_uri_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::decoded_path(instance), decoded_path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(copy_constructor_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(copy_constructor_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://www.example.com/"); @@ -235,8 +234,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(copy_constructor_test, T, tag_types) { BOOST_CHECK(instance == copy); } -BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://www.example.com/"); @@ -248,8 +247,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, tag_types) { BOOST_CHECK(instance == copy); } -BOOST_AUTO_TEST_CASE_TEMPLATE(username_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(username_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/ftp://john.doe:password@ftp.example.com/"); @@ -263,8 +262,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(username_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::password(instance), password)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(authority_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(authority_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://user:password@www.example.com/path?query#fragment"); @@ -275,8 +274,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(authority_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::authority(instance), authority)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(http_query_map_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(http_query_map_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://user:password@www.example.com/path?query#fragment"); @@ -293,8 +292,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_query_map_test, T, tag_types) { BOOST_CHECK(boost::equal(queries.begin()->second, value)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/xmpp:example-node@example.com?message;subject=Hello%20World"); @@ -313,9 +312,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, tag_types) { BOOST_CHECK(boost::equal((++queries.begin())->second, value_2)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(range_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(range_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://www.example.com/"); From deb5553469e95bbee7ec01c50c3b9208e757443b Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 3 Sep 2011 22:24:46 +0200 Subject: [PATCH 163/768] Removed tag dispatching from URI. --- boost/network/protocol/http/impl/request.hpp | 18 ++- .../protocol/http/message/wrappers/port.hpp | 2 +- .../protocol/http/message/wrappers/uri.hpp | 6 +- boost/network/uri.hpp | 15 +- boost/network/uri/accessors.hpp | 52 +++---- boost/network/uri/detail/uri_parts.hpp | 1 - boost/network/uri/directives.hpp | 10 +- boost/network/uri/directives/fragment.hpp | 6 +- boost/network/uri/directives/path.hpp | 6 +- boost/network/uri/directives/port.hpp | 10 +- boost/network/uri/directives/query.hpp | 12 +- boost/network/uri/http/uri.hpp | 101 -------------- boost/network/uri/mailto/uri.hpp | 80 ----------- boost/network/uri/uri.hpp | 131 ++++++++---------- boost/network/uri/uri_io.hpp | 11 +- libs/network/example/CMakeLists.txt | 8 +- libs/network/example/uri.cpp | 14 +- libs/network/test/uri/CMakeLists.txt | 2 - libs/network/test/uri/url_builder_test.cpp | 23 +-- libs/network/test/uri/url_test.cpp | 37 ++--- 20 files changed, 179 insertions(+), 366 deletions(-) delete mode 100644 boost/network/uri/http/uri.hpp delete mode 100644 boost/network/uri/mailto/uri.hpp diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index ca5a2c26a..763b09c67 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include @@ -50,7 +50,7 @@ namespace http { struct basic_request : public basic_message { - mutable boost::network::uri::http::basic_uri uri_; + mutable boost::network::uri::basic_uri::type> uri_; typedef basic_message base_type; public: @@ -80,11 +80,10 @@ namespace http { } void swap(basic_request & other) { - using boost::network::uri::swap; base_type & base_ref(other); basic_request & this_ref(*this); base_ref.swap(this_ref); - swap(other.uri_, this->uri_); + boost::swap(other.uri_, this->uri_); } string_type const host() const { @@ -92,7 +91,14 @@ namespace http { } port_type port() const { - return uri::port_us(uri_); + boost::optional port = uri::port_us(uri_); + if (!port) + { + typedef constants consts; + return boost::iequals(uri_.scheme_range(), + string_type(consts::https()))? 443 : 80; + } + return *port; } string_type const path() const { @@ -115,7 +121,7 @@ namespace http { uri_ = new_uri; } - boost::network::uri::http::basic_uri const & uri() const { + boost::network::uri::basic_uri::type> const & uri() const { return uri_; } diff --git a/boost/network/protocol/http/message/wrappers/port.hpp b/boost/network/protocol/http/message/wrappers/port.hpp index 9777ac277..786ce1e98 100644 --- a/boost/network/protocol/http/message/wrappers/port.hpp +++ b/boost/network/protocol/http/message/wrappers/port.hpp @@ -30,7 +30,7 @@ namespace boost { namespace network { namespace http { } operator boost::optional () { - return port_us(message_.uri()); + return uri::port_us(message_.uri()); } }; diff --git a/boost/network/protocol/http/message/wrappers/uri.hpp b/boost/network/protocol/http/message/wrappers/uri.hpp index 7d4be811a..622d53a4a 100644 --- a/boost/network/protocol/http/message/wrappers/uri.hpp +++ b/boost/network/protocol/http/message/wrappers/uri.hpp @@ -7,7 +7,7 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#include namespace boost { namespace network { namespace http { @@ -24,7 +24,7 @@ namespace boost { namespace network { namespace http { operator string_type() { return message_.uri().raw(); } - operator boost::network::uri::basic_uri () { + operator boost::network::uri::basic_uri::type> () { return message_.uri(); } }; @@ -40,6 +40,6 @@ namespace boost { namespace network { namespace http { } // namespace network -} // nmaespace boost +} // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_HPP_20100620 diff --git a/boost/network/uri.hpp b/boost/network/uri.hpp index 7472e8cbc..237818c65 100644 --- a/boost/network/uri.hpp +++ b/boost/network/uri.hpp @@ -8,19 +8,18 @@ #include #include -#include -#include +//#include +//#include namespace boost { namespace network { namespace uri { -typedef basic_uri uri; -typedef basic_uri wuri; - -namespace http { -typedef basic_uri uri; -} +typedef basic_uri uri; +typedef basic_uri wuri; +//namespace http { +//typedef basic_uri uri; +//} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/accessors.hpp b/boost/network/uri/accessors.hpp index 6123ab898..7281ec65d 100644 --- a/boost/network/uri/accessors.hpp +++ b/boost/network/uri/accessors.hpp @@ -43,72 +43,72 @@ struct key_value_sequence } // namespace details template < - class Tag, + class String, class Map > inline -Map &query_map(const basic_uri &uri, Map &map) { - typename basic_uri::const_range_type range = uri.query_range(); - details::key_value_sequence, Map> parser; +Map &query_map(const basic_uri &uri, Map &map) { + typename basic_uri::const_range_type range = uri.query_range(); + details::key_value_sequence, Map> parser; spirit::qi::parse(boost::begin(range), boost::end(range), parser, map); return map; } template < - class Tag + class String > -typename basic_uri::string_type username(const basic_uri &uri) { - typename basic_uri::const_range_type user_info_range = uri.user_info_range(); - typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); +String username(const basic_uri &uri) { + typename basic_uri::const_range_type user_info_range = uri.user_info_range(); + typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); for (; it != end; ++it) { if (*it == ':') { break; } } - return typename string::type(boost::begin(user_info_range), it); + return String(boost::begin(user_info_range), it); } template < - class Tag + class String > -typename basic_uri::string_type password(const basic_uri &uri) { - typename basic_uri::const_range_type user_info_range = uri.user_info_range(); - typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); +String password(const basic_uri &uri) { + typename basic_uri::const_range_type user_info_range = uri.user_info_range(); + typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); for (; it != end; ++it) { if (*it == ':') { ++it; break; } } - return typename string::type(it, boost::end(user_info_range)); + return String(it, boost::end(user_info_range)); } template < - class Tag + class String > -typename basic_uri::string_type decoded_path(const basic_uri &uri) { - typename basic_uri::const_range_type path_range = uri.path_range(); - typename basic_uri::string_type decoded_path; +String decoded_path(const basic_uri &uri) { + typename basic_uri::const_range_type path_range = uri.path_range(); + String decoded_path; decode(path_range, std::back_inserter(decoded_path)); return decoded_path; } template < - class Tag + class String > -typename basic_uri::string_type decoded_query(const basic_uri &uri) { - typename basic_uri::const_range_type query_range = uri.query_range(); - typename basic_uri::string_type decoded_query; +String decoded_query(const basic_uri &uri) { + typename basic_uri::const_range_type query_range = uri.query_range(); + String decoded_query; decode(query_range, std::back_inserter(decoded_query)); return decoded_query; } template < - class Tag + class String > -typename basic_uri::string_type decoded_fragment(const basic_uri &uri) { - typename basic_uri::const_range_type fragment_range = uri.fragment_range(); - typename basic_uri::string_type decoded_fragment; +String decoded_fragment(const basic_uri &uri) { + typename basic_uri::const_range_type fragment_range = uri.fragment_range(); + String decoded_fragment; decode(fragment_range, std::back_inserter(decoded_fragment)); return decoded_fragment; } diff --git a/boost/network/uri/detail/uri_parts.hpp b/boost/network/uri/detail/uri_parts.hpp index a2647e1ec..e069657ae 100644 --- a/boost/network/uri/detail/uri_parts.hpp +++ b/boost/network/uri/detail/uri_parts.hpp @@ -8,7 +8,6 @@ # include -# include namespace boost { diff --git a/boost/network/uri/directives.hpp b/boost/network/uri/directives.hpp index 6b47e77c3..e02a1a1da 100644 --- a/boost/network/uri/directives.hpp +++ b/boost/network/uri/directives.hpp @@ -17,22 +17,22 @@ namespace boost { namespace network { namespace uri { template < - class Tag + class String > inline -basic_uri &operator << (basic_uri &uri, const basic_uri &root_uri) { - if (root_uri.is_valid()) { +basic_uri &operator << (basic_uri &uri, const basic_uri &root_uri) { + if (empty(uri) && valid(root_uri)) { uri.append(boost::begin(root_uri), boost::end(root_uri)); } return uri; } template < - class Tag + class String , class Directive > inline -basic_uri &operator << (basic_uri &uri, const Directive &directive) { +basic_uri &operator << (basic_uri &uri, const Directive &directive) { directive(uri); return uri; } diff --git a/boost/network/uri/directives/fragment.hpp b/boost/network/uri/directives/fragment.hpp index 809f1f8a7..49d980530 100644 --- a/boost/network/uri/directives/fragment.hpp +++ b/boost/network/uri/directives/fragment.hpp @@ -20,11 +20,11 @@ struct fragment_directive { {} template < - class Tag + class String , template class Uri > - void operator () (Uri &uri) const { - typename string::type encoded_value; + void operator () (Uri &uri) const { + String encoded_value; static const char separator[] = {'#'}; uri.append(boost::begin(separator), boost::end(separator)); encode(boost::as_literal(value), std::back_inserter(encoded_value)); diff --git a/boost/network/uri/directives/path.hpp b/boost/network/uri/directives/path.hpp index d2b1afd5a..f4a4bd99c 100644 --- a/boost/network/uri/directives/path.hpp +++ b/boost/network/uri/directives/path.hpp @@ -49,11 +49,11 @@ struct encoded_path_directive { {} template < - class Tag + class StringT , template class Uri > - void operator () (Uri &uri) const { - typename string::type encoded_value; + void operator () (Uri &uri) const { + StringT encoded_value; encode(boost::as_literal(value), std::back_inserter(encoded_value)); uri.append(encoded_value); } diff --git a/boost/network/uri/directives/port.hpp b/boost/network/uri/directives/port.hpp index ae3a9bb88..567208d64 100644 --- a/boost/network/uri/directives/port.hpp +++ b/boost/network/uri/directives/port.hpp @@ -22,10 +22,10 @@ struct port_directive { {} template < - class Tag + class String , template class Uri > - void operator () (Uri &uri) const { + void operator () (Uri &uri) const { static const char separator[] = {':'}; uri.append(boost::begin(separator), boost::end(separator)); uri.append(value); @@ -43,13 +43,13 @@ struct port_directive_us { {} template < - class Tag + class String , template class Uri > - void operator () (Uri &uri) const { + void operator () (Uri &uri) const { static const char separator[] = {':'}; uri.append(boost::begin(separator), boost::end(separator)); - typename string::type port = boost::lexical_cast::type>(value); + String port = boost::lexical_cast(value); uri.append(port); } diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp index 59eb2ea06..bb4cb7a27 100644 --- a/boost/network/uri/directives/query.hpp +++ b/boost/network/uri/directives/query.hpp @@ -20,11 +20,11 @@ struct query_directive { {} template < - class Tag + class String , template class Uri > - void operator () (Uri &uri) const { - typename string::type encoded_value; + void operator () (Uri &uri) const { + String encoded_value; static const char separator[] = {'?'}; uri.append(boost::begin(separator), boost::end(separator)); uri.append(value); @@ -53,11 +53,11 @@ struct query_key_value_directive { {} template < - class Tag + class String , template class Uri > - void operator () (Uri &uri) const { - typename string::type encoded_key, encoded_value; + void operator () (Uri &uri) const { + String encoded_key, encoded_value; static const char qmark[] = {'?'}; static const char equal[] = {'='}; static const char scolon[] = {';'}; diff --git a/boost/network/uri/http/uri.hpp b/boost/network/uri/http/uri.hpp deleted file mode 100644 index ecee3f491..000000000 --- a/boost/network/uri/http/uri.hpp +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_HTTP_URI_INC__ -# define __BOOST_NETWORK_URI_HTTP_URI_INC__ - - -# include - - -namespace boost { -namespace network { -namespace uri { -namespace http { -template < - class Tag - > -class basic_uri - : public boost::network::uri::basic_uri { - - typedef boost::network::uri::basic_uri base_type; - -public: - - basic_uri() { - - } - - basic_uri(const typename base_type::string_type &uri) : base_type(uri) { - - } - - basic_uri &operator = (const typename base_type::string_type &uri) { - basic_uri(uri).swap(*this); - return *this; - } - -}; -} // namespace http - -template < - class Tag - > -bool is_http(const http::basic_uri &uri) { - static const char scheme_http[] = {'h', 't', 't', 'p'}; - return boost::equal(uri.scheme_range(), scheme_http); -} - -template < - class Tag - > -bool is_https(const http::basic_uri &uri) { - static const char scheme_https[] = {'h', 't', 't', 'p', 's'}; - return boost::equal(uri.scheme_range(), scheme_https); -} - -template < - class Tag - > -inline -bool is_valid(const http::basic_uri &uri) { - return is_http(uri) || is_https(uri); -} - -template < - class Tag - > -inline -typename basic_uri::string_type port(const http::basic_uri &uri) { - typedef typename basic_uri::range_type range_type; - typedef typename basic_uri::string_type string_type; - - static const char default_http_port[] = "80"; - static const char default_https_port[] = "443"; - - range_type scheme = uri.scheme_range(); - range_type port = uri.port_range(); - - if (boost::empty(port)) { - if (is_http(uri)) { - return string_type(boost::begin(default_http_port), - boost::end(default_http_port)); - } - else if (is_https(uri)) { - return string_type(boost::begin(default_https_port), - boost::end(default_https_port)); - } - } - return string_type(boost::begin(port), boost::end(port)); -} - -typedef basic_uri uri; -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_HTTP_URI_INC__ diff --git a/boost/network/uri/mailto/uri.hpp b/boost/network/uri/mailto/uri.hpp deleted file mode 100644 index 87490a502..000000000 --- a/boost/network/uri/mailto/uri.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_MAILTO_URI_INC__ -# define __BOOST_NETWORK_URI_MAILTO_URI_INC__ - - -# include - - -namespace boost { -namespace network { -namespace uri { -namespace mailto { -namespace details { -template < - class String - > -struct uri_parts - : boost::fusion::vector< - iterator_range // to - // headers - > -{ }; -} // namespace details -} // namespace mailto -} // namespace uri -} // namespace network -} // namespace boost - - -namespace boost { -namespace network { -namespace uri { -namespace mailto { - -template < - class Tag - > -class basic_uri - : public boost::network::uri::basic_uri { - - typedef boost::network::uri::basic_uri base_type; - -public: - - basic_uri() { - - } - - basic_uri(const typename base_type::string_type &uri) : base_type(uri) { - - } - - basic_uri &operator = (const typename base_type::string_type &uri) { - basic_uri(uri).swap(*this); - return *this; - } - - - -}; -} // namespace mailto - -template < - class Tag - > -bool is_mailto(const mailto::basic_uri &uri) { - static const char scheme_mailto[] = {'m', 'a', 'i', 'l', 't', 'o'}; - return boost::equal(uri.scheme_range(), scheme_mailto); -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_MAILTO_URI_INC__ diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index ef1fc58c3..0e5768794 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -9,13 +9,13 @@ # include -# include # include # include # ifdef BOOST_NETWORK_NO_LIB # include # endif // #ifdef BOOST_NETWORK_NO_LIB # include +# include # include # include # include @@ -40,14 +40,14 @@ bool parse(std::wstring::const_iterator first, template < - class Tag + class String > class basic_uri - : public boost::equality_comparable > { + : public boost::equality_comparable > { public: - typedef typename string::type string_type; + typedef String string_type; typedef typename string_type::iterator iterator; typedef boost::iterator_range range_type; typedef typename string_type::const_iterator const_iterator; @@ -216,187 +216,168 @@ class basic_uri void parse(); string_type uri_; - detail::uri_parts::type> uri_parts_; + detail::uri_parts uri_parts_; bool is_valid_; }; template < - class Tag + class String > inline -void basic_uri::parse() { +void basic_uri::parse() { const_iterator first(boost::begin(uri_)), last(boost::end(uri_)); is_valid_ = detail::parse(first, last, uri_parts_); } template < - class Tag + class String > inline -typename basic_uri::string_type scheme(const basic_uri &uri) { +String scheme(const basic_uri &uri) { return uri.scheme(); } template < - class Tag + class String > inline -typename basic_uri::string_type user_info(const basic_uri &uri) { +String user_info(const basic_uri &uri) { return uri.user_info(); } template < - class Tag + class String > inline -typename basic_uri::string_type host(const basic_uri &uri) { +String host(const basic_uri &uri) { return uri.host(); } template < - class Tag + class String > inline -typename basic_uri::string_type port(const basic_uri &uri) { +String port(const basic_uri &uri) { return uri.port(); } template < - class Tag - > -struct port_wrapper { - const basic_uri &uri; - - port_wrapper(const basic_uri &uri) : uri(uri) { - - } - - boost::optional to_optional() const { - typename basic_uri::string_type port = uri.port(); - return (port.empty())? - boost::optional() : - boost::optional(boost::lexical_cast(port)); - } - - operator boost::optional () const { - return to_optional(); - } - - operator unsigned short () const { - typedef typename string::type string_type; - typedef constants consts; - const boost::optional &port = to_optional(); - if (port) return *port; - return boost::iequals(uri.scheme_range(), string_type(consts::https())) ? 443 : 80; - } -}; - -template < - class Tag + class String > inline -port_wrapper port_us(const basic_uri &uri) { - return port_wrapper(uri); +boost::optional port_us(const basic_uri &uri) { + String port = uri.port(); + return (port.empty())? + boost::optional() : + boost::optional(boost::lexical_cast(port)); } template < - class Tag + class String > inline -typename basic_uri::string_type path(const basic_uri &uri) { +String path(const basic_uri &uri) { return uri.path(); } template < - class Tag + class String > inline -typename basic_uri::string_type query(const basic_uri &uri) { +String query(const basic_uri &uri) { return uri.query(); } template < - class Tag + class String > inline -typename basic_uri::string_type fragment(const basic_uri &uri) { +String fragment(const basic_uri &uri) { return uri.fragment(); } template < - class Tag + class String > inline -typename basic_uri::string_type authority(const basic_uri &uri) { - typename basic_uri::const_range_type user_info(uri.user_info_range()); - typename basic_uri::const_range_type port(uri.port_range()); - return typename basic_uri::string_type(user_info.begin(), port.end()); +String authority(const basic_uri &uri) { + typename basic_uri::const_range_type user_info(uri.user_info_range()); + typename basic_uri::const_range_type port(uri.port_range()); + return String(user_info.begin(), port.end()); } template < - class Tag + class String > inline -typename basic_uri::string_type netloc(const basic_uri &uri) { +String netloc(const basic_uri &uri) { return authority(uri); } template < - class Tag + class String > inline -bool is_valid(const basic_uri &uri) { +bool valid(const basic_uri &uri) { return uri.is_valid(); } template < - class Tag + class String + > +inline +bool is_valid(const basic_uri &uri) { + return valid(uri); +} + +template < + class String > inline -bool operator == (const basic_uri &lhs, const basic_uri &rhs) { +bool operator == (const basic_uri &lhs, const basic_uri &rhs) { return std::equal(lhs.begin(), lhs.end(), rhs.begin()); } } // namespace uri } // namespace network template < - class Tag + class String > inline -typename network::uri::basic_uri::iterator begin(network::uri::basic_uri &uri) { +typename network::uri::basic_uri::iterator begin(network::uri::basic_uri &uri) { return uri.begin(); } template < - class Tag + class String > inline -typename network::uri::basic_uri::iterator end(network::uri::basic_uri &uri) { +typename network::uri::basic_uri::iterator end(network::uri::basic_uri &uri) { return uri.end(); } template < - class Tag + class String > inline -typename network::uri::basic_uri::const_iterator begin(const network::uri::basic_uri &uri) { +typename network::uri::basic_uri::const_iterator begin(const network::uri::basic_uri &uri) { return uri.begin(); } template < - class Tag + class String > inline -typename network::uri::basic_uri::const_iterator end(const network::uri::basic_uri &uri) { +typename network::uri::basic_uri::const_iterator end(const network::uri::basic_uri &uri) { return uri.end(); } template < - class Tag + class String > inline -void swap(network::uri::basic_uri &lhs, network::uri::basic_uri &rhs) { +void swap(network::uri::basic_uri &lhs, network::uri::basic_uri &rhs) { lhs.swap(rhs); } } // namespace boost diff --git a/boost/network/uri/uri_io.hpp b/boost/network/uri/uri_io.hpp index efff221f4..1b1f6f2cb 100644 --- a/boost/network/uri/uri_io.hpp +++ b/boost/network/uri/uri_io.hpp @@ -3,16 +3,19 @@ # include +# include namespace boost { namespace network { namespace uri { -template < - class Tag - > inline -std::ostream &operator << (std::ostream &os, const basic_uri &uri) { +std::ostream &operator << (std::ostream &os, const basic_uri &uri) { + return os << uri.string(); +} + +inline +std::wostream &operator << (std::wostream &os, const basic_uri &uri) { return os << uri.string(); } } // namespace uri diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index e975c9902..b6592e00c 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -14,7 +14,7 @@ if (Boost_FOUND) endif (Boost_FOUND) if (OPENSSL_FOUND) - include_directories(${OPENSSL_INCLUDE_DIR}) + include_directories(${OPENSSL_INCLUDE_DIR}) endif (OPENSSL_FOUND) if (Boost_FOUND) @@ -22,11 +22,17 @@ if (Boost_FOUND) add_dependencies(http_client cppnetlib-uri-parsers) target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + if (OPENSSL_FOUND) + target_link_libraries(http_client ${OPENSSL_LIBRARIES}) + endif (OPENSSL_FOUND) add_executable(simple_wget simple_wget.cpp) add_dependencies(simple_wget cppnetlib-uri-parsers) target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + if (OPENSSL_FOUND) + target_link_libraries(simple_wget ${OPENSSL_LIBRARIES}) + endif (OPENSSL_FOUND) add_executable(hello_world_server http/hello_world_server.cpp) target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) diff --git a/libs/network/example/uri.cpp b/libs/network/example/uri.cpp index 72c46e205..412849a85 100644 --- a/libs/network/example/uri.cpp +++ b/libs/network/example/uri.cpp @@ -27,13 +27,13 @@ int main(int argc, char * argv[]) { std::string("a valid") : std::string("an invalid")) << " URI!" << std::endl; - /*<< Create a `boost::network::http::uri` object from the input. >>*/ - boost::network::uri::http::uri http_uri_(input); - /*<< Check if it's a valid HTTP URI. >>*/ - std::cout << "It's also " - << (boost::network::uri::is_valid(http_uri_)? - std::string("a valid HTTP URI") : std::string("an invalid HTTP URI.")) - << "!" << std::endl; + ///*<< Create a `boost::network::http::uri` object from the input. >>*/ + //boost::network::uri::http::uri http_uri_(input); + ///*<< Check if it's a valid HTTP URI. >>*/ + //std::cout << "It's also " + // << (boost::network::uri::is_valid(http_uri_)? + // std::string("a valid HTTP URI") : std::string("an invalid HTTP URI.")) + // << "!" << std::endl; return EXIT_SUCCESS; } diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index 5ca9fb1de..7afc6ea36 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -14,8 +14,6 @@ if (Boost_FOUND) set( TESTS url_test - url_http_test - url_mailto_test url_encoding_test url_builder_test ) diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index d98dd893c..512277a1f 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, uri_types) << uri::host(string_type(boost::begin(host), boost::end(host))) << uri::path(string_type(boost::begin(path), boost::end(path))) ; - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -68,11 +68,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_builder_test, T, uri_types) << uri::query(string_type(boost::begin(query), boost::end(query))) << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))) ; - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK_EQUAL(static_cast(uri::port_us(instance)), 80); + BOOST_CHECK(uri::port_us(instance)); + BOOST_CHECK_EQUAL(uri::port_us(instance).get(), 80); BOOST_CHECK(boost::equal(uri::port(instance), port)); BOOST_CHECK(boost::equal(uri::path(instance), path)); BOOST_CHECK(boost::equal(uri::query(instance), query)); @@ -96,7 +97,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(port_test, T, uri_types) << uri::port(8000) << uri::path(string_type(boost::begin(path), boost::end(path))) ; - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::port(instance), port)); @@ -121,7 +122,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, uri_types) << uri::encoded_path(string_type(boost::begin(decoded_path), boost::end(decoded_path))) //<< uri::path(uri::encoded(string_type(boost::begin(decoded_path), boost::end(decoded_path)))) ; - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::port(instance), port)); @@ -148,7 +149,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(query_test, T, uri_types) << uri::path(string_type(boost::begin(path), boost::end(path))) << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), string_type(boost::begin(query_value), boost::end(query_value))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -176,7 +177,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(query_2_test, T, uri_types) string_type(boost::begin(query_value), boost::end(query_value))) << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), string_type(boost::begin(query_value), boost::end(query_value))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -199,7 +200,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, uri_types) << uri::host(string_type(boost::begin(host), boost::end(host))) << uri::path(string_type(boost::begin(path), boost::end(path))) << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -223,7 +224,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, uri_types) instance << root_uri << uri::path(string_type(boost::begin(path), boost::end(path))) << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -245,7 +246,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, uri_types) // << uri::host(string_type(boost::begin(host), boost::end(host))) // << uri::path(string_type(boost::begin(path), boost::end(path))) // ; -// BOOST_REQUIRE(uri::is_valid(instance)); +// BOOST_REQUIRE(uri::valid(instance)); // BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); // BOOST_CHECK(boost::equal(uri::host(instance), host)); // BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -267,7 +268,7 @@ BOOST_AUTO_TEST_CASE(encoded_null_char_test) << uri::host("www.example.com") << uri::encoded_path("/") ; - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), scheme); BOOST_CHECK_EQUAL(uri::host(instance), host); BOOST_CHECK_EQUAL(uri::path(instance), path); diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index 48e56556d..091d96559 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(uri_test, T, uri_types) { const std::string path("/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -54,11 +54,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, uri_types) { const std::string fragment("fragment"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK_EQUAL(static_cast(uri::port_us(instance)), 80); + BOOST_CHECK(uri::port_us(instance)); + BOOST_CHECK_EQUAL(uri::port_us(instance).get(), 80); BOOST_CHECK(boost::equal(uri::port(instance), port)); BOOST_CHECK(boost::equal(uri::path(instance), path)); BOOST_CHECK(boost::equal(uri::query(instance), query)); @@ -75,7 +76,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(mailto_test, T, uri_types) { const std::string path("john.doe@example.com"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::path(instance), path)); } @@ -89,7 +90,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(file_test, T, uri_types) { const std::string path("/bin/bash"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::path(instance), path)); } @@ -105,7 +106,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_test, T, uri_types) { const std::string query("message;subject=Hello%20World"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::path(instance), path)); BOOST_CHECK(boost::equal(uri::query(instance), query)); @@ -121,7 +122,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, uri_types) { const std::string path("/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -137,7 +138,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_1, T, uri_types) { const std::string path("/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -153,7 +154,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_2, T, uri_types) { const std::string path("/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -170,7 +171,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ftp_test, T, uri_types) { const std::string path("/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); BOOST_CHECK(boost::equal(uri::host(instance), host)); @@ -186,7 +187,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(news_test, T, uri_types) { const std::string path("comp.infosystems.www.servers.unix"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::path(instance), path)); } @@ -200,7 +201,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(tel_test, T, uri_types) { const std::string path("+1-816-555-1212"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::path(instance), path)); } @@ -216,7 +217,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_uri_test, T, uri_types) { const std::string decoded_path("/Path With (Some) Encoded Characters!"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), encoded_path)); @@ -257,7 +258,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(username_test, T, uri_types) { const std::string password("password"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::username(instance), username)); BOOST_CHECK(boost::equal(uri::password(instance), password)); } @@ -270,7 +271,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(authority_test, T, uri_types) { const std::string authority("user:password@www.example.com:80"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::authority(instance), authority)); } @@ -281,7 +282,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_query_map_test, T, uri_types) { const std::string url("http://user:password@www.example.com/path?query#fragment"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); const std::string key("query"); const std::string value; @@ -299,7 +300,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, uri_types) { const std::string url("/service/xmpp:example-node@example.com?message;subject=Hello%20World"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); const std::string key_1("message"), key_2("subject"); const std::string value_1, value_2("Hello%20World"); @@ -320,6 +321,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(range_test, T, uri_types) const std::string url("http://www.example.com/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(instance, url)); } From 77e6e531981980d660d4eb126ed1d34861da4164 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 10 Sep 2011 12:52:25 +0200 Subject: [PATCH 164/768] Refactor build and cleaned headers. --- boost/network/uri/accessors.hpp | 1 + boost/network/uri/detail/parse_uri.hpp | 274 ------------------------- boost/network/uri/uri.hpp | 4 - libs/network/build/CMakeLists.txt | 2 +- libs/network/build/Jamfile.v2 | 6 +- libs/network/example/CMakeLists.txt | 16 +- libs/network/example/Jamfile.v2 | 10 +- libs/network/src/CMakeLists.txt | 2 +- libs/network/src/parse_uri_impl.cpp | 13 -- libs/network/src/uri/parse.cpp | 252 ++++++++++++++++++++++- libs/network/test/CMakeLists.txt | 8 +- libs/network/test/Jamfile.v2 | 2 +- libs/network/test/http/CMakeLists.txt | 4 +- libs/network/test/http/Jamfile.v2 | 18 +- libs/network/test/uri/CMakeLists.txt | 4 +- 15 files changed, 285 insertions(+), 331 deletions(-) delete mode 100644 boost/network/uri/detail/parse_uri.hpp delete mode 100644 libs/network/src/parse_uri_impl.cpp diff --git a/boost/network/uri/accessors.hpp b/boost/network/uri/accessors.hpp index 7281ec65d..aa57c6f45 100644 --- a/boost/network/uri/accessors.hpp +++ b/boost/network/uri/accessors.hpp @@ -12,6 +12,7 @@ # include # include # include +# include namespace boost { diff --git a/boost/network/uri/detail/parse_uri.hpp b/boost/network/uri/detail/parse_uri.hpp deleted file mode 100644 index a4fa0969a..000000000 --- a/boost/network/uri/detail/parse_uri.hpp +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright 2009, 2010, 2011 Dean Michael Berris, Jeroen Habraken, Glyn Matthews. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef BOOST_NETWORK_URL_DETAIL_PARSE_URL_HPP_ -# define BOOST_NETWORK_URL_DETAIL_PARSE_URL_HPP_ - - -# ifdef BOOST_NETWORK_NO_LIB -# define BOOST_NETWORK_INLINE inline -# else -# define BOOST_NETWORK_INLINE -# endif // BOOST_NETWORK_NO_LIB - - -#include -#include -#include -#include -#include -#include - - -namespace boost { -namespace network { -namespace uri { -namespace detail { -namespace qi = boost::spirit::qi; - -template < - class String, - typename Iterator - > -struct uri_grammar : qi::grammar()> { - - uri_grammar() : uri_grammar::base_type(start, "uri") { - using boost::spirit::repository::qi::iter_pos; - - // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" - gen_delims %= qi::char_(":/?#[]@"); - // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" - sub_delims %= qi::char_("!$&'()*+,;="); - // reserved = gen-delims / sub-delims - reserved %= gen_delims | sub_delims; - // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - unreserved %= qi::alnum | qi::char_("-._~"); - // pct-encoded = "%" HEXDIG HEXDIG - pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; - - // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - pchar %= qi::raw[ - unreserved | pct_encoded | sub_delims | qi::char_(":@") - ]; - - // segment = *pchar - segment %= qi::raw[*pchar]; - // segment-nz = 1*pchar - segment_nz %= qi::raw[+pchar]; - // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) - segment_nz_nc %= qi::raw[ - +(unreserved | pct_encoded | sub_delims | qi::char_("@")) - ]; - // path-abempty = *( "/" segment ) - path_abempty %= - iter_pos - >> qi::omit[qi::raw[*(qi::char_("/") >> segment)]] - >> iter_pos - ; - // path-absolute = "/" [ segment-nz *( "/" segment ) ] - path_absolute %= - iter_pos - >> qi::omit[qi::raw[ - qi::char_("/") - >> -(segment_nz >> *(qi::char_("/") >> segment)) - ]] - >> iter_pos - ; - // path-rootless = segment-nz *( "/" segment ) - path_rootless %= - iter_pos - >> qi::omit[qi::raw[ - segment_nz >> *(qi::char_("/") >> segment) - ]] - >> iter_pos - ; - // path-empty = 0 - path_empty %= - iter_pos - >> qi::omit[qi::eps] - >> iter_pos - ; - - // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) - scheme %= - iter_pos - >> qi::omit[qi::alpha >> *(qi::alnum | qi::char_("+.-"))] - >> iter_pos - ; - - // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) - user_info %= - iter_pos - >> qi::omit[qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))]] - >> iter_pos - ; - - ip_literal %= - qi::lit('[') >> (ipv6address | ipvfuture) >> ']' - ; - - ipvfuture %= - qi::lit('v') >> +qi::xdigit >> '.' >> +( unreserved | sub_delims | ':') - ; - - ipv6address %= qi::raw[ - qi::repeat(6)[h16 >> ':'] >> ls32 - | "::" >> qi::repeat(5)[h16 >> ':'] >> ls32 - | qi::raw[ h16] >> "::" >> qi::repeat(4)[h16 >> ':'] >> ls32 - | qi::raw[ +(*(h16 >> ':')) >> h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 - | qi::raw[qi::repeat(2)[*(h16 >> ':')] >> h16] >> "::" >> qi::repeat(2)[h16 >> ':'] >> ls32 - | qi::raw[qi::repeat(3)[*(h16 >> ':')] >> h16] >> "::" >> h16 >> ':' >> ls32 - | qi::raw[qi::repeat(4)[*(h16 >> ':')] >> h16] >> "::" >> ls32 - | qi::raw[qi::repeat(5)[*(h16 >> ':')] >> h16] >> "::" >> h16 - | qi::raw[qi::repeat(6)[*(h16 >> ':')] >> h16] >> "::" - - ]; - - // ls32 = ( h16 ":" h16 ) / IPv4address - ls32 %= (h16 >> ':' >> h16) | ipv4address - ; - - // h16 = 1*4HEXDIG - h16 %= qi::repeat(1, 4)[qi::xdigit] - ; - - // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 - dec_octet %= - !(qi::lit('0') >> qi::digit) - >> qi::raw[ - qi::uint_parser() - ]; - - // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet - ipv4address %= qi::raw[ - dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] - ]; - - // reg-name = *( unreserved / pct-encoded / sub-delims ) - reg_name %= qi::raw[ - *(unreserved | pct_encoded | sub_delims) - ]; - - // TODO, host = IP-literal / IPv4address / reg-name - host %= - iter_pos - >> qi::omit[ip_literal | ipv4address | reg_name] - >> iter_pos - ; - - // port %= qi::ushort_; - port %= - iter_pos - >> qi::omit[*qi::digit] - >> iter_pos - ; - - // query = *( pchar / "/" / "?" ) - query %= - iter_pos - >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] - >> iter_pos - ; - - // fragment = *( pchar / "/" / "?" ) - fragment %= - iter_pos - >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] - >> iter_pos - ; - - // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty - // authority = [ userinfo "@" ] host [ ":" port ] - hier_part %= - ( - "//" - >> -(user_info >> '@') - >> host - >> -(':' >> port) - >> path_abempty - ) - | - ( - qi::attr(iterator_range()) - >> qi::attr(iterator_range()) - >> qi::attr(iterator_range()) - >> ( - path_absolute - | path_rootless - | path_empty - ) - ) - ; - - start %= - scheme >> ':' - >> hier_part - >> -('?' >> query) - >> -('#' >> fragment) - ; - } - - qi::rule - gen_delims, sub_delims, reserved, unreserved; - qi::rule - pct_encoded, pchar; - - qi::rule - segment, segment_nz, segment_nz_nc; - qi::rule()> - path_abempty, path_absolute, path_rootless, path_empty; - - qi::rule - dec_octet, ipv4address, reg_name, ipv6address, ipvfuture, ip_literal; - - qi::rule - h16, ls32; - - qi::rule()> - host, port; - - qi::rule()> - scheme, user_info, query, fragment; - - qi::rule, - iterator_range, - iterator_range, - iterator_range >()> - hier_part; - - // actual uri parser - qi::rule()> start; - -}; - - -BOOST_NETWORK_INLINE -bool parse(std::string::const_iterator first, - std::string::const_iterator last, - uri_parts &parts) { - namespace qi = boost::spirit::qi; - static detail::uri_grammar grammar; - bool is_valid = qi::parse(first, last, grammar, parts); - return is_valid && (first == last); -} - -BOOST_NETWORK_INLINE -bool parse(std::wstring::const_iterator first, - std::wstring::const_iterator last, - uri_parts &parts) { - namespace qi = boost::spirit::qi; - static uri_grammar grammar; - bool is_valid = qi::parse(first, last, grammar, parts); - return is_valid && (first == last); -} -} // namespace detail -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // BOOST_NETWORK_URL_DETAIL_PARSE_URL_HPP_ - diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 0e5768794..c26a10f5e 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -11,10 +11,6 @@ # include # include # include -# ifdef BOOST_NETWORK_NO_LIB -# include -# endif // #ifdef BOOST_NETWORK_NO_LIB -# include # include # include # include diff --git a/libs/network/build/CMakeLists.txt b/libs/network/build/CMakeLists.txt index 3ed21b20d..8111a37b7 100644 --- a/libs/network/build/CMakeLists.txt +++ b/libs/network/build/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) find_package( Boost 1.43.0 COMPONENTS unit_test_framework system regex thread filesystem ) -add_library(cppnetlib-uri-parsers STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/parse_uri_impl.cpp) +add_library(cppnetlib-uri STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/parse_uri_impl.cpp) add_library(cppnetlib-server-parsers STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/server_request_parsers_impl.cpp) diff --git a/libs/network/build/Jamfile.v2 b/libs/network/build/Jamfile.v2 index 1a9e18906..f0fd0af91 100644 --- a/libs/network/build/Jamfile.v2 +++ b/libs/network/build/Jamfile.v2 @@ -18,13 +18,13 @@ project cpp-netlib : cpp-pch client : boost/network/include/http/client.hpp ; cpp-pch server : boost/network/include/http/server.hpp ; -lib cppnetlib-uri-parsers : libs/network/src/parse_uri_impl.cpp ; +lib cppnetlib-uri : libs/network/src/parse_uri_impl.cpp ; lib cppnetlib-server-parsers : libs/network/src/server_request_parsers_impl.cpp ; install headers : client server : ../../../boost/network/include/http ; -install libraries : cppnetlib-uri-parsers cppnetlib-server-parsers ; +install libraries : cppnetlib-uri cppnetlib-server-parsers ; -alias all : headers ; +alias all : headers ; diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index b6592e00c..912579e61 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -19,16 +19,16 @@ endif (OPENSSL_FOUND) if (Boost_FOUND) add_executable(http_client http_client.cpp) - add_dependencies(http_client cppnetlib-uri-parsers) - target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + add_dependencies(http_client cppnetlib-uri) + target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) if (OPENSSL_FOUND) target_link_libraries(http_client ${OPENSSL_LIBRARIES}) endif (OPENSSL_FOUND) add_executable(simple_wget simple_wget.cpp) - add_dependencies(simple_wget cppnetlib-uri-parsers) - target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + add_dependencies(simple_wget cppnetlib-uri) + target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) if (OPENSSL_FOUND) target_link_libraries(simple_wget ${OPENSSL_LIBRARIES}) @@ -45,13 +45,13 @@ if (Boost_FOUND) endif (UNIX) add_executable(uri uri.cpp) - add_dependencies(uri cppnetlib-uri-parsers) - target_link_libraries(uri cppnetlib-uri-parsers) + add_dependencies(uri cppnetlib-uri) + target_link_libraries(uri cppnetlib-uri) set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) add_executable(uri_builder uri_builder.cpp) - add_dependencies(uri_builder cppnetlib-uri-parsers) - target_link_libraries(uri_builder cppnetlib-uri-parsers) + add_dependencies(uri_builder cppnetlib-uri) + target_link_libraries(uri_builder cppnetlib-uri) set_target_properties(uri_builder PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) endif() diff --git a/libs/network/example/Jamfile.v2 b/libs/network/example/Jamfile.v2 index f09d9332c..df6ebde7c 100644 --- a/libs/network/example/Jamfile.v2 +++ b/libs/network/example/Jamfile.v2 @@ -21,19 +21,19 @@ project network_test : debug:BOOST_NETWORK_DEBUG ; -exe http_client : http_client.cpp /cpp-netlib//cppnetlib-uri-parsers ; +exe http_client : http_client.cpp /cpp-netlib//cppnetlib-uri ; # exe dispatch_table : dispatch_table.cpp ; -exe uri : uri.cpp /cpp-netlib//cppnetlib-uri-parsers ; +exe uri : uri.cpp /cpp-netlib//cppnetlib-uri ; -exe simple_wget : simple_wget.cpp /cpp-netlib//cppnetlib-uri-parsers ; +exe simple_wget : simple_wget.cpp /cpp-netlib//cppnetlib-uri ; exe hello_world_server : http/hello_world_server.cpp /cpp-netlib//cppnetlib-server-parsers ; -exe hello_world_client : http/hello_world_client.cpp /cpp-netlib//cppnetlib-uri-parsers ; +exe hello_world_client : http/hello_world_client.cpp /cpp-netlib//cppnetlib-uri ; -exe one_liner : http/one_liner.cpp /cpp-netlib//cppnetlib-uri-parsers ; +exe one_liner : http/one_liner.cpp /cpp-netlib//cppnetlib-uri ; exe fileserver : http/fileserver.cpp /cpp-netlib//cppnetlib-server-parsers ; diff --git a/libs/network/src/CMakeLists.txt b/libs/network/src/CMakeLists.txt index e06a58d1c..169a51bfd 100644 --- a/libs/network/src/CMakeLists.txt +++ b/libs/network/src/CMakeLists.txt @@ -8,7 +8,7 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) set(CPP-NETLIB_URI_SRCS uri/parse.cpp) -add_library(cppnetlib-uri-parsers ${CPP-NETLIB_URI_SRCS}) +add_library(cppnetlib-uri ${CPP-NETLIB_URI_SRCS}) set(CPP-NETLIB_HTTP_SERVER_SRCS server_request_parsers_impl.cpp) add_library(cppnetlib-server-parsers ${CPP-NETLIB_HTTP_SERVER_SRCS}) diff --git a/libs/network/src/parse_uri_impl.cpp b/libs/network/src/parse_uri_impl.cpp deleted file mode 100644 index 7de09346b..000000000 --- a/libs/network/src/parse_uri_impl.cpp +++ /dev/null @@ -1,13 +0,0 @@ - -// Copyright 2010-2011 Dean Michael Berris. -// Copyright 2009 Jeroen Habraken. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifdef BOOST_NETWORK_NO_LIB -#undef BOOST_NETWORK_NO_LIB -#endif - -#include - diff --git a/libs/network/src/uri/parse.cpp b/libs/network/src/uri/parse.cpp index 4aadb2628..972859b9b 100644 --- a/libs/network/src/uri/parse.cpp +++ b/libs/network/src/uri/parse.cpp @@ -4,9 +4,253 @@ // http://www.boost.org/LICENSE_1_0.txt) -#ifdef BOOST_NETWORK_NO_LIB -# undef BOOST_NETWORK_NO_LIB -#endif // BOOST_NETWORK_NO_LIB +#include +#include +#include +#include +#include +#include -#include +namespace boost { +namespace network { +namespace uri { +namespace detail { +namespace qi = boost::spirit::qi; + +template < + class String, + typename Iterator + > +struct uri_grammar : qi::grammar()> { + + uri_grammar() : uri_grammar::base_type(start, "uri") { + using boost::spirit::repository::qi::iter_pos; + + // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" + gen_delims %= qi::char_(":/?#[]@"); + // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + sub_delims %= qi::char_("!$&'()*+,;="); + // reserved = gen-delims / sub-delims + reserved %= gen_delims | sub_delims; + // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + unreserved %= qi::alnum | qi::char_("-._~"); + // pct-encoded = "%" HEXDIG HEXDIG + pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; + + // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + pchar %= qi::raw[ + unreserved | pct_encoded | sub_delims | qi::char_(":@") + ]; + + // segment = *pchar + segment %= qi::raw[*pchar]; + // segment-nz = 1*pchar + segment_nz %= qi::raw[+pchar]; + // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) + segment_nz_nc %= qi::raw[ + +(unreserved | pct_encoded | sub_delims | qi::char_("@")) + ]; + // path-abempty = *( "/" segment ) + path_abempty %= + iter_pos + >> qi::omit[qi::raw[*(qi::char_("/") >> segment)]] + >> iter_pos + ; + // path-absolute = "/" [ segment-nz *( "/" segment ) ] + path_absolute %= + iter_pos + >> qi::omit[qi::raw[ + qi::char_("/") + >> -(segment_nz >> *(qi::char_("/") >> segment)) + ]] + >> iter_pos + ; + // path-rootless = segment-nz *( "/" segment ) + path_rootless %= + iter_pos + >> qi::omit[qi::raw[ + segment_nz >> *(qi::char_("/") >> segment) + ]] + >> iter_pos + ; + // path-empty = 0 + path_empty %= + iter_pos + >> qi::omit[qi::eps] + >> iter_pos + ; + + // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + scheme %= + iter_pos + >> qi::omit[qi::alpha >> *(qi::alnum | qi::char_("+.-"))] + >> iter_pos + ; + + // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) + user_info %= + iter_pos + >> qi::omit[qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))]] + >> iter_pos + ; + + ip_literal %= + qi::lit('[') >> (ipv6address | ipvfuture) >> ']' + ; + + ipvfuture %= + qi::lit('v') >> +qi::xdigit >> '.' >> +( unreserved | sub_delims | ':') + ; + + ipv6address %= qi::raw[ + qi::repeat(6)[h16 >> ':'] >> ls32 + | "::" >> qi::repeat(5)[h16 >> ':'] >> ls32 + | qi::raw[ h16] >> "::" >> qi::repeat(4)[h16 >> ':'] >> ls32 + | qi::raw[ +(*(h16 >> ':')) >> h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 + | qi::raw[qi::repeat(2)[*(h16 >> ':')] >> h16] >> "::" >> qi::repeat(2)[h16 >> ':'] >> ls32 + | qi::raw[qi::repeat(3)[*(h16 >> ':')] >> h16] >> "::" >> h16 >> ':' >> ls32 + | qi::raw[qi::repeat(4)[*(h16 >> ':')] >> h16] >> "::" >> ls32 + | qi::raw[qi::repeat(5)[*(h16 >> ':')] >> h16] >> "::" >> h16 + | qi::raw[qi::repeat(6)[*(h16 >> ':')] >> h16] >> "::" + + ]; + + // ls32 = ( h16 ":" h16 ) / IPv4address + ls32 %= (h16 >> ':' >> h16) | ipv4address + ; + + // h16 = 1*4HEXDIG + h16 %= qi::repeat(1, 4)[qi::xdigit] + ; + + // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 + dec_octet %= + !(qi::lit('0') >> qi::digit) + >> qi::raw[ + qi::uint_parser() + ]; + + // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet + ipv4address %= qi::raw[ + dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] + ]; + + // reg-name = *( unreserved / pct-encoded / sub-delims ) + reg_name %= qi::raw[ + *(unreserved | pct_encoded | sub_delims) + ]; + + // TODO, host = IP-literal / IPv4address / reg-name + host %= + iter_pos + >> qi::omit[ip_literal | ipv4address | reg_name] + >> iter_pos + ; + + // port %= qi::ushort_; + port %= + iter_pos + >> qi::omit[*qi::digit] + >> iter_pos + ; + + // query = *( pchar / "/" / "?" ) + query %= + iter_pos + >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] + >> iter_pos + ; + + // fragment = *( pchar / "/" / "?" ) + fragment %= + iter_pos + >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] + >> iter_pos + ; + + // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty + // authority = [ userinfo "@" ] host [ ":" port ] + hier_part %= + ( + "//" + >> -(user_info >> '@') + >> host + >> -(':' >> port) + >> path_abempty + ) + | + ( + qi::attr(iterator_range()) + >> qi::attr(iterator_range()) + >> qi::attr(iterator_range()) + >> ( + path_absolute + | path_rootless + | path_empty + ) + ) + ; + + start %= + scheme >> ':' + >> hier_part + >> -('?' >> query) + >> -('#' >> fragment) + ; + } + + qi::rule + gen_delims, sub_delims, reserved, unreserved; + qi::rule + pct_encoded, pchar; + + qi::rule + segment, segment_nz, segment_nz_nc; + qi::rule()> + path_abempty, path_absolute, path_rootless, path_empty; + + qi::rule + dec_octet, ipv4address, reg_name, ipv6address, ipvfuture, ip_literal; + + qi::rule + h16, ls32; + + qi::rule()> + host, port; + + qi::rule()> + scheme, user_info, query, fragment; + + qi::rule, + iterator_range, + iterator_range, + iterator_range >()> + hier_part; + + // actual uri parser + qi::rule()> start; + +}; + +bool parse(std::string::const_iterator first, + std::string::const_iterator last, + uri_parts &parts) { + namespace qi = boost::spirit::qi; + static detail::uri_grammar grammar; + bool is_valid = qi::parse(first, last, grammar, parts); + return is_valid && (first == last); +} + +bool parse(std::wstring::const_iterator first, + std::wstring::const_iterator last, + uri_parts &parts) { + namespace qi = boost::spirit::qi; + static uri_grammar grammar; + bool is_valid = qi::parse(first, last, grammar, parts); + return is_valid && (first == last); +} +} // namespace detail +} // namespace uri +} // namespace network +} // namespace boost diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index 092499b5a..343cf5697 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -22,11 +22,11 @@ if (Boost_FOUND) set_source_files_properties(${test}.cpp PROPERTIES COMPILE_FLAGS "-Wall") add_executable(cpp-netlib-${test} ${test}.cpp) - add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) + add_dependencies(cpp-netlib-${test} cppnetlib-uri) - # add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) - # target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + # add_dependencies(cpp-netlib-${test} cppnetlib-uri) + # target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) + target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) endif() diff --git a/libs/network/test/Jamfile.v2 b/libs/network/test/Jamfile.v2 index f9ea75977..c04d04fbe 100644 --- a/libs/network/test/Jamfile.v2 +++ b/libs/network/test/Jamfile.v2 @@ -49,6 +49,6 @@ build-project http ; run message_test.cpp ; run message_transform_test.cpp ; -run url_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run url_test.cpp /cpp-netlib//cppnetlib-uri ; run client_server_include_failure.cpp ; diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index aa20424ba..dcc3749cb 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -31,8 +31,8 @@ if (Boost_FOUND) PROPERTIES COMPILE_FLAGS "-Wall") endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) - add_dependencies(cpp-netlib-http-${test} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers cppnetlib-client-connections) + add_dependencies(cpp-netlib-http-${test} cppnetlib-uri) + target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) endif() diff --git a/libs/network/test/http/Jamfile.v2 b/libs/network/test/http/Jamfile.v2 index b62c5b0f5..c5f317858 100644 --- a/libs/network/test/http/Jamfile.v2 +++ b/libs/network/test/http/Jamfile.v2 @@ -15,21 +15,21 @@ project network_test/http : debug:BOOST_NETWORK_DEBUG ; -run client_constructor_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; -run client_get_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; -run client_get_different_port_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; -run client_get_timeout_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run client_constructor_test.cpp /cpp-netlib//cppnetlib-uri ; +run client_get_test.cpp /cpp-netlib//cppnetlib-uri ; +run client_get_different_port_test.cpp /cpp-netlib//cppnetlib-uri ; +run client_get_timeout_test.cpp /cpp-netlib//cppnetlib-uri ; run client_include_inlined.cpp : BOOST_NETWORK_NO_LIB ; -run client_localhost_normal_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; -run client_localhost_ssl_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run client_localhost_normal_test.cpp /cpp-netlib//cppnetlib-uri ; +run client_localhost_ssl_test.cpp /cpp-netlib//cppnetlib-uri ; run message_async_ready_test.cpp ; -run message_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run message_test.cpp /cpp-netlib//cppnetlib-uri ; run request_incremental_parser_test.cpp ; -run request_linearize_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run request_linearize_test.cpp /cpp-netlib//cppnetlib-uri ; run response_incremental_parser_test.cpp /cpp-netlib//cppnetlib-server-parsers ; run server_constructor_test.cpp /cpp-netlib//cppnetlib-server-parsers ; run server_include_inlined.cpp : BOOST_NETWORK_NO_LIB ; -run url_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run url_test.cpp /cpp-netlib//cppnetlib-uri ; exe http_async_server : server_async.cpp /cpp-netlib//cppnetlib-server-parsers ; exe hello_world : server_hello_world.cpp /cpp-netlib//cppnetlib-server-parsers ; diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index 7afc6ea36..ab2f012a8 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -21,8 +21,8 @@ if (Boost_FOUND) set_source_files_properties(${test}.cpp PROPERTIES COMPILE_FLAGS "-Wall") add_executable(cpp-netlib-${test} ${test}.cpp) - add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + add_dependencies(cpp-netlib-${test} cppnetlib-uri) + target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) endif() From bd77b44d3f94a2ae2aa5d4fa0d467b3d347a3c58 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 17 Sep 2011 20:33:04 +0200 Subject: [PATCH 165/768] template is now a class . No support for std::wstring. --- boost/network/uri.hpp | 16 - boost/network/uri/accessors.hpp | 67 ++-- boost/network/uri/directives.hpp | 20 +- boost/network/uri/directives/authority.hpp | 28 +- boost/network/uri/directives/fragment.hpp | 30 +- boost/network/uri/directives/host.hpp | 24 +- boost/network/uri/directives/path.hpp | 61 +--- boost/network/uri/directives/port.hpp | 53 ++-- boost/network/uri/directives/query.hpp | 74 ++--- boost/network/uri/directives/scheme.hpp | 54 +--- boost/network/uri/directives/user_info.hpp | 26 +- boost/network/uri/uri.hpp | 170 ++++------ boost/network/uri/uri_io.hpp | 9 +- libs/network/test/uri/url_builder_test.cpp | 301 ++++++------------ libs/network/test/uri/url_encoding_test.cpp | 27 +- libs/network/test/uri/url_http_test.cpp | 61 ---- libs/network/test/uri/url_mailto_test.cpp | 30 -- libs/network/test/uri/url_test.cpp | 330 ++++++-------------- 18 files changed, 380 insertions(+), 1001 deletions(-) delete mode 100644 libs/network/test/uri/url_http_test.cpp delete mode 100644 libs/network/test/uri/url_mailto_test.cpp diff --git a/boost/network/uri.hpp b/boost/network/uri.hpp index 237818c65..e9ad1ffea 100644 --- a/boost/network/uri.hpp +++ b/boost/network/uri.hpp @@ -6,23 +6,7 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include #include -//#include -//#include - - -namespace boost { namespace network { namespace uri { - -typedef basic_uri uri; -typedef basic_uri wuri; - -//namespace http { -//typedef basic_uri uri; -//} -} // namespace uri -} // namespace network -} // namespace boost #endif diff --git a/boost/network/uri/accessors.hpp b/boost/network/uri/accessors.hpp index aa57c6f45..7b71862b3 100644 --- a/boost/network/uri/accessors.hpp +++ b/boost/network/uri/accessors.hpp @@ -20,14 +20,11 @@ namespace network { namespace uri { namespace details { template < - typename Uri, typename Map > struct key_value_sequence - : spirit::qi::grammar + : spirit::qi::grammar { - typedef typename Uri::const_iterator const_iterator; - key_value_sequence() : key_value_sequence::base_type(query) { @@ -37,79 +34,63 @@ struct key_value_sequence value = +spirit::qi::char_("a-zA-Z_0-9/%"); } - spirit::qi::rule query; - spirit::qi::rule()> pair; - spirit::qi::rule key, value; + spirit::qi::rule query; + spirit::qi::rule()> pair; + spirit::qi::rule key, value; }; } // namespace details template < - class String, class Map > inline -Map &query_map(const basic_uri &uri, Map &map) { - typename basic_uri::const_range_type range = uri.query_range(); - details::key_value_sequence, Map> parser; +Map &query_map(const uri &uri_, Map &map) { + uri::const_range_type range = uri_.query_range(); + details::key_value_sequence parser; spirit::qi::parse(boost::begin(range), boost::end(range), parser, map); return map; } -template < - class String - > -String username(const basic_uri &uri) { - typename basic_uri::const_range_type user_info_range = uri.user_info_range(); - typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); +std::string username(const uri &uri_) { + uri::const_range_type user_info_range = uri_.user_info_range(); + uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); for (; it != end; ++it) { if (*it == ':') { break; } } - return String(boost::begin(user_info_range), it); + return std::string(boost::begin(user_info_range), it); } -template < - class String - > -String password(const basic_uri &uri) { - typename basic_uri::const_range_type user_info_range = uri.user_info_range(); - typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); +std::string password(const uri &uri_) { + uri::const_range_type user_info_range = uri_.user_info_range(); + uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); for (; it != end; ++it) { if (*it == ':') { ++it; break; } } - return String(it, boost::end(user_info_range)); + return std::string(it, boost::end(user_info_range)); } -template < - class String - > -String decoded_path(const basic_uri &uri) { - typename basic_uri::const_range_type path_range = uri.path_range(); - String decoded_path; +std::string decoded_path(const uri &uri_) { + uri::const_range_type path_range = uri_.path_range(); + std::string decoded_path; decode(path_range, std::back_inserter(decoded_path)); return decoded_path; } -template < - class String - > -String decoded_query(const basic_uri &uri) { - typename basic_uri::const_range_type query_range = uri.query_range(); - String decoded_query; +std::string decoded_query(const uri &uri_) { + uri::const_range_type query_range = uri_.query_range(); + std::string decoded_query; decode(query_range, std::back_inserter(decoded_query)); return decoded_query; } -template < - class String - > -String decoded_fragment(const basic_uri &uri) { - typename basic_uri::const_range_type fragment_range = uri.fragment_range(); - String decoded_fragment; +std::string decoded_fragment(const uri &uri_) { + uri::const_range_type fragment_range = uri_.fragment_range(); + std::string decoded_fragment; decode(fragment_range, std::back_inserter(decoded_fragment)); return decoded_fragment; } diff --git a/boost/network/uri/directives.hpp b/boost/network/uri/directives.hpp index e02a1a1da..632cf44db 100644 --- a/boost/network/uri/directives.hpp +++ b/boost/network/uri/directives.hpp @@ -16,25 +16,21 @@ namespace boost { namespace network { namespace uri { -template < - class String - > inline -basic_uri &operator << (basic_uri &uri, const basic_uri &root_uri) { - if (empty(uri) && valid(root_uri)) { - uri.append(boost::begin(root_uri), boost::end(root_uri)); +uri &operator << (uri &uri_, const uri &root_uri) { + if (empty(uri_) && valid(root_uri)) { + uri_.append(boost::begin(root_uri), boost::end(root_uri)); } - return uri; + return uri_; } template < - class String - , class Directive + class Directive > inline -basic_uri &operator << (basic_uri &uri, const Directive &directive) { - directive(uri); - return uri; +uri &operator << (uri &uri_, const Directive &directive) { + directive(uri_); + return uri_; } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/authority.hpp b/boost/network/uri/directives/authority.hpp index 7d0830a0f..3d1295a40 100644 --- a/boost/network/uri/directives/authority.hpp +++ b/boost/network/uri/directives/authority.hpp @@ -2,40 +2,26 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ -# include - - - namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct authority_directive { - explicit authority_directive(const ValueType &value) - : value(value) + explicit authority_directive(const std::string &authority) + : authority(authority) {} - template < - class Tag - , template class Uri - > - void operator () (Uri &uri) const { - uri.append(value); + void operator () (uri &uri_) const { + uri_.append(authority); } - const ValueType &value; + std::string authority; }; -template < - class T - > inline -authority_directive authority(const T &value) { - return authority_directive(value); +authority_directive authority(const std::string &authority) { + return authority_directive(authority); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/fragment.hpp b/boost/network/uri/directives/fragment.hpp index 49d980530..33c57c2f1 100644 --- a/boost/network/uri/directives/fragment.hpp +++ b/boost/network/uri/directives/fragment.hpp @@ -10,37 +10,27 @@ namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct fragment_directive { - explicit fragment_directive(const ValueType &value) - : value(value) + explicit fragment_directive(const std::string &fragment) + : fragment(fragment) {} - template < - class String - , template class Uri - > - void operator () (Uri &uri) const { - String encoded_value; + void operator () (uri &uri_) const { + std::string encoded_fragment; static const char separator[] = {'#'}; - uri.append(boost::begin(separator), boost::end(separator)); - encode(boost::as_literal(value), std::back_inserter(encoded_value)); - uri.append(encoded_value); + uri_.append(boost::begin(separator), boost::end(separator)); + encode(fragment, std::back_inserter(encoded_fragment)); + uri_.append(encoded_fragment); } - const ValueType &value; + std::string fragment; }; -template < - class T - > inline -fragment_directive fragment(const T &value) { - return fragment_directive(value); +fragment_directive fragment(const std::string &fragment) { + return fragment_directive(fragment); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/host.hpp b/boost/network/uri/directives/host.hpp index e251edb84..a7f72efaa 100644 --- a/boost/network/uri/directives/host.hpp +++ b/boost/network/uri/directives/host.hpp @@ -9,33 +9,23 @@ namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct host_directive { - explicit host_directive(const ValueType &value) - : value(value) + explicit host_directive(const std::string &host) + : host(host) {} - template < - class Tag - , template class Uri - > - void operator () (Uri &uri) const { - uri.append(value); + void operator () (uri &uri_) const { + uri_.append(host); } - const ValueType &value; + std::string host; }; -template < - class T - > inline -host_directive host(const T &value) { - return host_directive(value); +host_directive host(const std::string &host) { + return host_directive(host); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/path.hpp b/boost/network/uri/directives/path.hpp index f4a4bd99c..241fe9e3d 100644 --- a/boost/network/uri/directives/path.hpp +++ b/boost/network/uri/directives/path.hpp @@ -9,73 +9,44 @@ namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct path_directive { - explicit path_directive(const ValueType &value) - : value(value) + explicit path_directive(const std::string &path) + : path(path) {} - template < - class Tag - , template class Uri - > - void operator () (Uri &uri) const { - (*this)(boost::as_literal(value), uri); + void operator () (uri &uri_) const { + uri_.append(path); } - template < - class Rng - , class Tag - , template class Uri - > - void operator () (const Rng &rng, Uri &uri) const { - uri.append(boost::begin(rng), boost::end(rng)); - } - - const ValueType &value; + std::string path; }; -template < - class ValueType - > struct encoded_path_directive { - explicit encoded_path_directive(const ValueType &value) - : value(value) + explicit encoded_path_directive(const std::string &path) + : path(path) {} - template < - class StringT - , template class Uri - > - void operator () (Uri &uri) const { - StringT encoded_value; - encode(boost::as_literal(value), std::back_inserter(encoded_value)); - uri.append(encoded_value); + void operator () (uri &uri_) const { + std::string encoded_path; + encode(path, std::back_inserter(encoded_path)); + uri_.append(encoded_path); } - const ValueType &value; + std::string path; }; -template < - class T - > inline -path_directive path(const T &value) { - return path_directive(value); +path_directive path(const std::string &path) { + return path_directive(path); } -template < - class T - > inline -encoded_path_directive encoded_path(const T &value) { - return encoded_path_directive(value); +encoded_path_directive encoded_path(const std::string &path) { + return encoded_path_directive(path); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/port.hpp b/boost/network/uri/directives/port.hpp index 567208d64..a31711dea 100644 --- a/boost/network/uri/directives/port.hpp +++ b/boost/network/uri/directives/port.hpp @@ -2,9 +2,8 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ -# include -# include # include +# include # include # include @@ -12,64 +11,48 @@ namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct port_directive { - explicit port_directive(const ValueType &value) - : value(value) + explicit port_directive(const std::string &port) + : port(port) {} - template < - class String - , template class Uri - > - void operator () (Uri &uri) const { + void operator () (uri &uri_) const { static const char separator[] = {':'}; - uri.append(boost::begin(separator), boost::end(separator)); - uri.append(value); + uri_.append(boost::begin(separator), boost::end(separator)); + uri_.append(port); } - const ValueType &value; + std::string port; }; struct port_directive_us { - explicit port_directive_us(boost::uint16_t value) - : value(value) + explicit port_directive_us(boost::uint16_t port) + : port(port) {} - template < - class String - , template class Uri - > - void operator () (Uri &uri) const { + void operator () (uri &uri_) const { static const char separator[] = {':'}; - uri.append(boost::begin(separator), boost::end(separator)); - String port = boost::lexical_cast(value); - uri.append(port); + uri_.append(boost::begin(separator), boost::end(separator)); + std::string port_ = boost::lexical_cast(port); + uri_.append(port_); } - boost::uint16_t value; + boost::uint16_t port; }; - -template < - class T - > inline -port_directive port(const T &value, - typename boost::disable_if::type>::type * = 0) { - return port_directive(value); +port_directive port(const std::string &port) { + return port_directive(port); } inline -port_directive_us port(boost::uint16_t value) { - return port_directive_us(value); +port_directive_us port(boost::uint16_t port) { + return port_directive_us(port); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp index bb4cb7a27..39520f1e0 100644 --- a/boost/network/uri/directives/query.hpp +++ b/boost/network/uri/directives/query.hpp @@ -10,84 +10,62 @@ namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct query_directive { - explicit query_directive(const ValueType &value) - : value(value) + explicit query_directive(const std::string &query) + : query(query) {} - template < - class String - , template class Uri - > - void operator () (Uri &uri) const { - String encoded_value; + void operator () (uri &uri_) const { + std::string encoded_query; static const char separator[] = {'?'}; - uri.append(boost::begin(separator), boost::end(separator)); - uri.append(value); + uri_.append(boost::begin(separator), boost::end(separator)); + uri_.append(query); } - const ValueType &value; + std::string query; }; -template < - class T - > inline -query_directive query(const T &value) { - return query_directive(value); +query_directive query(const std::string &query) { + return query_directive(query); } -template < - class KeyType - , class ValueType - > -struct query_key_value_directive { +struct query_key_query_directive { - query_key_value_directive(const KeyType &key, const ValueType &value) - : key(key), value(value) + query_key_query_directive(const std::string &key, const std::string &query) + : key(key), query(query) {} - template < - class String - , template class Uri - > - void operator () (Uri &uri) const { - String encoded_key, encoded_value; + void operator () (uri &uri_) const { + std::string encoded_key, encoded_query; static const char qmark[] = {'?'}; static const char equal[] = {'='}; static const char scolon[] = {';'}; - if (!uri.query_range()) + if (!uri_.query_range()) { - uri.append(boost::begin(qmark), boost::end(qmark)); + uri_.append(boost::begin(qmark), boost::end(qmark)); } else { - uri.append(boost::begin(scolon), boost::end(scolon)); + uri_.append(boost::begin(scolon), boost::end(scolon)); } - encode(boost::as_literal(key), std::back_inserter(encoded_key)); - uri.append(encoded_key); - uri.append(boost::begin(equal), boost::end(equal)); - encode(boost::as_literal(value), std::back_inserter(encoded_value)); - uri.append(encoded_value); + encode(key, std::back_inserter(encoded_key)); + uri_.append(encoded_key); + uri_.append(boost::begin(equal), boost::end(equal)); + encode(query, std::back_inserter(encoded_query)); + uri_.append(encoded_query); } - const KeyType &key; - const ValueType &value; + std::string key; + std::string query; }; -template < - class Key - , class Value - > inline -query_key_value_directive query(const Key &key, const Value &value) { - return query_key_value_directive(key, value); +query_key_query_directive query(const std::string &key, const std::string &query) { + return query_key_query_directive(key, query); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/scheme.hpp b/boost/network/uri/directives/scheme.hpp index 27726ac30..764265e2a 100644 --- a/boost/network/uri/directives/scheme.hpp +++ b/boost/network/uri/directives/scheme.hpp @@ -9,64 +9,26 @@ namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct scheme_directive { - explicit scheme_directive(const ValueType &value) - : value(value) + explicit scheme_directive(const std::string &scheme) + : scheme(scheme) {} - template < - class Tag - , template class Uri - > - void operator () (Uri &uri) const { + void operator () (uri &uri_) const { static const char separator[] = {':', '/', '/'}; - uri.append(value); - uri.append(boost::begin(separator), boost::end(separator)); + uri_.append(scheme); + uri_.append(boost::begin(separator), boost::end(separator)); } - const ValueType &value; + std::string scheme; }; -template < - class T - > inline -scheme_directive scheme(const T &value) { - return scheme_directive(value); +scheme_directive scheme(const std::string &scheme) { + return scheme_directive(scheme); } - -namespace schemes { -struct scheme_helper { - - scheme_helper(const char *scheme) - : scheme(scheme) { - - } - - template < - class Tag - , template class Uri - > - void operator () (Uri &uri) const { - static const char separator[] = {':', '/', '/'}; - uri.append(boost::begin(scheme), boost::end(scheme)); - uri.append(boost::begin(separator), boost::end(separator)); - } - - std::string scheme; - -}; - -//static scheme_helper http("http"); -//static scheme_helper https("https"); -//static scheme_helper ftp("ftp"); -//static scheme_helper mailto("mailto"); -} // namespace schemes } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/user_info.hpp b/boost/network/uri/directives/user_info.hpp index 881700a6a..a900eed93 100644 --- a/boost/network/uri/directives/user_info.hpp +++ b/boost/network/uri/directives/user_info.hpp @@ -9,35 +9,25 @@ namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct user_info_directive { - explicit user_info_directive(const ValueType &value) - : value(value) + explicit user_info_directive(const std::string &user_info) + : user_info(user_info) {} - template < - class Tag - , template class Uri - > - void operator () (Uri &uri) const { + void operator () (uri &uri_) const { static const char separator[] = {'@'}; - uri.append(value); - uri.append(boost::begin(separator), boost::end(separator)); + uri_.append(user_info); + uri_.append(boost::begin(separator), boost::end(separator)); } - const ValueType &value; + std::string user_info; }; -template < - class T - > inline -user_info_directive user_info(const T &value) { - return user_info_directive(value); +user_info_directive user_info(const std::string &user_info) { + return user_info_directive(user_info); } } // namespace uri } // namespace network diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index c26a10f5e..c2c7013dd 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -28,28 +28,21 @@ namespace detail { bool parse(std::string::const_iterator first, std::string::const_iterator last, uri_parts &parts); - -bool parse(std::wstring::const_iterator first, - std::wstring::const_iterator last, - uri_parts &parts); } // namespace detail -template < - class String - > -class basic_uri - : public boost::equality_comparable > { +class uri + : public boost::equality_comparable { public: - typedef String string_type; - typedef typename string_type::iterator iterator; + typedef std::string string_type; + typedef string_type::iterator iterator; typedef boost::iterator_range range_type; - typedef typename string_type::const_iterator const_iterator; + typedef string_type::const_iterator const_iterator; typedef boost::iterator_range const_range_type; - basic_uri() + uri() : is_valid_(false) { } @@ -57,38 +50,38 @@ class basic_uri template < class FwdIter > - basic_uri(const FwdIter &first, const FwdIter &last) + uri(const FwdIter &first, const FwdIter &last) : uri_(first, last), is_valid_(false) { parse(); } - basic_uri(const string_type &uri) + uri(const string_type &uri) : uri_(uri), is_valid_(false) { parse(); } - basic_uri(const basic_uri &other) + uri(const uri &other) : uri_(other.uri_), uri_parts_(other.uri_parts_), is_valid_(other.is_valid_) { } - basic_uri &operator = (const basic_uri &other) { - basic_uri(other).swap(*this); + uri &operator = (const uri &other) { + uri(other).swap(*this); return *this; } - basic_uri &operator = (const string_type &uri) { - basic_uri(uri).swap(*this); + uri &operator = (const string_type &uri_) { + uri(uri_).swap(*this); return *this; } - ~basic_uri() { + ~uri() { } - void swap(basic_uri &other) { + void swap(uri &other) { boost::swap(uri_, other.uri_); parse(); } @@ -212,168 +205,111 @@ class basic_uri void parse(); string_type uri_; - detail::uri_parts uri_parts_; + detail::uri_parts uri_parts_; bool is_valid_; }; -template < - class String - > inline -void basic_uri::parse() { +void uri::parse() { const_iterator first(boost::begin(uri_)), last(boost::end(uri_)); is_valid_ = detail::parse(first, last, uri_parts_); } -template < - class String - > inline -String scheme(const basic_uri &uri) { - return uri.scheme(); +std::string scheme(const uri &uri_) { + return uri_.scheme(); } -template < - class String - > inline -String user_info(const basic_uri &uri) { - return uri.user_info(); +std::string user_info(const uri &uri_) { + return uri_.user_info(); } -template < - class String - > inline -String host(const basic_uri &uri) { - return uri.host(); +std::string host(const uri &uri_) { + return uri_.host(); } -template < - class String - > inline -String port(const basic_uri &uri) { - return uri.port(); +std::string port(const uri &uri_) { + return uri_.port(); } -template < - class String - > inline -boost::optional port_us(const basic_uri &uri) { - String port = uri.port(); +boost::optional port_us(const uri &uri_) { + std::string port = uri_.port(); return (port.empty())? boost::optional() : boost::optional(boost::lexical_cast(port)); } -template < - class String - > inline -String path(const basic_uri &uri) { - return uri.path(); +std::string path(const uri &uri_) { + return uri_.path(); } -template < - class String - > inline -String query(const basic_uri &uri) { - return uri.query(); +std::string query(const uri &uri_) { + return uri_.query(); } -template < - class String - > inline -String fragment(const basic_uri &uri) { - return uri.fragment(); +std::string fragment(const uri &uri_) { + return uri_.fragment(); } -template < - class String - > inline -String authority(const basic_uri &uri) { - typename basic_uri::const_range_type user_info(uri.user_info_range()); - typename basic_uri::const_range_type port(uri.port_range()); - return String(user_info.begin(), port.end()); +std::string authority(const uri &uri_) { + uri::const_range_type user_info(uri_.user_info_range()); + uri::const_range_type port(uri_.port_range()); + return std::string(user_info.begin(), port.end()); } -template < - class String - > inline -String netloc(const basic_uri &uri) { - return authority(uri); +std::string netloc(const uri &uri_) { + return authority(uri_); } -template < - class String - > inline -bool valid(const basic_uri &uri) { - return uri.is_valid(); +bool valid(const uri &uri_) { + return uri_.is_valid(); } -template < - class String - > inline -bool is_valid(const basic_uri &uri) { - return valid(uri); +bool is_valid(const uri &uri_) { + return valid(uri_); } -template < - class String - > inline -bool operator == (const basic_uri &lhs, const basic_uri &rhs) { +bool operator == (const uri &lhs, const uri &rhs) { return std::equal(lhs.begin(), lhs.end(), rhs.begin()); } } // namespace uri } // namespace network -template < - class String - > inline -typename network::uri::basic_uri::iterator begin(network::uri::basic_uri &uri) { - return uri.begin(); +network::uri::uri::iterator begin(network::uri::uri &uri_) { + return uri_.begin(); } -template < - class String - > inline -typename network::uri::basic_uri::iterator end(network::uri::basic_uri &uri) { - return uri.end(); +network::uri::uri::iterator end(network::uri::uri &uri_) { + return uri_.end(); } -template < - class String - > inline -typename network::uri::basic_uri::const_iterator begin(const network::uri::basic_uri &uri) { - return uri.begin(); +network::uri::uri::const_iterator begin(const network::uri::uri &uri_) { + return uri_.begin(); } -template < - class String - > inline -typename network::uri::basic_uri::const_iterator end(const network::uri::basic_uri &uri) { - return uri.end(); +network::uri::uri::const_iterator end(const network::uri::uri &uri_) { + return uri_.end(); } -template < - class String - > inline -void swap(network::uri::basic_uri &lhs, network::uri::basic_uri &rhs) { +void swap(network::uri::uri &lhs, network::uri::uri &rhs) { lhs.swap(rhs); } } // namespace boost diff --git a/boost/network/uri/uri_io.hpp b/boost/network/uri/uri_io.hpp index 1b1f6f2cb..f900953d8 100644 --- a/boost/network/uri/uri_io.hpp +++ b/boost/network/uri/uri_io.hpp @@ -10,13 +10,8 @@ namespace boost { namespace network { namespace uri { inline -std::ostream &operator << (std::ostream &os, const basic_uri &uri) { - return os << uri.string(); -} - -inline -std::wostream &operator << (std::wostream &os, const basic_uri &uri) { - return os << uri.string(); +std::ostream &operator << (std::ostream &os, const uri &uri_) { + return os << uri_.string(); } } // namespace uri } // namespace network diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index 512277a1f..b9a35e9b6 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -19,257 +19,146 @@ using namespace boost::network; -typedef boost::mpl::list< - uri::uri - , uri::wuri - > uri_types; - -BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, uri_types) +BOOST_AUTO_TEST_CASE(builder_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string path("/"); - - uri_type instance; - //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); - instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << uri::host(string_type(boost::begin(host), boost::end(host))) - << uri::path(string_type(boost::begin(path), boost::end(path))) - ; + uri::uri instance; + instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_builder_test, T, uri_types) +BOOST_AUTO_TEST_CASE(full_uri_builder_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string user_info("user:password"); - const std::string host("www.example.com"); - const std::string port("80"); - const std::string path("/path"); - const std::string query("query"); - const std::string fragment("fragment"); - - uri_type instance; - instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << uri::user_info(string_type(boost::begin(user_info), boost::end(user_info))) - << uri::host(string_type(boost::begin(host), boost::end(host))) - << uri::port(string_type(boost::begin(port), boost::end(port))) - << uri::path(string_type(boost::begin(path), boost::end(path))) - << uri::query(string_type(boost::begin(query), boost::end(query))) - << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))) + uri::uri instance; + instance << uri::scheme("http") + << uri::user_info("user:password") + << uri::host("www.example.com") + << uri::port("80") + << uri::path("/path") + << uri::query("query") + << uri::fragment("fragment") ; BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::user_info(instance), "user:password"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); BOOST_CHECK(uri::port_us(instance)); BOOST_CHECK_EQUAL(uri::port_us(instance).get(), 80); - BOOST_CHECK(boost::equal(uri::port(instance), port)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::query(instance), query)); - BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); + BOOST_CHECK_EQUAL(uri::port(instance), "80"); + BOOST_CHECK_EQUAL(uri::path(instance), "/path"); + BOOST_CHECK_EQUAL(uri::query(instance), "query"); + BOOST_CHECK_EQUAL(uri::fragment(instance), "fragment"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(port_test, T, uri_types) +BOOST_AUTO_TEST_CASE(port_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string port("8000"); - const std::string path("/"); - - uri_type instance; - //instance << uri::scheme("http") << uri::host("www.example.com") << uri::port(8000) << uri::path("/"); - instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << uri::host(string_type(boost::begin(host), boost::end(host))) - << uri::port(8000) - << uri::path(string_type(boost::begin(path), boost::end(path))) - ; + uri::uri instance; + instance << uri::scheme("http") << uri::host("www.example.com") << uri::port(8000) << uri::path("/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::port(instance), port)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::port(instance), "8000"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, uri_types) +BOOST_AUTO_TEST_CASE(encoded_path_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string port("8000"); - const std::string encoded_path("/Path%20With%20%28Some%29%20Encoded%20Characters%21"); - const std::string decoded_path("/Path With (Some) Encoded Characters!"); - - uri_type instance; - instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << uri::host(string_type(boost::begin(host), boost::end(host))) + uri::uri instance; + instance << uri::scheme("http") + << uri::host("www.example.com") << uri::port(8000) - << uri::encoded_path(string_type(boost::begin(decoded_path), boost::end(decoded_path))) - //<< uri::path(uri::encoded(string_type(boost::begin(decoded_path), boost::end(decoded_path)))) + << uri::encoded_path("/Path%20With%20%28Some%29%20Encoded%20Characters%21") + //<< uri::path(uri::encoded("/Path%20With%20%28Some%29%20Encoded%20Characters%21") ; + std::cout << instance << std::endl; BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::port(instance), port)); - BOOST_CHECK(boost::equal(uri::path(instance), encoded_path)); - BOOST_CHECK(boost::equal(uri::decoded_path(instance), decoded_path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::port(instance), "8000"); + BOOST_CHECK_EQUAL(uri::path(instance), "/Path%20With%20%28Some%29%20Encoded%20Characters%21"); + BOOST_CHECK_EQUAL(uri::decoded_path(instance), "/Path With (Some) Encoded Characters!"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(query_test, T, uri_types) +BOOST_AUTO_TEST_CASE(query_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string path("/"); - const std::string query("key=value"); - const std::string query_key("key"); - const std::string query_value("value"); - - uri_type instance; - //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); - instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << uri::host(string_type(boost::begin(host), boost::end(host))) - << uri::path(string_type(boost::begin(path), boost::end(path))) - << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), - string_type(boost::begin(query_value), boost::end(query_value))); + uri::uri instance; + instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") + << uri::query("key", "value") + ; BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::query(instance), query)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); + BOOST_CHECK_EQUAL(uri::query(instance), "key=value"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(query_2_test, T, uri_types) +BOOST_AUTO_TEST_CASE(query_2_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string path("/"); - const std::string query("key=value;key=value"); - const std::string query_key("key"); - const std::string query_value("value"); - - uri_type instance; - //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); - instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << uri::host(string_type(boost::begin(host), boost::end(host))) - << uri::path(string_type(boost::begin(path), boost::end(path))) - << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), - string_type(boost::begin(query_value), boost::end(query_value))) - << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), - string_type(boost::begin(query_value), boost::end(query_value))); + uri::uri instance; + instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") + << uri::query("key1", "value1") << uri::query("key2", "value2") + ; BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::query(instance), query)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); + BOOST_CHECK_EQUAL(uri::query(instance), "key1=value1;key2=value2"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, uri_types) +BOOST_AUTO_TEST_CASE(fragment_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string path("/"); - const std::string fragment("fragment"); - - uri_type instance; - //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") << uri::fragment("fragment"); - instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << uri::host(string_type(boost::begin(host), boost::end(host))) - << uri::path(string_type(boost::begin(path), boost::end(path))) - << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))); + uri::uri instance; + instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") << uri::fragment("fragment"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); + BOOST_CHECK_EQUAL(uri::fragment(instance), "fragment"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, uri_types) +BOOST_AUTO_TEST_CASE(from_root_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string root("http://www.example.com/"); - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string path("/"); - const std::string fragment("fragment"); - - uri_type root_uri(boost::begin(root), boost::end(root)); - uri_type instance; - //instance << uri::uri("http://www.example.com/") << uri::path("/") << uri::fragment("fragment"); - instance << root_uri - << uri::path(string_type(boost::begin(path), boost::end(path))) - << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))); + uri::uri root_uri("http://www.example.com/"); + uri::uri instance; + instance << root_uri << uri::path("/") << uri::fragment("fragment"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); + BOOST_CHECK_EQUAL(uri::fragment(instance), "fragment"); } -//BOOST_AUTO_TEST_CASE_TEMPLATE(scheme_test, T, uri_types) +//BOOST_AUTO_TEST_CASE(scheme_test) +//{ +// uri_type instance; +// instance << uri::schemes::http << uri::host("www.example.com") << uri::path("/"); +// BOOST_REQUIRE(uri::valid(instance)); +// BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); +// BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); +// BOOST_CHECK_EQUAL(uri::path(instance), "/"); +//} + +//BOOST_AUTO_TEST_CASE(encoded_null_char_test) //{ -// typedef T uri_type; -// typedef typename uri_type::string_type string_type; +// typedef uri::uri uri_type; +// typedef uri_type::string_type string_type; // // const std::string scheme("http"); // const std::string host("www.example.com"); // const std::string path("/"); // // uri_type instance; -// //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); -// instance << uri::schemes::http -// << uri::host(string_type(boost::begin(host), boost::end(host))) -// << uri::path(string_type(boost::begin(path), boost::end(path))) +// // there is a potential bug in the way we process ranges if the +// // strings are null terminated. +// instance << uri::scheme("http") +// << uri::host("www.example.com") +// << uri::encoded_path("/") // ; // BOOST_REQUIRE(uri::valid(instance)); -// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); -// BOOST_CHECK(boost::equal(uri::host(instance), host)); -// BOOST_CHECK(boost::equal(uri::path(instance), path)); +// BOOST_CHECK_EQUAL(uri::scheme(instance), scheme); +// BOOST_CHECK_EQUAL(uri::host(instance), host); +// BOOST_CHECK_EQUAL(uri::path(instance), path); //} - -BOOST_AUTO_TEST_CASE(encoded_null_char_test) -{ - typedef uri::uri uri_type; - typedef uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string path("/"); - - uri_type instance; - // there is a potential bug in the way we process ranges if the - // strings are null terminated. - instance << uri::scheme("http") - << uri::host("www.example.com") - << uri::encoded_path("/") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), scheme); - BOOST_CHECK_EQUAL(uri::host(instance), host); - BOOST_CHECK_EQUAL(uri::path(instance), path); -} diff --git a/libs/network/test/uri/url_encoding_test.cpp b/libs/network/test/uri/url_encoding_test.cpp index bc08f8c1c..6ca37939b 100644 --- a/libs/network/test/uri/url_encoding_test.cpp +++ b/libs/network/test/uri/url_encoding_test.cpp @@ -8,41 +8,26 @@ #include #include #include -#include -#include -#include -#include -#include #include using namespace boost::network; -typedef boost::mpl::list< - tags::default_string - , tags::default_wstring - > tag_types; - - -BOOST_AUTO_TEST_CASE_TEMPLATE(encoding_test, T, tag_types) { - typedef typename string::type string_type; +BOOST_AUTO_TEST_CASE(encoding_test) { const std::string unencoded(" !\"#$%&\'()*"); const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A"); - string_type instance; + std::string instance; uri::encode(unencoded, std::back_inserter(instance)); - BOOST_CHECK(boost::equal(instance, encoded)); + BOOST_CHECK_EQUAL(instance, encoded); } - -BOOST_AUTO_TEST_CASE_TEMPLATE(decoding_test, T, tag_types) { - typedef typename string::type string_type; - +BOOST_AUTO_TEST_CASE(decoding_test) { const std::string unencoded(" !\"#$%&\'()*"); const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A"); - string_type instance; + std::string instance; uri::decode(encoded, std::back_inserter(instance)); - BOOST_CHECK(boost::equal(instance, unencoded)); + BOOST_CHECK_EQUAL(instance, unencoded); } diff --git a/libs/network/test/uri/url_http_test.cpp b/libs/network/test/uri/url_http_test.cpp deleted file mode 100644 index ed162df89..000000000 --- a/libs/network/test/uri/url_http_test.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#define BOOST_TEST_MODULE HTTP URL Test -#include -#include -#include -#include -#include - -using namespace boost::network; - -typedef boost::mpl::list< - tags::default_string - , tags::default_wstring - > tag_types; - - -BOOST_AUTO_TEST_CASE_TEMPLATE(valid_http, T, tag_types) -{ - typedef uri::http::basic_uri uri_type; - typedef typename uri_type::string_type string_type; - const std::string url("http://example.com/"); - uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_http(instance)); - BOOST_REQUIRE(uri::is_valid(instance)); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(valid_https, T, tag_types) -{ - typedef uri::http::basic_uri uri_type; - typedef typename uri_type::string_type string_type; - const std::string url("https://example.com/"); - uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_https(instance)); - BOOST_REQUIRE(uri::is_valid(instance)); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(invalid_https, T, tag_types) -{ - typedef uri::http::basic_uri uri_type; - typedef typename uri_type::string_type string_type; - const std::string url("http://example.com/"); - uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(!uri::is_https(instance)); - BOOST_REQUIRE(uri::is_valid(instance)); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(not_http, T, tag_types) -{ - typedef uri::http::basic_uri uri_type; - typedef typename uri_type::string_type string_type; - const std::string url("/service/mailto:john.doe@example.com"); - uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(!uri::is_http(instance)); - BOOST_REQUIRE(!uri::is_https(instance)); - BOOST_REQUIRE(!uri::is_valid(instance)); -} diff --git a/libs/network/test/uri/url_mailto_test.cpp b/libs/network/test/uri/url_mailto_test.cpp deleted file mode 100644 index 8765748fe..000000000 --- a/libs/network/test/uri/url_mailto_test.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#define BOOST_TEST_MODULE mailto URL Test -#include -#include -#include -#include -#include - -using namespace boost::network; - -typedef boost::mpl::list< - tags::default_string - , tags::default_wstring - > tag_types; - - -BOOST_AUTO_TEST_CASE_TEMPLATE(valid_mailto, T, tag_types) -{ - typedef uri::mailto::basic_uri uri_type; - typedef typename uri_type::string_type string_type; - const std::string url("/service/mailto:john.doe@example.com"); - uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_mailto(instance)); - BOOST_REQUIRE(uri::is_valid(instance)); -} diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index 091d96559..700cfc5f9 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -8,319 +8,173 @@ #include #include #include -#include -#include +#include #include -#include -#include #include using namespace boost::network; -typedef boost::mpl::list< - uri::uri - , uri::wuri - > uri_types; - -BOOST_AUTO_TEST_CASE_TEMPLATE(uri_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://www.example.com/"); - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string path("/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(uri_test) { + uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://user:password@www.example.com/path?query#fragment"); - const std::string scheme("http"); - const std::string user_info("user:password"); - const std::string host("www.example.com"); - const std::string port = "80"; - const std::string path("/path"); - const std::string query("query"); - const std::string fragment("fragment"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(full_uri_test) { + uri::uri instance("http://user:password@www.example.com/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::user_info(instance), "user:password"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); BOOST_CHECK(uri::port_us(instance)); BOOST_CHECK_EQUAL(uri::port_us(instance).get(), 80); - BOOST_CHECK(boost::equal(uri::port(instance), port)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::query(instance), query)); - BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); + BOOST_CHECK_EQUAL(uri::port(instance), "80"); + BOOST_CHECK_EQUAL(uri::path(instance), "/path"); + BOOST_CHECK_EQUAL(uri::query(instance), "query"); + BOOST_CHECK_EQUAL(uri::fragment(instance), "fragment"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(mailto_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/mailto:john.doe@example.com"); - const std::string scheme("mailto"); - // RFC 3986 interprets this as the path - const std::string path("john.doe@example.com"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(mailto_test) { + uri::uri instance("mailto:john.doe@example.com"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "mailto"); + BOOST_CHECK_EQUAL(uri::path(instance), "john.doe@example.com"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(file_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/file:///bin/bash"); - const std::string scheme("file"); - const std::string path("/bin/bash"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(file_test) { + uri::uri instance("file:///bin/bash"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "file"); + BOOST_CHECK_EQUAL(uri::path(instance), "/bin/bash"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/xmpp:example-node@example.com?message;subject=Hello%20World"); - const std::string scheme("xmpp"); - // RFC 3986 interprets this as the path - const std::string path("example-node@example.com"); - const std::string query("message;subject=Hello%20World"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(xmpp_test) { + uri::uri instance("xmpp:example-node@example.com?message;subject=Hello%20World"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::query(instance), query)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "xmpp"); + BOOST_CHECK_EQUAL(uri::path(instance), "example-node@example.com"); + BOOST_CHECK_EQUAL(uri::query(instance), "message;subject=Hello%20World"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://129.79.245.252/"); - const std::string scheme("http"); - const std::string host("129.79.245.252"); - const std::string path("/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(ipv4_address_test) { + uri::uri instance("http://129.79.245.252/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "129.79.245.252"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_1, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://[1080::8:800:200c:417a]/"); - const std::string scheme("http"); - const std::string host("[1080:0:0:0:8:800:200C:417A]"); - const std::string path("/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(ipv6_address_test_1) { + uri::uri instance("http://[1080::8:800:200c:417a]/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "[1080:0:0:0:8:800:200C:417A]"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_2, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/"); - const std::string scheme("http"); - const std::string host("[2001:db8:85a3:8d3:1319:8a2e:370:7348]"); - const std::string path("/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(ipv6_address_test_2) { + uri::uri instance("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "[2001:db8:85a3:8d3:1319:8a2e:370:7348]"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ftp_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/ftp://john.doe@ftp.example.com/"); - const std::string scheme("ftp"); - const std::string user_info("john.doe"); - const std::string host("ftp.example.com"); - const std::string path("/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(ftp_test) { + uri::uri instance("ftp://john.doe@ftp.example.com/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "ftp"); + BOOST_CHECK_EQUAL(uri::user_info(instance), "john.doe"); + BOOST_CHECK_EQUAL(uri::host(instance), "ftp.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(news_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/news:comp.infosystems.www.servers.unix"); - const std::string scheme("news"); - const std::string path("comp.infosystems.www.servers.unix"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(news_test) { + uri::uri instance("news:comp.infosystems.www.servers.unix"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "news"); + BOOST_CHECK_EQUAL(uri::path(instance), "comp.infosystems.www.servers.unix"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(tel_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/tel:+1-816-555-1212"); - const std::string scheme("tel"); - const std::string path("+1-816-555-1212"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(tel_test) { + uri::uri instance("tel:+1-816-555-1212"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "tel"); + BOOST_CHECK_EQUAL(uri::path(instance), "+1-816-555-1212"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_uri_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://www.example.com/Path%20With%20%28Some%29%20Encoded%20Characters%21"); - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string encoded_path("/Path%20With%20%28Some%29%20Encoded%20Characters%21"); - const std::string decoded_path("/Path With (Some) Encoded Characters!"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(encoded_uri_test) { + uri::uri instance("http://www.example.com/Path%20With%20%28Some%29%20Encoded%20Characters%21"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), encoded_path)); - BOOST_CHECK(boost::equal(uri::decoded_path(instance), decoded_path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/Path%20With%20%28Some%29%20Encoded%20Characters%21"); + BOOST_CHECK_EQUAL(uri::decoded_path(instance), "/Path With (Some) Encoded Characters!"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(copy_constructor_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://www.example.com/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); - uri_type copy = instance; +BOOST_AUTO_TEST_CASE(copy_constructor_test) { + uri::uri instance("http://www.example.com/"); + uri::uri copy = instance; BOOST_CHECK(instance == copy); } -BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://www.example.com/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); - uri_type copy; +BOOST_AUTO_TEST_CASE(assignment_test) { + uri::uri instance("http://www.example.com/"); + uri::uri copy; copy = instance; - BOOST_CHECK(instance.string() == copy.string()); - BOOST_CHECK(instance == copy); + BOOST_CHECK_EQUAL(instance.string(), copy.string()); + BOOST_CHECK_EQUAL(instance, copy); } -BOOST_AUTO_TEST_CASE_TEMPLATE(username_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/ftp://john.doe:password@ftp.example.com/"); - const std::string scheme("http"); - const std::string username("john.doe"); - const std::string password("password"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(username_test) { + uri::uri instance("ftp://john.doe:password@ftp.example.com/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::username(instance), username)); - BOOST_CHECK(boost::equal(uri::password(instance), password)); + BOOST_CHECK_EQUAL(uri::username(instance), "john.doe"); + BOOST_CHECK_EQUAL(uri::password(instance), "password"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(authority_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://user:password@www.example.com/path?query#fragment"); - const std::string authority("user:password@www.example.com:80"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(authority_test) { + uri::uri instance("http://user:password@www.example.com/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::authority(instance), authority)); + BOOST_CHECK_EQUAL(uri::authority(instance), "user:password@www.example.com:80"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(http_query_map_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://user:password@www.example.com/path?query#fragment"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(http_query_map_test) { + uri::uri instance("http://user:password@www.example.com/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); const std::string key("query"); const std::string value; - std::map queries; + std::map queries; uri::query_map(instance, queries); BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(1)); - BOOST_CHECK(boost::equal(queries.begin()->first, key)); - BOOST_CHECK(boost::equal(queries.begin()->second, value)); + BOOST_CHECK_EQUAL(queries.begin()->first, key); + BOOST_CHECK_EQUAL(queries.begin()->second, value); } -BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/xmpp:example-node@example.com?message;subject=Hello%20World"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(xmpp_query_map_test) { + uri::uri instance("xmpp:example-node@example.com?message;subject=Hello%20World"); BOOST_REQUIRE(uri::valid(instance)); const std::string key_1("message"), key_2("subject"); const std::string value_1, value_2("Hello%20World"); - std::map queries; + std::map queries; uri::query_map(instance, queries); BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(2)); - BOOST_CHECK(boost::equal(queries.begin()->first, key_1)); - BOOST_CHECK(boost::equal(queries.begin()->second, value_1)); - BOOST_CHECK(boost::equal((++queries.begin())->first, key_2)); - BOOST_CHECK(boost::equal((++queries.begin())->second, value_2)); + BOOST_CHECK_EQUAL(queries.begin()->first, key_1); + BOOST_CHECK_EQUAL(queries.begin()->second, value_1); + BOOST_CHECK_EQUAL((++queries.begin())->first, key_2); + BOOST_CHECK_EQUAL((++queries.begin())->second, value_2); } -BOOST_AUTO_TEST_CASE_TEMPLATE(range_test, T, uri_types) +BOOST_AUTO_TEST_CASE(range_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - const std::string url("http://www.example.com/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); + uri::uri instance(url); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(instance, url)); } From 3458473a127e1f9b76179f28e2ed9a76d3af7138 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 18 Sep 2011 10:25:08 +0200 Subject: [PATCH 166/768] Cleaned up the URI tests a little further. --- boost/network/uri/directives/authority.hpp | 7 +++- boost/network/uri/directives/fragment.hpp | 12 +++--- boost/network/uri/directives/host.hpp | 7 +++- boost/network/uri/directives/path.hpp | 7 +++- boost/network/uri/directives/port.hpp | 34 ++++++---------- boost/network/uri/directives/query.hpp | 33 ++++++++-------- boost/network/uri/directives/scheme.hpp | 10 +++-- boost/network/uri/directives/user_info.hpp | 10 +++-- boost/network/uri/uri.hpp | 15 +++++++ libs/network/test/uri/url_builder_test.cpp | 40 ++++++++----------- libs/network/test/uri/url_test.cpp | 46 ++++++++++++++++------ 11 files changed, 125 insertions(+), 96 deletions(-) diff --git a/boost/network/uri/directives/authority.hpp b/boost/network/uri/directives/authority.hpp index 3d1295a40..807de4af7 100644 --- a/boost/network/uri/directives/authority.hpp +++ b/boost/network/uri/directives/authority.hpp @@ -11,8 +11,11 @@ struct authority_directive { : authority(authority) {} - void operator () (uri &uri_) const { - uri_.append(authority); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append(authority); } std::string authority; diff --git a/boost/network/uri/directives/fragment.hpp b/boost/network/uri/directives/fragment.hpp index 33c57c2f1..0beadd421 100644 --- a/boost/network/uri/directives/fragment.hpp +++ b/boost/network/uri/directives/fragment.hpp @@ -16,12 +16,12 @@ struct fragment_directive { : fragment(fragment) {} - void operator () (uri &uri_) const { - std::string encoded_fragment; - static const char separator[] = {'#'}; - uri_.append(boost::begin(separator), boost::end(separator)); - encode(fragment, std::back_inserter(encoded_fragment)); - uri_.append(encoded_fragment); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append("#"); + uri.append(fragment); } std::string fragment; diff --git a/boost/network/uri/directives/host.hpp b/boost/network/uri/directives/host.hpp index a7f72efaa..75cf1d038 100644 --- a/boost/network/uri/directives/host.hpp +++ b/boost/network/uri/directives/host.hpp @@ -15,8 +15,11 @@ struct host_directive { : host(host) {} - void operator () (uri &uri_) const { - uri_.append(host); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append(host); } std::string host; diff --git a/boost/network/uri/directives/path.hpp b/boost/network/uri/directives/path.hpp index 241fe9e3d..4921a3eb2 100644 --- a/boost/network/uri/directives/path.hpp +++ b/boost/network/uri/directives/path.hpp @@ -15,8 +15,11 @@ struct path_directive { : path(path) {} - void operator () (uri &uri_) const { - uri_.append(path); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append(path); } std::string path; diff --git a/boost/network/uri/directives/port.hpp b/boost/network/uri/directives/port.hpp index a31711dea..9e561486b 100644 --- a/boost/network/uri/directives/port.hpp +++ b/boost/network/uri/directives/port.hpp @@ -17,31 +17,19 @@ struct port_directive { : port(port) {} - void operator () (uri &uri_) const { - static const char separator[] = {':'}; - uri_.append(boost::begin(separator), boost::end(separator)); - uri_.append(port); - } - - std::string port; - -}; - - -struct port_directive_us { - - explicit port_directive_us(boost::uint16_t port) - : port(port) + explicit port_directive(boost::uint16_t port) + : port(boost::lexical_cast(port)) {} - void operator () (uri &uri_) const { - static const char separator[] = {':'}; - uri_.append(boost::begin(separator), boost::end(separator)); - std::string port_ = boost::lexical_cast(port); - uri_.append(port_); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append(":"); + uri.append(port); } - boost::uint16_t port; + std::string port; }; @@ -51,8 +39,8 @@ port_directive port(const std::string &port) { } inline -port_directive_us port(boost::uint16_t port) { - return port_directive_us(port); +port_directive port(boost::uint16_t port) { + return port_directive(port); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp index 39520f1e0..d2afbcadf 100644 --- a/boost/network/uri/directives/query.hpp +++ b/boost/network/uri/directives/query.hpp @@ -16,11 +16,12 @@ struct query_directive { : query(query) {} - void operator () (uri &uri_) const { - std::string encoded_query; - static const char separator[] = {'?'}; - uri_.append(boost::begin(separator), boost::end(separator)); - uri_.append(query); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append("?"); + uri.append(query); } std::string query; @@ -38,24 +39,22 @@ struct query_key_query_directive { : key(key), query(query) {} - void operator () (uri &uri_) const { + template < + class Uri + > + void operator () (Uri &uri) const { std::string encoded_key, encoded_query; - static const char qmark[] = {'?'}; - static const char equal[] = {'='}; - static const char scolon[] = {';'}; - if (!uri_.query_range()) + if (!uri.query_range()) { - uri_.append(boost::begin(qmark), boost::end(qmark)); + uri.append("?"); } else { - uri_.append(boost::begin(scolon), boost::end(scolon)); + uri.append(";"); } - encode(key, std::back_inserter(encoded_key)); - uri_.append(encoded_key); - uri_.append(boost::begin(equal), boost::end(equal)); - encode(query, std::back_inserter(encoded_query)); - uri_.append(encoded_query); + uri.append(key); + uri.append("="); + uri.append(query); } std::string key; diff --git a/boost/network/uri/directives/scheme.hpp b/boost/network/uri/directives/scheme.hpp index 764265e2a..708436006 100644 --- a/boost/network/uri/directives/scheme.hpp +++ b/boost/network/uri/directives/scheme.hpp @@ -15,10 +15,12 @@ struct scheme_directive { : scheme(scheme) {} - void operator () (uri &uri_) const { - static const char separator[] = {':', '/', '/'}; - uri_.append(scheme); - uri_.append(boost::begin(separator), boost::end(separator)); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append(scheme); + uri.append("://"); } std::string scheme; diff --git a/boost/network/uri/directives/user_info.hpp b/boost/network/uri/directives/user_info.hpp index a900eed93..cd7e7e788 100644 --- a/boost/network/uri/directives/user_info.hpp +++ b/boost/network/uri/directives/user_info.hpp @@ -15,10 +15,12 @@ struct user_info_directive { : user_info(user_info) {} - void operator () (uri &uri_) const { - static const char separator[] = {'@'}; - uri_.append(user_info); - uri_.append(boost::begin(separator), boost::end(separator)); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append(user_info); + uri.append("@"); } std::string user_info; diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index c2c7013dd..3332d86a6 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -281,6 +281,21 @@ bool is_valid(const uri &uri_) { return valid(uri_); } +inline +bool is_hierarchical(const uri &uri_) { + //uri::const_range_type scheme = uri_.scheme_range(); + //uri::const_range_type user_info = uri_.user_info_range(); + //return is_valid(uri_) && + // boost::equal(std::make_pair(boost::end(scheme), + // boost::begin(user_info)), + // boost::as_literal("://")); + return false; +} + +bool is_opaque(const uri &uri_) { + return false; +} + inline bool operator == (const uri &lhs, const uri &rhs) { return std::equal(lhs.begin(), lhs.end(), rhs.begin()); diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index b9a35e9b6..fb55e96ad 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -70,10 +70,9 @@ BOOST_AUTO_TEST_CASE(encoded_path_test) instance << uri::scheme("http") << uri::host("www.example.com") << uri::port(8000) - << uri::encoded_path("/Path%20With%20%28Some%29%20Encoded%20Characters%21") - //<< uri::path(uri::encoded("/Path%20With%20%28Some%29%20Encoded%20Characters%21") + << uri::encoded_path("/Path With (Some) Encoded Characters!") + ; ; - std::cout << instance << std::endl; BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); @@ -141,24 +140,17 @@ BOOST_AUTO_TEST_CASE(from_root_test) // BOOST_CHECK_EQUAL(uri::path(instance), "/"); //} -//BOOST_AUTO_TEST_CASE(encoded_null_char_test) -//{ -// typedef uri::uri uri_type; -// typedef uri_type::string_type string_type; -// -// const std::string scheme("http"); -// const std::string host("www.example.com"); -// const std::string path("/"); -// -// uri_type instance; -// // there is a potential bug in the way we process ranges if the -// // strings are null terminated. -// instance << uri::scheme("http") -// << uri::host("www.example.com") -// << uri::encoded_path("/") -// ; -// BOOST_REQUIRE(uri::valid(instance)); -// BOOST_CHECK_EQUAL(uri::scheme(instance), scheme); -// BOOST_CHECK_EQUAL(uri::host(instance), host); -// BOOST_CHECK_EQUAL(uri::path(instance), path); -//} +BOOST_AUTO_TEST_CASE(encoded_null_char_test) +{ + // there is a potential bug in the way we process ranges if the + // strings are null terminated. + uri::uri instance; + instance << uri::scheme("http") + << uri::host("www.example.com") + << uri::encoded_path("/") + ; + BOOST_REQUIRE(uri::valid(instance)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); +} diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index 700cfc5f9..e48146a49 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -16,9 +16,35 @@ using namespace boost::network; -BOOST_AUTO_TEST_CASE(uri_test) { +BOOST_AUTO_TEST_CASE(basic_uri_range_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); + BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); + BOOST_CHECK(boost::equal(instance.user_info_range(), boost::as_literal(""))); + BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); + BOOST_CHECK(boost::equal(instance.port_range(), boost::as_literal(""))); + BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/"))); + BOOST_CHECK(boost::equal(instance.query_range(), boost::as_literal(""))); + BOOST_CHECK(boost::equal(instance.fragment_range(), boost::as_literal(""))); +} + +BOOST_AUTO_TEST_CASE(full_uri_range_test) { + uri::uri instance("http://user:password@www.example.com/path?query#fragment"); + BOOST_REQUIRE(uri::valid(instance)); + BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); + BOOST_CHECK(boost::equal(instance.user_info_range(), boost::as_literal("user:password"))); + BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); + BOOST_CHECK(boost::equal(instance.port_range(), boost::as_literal("80"))); + BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/path"))); + BOOST_CHECK(boost::equal(instance.query_range(), boost::as_literal("query"))); + BOOST_CHECK(boost::equal(instance.fragment_range(), boost::as_literal("fragment"))); +} + +BOOST_AUTO_TEST_CASE(basic_uri_test) { + uri::uri instance("http://www.example.com/"); + uri::uri::const_range_type scheme = instance.scheme_range(); + uri::uri::const_range_type user_info = instance.host_range(); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); BOOST_CHECK_EQUAL(uri::path(instance), "/"); @@ -144,31 +170,27 @@ BOOST_AUTO_TEST_CASE(authority_test) { } BOOST_AUTO_TEST_CASE(http_query_map_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); + uri::uri instance("http://user:password@www.example.com/path?query=something#fragment"); BOOST_REQUIRE(uri::valid(instance)); - const std::string key("query"); - const std::string value; std::map queries; uri::query_map(instance, queries); BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(1)); - BOOST_CHECK_EQUAL(queries.begin()->first, key); - BOOST_CHECK_EQUAL(queries.begin()->second, value); + BOOST_CHECK_EQUAL(queries.begin()->first, "query"); + BOOST_CHECK_EQUAL(queries.begin()->second, "something"); } BOOST_AUTO_TEST_CASE(xmpp_query_map_test) { uri::uri instance("xmpp:example-node@example.com?message;subject=Hello%20World"); BOOST_REQUIRE(uri::valid(instance)); - const std::string key_1("message"), key_2("subject"); - const std::string value_1, value_2("Hello%20World"); std::map queries; uri::query_map(instance, queries); BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(2)); - BOOST_CHECK_EQUAL(queries.begin()->first, key_1); - BOOST_CHECK_EQUAL(queries.begin()->second, value_1); - BOOST_CHECK_EQUAL((++queries.begin())->first, key_2); - BOOST_CHECK_EQUAL((++queries.begin())->second, value_2); + BOOST_CHECK_EQUAL(queries.begin()->first, "message"); + BOOST_CHECK_EQUAL(queries.begin()->second, ""); + BOOST_CHECK_EQUAL((++queries.begin())->first, "subject"); + BOOST_CHECK_EQUAL((++queries.begin())->second, "Hello%20World"); } BOOST_AUTO_TEST_CASE(range_test) From 97731a1518d7464beed7f8ec1f3e85b4981933b6 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 18 Sep 2011 16:47:36 +0200 Subject: [PATCH 167/768] Minor clarifications in URI test. --- libs/network/test/uri/url_test.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index e48146a49..a6ab8e125 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -20,12 +20,12 @@ BOOST_AUTO_TEST_CASE(basic_uri_range_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); - BOOST_CHECK(boost::equal(instance.user_info_range(), boost::as_literal(""))); + BOOST_CHECK(boost::empty(instance.user_info_range())); BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); - BOOST_CHECK(boost::equal(instance.port_range(), boost::as_literal(""))); + BOOST_CHECK(boost::empty(instance.port_range())); BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/"))); - BOOST_CHECK(boost::equal(instance.query_range(), boost::as_literal(""))); - BOOST_CHECK(boost::equal(instance.fragment_range(), boost::as_literal(""))); + BOOST_CHECK(boost::empty(instance.query_range())); + BOOST_CHECK(boost::empty(instance.fragment_range())); } BOOST_AUTO_TEST_CASE(full_uri_range_test) { @@ -42,8 +42,6 @@ BOOST_AUTO_TEST_CASE(full_uri_range_test) { BOOST_AUTO_TEST_CASE(basic_uri_test) { uri::uri instance("http://www.example.com/"); - uri::uri::const_range_type scheme = instance.scheme_range(); - uri::uri::const_range_type user_info = instance.host_range(); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); From bb9521f99421973c4f21b07c54bd11b1c962ba41 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Tue, 27 Sep 2011 22:16:16 +0200 Subject: [PATCH 168/768] Added test and applied fix for issue #67. --- boost/network/uri/uri.hpp | 5 +++-- libs/network/test/uri/url_test.cpp | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 3332d86a6..0e6371d81 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -72,8 +72,9 @@ class uri return *this; } - uri &operator = (const string_type &uri_) { - uri(uri_).swap(*this); + uri &operator = (const string_type &uri) { + uri_ = uri; + parse(); return *this; } diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index a6ab8e125..e56f4a327 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -198,3 +198,13 @@ BOOST_AUTO_TEST_CASE(range_test) BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(instance, url)); } + +BOOST_AUTO_TEST_CASE(issue_67_test) +{ + const std::string site_name("http://www.google.com/"); + uri::uri bar0; + uri::uri bar1 = site_name; + bar0 = site_name; + BOOST_CHECK(uri::is_valid(bar0)); + BOOST_CHECK(uri::is_valid(bar1)); +} From da52a8367d84b8c1e4d2d15a44633b13c7220e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Haisman?= Date: Sun, 2 Oct 2011 22:08:26 +0200 Subject: [PATCH 169/768] boost/network/support/is_tcp.hpp: Add new line to the end of the file to avoid GCC warning. boost/network/support/is_udp.hpp: Ditto. --- boost/network/support/is_tcp.hpp | 2 +- boost/network/support/is_udp.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/boost/network/support/is_tcp.hpp b/boost/network/support/is_tcp.hpp index c041f125f..2f5413cfd 100644 --- a/boost/network/support/is_tcp.hpp +++ b/boost/network/support/is_tcp.hpp @@ -23,4 +23,4 @@ namespace boost { namespace network { } // namespace boost -#endif // BOOST_NETWORK_SUPPORT_IS_TCP_HPP_20100622 \ No newline at end of file +#endif // BOOST_NETWORK_SUPPORT_IS_TCP_HPP_20100622 diff --git a/boost/network/support/is_udp.hpp b/boost/network/support/is_udp.hpp index cacbc5e0e..2621fc10f 100644 --- a/boost/network/support/is_udp.hpp +++ b/boost/network/support/is_udp.hpp @@ -24,4 +24,4 @@ namespace boost { namespace network { } // namespace boost -#endif // BOOST_NETWORK_SUPPORT_IS_UDP_HPP_20100622 \ No newline at end of file +#endif // BOOST_NETWORK_SUPPORT_IS_UDP_HPP_20100622 From b16cc29d17aa271c00c07599d2714de386349237 Mon Sep 17 00:00:00 2001 From: Vaclav Zeman Date: Mon, 3 Oct 2011 13:17:07 +0200 Subject: [PATCH 170/768] boost\network\protocol\http\server\impl\parsers.ipp: Use intermediate variable to fix compilation. --- boost/network/protocol/http/server/impl/parsers.ipp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/boost/network/protocol/http/server/impl/parsers.ipp b/boost/network/protocol/http/server/impl/parsers.ipp index e39c7b26d..2b7755ef6 100644 --- a/boost/network/protocol/http/server/impl/parsers.ipp +++ b/boost/network/protocol/http/server/impl/parsers.ipp @@ -24,8 +24,9 @@ namespace boost { namespace network { namespace http { BOOST_NETWORK_INLINE void parse_version(std::string const & partial_parsed, fusion::tuple & version_pair) { using namespace boost::spirit::qi; + std::string::const_iterator it = partial_parsed.begin(); parse( - partial_parsed.begin(), partial_parsed.end(), + it, partial_parsed.end(), ( lit("HTTP/") >> ushort_ @@ -37,8 +38,9 @@ namespace boost { namespace network { namespace http { BOOST_NETWORK_INLINE void parse_headers(std::string const & input, std::vector & container) { using namespace boost::spirit::qi; + std::string::const_iterator it = input.begin(); parse( - input.begin(), input.end(), + it, input.end(), *( +(alnum|(punct-':')) >> lit(": ") From bc4e1bf44813d28a75945216204a3be9ee8a658d Mon Sep 17 00:00:00 2001 From: dsevilla Date: Wed, 23 Nov 2011 02:35:49 +0100 Subject: [PATCH 171/768] Fix for issue #73 in 0.9-devel branch. --- boost/network/protocol/http/client/macros.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boost/network/protocol/http/client/macros.hpp b/boost/network/protocol/http/client/macros.hpp index 92c9f5e8c..f4fad800c 100644 --- a/boost/network/protocol/http/client/macros.hpp +++ b/boost/network/protocol/http/client/macros.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_NETWORK_HTTP_BODY_CALLBACK #define BOOST_NETWORK_HTTP_BODY_CALLBACK(function_name, range_name, error_name) \ - void function_name (boost::iterator_range const & range_name, boost::system::error_code const & error_name) + void function_name (boost::iterator_range const & range_name, boost::system::error_code const & error_name) #endif #endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 */ From e09356f156fd5f349a27ec9d26fe4d8b46926810 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sat, 20 Aug 2011 11:48:14 +1000 Subject: [PATCH 172/768] Squashed commit of the following: commit e84929c5985440503b90a70aa8baf61e2cdc628f Author: Dean Michael Berris Date: Fri Aug 19 19:04:54 2011 +1000 Adding Copyright information. commit 50b9c226a5c2aa7a9baed82e5021c14dd3ae9d9b Author: Dean Michael Berris Date: Fri Aug 19 19:01:14 2011 +1000 Internal refactor complete, now testing can start to happen. commit 4e7349ad1fb4946b916150d5b09d2ee1748c82fb Author: Dean Michael Berris Date: Fri Aug 19 17:49:13 2011 +1000 WIP: broken build because Boost 1.45 asio seems to not have support for wide strings in API. --- CMakeLists.txt | 8 +- .../http/client/connection/async_base.hpp | 89 ++-- .../http/client/connection/async_normal.hpp | 169 ++++---- .../connection/async_protocol_handler.hpp | 30 +- .../http/client/connection/async_ssl.hpp | 410 ------------------ .../client/connection/connection_delegate.hpp | 30 ++ .../connection_delegate_factory.hpp | 56 +++ .../client/connection/normal_delegate.hpp | 45 ++ .../client/connection/normal_delegate.ipp | 42 ++ .../http/client/connection/ssl_delegate.hpp | 58 +++ .../http/client/connection/ssl_delegate.ipp | 64 +++ .../protocol/http/traits/delegate_factory.hpp | 39 ++ boost/network/traits/char.hpp | 7 +- libs/network/example/CMakeLists.txt | 8 +- libs/network/src/CMakeLists.txt | 8 +- libs/network/test/CMakeLists.txt | 2 - libs/network/test/http/CMakeLists.txt | 8 +- .../server_async_run_stop_concurrency.cpp | 226 +++++----- 18 files changed, 623 insertions(+), 676 deletions(-) delete mode 100644 boost/network/protocol/http/client/connection/async_ssl.hpp create mode 100644 boost/network/protocol/http/client/connection/connection_delegate.hpp create mode 100644 boost/network/protocol/http/client/connection/connection_delegate_factory.hpp create mode 100644 boost/network/protocol/http/client/connection/normal_delegate.hpp create mode 100644 boost/network/protocol/http/client/connection/normal_delegate.ipp create mode 100644 boost/network/protocol/http/client/connection/ssl_delegate.hpp create mode 100644 boost/network/protocol/http/client/connection/ssl_delegate.ipp create mode 100644 boost/network/protocol/http/traits/delegate_factory.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1475321ce..eba49491b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,18 +6,24 @@ cmake_minimum_required(VERSION 2.6) project(CPP-NETLIB) find_package( Boost 1.41.0 ) +find_package( OpenSSL ) +find_package( Threads ) set(CMAKE_VERBOSE_MAKEFILE true) if (CMAKE_BUILD_TYPE MATCHES Debug) add_definitions(-DBOOST_NETWORK_DEBUG) endif() - if (Boost_FOUND) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTI_THREADED ON) include_directories(${Boost_INCLUDE_DIRS}) endif() enable_testing() + +if (OPENSSL_FOUND) + add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) +endif() + add_subdirectory(libs/network/src) add_subdirectory(libs/network/test) add_subdirectory(libs/mime/test) diff --git a/boost/network/protocol/http/client/connection/async_base.hpp b/boost/network/protocol/http/client/connection/async_base.hpp index 8916fedc2..943ca2106 100644 --- a/boost/network/protocol/http/client/connection/async_base.hpp +++ b/boost/network/protocol/http/client/connection/async_base.hpp @@ -8,45 +8,64 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#include +#include #include -#ifdef BOOST_NETWORK_ENABLE_HTTPS -#include -#endif namespace boost { namespace network { namespace http { namespace impl { - template - struct async_connection_base { - typedef typename resolver_policy::type resolver_base; - typedef typename resolver_base::resolver_type resolver_type; - typedef typename resolver_base::resolve_function resolve_function; - typedef typename string::type string_type; - typedef basic_request request; - typedef basic_response response; - typedef - function const &, system::error_code const &)> - body_callback_function_type; - - static boost::shared_ptr > new_connection(resolve_function resolve, resolver_type & resolver, bool follow_redirect, bool https, optional certificate_filename=optional(), optional const & verify_path=optional()) { - boost::shared_ptr > temp; - if (https) { -#ifdef BOOST_NETWORK_ENABLE_HTTPS - temp.reset(new https_async_connection(resolver, resolve, follow_redirect, certificate_filename, verify_path)); - return temp; -#else - throw std::runtime_error("HTTPS not supported."); -#endif - } - temp.reset(new http_async_connection(resolver, resolve, follow_redirect)); - assert(temp.get() != 0); - return temp; - } - - virtual response start(request const & request, string_type const & method, bool get_body, body_callback_function_type callback) = 0; - - virtual ~async_connection_base() {} - - }; + template + struct async_connection_base { + typedef async_connection_base this_type; + typedef typename resolver_policy::type resolver_base; + typedef typename resolver_base::resolver_type resolver_type; + typedef typename resolver_base::resolve_function resolve_function; + typedef typename string::type string_type; + typedef basic_request request; + typedef basic_response response; + typedef iterator_range char_const_range; + typedef function + body_callback_function_type; + typedef shared_ptr connection_ptr; + + // This is the factory function which constructs the appropriate async + // connection implementation with the correct delegate chosen based on the + // tag. + static connection_ptr new_connection( + resolve_function resolve, + resolver_type & resolver, + bool follow_redirect, + bool https, + optional certificate_filename=optional(), + optional const & verify_path=optional()) { + typedef http_async_connection + async_connection; + typedef typename delegate_factory::type delegate_factory_type; + connection_ptr temp; + temp.reset( + new async_connection( + resolver, + resolve, + follow_redirect, + delegate_factory_type::new_connection_delegate( + resolver.get_io_service(), + https, + certificate_filename, + verify_path))); + BOOST_ASSERT(temp.get() != 0); + return temp; + } + + // This is the pure virtual entry-point for all asynchronous connections. + virtual response start( + request const & request, + string_type const & method, + bool get_body, + body_callback_function_type callback) = 0; + + virtual ~async_connection_base() {} + + }; } // namespace impl diff --git a/boost/network/protocol/http/client/connection/async_normal.hpp b/boost/network/protocol/http/client/connection/async_normal.hpp index aaa7d85b0..f1d0e9e3b 100644 --- a/boost/network/protocol/http/client/connection/async_normal.hpp +++ b/boost/network/protocol/http/client/connection/async_normal.hpp @@ -29,6 +29,8 @@ #include #include +#include + namespace boost { namespace network { namespace http { namespace impl { template @@ -53,16 +55,20 @@ namespace boost { namespace network { namespace http { namespace impl { typedef typename base::resolver_base::resolve_function resolve_function; typedef typename base::body_callback_function_type body_callback_function_type; typedef http_async_connection this_type; + typedef typename delegate_factory::type delegate_factory_type; + typedef typename delegate_factory_type::connection_delegate_ptr + connection_delegate_ptr; http_async_connection(resolver_type & resolver, resolve_function resolve, - bool follow_redirect) + bool follow_redirect, + connection_delegate_ptr delegate) : follow_redirect_(follow_redirect), resolver_(resolver), resolve_(resolve), - request_strand_(resolver.get_io_service()) {} - + request_strand_(resolver.get_io_service()), + delegate_(delegate) {} // This is the main entry point for the connection/request pipeline. We're // overriding async_connection_base<...>::start(...) here which is called @@ -77,14 +83,17 @@ namespace boost { namespace network { namespace http { namespace impl { std::ostreambuf_iterator::type>(&command_streambuf)); this->method = method; boost::uint16_t port_ = port(request); - resolve_(resolver_, host(request), - port_, - request_strand_.wrap( - boost::bind( - &this_type::handle_resolved, - this_type::shared_from_this(), - port_, get_body, callback, - _1, _2))); + resolve_(resolver_, + host(request), + port_, + request_strand_.wrap( + boost::bind(&this_type::handle_resolved, + this_type::shared_from_this(), + port_, + get_body, + callback, + _1, + _2))); return response_; } @@ -108,26 +117,22 @@ namespace boost { namespace network { namespace http { namespace impl { body_callback_function_type callback, boost::system::error_code const & ec, resolver_iterator_pair endpoint_range) { - resolver_iterator iter = boost::begin(endpoint_range); if (!ec && !boost::empty(endpoint_range)) { // Here we deal with the case that there was an error encountered and // that there's still more endpoints to try connecting to. - boost::asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), - port); - socket_.reset( - new boost::asio::ip::tcp::socket( - resolver_.get_io_service())); - socket_->async_connect(endpoint, - request_strand_.wrap( - boost::bind( - &this_type::handle_connected, - this_type::shared_from_this(), - port, - get_body, - callback, - std::make_pair(++iter, - resolver_iterator()), - placeholders::error))); + resolver_iterator iter = boost::begin(endpoint_range); + asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); + delegate_->connect(endpoint, + request_strand_.wrap( + boost::bind( + &this_type::handle_connected, + this_type::shared_from_this(), + port, + get_body, + callback, + std::make_pair(++iter, + resolver_iterator()), + placeholders::error))); } else { set_errors(ec ? ec : boost::asio::error::host_not_found); } @@ -139,35 +144,31 @@ namespace boost { namespace network { namespace http { namespace impl { resolver_iterator_pair endpoint_range, boost::system::error_code const & ec) { if (!ec) { - boost::asio::async_write( - *socket_ - , command_streambuf - , request_strand_.wrap( - boost::bind( - &this_type::handle_sent_request, - this_type::shared_from_this(), - get_body, callback, - placeholders::error, - placeholders::bytes_transferred - ))); + BOOST_ASSERT(delegate_.get() != 0); + delegate_->write(command_streambuf, + request_strand_.wrap( + boost::bind( + &this_type::handle_sent_request, + this_type::shared_from_this(), + get_body, + callback, + placeholders::error, + placeholders::bytes_transferred))); } else { if (!boost::empty(endpoint_range)) { resolver_iterator iter = boost::begin(endpoint_range); - boost::asio::ip::tcp::endpoint endpoint( - iter->endpoint().address(), - port - ); - socket_.reset(new boost::asio::ip::tcp::socket( - resolver_.get_io_service())); - socket_->async_connect( - endpoint, - request_strand_.wrap( - boost::bind( - &this_type::handle_connected, - this_type::shared_from_this(), - port, get_body, callback, std::make_pair(++iter, resolver_iterator()), - placeholders::error - ))); + asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); + delegate_->connect(endpoint, + request_strand_.wrap( + boost::bind( + &this_type::handle_connected, + this_type::shared_from_this(), + port, + get_body, + callback, + std::make_pair(++iter, + resolver_iterator()), + placeholders::error))); } else { set_errors(ec ? ec : boost::asio::error::host_not_found); } @@ -178,17 +179,20 @@ namespace boost { namespace network { namespace http { namespace impl { version, status, status_message, headers, body }; - void handle_sent_request(bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { + void handle_sent_request(bool get_body, + body_callback_function_type callback, + boost::system::error_code const & ec, + std::size_t bytes_transferred) { if (!ec) { - socket_->async_read_some( - boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), - request_strand_.wrap( - boost::bind( - &this_type::handle_received_data, - this_type::shared_from_this(), - version, get_body, callback, - placeholders::error, - placeholders::bytes_transferred))); + delegate_->read_some( + boost::asio::mutable_buffers_1(this->part.c_array(), + this->part.size()), + request_strand_.wrap( + boost::bind(&this_type::handle_received_data, + this_type::shared_from_this(), + version, get_body, callback, + placeholders::error, + placeholders::bytes_transferred))); } else { set_errors(ec); } @@ -201,7 +205,7 @@ namespace boost { namespace network { namespace http { namespace impl { switch(state) { case version: parsed_ok = - this->parse_version(*socket_, + this->parse_version(delegate_, request_strand_.wrap( boost::bind( &this_type::handle_received_data, @@ -213,7 +217,7 @@ namespace boost { namespace network { namespace http { namespace impl { if (!parsed_ok || indeterminate(parsed_ok)) return; case status: parsed_ok = - this->parse_status(*socket_, + this->parse_status(delegate_, request_strand_.wrap( boost::bind( &this_type::handle_received_data, @@ -225,7 +229,7 @@ namespace boost { namespace network { namespace http { namespace impl { if (!parsed_ok || indeterminate(parsed_ok)) return; case status_message: parsed_ok = - this->parse_status_message(*socket_, + this->parse_status_message(delegate_, request_strand_.wrap( boost::bind( &this_type::handle_received_data, @@ -243,7 +247,7 @@ namespace boost { namespace network { namespace http { namespace impl { // that the data remaining in the buffer is dealt with before // another call to get more data for the body is scheduled. fusion::tie(parsed_ok, remainder) = - this->parse_headers(*socket_, + this->parse_headers(delegate_, request_strand_.wrap( boost::bind( &this_type::handle_received_data, @@ -289,21 +293,22 @@ namespace boost { namespace network { namespace http { namespace impl { // wait before scheduling another read. callback(make_iterator_range(begin, end), ec); - socket_->async_read_some( - boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), - request_strand_.wrap( - boost::bind( - &this_type::handle_received_data, - this_type::shared_from_this(), - body, get_body, callback, - placeholders::error, placeholders::bytes_transferred) - ) - ); + delegate_->read_some( + boost::asio::mutable_buffers_1(this->part.c_array(), + this->part.size()), + request_strand_.wrap( + boost::bind(&this_type::handle_received_data, + this_type::shared_from_this(), + body, + get_body, + callback, + placeholders::error, + placeholders::bytes_transferred))); } else { // Here we handle the body data ourself and append to an // ever-growing string buffer. this->parse_body( - *socket_, + delegate_, request_strand_.wrap( boost::bind( &this_type::handle_received_data, @@ -356,7 +361,7 @@ namespace boost { namespace network { namespace http { namespace impl { typename protocol_base::buffer_type::const_iterator end = begin; std::advance(end, bytes_transferred); callback(make_iterator_range(begin, end), ec); - socket_->async_read_some( + delegate_->read_some( boost::asio::mutable_buffers_1( this->part.c_array(), this->part.size()), @@ -374,7 +379,7 @@ namespace boost { namespace network { namespace http { namespace impl { // make sure that we deal with the remainder // from the headers part in case we do have data // that's still in the buffer. - this->parse_body(*socket_, + this->parse_body(delegate_, request_strand_.wrap( boost::bind( &this_type::handle_received_data, @@ -415,9 +420,9 @@ namespace boost { namespace network { namespace http { namespace impl { bool follow_redirect_; resolver_type & resolver_; - boost::shared_ptr socket_; resolve_function resolve_; boost::asio::io_service::strand request_strand_; + connection_delegate_ptr delegate_; boost::asio::streambuf command_streambuf; string_type method; }; diff --git a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp index 66b510585..f0368c0e1 100644 --- a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp +++ b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp @@ -85,8 +85,8 @@ namespace boost { namespace network { namespace http { namespace impl { } }; - template - logic::tribool parse_version(Socket & socket_, + template + logic::tribool parse_version(Delegate & delegate_, Callback callback, size_t bytes) { logic::tribool parsed_ok; @@ -133,7 +133,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::end(result_range) ); part_begin = part.begin(); - socket_.async_read_some( + delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); @@ -141,8 +141,8 @@ namespace boost { namespace network { namespace http { namespace impl { return parsed_ok; } - template - logic::tribool parse_status(Socket & socket_, + template + logic::tribool parse_status(Delegate & delegate_, Callback callback, size_t bytes) { logic::tribool parsed_ok; @@ -189,7 +189,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::end(result_range) ); part_begin = part.begin(); - socket_.async_read_some( + delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); @@ -197,8 +197,8 @@ namespace boost { namespace network { namespace http { namespace impl { return parsed_ok; } - template - logic::tribool parse_status_message(Socket & socket_, + template + logic::tribool parse_status_message(Delegate & delegate_, Callback callback, size_t bytes) { logic::tribool parsed_ok; @@ -241,7 +241,7 @@ namespace boost { namespace network { namespace http { namespace impl { boost::begin(result_range), boost::end(result_range)); part_begin = part.begin(); - socket_.async_read_some( + delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); @@ -289,8 +289,8 @@ namespace boost { namespace network { namespace http { namespace impl { headers_promise.set_value(headers); } - template - fusion::tuple parse_headers(Socket & socket_, + template + fusion::tuple parse_headers(Delegate & delegate_, Callback callback, size_t bytes) { logic::tribool parsed_ok; @@ -332,7 +332,7 @@ namespace boost { namespace network { namespace http { namespace impl { partial_parsed.append(boost::begin(result_range), boost::end(result_range)); part_begin = part.begin(); - socket_.async_read_some( + delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); @@ -346,13 +346,13 @@ namespace boost { namespace network { namespace http { namespace impl { ); } - template - void parse_body(Socket & socket_, Callback callback, size_t bytes) { + template + void parse_body(Delegate & delegate_, Callback callback, size_t bytes) { // TODO: we should really not use a string for the partial body // buffer. partial_parsed.append(part_begin, bytes); part_begin = part.begin(); - socket_.async_read_some( + delegate_->read_some( boost::asio::mutable_buffers_1(part.c_array(), part.size()), callback ); diff --git a/boost/network/protocol/http/client/connection/async_ssl.hpp b/boost/network/protocol/http/client/connection/async_ssl.hpp deleted file mode 100644 index 1b2af32f1..000000000 --- a/boost/network/protocol/http/client/connection/async_ssl.hpp +++ /dev/null @@ -1,410 +0,0 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_ASYNC_CONNECTION_HPP_20100601 -#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_ASYNC_CONNECTION_HPP_20100601 - -// Copyright 2010 (C) Dean Michael Berris -// Copyright 2010 (C) Sinefunc, Inc. -// Copyright 2011 Dean Michael Berris (dberris@google.com). -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { namespace impl { - - template - struct async_connection_base; - - template - struct https_async_connection - : async_connection_base, - protected http_async_protocol_handler, - boost::enable_shared_from_this > - { - typedef async_connection_base base; - typedef http_async_protocol_handler protocol_base; - typedef typename base::resolver_type resolver_type; - typedef typename base::resolver_base::resolver_iterator resolver_iterator; - typedef typename base::resolver_base::resolver_iterator_pair resolver_iterator_pair; - typedef typename base::response response; - typedef typename base::string_type string_type; - typedef typename base::request request; - typedef typename base::resolver_base::resolve_function resolve_function; - typedef typename base::body_callback_function_type body_callback_function_type; - - https_async_connection( - resolver_type & resolver, - resolve_function resolve, - bool follow_redirect, - optional const & certificate_filename = optional(), - optional const & verify_path = optional() - ) : - follow_redirect_(follow_redirect), - resolver_(resolver), - certificate_filename_(certificate_filename), - verify_path_(verify_path), - resolve_(resolve), - request_strand_(resolver.get_io_service()) - {} - - - virtual response start(request const & request, string_type const & method, bool get_body, body_callback_function_type callback) { - response response_; - this->init_response(response_, get_body); - linearize(request, method, version_major, version_minor, - std::ostreambuf_iterator::type>(&command_streambuf)); - this->method = method; - boost::uint16_t port_ = port(request); - resolve_(resolver_, host(request), - port_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_resolved, - https_async_connection::shared_from_this(), - port_, get_body, callback, - _1, _2))); - return response_; - } - - private: - void handle_resolved(boost::uint16_t port, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, resolver_iterator_pair endpoint_range) { - resolver_iterator iter = boost::begin(endpoint_range); - if (!ec && !boost::empty(endpoint_range)) { - boost::asio::ip::tcp::endpoint endpoint( - iter->endpoint().address(), - port - ); - context_.reset(new boost::asio::ssl::context( - resolver_.get_io_service(), - boost::asio::ssl::context::sslv23_client - ) - ); - if (certificate_filename_ || verify_path_) { - context_->set_verify_mode(boost::asio::ssl::context::verify_peer); - if (certificate_filename_) context_->load_verify_file(*certificate_filename_); - if (verify_path_) context_->add_verify_path(*verify_path_); - } else { - context_->set_verify_mode(boost::asio::ssl::context::verify_none); - } - socket_.reset(new boost::asio::ssl::stream( - resolver_.get_io_service(), - *context_ - ) - ); - socket_->lowest_layer().async_connect( - endpoint, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_connected, - https_async_connection::shared_from_this(), - port, get_body, callback, std::make_pair(++iter, resolver_iterator()), - boost::asio::placeholders::error - ))); - } else { - boost::system::system_error error(ec ? ec : boost::asio::error::host_not_found); - this->version_promise.set_exception(boost::copy_exception(error)); - this->status_promise.set_exception(boost::copy_exception(error)); - this->status_message_promise.set_exception(boost::copy_exception(error)); - this->headers_promise.set_exception(boost::copy_exception(error)); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - this->body_promise.set_exception(boost::copy_exception(error)); - } - } - - void handle_connected(boost::uint16_t port, bool get_body, body_callback_function_type callback, resolver_iterator_pair endpoint_range, boost::system::error_code const & ec) { - if (!ec) { - socket_->async_handshake(boost::asio::ssl::stream_base::client, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_handshake, - https_async_connection::shared_from_this(), - port, get_body, callback, - boost::asio::placeholders::error - ) - ) - ); - } else { - if (!boost::empty(endpoint_range)) { - resolver_iterator iter = boost::begin(endpoint_range); - boost::asio::ip::tcp::endpoint endpoint( - iter->endpoint().address(), - port - ); - socket_.reset(new boost::asio::ssl::stream( - resolver_.get_io_service() - , *context_ - ) - ); - socket_->lowest_layer().async_connect( - endpoint, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_connected, - https_async_connection::shared_from_this(), - port, get_body, callback, std::make_pair(++iter, resolver_iterator()), - boost::asio::placeholders::error - ))); - } else { - boost::system::system_error error( - ec ? ec : boost::asio::error::host_not_found - ); - this->version_promise.set_exception(boost::copy_exception(error)); - this->status_promise.set_exception(boost::copy_exception(error)); - this->status_message_promise.set_exception(boost::copy_exception(error)); - this->headers_promise.set_exception(boost::copy_exception(error)); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - this->body_promise.set_exception(boost::copy_exception(error)); - } - } - } - - void handle_handshake(boost::uint16_t port, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec) { - if (!ec) { - boost::asio::async_write( - *socket_ - , command_streambuf - , request_strand_.wrap( - boost::bind( - &https_async_connection::handle_sent_request, - https_async_connection::shared_from_this(), - get_body, callback, - boost::asio::placeholders::error, - boost::asio::placeholders::bytes_transferred - ))); - } else { - boost::system::system_error error( - ec ? ec : boost::asio::error::host_not_found - ); - this->version_promise.set_exception(boost::copy_exception(error)); - this->status_promise.set_exception(boost::copy_exception(error)); - this->status_message_promise.set_exception(boost::copy_exception(error)); - this->headers_promise.set_exception(boost::copy_exception(error)); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - this->body_promise.set_exception(boost::copy_exception(error)); - } - } - - enum state_t { - version, status, status_message, headers, body - }; - - void handle_sent_request(bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { - if (!ec) { - socket_->async_read_some( - boost::asio::mutable_buffers_1( - this->part.c_array(), - this->part.size()), - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - version, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); - } else { - boost::system::system_error error( - ec ? ec : boost::asio::error::host_not_found - ); - this->version_promise.set_exception(boost::copy_exception(error)); - this->status_promise.set_exception(boost::copy_exception(error)); - this->status_message_promise.set_exception(boost::copy_exception(error)); - this->headers_promise.set_exception(boost::copy_exception(error)); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - this->body_promise.set_exception(boost::copy_exception(error)); - } - } - - void handle_received_data(state_t state, bool get_body, body_callback_function_type callback, boost::system::error_code const & ec, std::size_t bytes_transferred) { - if (!ec || ec == boost::asio::error::eof) { - logic::tribool parsed_ok; - size_t remainder; - switch(state) { - case version: - parsed_ok = - this->parse_version( - *socket_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - status, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred - ); - if (parsed_ok != true) return; - case status: - parsed_ok = - this->parse_status(*socket_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - status_message, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred - ); - if (parsed_ok != true) return; - case status_message: - parsed_ok = - this->parse_status_message(*socket_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - headers, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred - ); - if (parsed_ok != true) return; - case headers: - fusion::tie(parsed_ok, remainder) = - this->parse_headers(*socket_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - headers, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred - ); - if (parsed_ok != true) return; - if (!get_body) { - this->body_promise.set_value(""); - return; - } - if (callback) { - typename protocol_base::buffer_type::const_iterator begin = this->part.begin(); - std::advance(begin, remainder); - typename protocol_base::buffer_type::const_iterator end = begin; - std::advance(end, this->part.size() - remainder); - callback(make_iterator_range(begin, end), ec); - socket_->async_read_some( - boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - body, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); - this->body_promise.set_value(""); - } else { - this->parse_body( - *socket_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - body, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - remainder); - } - break; - case body: - if (ec == boost::asio::error::eof) { - if (callback) { - typename protocol_base::buffer_type::const_iterator begin = this->part.begin(), end = begin; - std::advance(end, bytes_transferred); - callback(make_iterator_range(begin, end), ec); - } else { - string_type body; - std::swap(body, this->partial_parsed); - body.append( - this->part.begin() - , bytes_transferred - ); - this->body_promise.set_value(body); - } - // TODO set the destination value somewhere! - this->destination_promise.set_value(""); - this->source_promise.set_value(""); - this->part.assign('\0'); - this->response_parser_.reset(); - } else { - if (callback) { - typename protocol_base::buffer_type::const_iterator begin = this->part.begin(), end = begin; - std::advance(end, bytes_transferred); - callback(make_iterator_range(begin, end), ec); - socket_->async_read_some( - boost::asio::mutable_buffers_1(this->part.c_array(), this->part.size()), - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - body, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred))); - } else { - this->parse_body( - *socket_, - request_strand_.wrap( - boost::bind( - &https_async_connection::handle_received_data, - https_async_connection::shared_from_this(), - body, get_body, callback, - boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred - ) - ), - bytes_transferred); - } - } - break; - default: - BOOST_ASSERT(false && "Bug, report this to the developers!"); - } - } else { - boost::system::system_error error(ec); - this->source_promise.set_exception(boost::copy_exception(error)); - this->destination_promise.set_exception(boost::copy_exception(error)); - switch (state) { - case version: - this->version_promise.set_exception(boost::copy_exception(error)); - case status: - this->status_promise.set_exception(boost::copy_exception(error)); - case status_message: - this->status_message_promise.set_exception(boost::copy_exception(error)); - case headers: - this->headers_promise.set_exception(boost::copy_exception(error)); - case body: - if (get_body) this->body_promise.set_exception(boost::copy_exception(error)); - break; - default: - BOOST_ASSERT(false && "Bug, report this to the developers!"); - } - } - } - - bool follow_redirect_; - resolver_type & resolver_; - optional certificate_filename_, verify_path_; - resolve_function resolve_; - boost::shared_ptr context_; - boost::shared_ptr > socket_; - boost::asio::io_service::strand request_strand_; - boost::asio::streambuf command_streambuf; - string_type method; - }; - -} // namespace impl - -} // namespace http - -} // namespace network - -} // namespace boost - -#endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_ASYNC_CONNECTION_HPP_20100601 diff --git a/boost/network/protocol/http/client/connection/connection_delegate.hpp b/boost/network/protocol/http/client/connection/connection_delegate.hpp new file mode 100644 index 000000000..0e18b231c --- /dev/null +++ b/boost/network/protocol/http/client/connection/connection_delegate.hpp @@ -0,0 +1,30 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ +#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +namespace boost { namespace network { namespace http { namespace impl { + +struct connection_delegate { + virtual void connect(asio::ip::tcp::endpoint & endpoint, + function handler) = 0; + virtual void write(asio::streambuf & command_streambuf, + function handler) = 0; + virtual void read_some(asio::mutable_buffers_1 const & read_buffer, + function handler) = 0; + virtual ~connection_delegate() {} +}; + +} /* impl */ + +} /* http */ + +} /* network */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_CONNECTION_DELEGATE_HPP_ */ diff --git a/boost/network/protocol/http/client/connection/connection_delegate_factory.hpp b/boost/network/protocol/http/client/connection/connection_delegate_factory.hpp new file mode 100644 index 000000000..eca673666 --- /dev/null +++ b/boost/network/protocol/http/client/connection/connection_delegate_factory.hpp @@ -0,0 +1,56 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 +#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#ifdef BOOST_NETWORK_ENABLE_HTTPS +#include +#endif /* BOOST_NETWORK_ENABLE_HTTPS */ + +namespace boost { namespace network { namespace http { namespace impl { + +struct ssl_delegate; + +struct normal_delegate; + +template +struct connection_delegate_factory { + typedef shared_ptr connection_delegate_ptr; + typedef typename string::type string_type; + + // This is the factory method that actually returns the delegate instance. + // TODO Support passing in proxy settings when crafting connections. + static connection_delegate_ptr new_connection_delegate( + asio::io_service & service, + bool https, + optional certificate_filename, + optional verify_path) { + connection_delegate_ptr delegate; + if (https) { +#ifdef BOOST_NETWORK_ENABLE_HTTPS + delegate.reset(new ssl_delegate(service, + certificate_filename, + verify_path)); +#else + BOOST_THROW_EXCEPTION(std::runtime_error("HTTPS not supported.")); +#endif /* BOOST_NETWORK_ENABLE_HTTPS */ + } else { + delegate.reset(new normal_delegate(service)); + } + return delegate; + } +}; + +} /* impl */ +} /* http */ +} /* network */ +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_DELEGATE_FACTORY_HPP_20110819 */ diff --git a/boost/network/protocol/http/client/connection/normal_delegate.hpp b/boost/network/protocol/http/client/connection/normal_delegate.hpp new file mode 100644 index 000000000..8b3d79c51 --- /dev/null +++ b/boost/network/protocol/http/client/connection/normal_delegate.hpp @@ -0,0 +1,45 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 +#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +namespace boost { namespace network { namespace http { namespace impl { + +struct normal_delegate : connection_delegate { + normal_delegate(asio::io_service & service); + + virtual void connect(asio::ip::tcp::endpoint & endpoint, + function handler); + virtual void write(asio::streambuf & command_streambuf, + function handler); + virtual void read_some(asio::mutable_buffers_1 const & read_buffer, + function handler); + ~normal_delegate(); + + private: + asio::io_service & service_; + scoped_ptr socket_; + + normal_delegate(normal_delegate const &); // = delete + normal_delegate& operator=(normal_delegate); // = delete +}; + +} /* impl */ + +} /* http */ + +} /* network */ + +} /* boost */ + +#ifdef BOOST_NETWORK_NO_LIB +#include +#endif /* BOOST_NETWORK_NO_LIB */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_20110819 */ diff --git a/boost/network/protocol/http/client/connection/normal_delegate.ipp b/boost/network/protocol/http/client/connection/normal_delegate.ipp new file mode 100644 index 000000000..f084dc163 --- /dev/null +++ b/boost/network/protocol/http/client/connection/normal_delegate.ipp @@ -0,0 +1,42 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 +#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include + +boost::network::http::impl::normal_delegate::normal_delegate(asio::io_service & service) + : service_(service) +{} + +void boost::network::http::impl::normal_delegate::connect( + asio::ip::tcp::endpoint & endpoint, + function handler) { + socket_.reset(new asio::ip::tcp::socket(service_)); + socket_->async_connect(endpoint, handler); +} + +void boost::network::http::impl::normal_delegate::write( + asio::streambuf & command_streambuf, + function handler) { + asio::async_write(*socket_, command_streambuf, handler); +} + +void boost::network::http::impl::normal_delegate::read_some( + asio::mutable_buffers_1 const & read_buffer, + function handler) { + socket_->async_read_some(read_buffer, handler); +} + +boost::network::http::impl::normal_delegate::~normal_delegate() {} + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 */ diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.hpp b/boost/network/protocol/http/client/connection/ssl_delegate.hpp new file mode 100644 index 000000000..a1cb9a0c6 --- /dev/null +++ b/boost/network/protocol/http/client/connection/ssl_delegate.hpp @@ -0,0 +1,58 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 +#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace network { namespace http { namespace impl { + +struct ssl_delegate : connection_delegate, enable_shared_from_this { + ssl_delegate(asio::io_service & service, + optional certificate_filename, + optional verify_path); + + virtual void connect(asio::ip::tcp::endpoint & endpoint, + function handler); + virtual void write(asio::streambuf & command_streambuf, + function handler); + virtual void read_some(asio::mutable_buffers_1 const & read_buffer, + function handler); + ~ssl_delegate(); + + private: + asio::io_service & service_; + optional certificate_filename_, verify_path_; + scoped_ptr context_; + scoped_ptr > socket_; + + ssl_delegate(ssl_delegate const &); // = delete + ssl_delegate& operator=(ssl_delegate); // = delete + + void handle_connected(system::error_code const & ec, + function handler); +}; + +} /* impl */ + +} /* http */ + +} /* network */ + +} /* boost */ + +#ifdef BOOST_NETWORK_NO_LIB +#include +#endif /* BOOST_NETWORK_NO_LIB */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_20110819 */ diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.ipp b/boost/network/protocol/http/client/connection/ssl_delegate.ipp new file mode 100644 index 000000000..ed8531e31 --- /dev/null +++ b/boost/network/protocol/http/client/connection/ssl_delegate.ipp @@ -0,0 +1,64 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 +#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +boost::network::http::impl::ssl_delegate::ssl_delegate(asio::io_service & service, + optional certificate_filename, + optional verify_path) : + service_(service), + certificate_filename_(certificate_filename), + verify_path_(verify_path) {} + +void boost::network::http::impl::ssl_delegate::connect( + asio::ip::tcp::endpoint & endpoint, + function handler) { + context_.reset(new asio::ssl::context( + service_, + asio::ssl::context::sslv23_client)); + if (certificate_filename_ || verify_path_) { + context_->set_verify_mode(asio::ssl::context::verify_peer); + if (certificate_filename_) context_->load_verify_file(*certificate_filename_); + if (verify_path_) context_->add_verify_path(*verify_path_); + } else { + context_->set_verify_mode(asio::ssl::context::verify_none); + } + socket_.reset(new asio::ssl::stream(service_, *context_)); + socket_->lowest_layer().async_connect( + endpoint, + bind(&boost::network::http::impl::ssl_delegate::handle_connected, + boost::network::http::impl::ssl_delegate::shared_from_this(), + asio::placeholders::error, + handler)); +} + +void boost::network::http::impl::ssl_delegate::handle_connected(system::error_code const & ec, + function handler) { + if (!ec) { + socket_->async_handshake(asio::ssl::stream_base::client, handler); + } else { + handler(ec); + } +} + +void boost::network::http::impl::ssl_delegate::write( + asio::streambuf & command_streambuf, + function handler) { + asio::async_write(*socket_, command_streambuf, handler); +} + +void boost::network::http::impl::ssl_delegate::read_some( + asio::mutable_buffers_1 const & read_buffer, + function handler) { + socket_->async_read_some(read_buffer, handler); +} + +boost::network::http::impl::ssl_delegate::~ssl_delegate() {} + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 */ diff --git a/boost/network/protocol/http/traits/delegate_factory.hpp b/boost/network/protocol/http/traits/delegate_factory.hpp new file mode 100644 index 000000000..714fc590e --- /dev/null +++ b/boost/network/protocol/http/traits/delegate_factory.hpp @@ -0,0 +1,39 @@ +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_DELEGATE_FACTORY_HPP_20110819 +#define BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_DELEGATE_FACTORY_HPP_20110819 + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +namespace boost { namespace network { namespace http { + +namespace impl { + +template +struct connection_delegate_factory; + +} /* impl */ + +template struct unsupported_tag; + +template +struct delegate_factory { + typedef unsupported_tag type; +}; + +template +struct delegate_factory >::type> { + typedef impl::connection_delegate_factory type; +}; + +} /* http */ +} /* network */ +} /* boost */ + + + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_DELEGATE_FACTORY_HPP_20110819 */ diff --git a/boost/network/traits/char.hpp b/boost/network/traits/char.hpp index 66e7dbbeb..79e73441d 100644 --- a/boost/network/traits/char.hpp +++ b/boost/network/traits/char.hpp @@ -6,10 +6,8 @@ #ifndef BOOST_NETWORK_TRAITS_CHAR_HPP #define BOOST_NETWORK_TRAITS_CHAR_HPP -#include #include #include -#include namespace boost { namespace network { @@ -21,13 +19,13 @@ namespace boost { namespace network { { typedef unsupported_tag type; }; - + template struct char_ >::type> { typedef char type; }; - + template struct char_ >::type> { @@ -39,4 +37,3 @@ namespace boost { namespace network { } // namespace boost #endif // BOOST_NETWORK_TRAITS_CHAR_HPP - diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 293a6ad30..2eccb3c3e 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -17,11 +17,11 @@ if (Boost_FOUND) add_executable(hello_world_server http/hello_world_server.cpp) add_executable(fileserver http/fileserver.cpp) add_executable(uri uri.cpp) - add_dependencies(http_client cppnetlib-uri-parsers) - add_dependencies(simple_wget cppnetlib-uri-parsers) + add_dependencies(http_client cppnetlib-uri-parsers cppnetlib-client-connections) + add_dependencies(simple_wget cppnetlib-uri-parsers cppnetlib-client-connections) add_dependencies(uri cppnetlib-uri-parsers) - target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers) - target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers) + target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers cppnetlib-client-connections) + target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers cppnetlib-client-connections) target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} ) target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) target_link_libraries(uri cppnetlib-uri-parsers) diff --git a/libs/network/src/CMakeLists.txt b/libs/network/src/CMakeLists.txt index dae683daf..e06a58d1c 100644 --- a/libs/network/src/CMakeLists.txt +++ b/libs/network/src/CMakeLists.txt @@ -1,13 +1,17 @@ -# Copyright (c) Glyn Matthews 2011. +# Copyright (c) Glyn Matthews 2011. +# Copyright 2011 Dean Michael Berris (dberris@google.com) +# Copyright 2011 Google, Inc. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) -# boost_network_uri include_directories(${CPP-NETLIB_SOURCE_DIR}) set(CPP-NETLIB_URI_SRCS uri/parse.cpp) add_library(cppnetlib-uri-parsers ${CPP-NETLIB_URI_SRCS}) set(CPP-NETLIB_HTTP_SERVER_SRCS server_request_parsers_impl.cpp) add_library(cppnetlib-server-parsers ${CPP-NETLIB_HTTP_SERVER_SRCS}) + +set(CPP-NETLIB_HTTP_CLIENT_SRCS client.cpp) +add_library(cppnetlib-client-connections ${CPP-NETLIB_HTTP_CLIENT_SRCS}) diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index 190affb4a..092499b5a 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -5,8 +5,6 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) find_package( Boost 1.41.0 COMPONENTS unit_test_framework system regex date_time thread filesystem ) -find_package( OpenSSL ) -find_package( Threads ) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 018993729..aa20424ba 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -23,14 +23,8 @@ if (Boost_FOUND) client_get_test client_get_different_port_test client_get_timeout_test - # TODO: refactor these so that local servers are no longer necessary - # client_localhost_normal_test client_get_streaming_test ) - # TODO: refactor these so that local servers are no longer necessary - #if (OPENSSL_FOUND) - # set ( TESTS ${TESTS} client_localhost_ssl_test ) - #endif (OPENSSL_FOUND) foreach ( test ${TESTS} ) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) set_source_files_properties(${test}.cpp @@ -38,7 +32,7 @@ if (Boost_FOUND) endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) add_dependencies(cpp-netlib-http-${test} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers cppnetlib-client-connections) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) endif() diff --git a/libs/network/test/http/server_async_run_stop_concurrency.cpp b/libs/network/test/http/server_async_run_stop_concurrency.cpp index d85e0dfb7..e9a4e25ac 100644 --- a/libs/network/test/http/server_async_run_stop_concurrency.cpp +++ b/libs/network/test/http/server_async_run_stop_concurrency.cpp @@ -22,118 +22,118 @@ struct dummy_async_handler { int main(int argc, char * argv[]) { dummy_async_handler async_handler; -#define ASYNC_SERVER_TEST_CONFIG \ - http::_address = "127.0.0.1", \ - http::_port = "80", \ - http::_handler = async_handler, \ - http::_thread_pool = pool, \ - http::_reuse_address = true - -#define ASYNC_SERVER_SLEEP_TIME \ - boost::posix_time::milliseconds(100) - - // stop from main thread - { - BOOST_NETWORK_MESSAGE("TEST: stop without running"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - server_instance.stop(); - } - - // run-stop from main thread - { - BOOST_NETWORK_MESSAGE("TEST: stop from main thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - server_instance.stop(); - running_thread.join(); - } - - // run-stop from another thread - { - BOOST_NETWORK_MESSAGE("TEST: stop from another thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - stopping_thread.join(); - running_thread.join(); - } - - // run-stop-run-stop from another thread - { - BOOST_NETWORK_MESSAGE("TEST: run-stop-run-stop from another thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - stopping_thread.join(); - running_thread.join(); - second_stopping_thread.join(); - second_running_thread.join(); - } - - // run-run-stop from another thread - { - BOOST_NETWORK_MESSAGE("TEST: run-run-stop from another thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - stopping_thread.join(); - running_thread.join(); - second_running_thread.join(); - } - - // run-stop-stop from another thread - { - BOOST_NETWORK_MESSAGE("TEST: run-stop-stop from another thread"); - util::thread_pool pool; - async_server server_instance(ASYNC_SERVER_TEST_CONFIG); - - boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); - boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); - - stopping_thread.join(); - second_stopping_thread.join(); - running_thread.join(); - } - +#define ASYNC_SERVER_TEST_CONFIG \ + http::_address = "127.0.0.1", \ + http::_port = "8007", \ + http::_handler = async_handler, \ + http::_thread_pool = pool, \ + http::_reuse_address = true + +#define ASYNC_SERVER_SLEEP_TIME \ + boost::posix_time::milliseconds(100) + + // stop from main thread + { + BOOST_NETWORK_MESSAGE("TEST: stop without running"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + server_instance.stop(); + } + + // run-stop from main thread + { + BOOST_NETWORK_MESSAGE("TEST: stop from main thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + server_instance.stop(); + running_thread.join(); + } + + // run-stop from another thread + { + BOOST_NETWORK_MESSAGE("TEST: stop from another thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + stopping_thread.join(); + running_thread.join(); + } + + // run-stop-run-stop from another thread + { + BOOST_NETWORK_MESSAGE("TEST: run-stop-run-stop from another thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + stopping_thread.join(); + running_thread.join(); + second_stopping_thread.join(); + second_running_thread.join(); + } + + // run-run-stop from another thread + { + BOOST_NETWORK_MESSAGE("TEST: run-run-stop from another thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread second_running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + stopping_thread.join(); + running_thread.join(); + second_running_thread.join(); + } + + // run-stop-stop from another thread + { + BOOST_NETWORK_MESSAGE("TEST: run-stop-stop from another thread"); + util::thread_pool pool; + async_server server_instance(ASYNC_SERVER_TEST_CONFIG); + + boost::thread running_thread(boost::bind(&async_server::run, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + boost::thread second_stopping_thread(boost::bind(&async_server::stop, &server_instance)); + boost::this_thread::sleep(ASYNC_SERVER_SLEEP_TIME); + + stopping_thread.join(); + second_stopping_thread.join(); + running_thread.join(); + } + #undef ASYNC_SERVER_TEST_CONFIG - - return 0; + + return 0; } From d2d0c8a20f3692586ddfee38d3d950770c5e2f9b Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 21 Aug 2011 00:17:08 +1000 Subject: [PATCH 173/768] Adding missing client.cpp --- libs/network/src/client.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 libs/network/src/client.cpp diff --git a/libs/network/src/client.cpp b/libs/network/src/client.cpp new file mode 100644 index 000000000..3ce8c1f19 --- /dev/null +++ b/libs/network/src/client.cpp @@ -0,0 +1,17 @@ + +// Copyright 2011 Dean Michael Berris (dberris@google.com). +// Copyright 2011 Google, Inc. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef BOOST_NETWORK_NO_LIB +#warn Building the library even with BOOST_NETWORK_NO_LIB defined. +#undef BOOST_NETWORK_NO_LIB +#endif + +#include + +#ifdef BOOST_NETWORK_ENABLE_HTTPS +#include +#endif From 1619604403e7951f42d84e59a2726acdb3a06b28 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 21 Aug 2011 15:10:52 +0200 Subject: [PATCH 174/768] Added some missing headers. --- .../protocol/http/client/connection/normal_delegate.hpp | 2 ++ .../network/protocol/http/client/connection/ssl_delegate.ipp | 1 + libs/network/test/http/client_get_streaming_test.cpp | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/boost/network/protocol/http/client/connection/normal_delegate.hpp b/boost/network/protocol/http/client/connection/normal_delegate.hpp index 8b3d79c51..d18f1461a 100644 --- a/boost/network/protocol/http/client/connection/normal_delegate.hpp +++ b/boost/network/protocol/http/client/connection/normal_delegate.hpp @@ -8,6 +8,8 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#include +#include namespace boost { namespace network { namespace http { namespace impl { diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.ipp b/boost/network/protocol/http/client/connection/ssl_delegate.ipp index ed8531e31..c7ee5e573 100644 --- a/boost/network/protocol/http/client/connection/ssl_delegate.ipp +++ b/boost/network/protocol/http/client/connection/ssl_delegate.ipp @@ -8,6 +8,7 @@ // http://www.boost.org/LICENSE_1_0.txt) #include +#include boost::network::http::impl::ssl_delegate::ssl_delegate(asio::io_service & service, optional certificate_filename, diff --git a/libs/network/test/http/client_get_streaming_test.cpp b/libs/network/test/http/client_get_streaming_test.cpp index 19009fa23..aa1bdd902 100644 --- a/libs/network/test/http/client_get_streaming_test.cpp +++ b/libs/network/test/http/client_get_streaming_test.cpp @@ -1,4 +1,4 @@ -// Copyright 2011 Dean Michael Berris <mikhailberis@gmail.com>. +// Copyright 2011 Dean Michael Berris <mikhailberis@gmail.com>. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -43,6 +43,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_streaming_test, client, async_only BOOST_CHECK_EQUAL ( response.status_message(), std::string("OK") ); dummy_body = body(response); } - BOOST_CHECK ( dummy_body == typename client::string_type() ); + BOOST_CHECK ( dummy_body == typename client::string_type() ); } From d9e2a7e83b33d3239395208cb5e49e8c8a94bdb2 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 20 Aug 2011 08:58:47 +0200 Subject: [PATCH 175/768] Added first unit test for a URI builder. --- boost/network/uri/builder.hpp | 141 +++++++++++++++++++++++++ boost/network/uri/http/uri.hpp | 6 ++ boost/network/uri/mailto/uri.hpp | 8 +- boost/network/uri/uri_accessors.hpp | 6 ++ libs/network/test/uri/CMakeLists.txt | 1 + libs/network/test/uri/builder_test.cpp | 47 +++++++++ 6 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 boost/network/uri/builder.hpp create mode 100644 libs/network/test/uri/builder_test.cpp diff --git a/boost/network/uri/builder.hpp b/boost/network/uri/builder.hpp new file mode 100644 index 000000000..ef20749ee --- /dev/null +++ b/boost/network/uri/builder.hpp @@ -0,0 +1,141 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef __BOOST_NETWORK_URI_BUILDER_INC__ +# define __BOOST_NETWORK_URI_BUILDER_INC__ + + +# include + + +namespace boost { +namespace network { +namespace uri { +namespace builder { +template < + class T + > +struct scheme_t { + scheme_t(const T &scheme) + : scheme(scheme) { + + } + + const T &scheme; +}; + +template < + class T + > +inline +scheme_t scheme(const T &scheme) { + return scheme_t(scheme); +} + +template < + class T + > +struct host_t { + host_t(const T &host) + : host(host) { + + } + + const T &host; +}; + +template < + class T + > +inline +host_t host(const T &host) { + return host_t(host); +} + +template < + class T + > +struct path_t { + path_t(const T &path) + : path(path) { + + } + + const T &path; +}; + +template < + class T + > +inline +path_t path(const T &path) { + return path_t(path); +} +} // namespace builder + +template < + class Tag + > +class basic_builder { + +public: + +public: + + basic_builder(basic_uri &uri) + : uri_(uri) { + + } + + const basic_uri &uri() const { + return uri_; + } + +private: + basic_uri &uri_; +}; + +template < + class Tag + > +inline +basic_builder operator << (basic_uri &uri, const builder::scheme_t::type> &scheme) { + // uri.set_scheme( + return basic_builder(uri); +} + +template < + class Tag + > +inline +basic_builder &operator << (basic_builder &builder, const builder::scheme_t::type> &scheme) { + // uri.set_scheme( + return builder; +} + +template < + class Tag + > +inline +basic_builder &operator << (basic_builder &builder, const builder::host_t::type> &host) { + // uri.set_host( + return builder; +} + +template < + class Tag + > +inline +basic_builder &operator << (basic_builder &builder, const builder::path_t::type> &path) { + // uri.set_path( + return builder; +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_BUILDER_INC__ diff --git a/boost/network/uri/http/uri.hpp b/boost/network/uri/http/uri.hpp index d4c859031..ecee3f491 100644 --- a/boost/network/uri/http/uri.hpp +++ b/boost/network/uri/http/uri.hpp @@ -1,3 +1,9 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + #ifndef __BOOST_NETWORK_URI_HTTP_URI_INC__ # define __BOOST_NETWORK_URI_HTTP_URI_INC__ diff --git a/boost/network/uri/mailto/uri.hpp b/boost/network/uri/mailto/uri.hpp index aff33c275..87490a502 100644 --- a/boost/network/uri/mailto/uri.hpp +++ b/boost/network/uri/mailto/uri.hpp @@ -1,3 +1,9 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + #ifndef __BOOST_NETWORK_URI_MAILTO_URI_INC__ # define __BOOST_NETWORK_URI_MAILTO_URI_INC__ @@ -54,7 +60,7 @@ class basic_uri return *this; } - + }; } // namespace mailto diff --git a/boost/network/uri/uri_accessors.hpp b/boost/network/uri/uri_accessors.hpp index 74f40cc21..93052f640 100644 --- a/boost/network/uri/uri_accessors.hpp +++ b/boost/network/uri/uri_accessors.hpp @@ -1,3 +1,9 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + #ifndef __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ # define __BOOST_NETWORK_URI_URI_ACCESSORS_INC__ diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index 0c1e48a5a..c41614b35 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -17,6 +17,7 @@ if (Boost_FOUND) url_test url_http_test url_mailto_test + builder_test ) foreach (test ${TESTS}) set_source_files_properties(${test}.cpp diff --git a/libs/network/test/uri/builder_test.cpp b/libs/network/test/uri/builder_test.cpp new file mode 100644 index 000000000..c7dfebdc2 --- /dev/null +++ b/libs/network/test/uri/builder_test.cpp @@ -0,0 +1,47 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE URI builder test +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace boost::network; + +typedef boost::mpl::list< + tags::default_string +// , tags::default_wstring + > tag_types; + + +BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + + uri_type instance; + uri::basic_builder builder(instance); + builder << uri::builder::scheme(string_type(boost::begin(scheme), + boost::end(scheme))) + << uri::builder::host(string_type(boost::begin(host), + boost::end(host))) + << uri::builder::path(string_type(boost::begin(path), + boost::end(path))) + ; + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} From 3b3e942ed5e6512c420875a8bb9533340aaf3308 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Mon, 22 Aug 2011 23:21:07 +0200 Subject: [PATCH 176/768] Added some functions that allow encoding and decoding of URI strings. --- boost/network/uri/decode.hpp | 98 +++++++++++ boost/network/uri/encode.hpp | 164 ++++++++++++++++++ boost/network/uri/uri.hpp | 8 + .../test/http/server_async_less_copy.cpp | 5 +- libs/network/test/uri/CMakeLists.txt | 1 + libs/network/test/uri/builder_test.cpp | 10 +- libs/network/test/uri/url_encoding_test.cpp | 48 +++++ 7 files changed, 325 insertions(+), 9 deletions(-) create mode 100644 boost/network/uri/decode.hpp create mode 100644 boost/network/uri/encode.hpp create mode 100644 libs/network/test/uri/url_encoding_test.cpp diff --git a/boost/network/uri/decode.hpp b/boost/network/uri/decode.hpp new file mode 100644 index 000000000..e56e3f6e8 --- /dev/null +++ b/boost/network/uri/decode.hpp @@ -0,0 +1,98 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef __BOOST_NETWORK_URI_DECODE_INC__ +# define __BOOST_NETWORK_URI_DECODE_INC__ + + +# include +# include +# include +# include + + +namespace boost { +namespace network { +namespace uri { +namespace detail { +template < + typename CharT + > +CharT letter_to_hex(CharT in) +{ + switch (in) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return in - '0'; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + return in + 10 - 'a'; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + return in + 10 - 'A'; + } + return CharT(); +} +} // namespace detail + +template < + class InputIterator, + class OutputIterator + > +OutputIterator decode(const InputIterator &in_begin, const InputIterator &in_end, const OutputIterator &out_begin) { + typedef typename boost::iterator_value::type value_type; + + InputIterator it = in_begin; + OutputIterator out = out_begin; + while (it != in_end) { + if (*it == '%') + { + ++it; + value_type v0 = detail::letter_to_hex(*it); + ++it; + value_type v1 = detail::letter_to_hex(*it); + ++it; + *out++ = 0x10 * v0 + v1; + } + else + { + *out++ = *it++; + } + } + return out; +} + +template < + class SinglePassRange, + class OutputIterator + > +inline +OutputIterator decode(const SinglePassRange &range, const OutputIterator &out) { + return decode(boost::begin(range), boost::end(range), out); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DECODE_INC__ diff --git a/boost/network/uri/encode.hpp b/boost/network/uri/encode.hpp new file mode 100644 index 000000000..18b344ee5 --- /dev/null +++ b/boost/network/uri/encode.hpp @@ -0,0 +1,164 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef __BOOST_NETWORK_URI_ENCODE_INC__ +# define __BOOST_NETWORK_URI_ENCODE_INC__ + + +# include +# include +# include +# include + + +namespace boost { +namespace network { +namespace uri { +namespace detail { +template < + typename CharT + > +inline +CharT hex_to_letter(CharT in) { + switch (in) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + return in + '0'; + case 10: + case 11: + case 12: + case 13: + case 14: + default: + return in - 10 + 'A'; + } + return CharT(); +} + + +template < + typename CharT, + class OutputIterator + > +void encode_char(CharT in, OutputIterator &out) { + switch (in) + { + case 'a': + case 'A': + case 'b': + case 'B': + case 'c': + case 'C': + case 'd': + case 'D': + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + case 'h': + case 'H': + case 'i': + case 'I': + case 'j': + case 'J': + case 'k': + case 'K': + case 'l': + case 'L': + case 'm': + case 'M': + case 'n': + case 'N': + case 'o': + case 'O': + case 'p': + case 'P': + case 'q': + case 'Q': + case 'r': + case 'R': + case 's': + case 'S': + case 't': + case 'T': + case 'u': + case 'U': + case 'v': + case 'V': + case 'w': + case 'W': + case 'x': + case 'X': + case 'y': + case 'Y': + case 'z': + case 'Z': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + case '.': + case '_': + case '~': + out++ = in; + break; + default: + out++ = '%'; + out++ = hex_to_letter(in >> 4); + out++ = hex_to_letter(in & 0x0f); + ; + } +} +} // namespace detail + +template < + class InputIterator, + class OutputIterator + > +OutputIterator encode(const InputIterator &in_begin, const InputIterator &in_end, const OutputIterator &out_begin) { + typedef typename boost::iterator_value::type value_type; + + InputIterator it = in_begin; + OutputIterator out = out_begin; + while (it != in_end) { + detail::encode_char(*it, out); + ++it; + } + return out; +} + +template < + class SinglePassRange, + class OutputIterator + > +inline +OutputIterator encode(const SinglePassRange &range, const OutputIterator &out) { + return encode(boost::begin(range), boost::end(range), out); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_ENCODE_INC__ diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index dd28af535..4ccb4e19c 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -324,6 +324,14 @@ typename basic_uri::string_type authority(const basic_uri &uri) { return typename basic_uri::string_type(user_info.begin(), port.end()); } +template < + class Tag + > +inline +typename basic_uri::string_type netloc(const basic_uri &uri) { + return authority(uri); +} + template < class Tag > diff --git a/libs/network/test/http/server_async_less_copy.cpp b/libs/network/test/http/server_async_less_copy.cpp index 73d8aa5f3..c1ca4786b 100644 --- a/libs/network/test/http/server_async_less_copy.cpp +++ b/libs/network/test/http/server_async_less_copy.cpp @@ -1,5 +1,5 @@ -// Copyright 2010 Dean Michael Berris. +// Copyright 2010 Dean Michael Berris. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) @@ -51,11 +51,10 @@ struct async_hello_world { }; int main(int argc, char * argv[]) { - utils::thread_pool thread_pool(2); + utils::thread_pool thread_pool(2); async_hello_world handler; std::string port = "8000"; if (argc > 1) port = argv[1]; - std::cerr << "Configuration: port = " << port << std::endl; server instance("127.0.0.1", port, handler, thread_pool, http::_reuse_address=true); instance.run(); return 0; diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index c41614b35..fb0e9bcb0 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -17,6 +17,7 @@ if (Boost_FOUND) url_test url_http_test url_mailto_test + url_encoding_test builder_test ) foreach (test ${TESTS}) diff --git a/libs/network/test/uri/builder_test.cpp b/libs/network/test/uri/builder_test.cpp index c7dfebdc2..862d89f87 100644 --- a/libs/network/test/uri/builder_test.cpp +++ b/libs/network/test/uri/builder_test.cpp @@ -26,6 +26,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) { typedef uri::basic_uri uri_type; typedef typename uri_type::string_type string_type; + namespace urib = uri::builder; const std::string scheme("http"); const std::string host("www.example.com"); @@ -33,12 +34,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) uri_type instance; uri::basic_builder builder(instance); - builder << uri::builder::scheme(string_type(boost::begin(scheme), - boost::end(scheme))) - << uri::builder::host(string_type(boost::begin(host), - boost::end(host))) - << uri::builder::path(string_type(boost::begin(path), - boost::end(path))) + builder << urib::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << urib::host(string_type(boost::begin(host), boost::end(host))) + << urib::path(string_type(boost::begin(path), boost::end(path))) ; BOOST_REQUIRE(uri::is_valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); diff --git a/libs/network/test/uri/url_encoding_test.cpp b/libs/network/test/uri/url_encoding_test.cpp new file mode 100644 index 000000000..bc08f8c1c --- /dev/null +++ b/libs/network/test/uri/url_encoding_test.cpp @@ -0,0 +1,48 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE URL encoding test +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace boost::network; + +typedef boost::mpl::list< + tags::default_string + , tags::default_wstring + > tag_types; + + +BOOST_AUTO_TEST_CASE_TEMPLATE(encoding_test, T, tag_types) { + typedef typename string::type string_type; + + const std::string unencoded(" !\"#$%&\'()*"); + const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A"); + + string_type instance; + uri::encode(unencoded, std::back_inserter(instance)); + BOOST_CHECK(boost::equal(instance, encoded)); +} + + +BOOST_AUTO_TEST_CASE_TEMPLATE(decoding_test, T, tag_types) { + typedef typename string::type string_type; + + const std::string unencoded(" !\"#$%&\'()*"); + const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A"); + + string_type instance; + uri::decode(encoded, std::back_inserter(instance)); + BOOST_CHECK(boost::equal(instance, unencoded)); +} From a525cc696e5c86ecbdcd6c00935285e560244b24 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Tue, 23 Aug 2011 07:59:01 +0200 Subject: [PATCH 177/768] Added unit tests for encoded strings in URL. --- boost/network/uri/uri_accessors.hpp | 12 ++++++++++++ libs/network/test/uri/url_test.cpp | 8 +++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/boost/network/uri/uri_accessors.hpp b/boost/network/uri/uri_accessors.hpp index 93052f640..337a1addf 100644 --- a/boost/network/uri/uri_accessors.hpp +++ b/boost/network/uri/uri_accessors.hpp @@ -9,6 +9,8 @@ # include +# include +# include # include @@ -80,6 +82,16 @@ typename basic_uri::string_type password(const basic_uri &uri) { } return typename string::type(it, boost::end(user_info_range)); } + +template < + class Tag + > +typename basic_uri::string_type decoded_path(const basic_uri &uri) { + typename basic_uri::const_range_type path_range = uri.path_range(); + typename basic_uri::string_type decoded_path; + decode(path_range, std::back_inserter(decoded_path)); + return decoded_path; +} } // namespace uri } // namespace network } // namespace boost diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index b63607d96..ce6185ebe 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -201,16 +201,18 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_uri_test, T, tag_types) { typedef uri::basic_uri uri_type; typedef typename uri_type::string_type string_type; - const std::string url("http://www.example.com/"); + const std::string url("http://www.example.com/Path%20With%20%28Some%29%20Encoded%20Characters%21"); const std::string scheme("http"); const std::string host("www.example.com"); - const std::string path("/"); + const std::string encoded_path("/Path%20With%20%28Some%29%20Encoded%20Characters%21"); + const std::string decoded_path("/Path With (Some) Encoded Characters!"); uri_type instance(string_type(boost::begin(url), boost::end(url))); BOOST_REQUIRE(uri::is_valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::path(instance), encoded_path)); + BOOST_CHECK(boost::equal(uri::decoded_path(instance), decoded_path)); } BOOST_AUTO_TEST_CASE_TEMPLATE(copy_constructor_test, T, tag_types) { From 5431abb29cb2c47e738164ffda9b55d3e80e570d Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Thu, 25 Aug 2011 20:11:24 +0200 Subject: [PATCH 178/768] Added a first draft of IPv6 support; initial unit tests succeed. --- boost/network/uri/detail/parse_uri.hpp | 37 +++++++++++++++++- boost/network/uri/uri_accessors.hpp | 20 ++++++++++ libs/network/test/uri/url_test.cpp | 54 +++++++++++++++----------- 3 files changed, 86 insertions(+), 25 deletions(-) diff --git a/boost/network/uri/detail/parse_uri.hpp b/boost/network/uri/detail/parse_uri.hpp index dc9e1cb96..424bafd52 100644 --- a/boost/network/uri/detail/parse_uri.hpp +++ b/boost/network/uri/detail/parse_uri.hpp @@ -106,6 +106,36 @@ struct uri_grammar : qi::grammar()> { >> iter_pos ; + ip_literal %= + qi::lit('[') >> (ipv6address | ipvfuture) >> ']' + ; + + ipvfuture %= + qi::lit('v') >> +qi::xdigit >> '.' >> +( unreserved | sub_delims | ':') + ; + + ipv6address %= qi::raw[ + //qi::lit("1080:0:0:0:8:800:200C:417A") + qi::repeat(6)[h16 >> ':'] >> ls32 + | "::" >> qi::repeat(5)[h16 >> ':'] >> ls32 + | qi::raw[ h16] >> "::" >> qi::repeat(4)[h16 >> ':'] >> ls32 + | qi::raw[+(*(h16 >> ':')) >> h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 + | qi::raw[qi::repeat(2)[*(h16 >> ':')] >> h16] >> "::" >> qi::repeat(2)[h16 >> ':'] >> ls32 + | qi::raw[qi::repeat(3)[*(h16 >> ':')] >> h16] >> "::" >> h16 >> ':' >> ls32 + | qi::raw[qi::repeat(4)[*(h16 >> ':')] >> h16] >> "::" >> ls32 + | qi::raw[qi::repeat(5)[*(h16 >> ':')] >> h16] >> "::" >> h16 + | qi::raw[qi::repeat(6)[*(h16 >> ':')] >> h16] >> "::" + + ]; + + // ls32 = ( h16 ":" h16 ) / IPv4address + ls32 %= (h16 >> ':' >> h16) | ipv4address + ; + + // h16 = 1*4HEXDIG + h16 %= qi::repeat(1, 4)[qi::xdigit] + ; + // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 dec_octet %= !(qi::lit('0') >> qi::digit) @@ -126,7 +156,7 @@ struct uri_grammar : qi::grammar()> { // TODO, host = IP-literal / IPv4address / reg-name host %= iter_pos - >> qi::omit[ipv4address | reg_name] + >> qi::omit[ip_literal | ipv4address | reg_name] >> iter_pos ; @@ -193,7 +223,10 @@ struct uri_grammar : qi::grammar()> { path_abempty, path_absolute, path_rootless, path_empty; qi::rule - dec_octet, ipv4address, reg_name; + dec_octet, ipv4address, reg_name, ipv6address, ipvfuture, ip_literal; + + qi::rule + h16, ls32; qi::rule()> host, port; diff --git a/boost/network/uri/uri_accessors.hpp b/boost/network/uri/uri_accessors.hpp index 337a1addf..88ed97e16 100644 --- a/boost/network/uri/uri_accessors.hpp +++ b/boost/network/uri/uri_accessors.hpp @@ -92,6 +92,26 @@ typename basic_uri::string_type decoded_path(const basic_uri &uri) { decode(path_range, std::back_inserter(decoded_path)); return decoded_path; } + +template < + class Tag + > +typename basic_uri::string_type decoded_query(const basic_uri &uri) { + typename basic_uri::const_range_type query_range = uri.query_range(); + typename basic_uri::string_type decoded_query; + decode(query_range, std::back_inserter(decoded_query)); + return decoded_query; +} + +template < + class Tag + > +typename basic_uri::string_type decoded_fragment(const basic_uri &uri) { + typename basic_uri::const_range_type fragment_range = uri.fragment_range(); + typename basic_uri::string_type decoded_fragment; + decode(fragment_range, std::back_inserter(decoded_fragment)); + return decoded_fragment; +} } // namespace uri } // namespace network } // namespace boost diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index ce6185ebe..a5ba2af51 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -127,29 +127,37 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -//// IPv6 is not yet supported by the parser -//BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test, T, tag_types) { -// typedef uri::basic_uri uri_type; -// typedef typename uri_type::string_type string_type; -// -// const std::string url("http://1080:0:0:0:8:800:200C:417A/"); -// const std::string scheme("http"); -// const std::string host("1080:0:0:8:800:200C:417A"); -// const std::string path("/"); -// -// uri_type instance(string_type(boost::begin(url), boost::end(url))); -// std::cout << uri::scheme(instance) << std::endl; -// std::cout << uri::user_info(instance) << std::endl; -// std::cout << uri::host(instance) << std::endl; -// std::cout << uri::port(instance) << std::endl; -// std::cout << uri::path(instance) << std::endl; -// std::cout << uri::query(instance) << std::endl; -// std::cout << uri::fragment(instance) << std::endl; -// BOOST_REQUIRE(uri::is_valid(instance)); -// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); -// BOOST_CHECK(boost::equal(uri::host(instance), host)); -// BOOST_CHECK(boost::equal(uri::path(instance), path)); -//} +BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_1, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://[1080::8:800:200c:417a]/"); + const std::string scheme("http"); + const std::string host("[1080:0:0:0:8:800:200C:417A]"); + const std::string path("/"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_2, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/"); + const std::string scheme("http"); + const std::string host("[2001:db8:85a3:8d3:1319:8a2e:370:7348]"); + const std::string path("/"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} BOOST_AUTO_TEST_CASE_TEMPLATE(ftp_test, T, tag_types) { typedef uri::basic_uri uri_type; From 7eb3c99b79543b8f3c92b88d3303f02ddda2fcf1 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Fri, 26 Aug 2011 08:08:19 +0200 Subject: [PATCH 179/768] First (and limited) draft of URI builder syntax. --- boost/network/uri/builder.hpp | 141 ------------------ boost/network/uri/detail/parse_uri.hpp | 3 +- boost/network/uri/directives.hpp | 37 +++++ boost/network/uri/directives/authority.hpp | 14 ++ boost/network/uri/directives/fragment.hpp | 14 ++ boost/network/uri/directives/host.hpp | 51 +++++++ boost/network/uri/directives/path.hpp | 51 +++++++ boost/network/uri/directives/port.hpp | 14 ++ boost/network/uri/directives/query.hpp | 14 ++ boost/network/uri/directives/scheme.hpp | 55 +++++++ boost/network/uri/directives/user_info.hpp | 14 ++ boost/network/uri/uri.hpp | 13 ++ libs/network/test/uri/CMakeLists.txt | 2 +- ...{builder_test.cpp => url_builder_test.cpp} | 16 +- libs/network/test/uri/url_mailto_test.cpp | 2 +- 15 files changed, 289 insertions(+), 152 deletions(-) delete mode 100644 boost/network/uri/builder.hpp create mode 100644 boost/network/uri/directives.hpp create mode 100644 boost/network/uri/directives/authority.hpp create mode 100644 boost/network/uri/directives/fragment.hpp create mode 100644 boost/network/uri/directives/host.hpp create mode 100644 boost/network/uri/directives/path.hpp create mode 100644 boost/network/uri/directives/port.hpp create mode 100644 boost/network/uri/directives/query.hpp create mode 100644 boost/network/uri/directives/scheme.hpp create mode 100644 boost/network/uri/directives/user_info.hpp rename libs/network/test/uri/{builder_test.cpp => url_builder_test.cpp} (76%) diff --git a/boost/network/uri/builder.hpp b/boost/network/uri/builder.hpp deleted file mode 100644 index ef20749ee..000000000 --- a/boost/network/uri/builder.hpp +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_BUILDER_INC__ -# define __BOOST_NETWORK_URI_BUILDER_INC__ - - -# include - - -namespace boost { -namespace network { -namespace uri { -namespace builder { -template < - class T - > -struct scheme_t { - scheme_t(const T &scheme) - : scheme(scheme) { - - } - - const T &scheme; -}; - -template < - class T - > -inline -scheme_t scheme(const T &scheme) { - return scheme_t(scheme); -} - -template < - class T - > -struct host_t { - host_t(const T &host) - : host(host) { - - } - - const T &host; -}; - -template < - class T - > -inline -host_t host(const T &host) { - return host_t(host); -} - -template < - class T - > -struct path_t { - path_t(const T &path) - : path(path) { - - } - - const T &path; -}; - -template < - class T - > -inline -path_t path(const T &path) { - return path_t(path); -} -} // namespace builder - -template < - class Tag - > -class basic_builder { - -public: - -public: - - basic_builder(basic_uri &uri) - : uri_(uri) { - - } - - const basic_uri &uri() const { - return uri_; - } - -private: - basic_uri &uri_; -}; - -template < - class Tag - > -inline -basic_builder operator << (basic_uri &uri, const builder::scheme_t::type> &scheme) { - // uri.set_scheme( - return basic_builder(uri); -} - -template < - class Tag - > -inline -basic_builder &operator << (basic_builder &builder, const builder::scheme_t::type> &scheme) { - // uri.set_scheme( - return builder; -} - -template < - class Tag - > -inline -basic_builder &operator << (basic_builder &builder, const builder::host_t::type> &host) { - // uri.set_host( - return builder; -} - -template < - class Tag - > -inline -basic_builder &operator << (basic_builder &builder, const builder::path_t::type> &path) { - // uri.set_path( - return builder; -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_BUILDER_INC__ diff --git a/boost/network/uri/detail/parse_uri.hpp b/boost/network/uri/detail/parse_uri.hpp index 424bafd52..a4fa0969a 100644 --- a/boost/network/uri/detail/parse_uri.hpp +++ b/boost/network/uri/detail/parse_uri.hpp @@ -115,11 +115,10 @@ struct uri_grammar : qi::grammar()> { ; ipv6address %= qi::raw[ - //qi::lit("1080:0:0:0:8:800:200C:417A") qi::repeat(6)[h16 >> ':'] >> ls32 | "::" >> qi::repeat(5)[h16 >> ':'] >> ls32 | qi::raw[ h16] >> "::" >> qi::repeat(4)[h16 >> ':'] >> ls32 - | qi::raw[+(*(h16 >> ':')) >> h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 + | qi::raw[ +(*(h16 >> ':')) >> h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 | qi::raw[qi::repeat(2)[*(h16 >> ':')] >> h16] >> "::" >> qi::repeat(2)[h16 >> ':'] >> ls32 | qi::raw[qi::repeat(3)[*(h16 >> ':')] >> h16] >> "::" >> h16 >> ':' >> ls32 | qi::raw[qi::repeat(4)[*(h16 >> ':')] >> h16] >> "::" >> ls32 diff --git a/boost/network/uri/directives.hpp b/boost/network/uri/directives.hpp new file mode 100644 index 000000000..a389ac744 --- /dev/null +++ b/boost/network/uri/directives.hpp @@ -0,0 +1,37 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_INC__ + + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + + +namespace boost { +namespace network { +namespace uri { +template < + class Tag + , class Directive + > +inline +basic_uri &operator << (basic_uri &uri, const Directive &directive) { + directive(uri); + return uri; +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_INC__ diff --git a/boost/network/uri/directives/authority.hpp b/boost/network/uri/directives/authority.hpp new file mode 100644 index 000000000..78bc5aaf4 --- /dev/null +++ b/boost/network/uri/directives/authority.hpp @@ -0,0 +1,14 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ + + +namespace boost { +namespace network { +namespace uri { + +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ diff --git a/boost/network/uri/directives/fragment.hpp b/boost/network/uri/directives/fragment.hpp new file mode 100644 index 000000000..94b2b3cfd --- /dev/null +++ b/boost/network/uri/directives/fragment.hpp @@ -0,0 +1,14 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ + + +namespace boost { +namespace network { +namespace uri { + +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ diff --git a/boost/network/uri/directives/host.hpp b/boost/network/uri/directives/host.hpp new file mode 100644 index 000000000..360c584d7 --- /dev/null +++ b/boost/network/uri/directives/host.hpp @@ -0,0 +1,51 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ + + +namespace boost { +namespace network { +namespace uri { +template < + class ValueType + > +struct host_directive { + + explicit host_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + uri.append(value); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + uri.append(value); + } + + const ValueType &value; + +}; + +template < + class T + > +inline +host_directive host(const T &value) { + return host_directive(value); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ diff --git a/boost/network/uri/directives/path.hpp b/boost/network/uri/directives/path.hpp new file mode 100644 index 000000000..7d48092c3 --- /dev/null +++ b/boost/network/uri/directives/path.hpp @@ -0,0 +1,51 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_PATH_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_PATH_INC__ + + +namespace boost { +namespace network { +namespace uri { +template < + class ValueType + > +struct path_directive { + + explicit path_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + uri.append(value); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + uri.append(value); + } + + const ValueType &value; + +}; + +template < + class T + > +inline +path_directive path(const T &value) { + return path_directive(value); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_PATH_INC__ diff --git a/boost/network/uri/directives/port.hpp b/boost/network/uri/directives/port.hpp new file mode 100644 index 000000000..06eab0ba8 --- /dev/null +++ b/boost/network/uri/directives/port.hpp @@ -0,0 +1,14 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ + + +namespace boost { +namespace network { +namespace uri { + +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp new file mode 100644 index 000000000..c9f803a58 --- /dev/null +++ b/boost/network/uri/directives/query.hpp @@ -0,0 +1,14 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ + + +namespace boost { +namespace network { +namespace uri { + +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ diff --git a/boost/network/uri/directives/scheme.hpp b/boost/network/uri/directives/scheme.hpp new file mode 100644 index 000000000..ec07b103b --- /dev/null +++ b/boost/network/uri/directives/scheme.hpp @@ -0,0 +1,55 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ + + +namespace boost { +namespace network { +namespace uri { +template < + class ValueType + > +struct scheme_directive { + + explicit scheme_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + char separator[] = {':', '/', '/'}; + uri.append(value); + uri.append(boost::begin(separator), boost::end(separator)); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + char separator[] = {':', '/', '/'}; + uri.append(value); + uri.append(boost::begin(separator), boost::end(separator)); + } + + const ValueType &value; + +}; + +template < + class T + > +inline +scheme_directive scheme(const T &value) { + return scheme_directive(value); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ diff --git a/boost/network/uri/directives/user_info.hpp b/boost/network/uri/directives/user_info.hpp new file mode 100644 index 000000000..e4c6bd21d --- /dev/null +++ b/boost/network/uri/directives/user_info.hpp @@ -0,0 +1,14 @@ +#ifndef __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ +# define __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ + + +namespace boost { +namespace network { +namespace uri { + +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 4ccb4e19c..c6c95992b 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -193,6 +193,19 @@ class basic_uri return is_valid_; } + void append(const string_type &data) { + uri_.append(data); + parse(); + } + + template < + class Iterator + > + void append(Iterator first, Iterator last) { + uri_.append(first, last); + parse(); + } + private: void parse(); diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index fb0e9bcb0..3d6c147cf 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -18,7 +18,7 @@ if (Boost_FOUND) url_http_test url_mailto_test url_encoding_test - builder_test + url_builder_test ) foreach (test ${TESTS}) set_source_files_properties(${test}.cpp diff --git a/libs/network/test/uri/builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp similarity index 76% rename from libs/network/test/uri/builder_test.cpp rename to libs/network/test/uri/url_builder_test.cpp index 862d89f87..deb77d59e 100644 --- a/libs/network/test/uri/builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -7,18 +7,21 @@ #include #include #include -#include +#include #include #include #include #include +#include + + using namespace boost::network; typedef boost::mpl::list< tags::default_string -// , tags::default_wstring + , tags::default_wstring > tag_types; @@ -26,17 +29,16 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) { typedef uri::basic_uri uri_type; typedef typename uri_type::string_type string_type; - namespace urib = uri::builder; const std::string scheme("http"); const std::string host("www.example.com"); const std::string path("/"); uri_type instance; - uri::basic_builder builder(instance); - builder << urib::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << urib::host(string_type(boost::begin(host), boost::end(host))) - << urib::path(string_type(boost::begin(path), boost::end(path))) + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::path(string_type(boost::begin(path), boost::end(path))) ; BOOST_REQUIRE(uri::is_valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); diff --git a/libs/network/test/uri/url_mailto_test.cpp b/libs/network/test/uri/url_mailto_test.cpp index d3c931f15..8765748fe 100644 --- a/libs/network/test/uri/url_mailto_test.cpp +++ b/libs/network/test/uri/url_mailto_test.cpp @@ -15,7 +15,7 @@ using namespace boost::network; typedef boost::mpl::list< tags::default_string -// , tags::default_wstring + , tags::default_wstring > tag_types; From 519708ab0c67116ec19af790d18904515fe84656 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Fri, 26 Aug 2011 22:49:12 +0200 Subject: [PATCH 180/768] Added more URI builder tests. --- .../uri/{uri_accessors.hpp => accessors.hpp} | 0 boost/network/uri/directives.hpp | 4 - boost/network/uri/directives/authority.hpp | 43 +++++ boost/network/uri/directives/fragment.hpp | 47 +++++ boost/network/uri/directives/host.hpp | 6 + boost/network/uri/directives/path.hpp | 15 +- boost/network/uri/directives/port.hpp | 78 +++++++++ boost/network/uri/directives/query.hpp | 117 +++++++++++++ boost/network/uri/directives/scheme.hpp | 10 +- boost/network/uri/directives/user_info.hpp | 47 +++++ boost/network/uri/encode.hpp | 1 + boost/network/uri/uri.hpp | 4 - boost/network/uri/uri_io.hpp | 23 +++ libs/network/example/simple_wget.cpp | 2 +- libs/network/test/uri/CMakeLists.txt | 50 +++--- libs/network/test/uri/url_builder_test.cpp | 164 +++++++++++++++++- libs/network/test/uri/url_test.cpp | 3 +- 17 files changed, 571 insertions(+), 43 deletions(-) rename boost/network/uri/{uri_accessors.hpp => accessors.hpp} (100%) create mode 100644 boost/network/uri/uri_io.hpp diff --git a/boost/network/uri/uri_accessors.hpp b/boost/network/uri/accessors.hpp similarity index 100% rename from boost/network/uri/uri_accessors.hpp rename to boost/network/uri/accessors.hpp diff --git a/boost/network/uri/directives.hpp b/boost/network/uri/directives.hpp index a389ac744..233c630ca 100644 --- a/boost/network/uri/directives.hpp +++ b/boost/network/uri/directives.hpp @@ -11,10 +11,6 @@ # include # include # include -# include -# include -# include -# include namespace boost { diff --git a/boost/network/uri/directives/authority.hpp b/boost/network/uri/directives/authority.hpp index 78bc5aaf4..e7d135f92 100644 --- a/boost/network/uri/directives/authority.hpp +++ b/boost/network/uri/directives/authority.hpp @@ -2,10 +2,53 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { +template < + class ValueType + > +struct authority_directive { + + explicit authority_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + uri.append(value); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + uri.append(value); + } + + const ValueType &value; + +}; +template < + class T + > +inline +authority_directive authority(const T &value) { + return authority_directive(value); +} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/fragment.hpp b/boost/network/uri/directives/fragment.hpp index 94b2b3cfd..ef7a01c21 100644 --- a/boost/network/uri/directives/fragment.hpp +++ b/boost/network/uri/directives/fragment.hpp @@ -2,10 +2,57 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { +template < + class ValueType + > +struct fragment_directive { + + explicit fragment_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + static const char separator[] = {'#'}; + uri.append(boost::begin(separator), boost::end(separator)); + uri.append(value); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + static const char separator[] = {'#'}; + uri.append(boost::begin(separator), boost::end(separator)); + uri.append(value); + } + + const ValueType &value; + +}; +template < + class T + > +inline +fragment_directive fragment(const T &value) { + return fragment_directive(value); +} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/host.hpp b/boost/network/uri/directives/host.hpp index 360c584d7..d82d17489 100644 --- a/boost/network/uri/directives/host.hpp +++ b/boost/network/uri/directives/host.hpp @@ -2,6 +2,12 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { diff --git a/boost/network/uri/directives/path.hpp b/boost/network/uri/directives/path.hpp index 7d48092c3..697c1d423 100644 --- a/boost/network/uri/directives/path.hpp +++ b/boost/network/uri/directives/path.hpp @@ -2,6 +2,13 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_PATH_INC__ +# include +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { @@ -20,7 +27,9 @@ struct path_directive { > typename enable_if, void>::type operator () (Uri &uri) const { - uri.append(value); + typename string::type encoded_value; + encode(boost::begin(value), boost::end(value), std::back_inserter(encoded_value)); + uri.append(encoded_value); } template < @@ -29,7 +38,9 @@ struct path_directive { > typename enable_if >, void>::type operator () (Uri &uri) const { - uri.append(value); + typename string::type encoded_value; + encode(boost::begin(value), boost::end(value), std::back_inserter(encoded_value)); + uri.append(encoded_value); } const ValueType &value; diff --git a/boost/network/uri/directives/port.hpp b/boost/network/uri/directives/port.hpp index 06eab0ba8..59e2d9a4c 100644 --- a/boost/network/uri/directives/port.hpp +++ b/boost/network/uri/directives/port.hpp @@ -2,10 +2,88 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ +# include +# include +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { +template < + class ValueType + > +struct port_directive { + + explicit port_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + static const char separator[] = {':'}; + uri.append(boost::begin(separator), boost::end(separator)); + uri.append(value); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + static const char separator[] = {':'}; + uri.append(boost::begin(separator), boost::end(separator)); + uri.append(value); + } + + const ValueType &value; + +}; + + +struct port_directive_us { + + explicit port_directive_us(boost::uint16_t value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + void operator () (Uri &uri) const { + static const char separator[] = {':'}; + uri.append(boost::begin(separator), boost::end(separator)); + typename string::type port = boost::lexical_cast::type>(value); + uri.append(port); + } + + boost::uint16_t value; + +}; + + +template < + class T + > +inline +port_directive port(const T &value, + typename boost::disable_if::type>::type * = 0) { + return port_directive(value); +} +inline +port_directive_us port(boost::uint16_t value) { + return port_directive_us(value); +} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp index c9f803a58..3908c8820 100644 --- a/boost/network/uri/directives/query.hpp +++ b/boost/network/uri/directives/query.hpp @@ -2,10 +2,127 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { +template < + class ValueType + > +struct query_directive { + + explicit query_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + static const char separator[] = {'?'}; + uri.append(boost::begin(separator), boost::end(separator)); + uri.append(value); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + static const char separator[] = {'?'}; + uri.append(boost::begin(separator), boost::end(separator)); + uri.append(value); + } + + const ValueType &value; + +}; + +template < + class T + > +inline +query_directive query(const T &value) { + return query_directive(value); +} + +template < + class KeyType + , class ValueType + > +struct query_key_value_directive { + + query_key_value_directive(const KeyType &key, const ValueType &value) + : key(key), value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + static const char separator_1[] = {'?'}; + static const char separator_2[] = {'='}; + static const char separator_3[] = {';'}; + if (!uri.query_range()) + { + uri.append(boost::begin(separator_1), boost::end(separator_1)); + } + else + { + uri.append(boost::begin(separator_3), boost::end(separator_3)); + } + uri.append(key); + uri.append(boost::begin(separator_2), boost::end(separator_2)); + typename string::type encoded_value; + encode(boost::begin(value), boost::end(value), std::back_inserter(encoded_value)); + uri.append(encoded_value); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + static const char separator_1[] = {'?'}; + static const char separator_2[] = {'='}; + static const char separator_3[] = {';'}; + if (!uri.query_range()) + { + uri.append(boost::begin(separator_1), boost::end(separator_1)); + } + else + { + uri.append(boost::begin(separator_3), boost::end(separator_3)); + } + uri.append(key); + uri.append(boost::begin(separator_2), boost::end(separator_2)); + uri.append(value); + } + + const KeyType &key; + const ValueType &value; + +}; +template < + class Key + , class Value + > +inline +query_key_value_directive query(const Key &key, const Value &value) { + return query_key_value_directive(key, value); +} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/scheme.hpp b/boost/network/uri/directives/scheme.hpp index ec07b103b..3ac337704 100644 --- a/boost/network/uri/directives/scheme.hpp +++ b/boost/network/uri/directives/scheme.hpp @@ -2,6 +2,12 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { @@ -20,7 +26,7 @@ struct scheme_directive { > typename enable_if, void>::type operator () (Uri &uri) const { - char separator[] = {':', '/', '/'}; + static const char separator[] = {':', '/', '/'}; uri.append(value); uri.append(boost::begin(separator), boost::end(separator)); } @@ -31,7 +37,7 @@ struct scheme_directive { > typename enable_if >, void>::type operator () (Uri &uri) const { - char separator[] = {':', '/', '/'}; + static const char separator[] = {':', '/', '/'}; uri.append(value); uri.append(boost::begin(separator), boost::end(separator)); } diff --git a/boost/network/uri/directives/user_info.hpp b/boost/network/uri/directives/user_info.hpp index e4c6bd21d..871123ffd 100644 --- a/boost/network/uri/directives/user_info.hpp +++ b/boost/network/uri/directives/user_info.hpp @@ -2,10 +2,57 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ +# include +# include +# include +# include + + namespace boost { namespace network { namespace uri { +template < + class ValueType + > +struct user_info_directive { + + explicit user_info_directive(const ValueType &value) + : value(value) + {} + + template < + class Tag + , template class Uri + > + typename enable_if, void>::type + operator () (Uri &uri) const { + static const char separator[] = {'@'}; + uri.append(value); + uri.append(boost::begin(separator), boost::end(separator)); + } + + template < + class Tag + , template class Uri + > + typename enable_if >, void>::type + operator () (Uri &uri) const { + static const char separator[] = {'@'}; + uri.append(value); + uri.append(boost::begin(separator), boost::end(separator)); + } + + const ValueType &value; + +}; +template < + class T + > +inline +user_info_directive user_info(const T &value) { + return user_info_directive(value); +} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/encode.hpp b/boost/network/uri/encode.hpp index 18b344ee5..39d3da47f 100644 --- a/boost/network/uri/encode.hpp +++ b/boost/network/uri/encode.hpp @@ -121,6 +121,7 @@ void encode_char(CharT in, OutputIterator &out) { case '.': case '_': case '~': + case '/': out++ = in; break; default: diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index c6c95992b..2e3d916e2 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -185,10 +185,6 @@ class basic_uri return uri_; } - string_type raw() const { - return string(); - } - bool is_valid() const { return is_valid_; } diff --git a/boost/network/uri/uri_io.hpp b/boost/network/uri/uri_io.hpp new file mode 100644 index 000000000..efff221f4 --- /dev/null +++ b/boost/network/uri/uri_io.hpp @@ -0,0 +1,23 @@ +#ifndef __BOOST_NETWORK_URI_URI_IO_INC__ +# define __BOOST_NETWORK_URI_URI_IO_INC__ + + +# include + + +namespace boost { +namespace network { +namespace uri { +template < + class Tag + > +inline +std::ostream &operator << (std::ostream &os, const basic_uri &uri) { + return os << uri.string(); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_URI_IO_INC__ diff --git a/libs/network/example/simple_wget.cpp b/libs/network/example/simple_wget.cpp index 464652016..45821f447 100644 --- a/libs/network/example/simple_wget.cpp +++ b/libs/network/example/simple_wget.cpp @@ -29,7 +29,7 @@ namespace { template < class Tag > -std::string get_filename(const uri::http::basic_uri &url) { +std::string get_filename(const uri::basic_uri &url) { std::string path = uri::path(url); std::size_t index = path.find_last_of('/'); std::string filename = path.substr(index + 1); diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index 3d6c147cf..5ca9fb1de 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -7,31 +7,29 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) find_package( Boost 1.41.0 COMPONENTS unit_test_framework system regex date_time filesystem ) find_package( OpenSSL ) find_package( Threads ) -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_MULTITHREADED ON) - if (Boost_FOUND) - set( - TESTS - url_test - url_http_test - url_mailto_test - url_encoding_test - url_builder_test - ) - foreach (test ${TESTS}) - set_source_files_properties(${test}.cpp - PROPERTIES COMPILE_FLAGS "-Wall") - add_executable(cpp-netlib-${test} ${test}.cpp) - add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) - if (OPENSSL_FOUND) - target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) - endif() - set_target_properties(cpp-netlib-${test} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) - add_test(cpp-netlib-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) - endforeach (test) - -endif() + set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_MULTITHREADED ON) + set( + TESTS + url_test + url_http_test + url_mailto_test + url_encoding_test + url_builder_test + ) + foreach (test ${TESTS}) + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") + add_executable(cpp-netlib-${test} ${test}.cpp) + add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) + target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + if (OPENSSL_FOUND) + target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) + endif() + set_target_properties(cpp-netlib-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) + endforeach (test) +endif(Boost_FOUND) diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index deb77d59e..d1d666d7b 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -8,15 +8,14 @@ #include #include #include +#include +#include #include #include #include #include -#include - - using namespace boost::network; typedef boost::mpl::list< @@ -45,3 +44,162 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); } + +BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_builder_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string user_info("user:password"); + const std::string host("www.example.com"); + const std::string port("80"); + const std::string path("/path"); + const std::string query("query"); + const std::string fragment("fragment"); + + uri_type instance; + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::user_info(string_type(boost::begin(user_info), boost::end(user_info))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::port(string_type(boost::begin(port), boost::end(port))) + << uri::path(string_type(boost::begin(path), boost::end(path))) + << uri::query(string_type(boost::begin(query), boost::end(query))) + << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))) + ; + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK_EQUAL(static_cast(uri::port_us(instance)), 80); + BOOST_CHECK(boost::equal(uri::port(instance), port)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::query(instance), query)); + BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(port_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string port("8000"); + const std::string path("/"); + + uri_type instance; + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::port(8000) << uri::path("/"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::port(8000) + << uri::path(string_type(boost::begin(path), boost::end(path))) + ; + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::port(instance), port)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string port("8000"); + const std::string encoded_path("/Path%20With%20%28Some%29%20Encoded%20Characters%21"); + const std::string decoded_path("/Path With (Some) Encoded Characters!"); + + uri_type instance; + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::port(8000) + << uri::path(string_type(boost::begin(decoded_path), boost::end(decoded_path))) + ; + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::port(instance), port)); + BOOST_CHECK(boost::equal(uri::path(instance), encoded_path)); + BOOST_CHECK(boost::equal(uri::decoded_path(instance), decoded_path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(query_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + const std::string query("key=value"); + const std::string query_key("key"); + const std::string query_value("value"); + + uri_type instance; + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::path(string_type(boost::begin(path), boost::end(path))) + << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), + string_type(boost::begin(query_value), boost::end(query_value))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::query(instance), query)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(query_2_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + const std::string query("key=value;key=value"); + const std::string query_key("key"); + const std::string query_value("value"); + + uri_type instance; + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::path(string_type(boost::begin(path), boost::end(path))) + << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), + string_type(boost::begin(query_value), boost::end(query_value))) + << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), + string_type(boost::begin(query_value), boost::end(query_value))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::query(instance), query)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + const std::string fragment("fragment"); + + uri_type instance; + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") << uri::fragment("fragment"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::path(string_type(boost::begin(path), boost::end(path))) + << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); +} diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index a5ba2af51..b0a313168 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -18,6 +18,7 @@ using namespace boost::network; + typedef boost::mpl::list< tags::default_string , tags::default_wstring From 7b80e6301ad72c44b2e2be6ee46e3da51b8fb6d8 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 27 Aug 2011 22:16:16 +0200 Subject: [PATCH 181/768] Updated the builder directives & tests; added a very short example. --- boost/network/uri/decode.hpp | 7 ++- boost/network/uri/directives/authority.hpp | 18 +----- boost/network/uri/directives/fragment.hpp | 25 +++----- boost/network/uri/directives/host.hpp | 18 +----- boost/network/uri/directives/path.hpp | 47 +++++++++++---- boost/network/uri/directives/port.hpp | 19 +------ boost/network/uri/directives/query.hpp | 66 ++++++---------------- boost/network/uri/directives/scheme.hpp | 48 ++++++++++------ boost/network/uri/directives/user_info.hpp | 20 +------ boost/network/uri/encode.hpp | 8 ++- boost/network/uri/uri.hpp | 4 ++ libs/network/example/CMakeLists.txt | 3 + libs/network/example/uri_builder.cpp | 25 ++++++++ libs/network/test/uri/url_builder_test.cpp | 46 ++++++++++++++- 14 files changed, 189 insertions(+), 165 deletions(-) create mode 100644 libs/network/example/uri_builder.cpp diff --git a/boost/network/uri/decode.hpp b/boost/network/uri/decode.hpp index e56e3f6e8..7f1441f26 100644 --- a/boost/network/uri/decode.hpp +++ b/boost/network/uri/decode.hpp @@ -59,7 +59,9 @@ template < class InputIterator, class OutputIterator > -OutputIterator decode(const InputIterator &in_begin, const InputIterator &in_end, const OutputIterator &out_begin) { +OutputIterator decode(const InputIterator &in_begin, + const InputIterator &in_end, + const OutputIterator &out_begin) { typedef typename boost::iterator_value::type value_type; InputIterator it = in_begin; @@ -87,7 +89,8 @@ template < class OutputIterator > inline -OutputIterator decode(const SinglePassRange &range, const OutputIterator &out) { +OutputIterator decode(const SinglePassRange &range, + const OutputIterator &out) { return decode(boost::begin(range), boost::end(range), out); } } // namespace uri diff --git a/boost/network/uri/directives/authority.hpp b/boost/network/uri/directives/authority.hpp index e7d135f92..6e723cfe8 100644 --- a/boost/network/uri/directives/authority.hpp +++ b/boost/network/uri/directives/authority.hpp @@ -2,10 +2,8 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ -# include -# include -# include -# include +# include + namespace boost { @@ -24,17 +22,7 @@ struct authority_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - uri.append(value); - } - - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { uri.append(value); } diff --git a/boost/network/uri/directives/fragment.hpp b/boost/network/uri/directives/fragment.hpp index ef7a01c21..809f1f8a7 100644 --- a/boost/network/uri/directives/fragment.hpp +++ b/boost/network/uri/directives/fragment.hpp @@ -2,10 +2,9 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_FRAGMENT_INC__ -# include -# include -# include -# include +# include +# include +# include namespace boost { @@ -24,22 +23,12 @@ struct fragment_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { + typename string::type encoded_value; static const char separator[] = {'#'}; uri.append(boost::begin(separator), boost::end(separator)); - uri.append(value); - } - - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { - static const char separator[] = {'#'}; - uri.append(boost::begin(separator), boost::end(separator)); - uri.append(value); + encode(boost::as_literal(value), std::back_inserter(encoded_value)); + uri.append(encoded_value); } const ValueType &value; diff --git a/boost/network/uri/directives/host.hpp b/boost/network/uri/directives/host.hpp index d82d17489..e251edb84 100644 --- a/boost/network/uri/directives/host.hpp +++ b/boost/network/uri/directives/host.hpp @@ -2,10 +2,8 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_HOST_INC__ -# include -# include -# include -# include +# include +# include namespace boost { @@ -24,17 +22,7 @@ struct host_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - uri.append(value); - } - - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { uri.append(value); } diff --git a/boost/network/uri/directives/path.hpp b/boost/network/uri/directives/path.hpp index 697c1d423..d2b1afd5a 100644 --- a/boost/network/uri/directives/path.hpp +++ b/boost/network/uri/directives/path.hpp @@ -3,10 +3,7 @@ # include -# include -# include -# include -# include +# include namespace boost { @@ -25,21 +22,39 @@ struct path_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - typename string::type encoded_value; - encode(boost::begin(value), boost::end(value), std::back_inserter(encoded_value)); - uri.append(encoded_value); + void operator () (Uri &uri) const { + (*this)(boost::as_literal(value), uri); + } + + template < + class Rng + , class Tag + , template class Uri + > + void operator () (const Rng &rng, Uri &uri) const { + uri.append(boost::begin(rng), boost::end(rng)); } + const ValueType &value; + +}; + +template < + class ValueType + > +struct encoded_path_directive { + + explicit encoded_path_directive(const ValueType &value) + : value(value) + {} + template < class Tag , template class Uri > - typename enable_if >, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { typename string::type encoded_value; - encode(boost::begin(value), boost::end(value), std::back_inserter(encoded_value)); + encode(boost::as_literal(value), std::back_inserter(encoded_value)); uri.append(encoded_value); } @@ -54,6 +69,14 @@ inline path_directive path(const T &value) { return path_directive(value); } + +template < + class T + > +inline +encoded_path_directive encoded_path(const T &value) { + return encoded_path_directive(value); +} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/port.hpp b/boost/network/uri/directives/port.hpp index 59e2d9a4c..ae3a9bb88 100644 --- a/boost/network/uri/directives/port.hpp +++ b/boost/network/uri/directives/port.hpp @@ -2,12 +2,11 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ -# include # include -# include -# include # include # include +# include +# include namespace boost { @@ -26,19 +25,7 @@ struct port_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - static const char separator[] = {':'}; - uri.append(boost::begin(separator), boost::end(separator)); - uri.append(value); - } - - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { static const char separator[] = {':'}; uri.append(boost::begin(separator), boost::end(separator)); uri.append(value); diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp index 3908c8820..59eb2ea06 100644 --- a/boost/network/uri/directives/query.hpp +++ b/boost/network/uri/directives/query.hpp @@ -2,10 +2,9 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_QUERY_INC__ -# include -# include -# include -# include +# include +# include +# include namespace boost { @@ -24,19 +23,8 @@ struct query_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - static const char separator[] = {'?'}; - uri.append(boost::begin(separator), boost::end(separator)); - uri.append(value); - } - - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { + typename string::type encoded_value; static const char separator[] = {'?'}; uri.append(boost::begin(separator), boost::end(separator)); uri.append(value); @@ -68,48 +56,26 @@ struct query_key_value_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - static const char separator_1[] = {'?'}; - static const char separator_2[] = {'='}; - static const char separator_3[] = {';'}; + void operator () (Uri &uri) const { + typename string::type encoded_key, encoded_value; + static const char qmark[] = {'?'}; + static const char equal[] = {'='}; + static const char scolon[] = {';'}; if (!uri.query_range()) { - uri.append(boost::begin(separator_1), boost::end(separator_1)); + uri.append(boost::begin(qmark), boost::end(qmark)); } else { - uri.append(boost::begin(separator_3), boost::end(separator_3)); + uri.append(boost::begin(scolon), boost::end(scolon)); } - uri.append(key); - uri.append(boost::begin(separator_2), boost::end(separator_2)); - typename string::type encoded_value; - encode(boost::begin(value), boost::end(value), std::back_inserter(encoded_value)); + encode(boost::as_literal(key), std::back_inserter(encoded_key)); + uri.append(encoded_key); + uri.append(boost::begin(equal), boost::end(equal)); + encode(boost::as_literal(value), std::back_inserter(encoded_value)); uri.append(encoded_value); } - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { - static const char separator_1[] = {'?'}; - static const char separator_2[] = {'='}; - static const char separator_3[] = {';'}; - if (!uri.query_range()) - { - uri.append(boost::begin(separator_1), boost::end(separator_1)); - } - else - { - uri.append(boost::begin(separator_3), boost::end(separator_3)); - } - uri.append(key); - uri.append(boost::begin(separator_2), boost::end(separator_2)); - uri.append(value); - } - const KeyType &key; const ValueType &value; diff --git a/boost/network/uri/directives/scheme.hpp b/boost/network/uri/directives/scheme.hpp index 3ac337704..27726ac30 100644 --- a/boost/network/uri/directives/scheme.hpp +++ b/boost/network/uri/directives/scheme.hpp @@ -2,10 +2,8 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_SCHEME_INC__ -# include -# include -# include -# include +# include +# include namespace boost { @@ -24,19 +22,7 @@ struct scheme_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - static const char separator[] = {':', '/', '/'}; - uri.append(value); - uri.append(boost::begin(separator), boost::end(separator)); - } - - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { static const char separator[] = {':', '/', '/'}; uri.append(value); uri.append(boost::begin(separator), boost::end(separator)); @@ -53,6 +39,34 @@ inline scheme_directive scheme(const T &value) { return scheme_directive(value); } + +namespace schemes { +struct scheme_helper { + + scheme_helper(const char *scheme) + : scheme(scheme) { + + } + + template < + class Tag + , template class Uri + > + void operator () (Uri &uri) const { + static const char separator[] = {':', '/', '/'}; + uri.append(boost::begin(scheme), boost::end(scheme)); + uri.append(boost::begin(separator), boost::end(separator)); + } + + std::string scheme; + +}; + +//static scheme_helper http("http"); +//static scheme_helper https("https"); +//static scheme_helper ftp("ftp"); +//static scheme_helper mailto("mailto"); +} // namespace schemes } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/user_info.hpp b/boost/network/uri/directives/user_info.hpp index 871123ffd..881700a6a 100644 --- a/boost/network/uri/directives/user_info.hpp +++ b/boost/network/uri/directives/user_info.hpp @@ -2,10 +2,8 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_USER_INFO_INC__ -# include -# include -# include -# include +# include +# include namespace boost { @@ -24,19 +22,7 @@ struct user_info_directive { class Tag , template class Uri > - typename enable_if, void>::type - operator () (Uri &uri) const { - static const char separator[] = {'@'}; - uri.append(value); - uri.append(boost::begin(separator), boost::end(separator)); - } - - template < - class Tag - , template class Uri - > - typename enable_if >, void>::type - operator () (Uri &uri) const { + void operator () (Uri &uri) const { static const char separator[] = {'@'}; uri.append(value); uri.append(boost::begin(separator), boost::end(separator)); diff --git a/boost/network/uri/encode.hpp b/boost/network/uri/encode.hpp index 39d3da47f..4c1d2fcee 100644 --- a/boost/network/uri/encode.hpp +++ b/boost/network/uri/encode.hpp @@ -9,6 +9,7 @@ # include +# include # include # include # include @@ -137,7 +138,9 @@ template < class InputIterator, class OutputIterator > -OutputIterator encode(const InputIterator &in_begin, const InputIterator &in_end, const OutputIterator &out_begin) { +OutputIterator encode(const InputIterator &in_begin, + const InputIterator &in_end, + const OutputIterator &out_begin) { typedef typename boost::iterator_value::type value_type; InputIterator it = in_begin; @@ -154,7 +157,8 @@ template < class OutputIterator > inline -OutputIterator encode(const SinglePassRange &range, const OutputIterator &out) { +OutputIterator encode(const SinglePassRange &range, + const OutputIterator &out) { return encode(boost::begin(range), boost::end(range), out); } } // namespace uri diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 2e3d916e2..fe7c8e264 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -361,4 +361,8 @@ bool operator == (const basic_uri &lhs, const basic_uri &rhs) { } // namespace boost +# include +# include + + #endif // __BOOST_NETWORK_URI_INC__ diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 2eccb3c3e..5bf5d4510 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -17,6 +17,7 @@ if (Boost_FOUND) add_executable(hello_world_server http/hello_world_server.cpp) add_executable(fileserver http/fileserver.cpp) add_executable(uri uri.cpp) + add_executable(uri_builder uri_builder.cpp) add_dependencies(http_client cppnetlib-uri-parsers cppnetlib-client-connections) add_dependencies(simple_wget cppnetlib-uri-parsers cppnetlib-client-connections) add_dependencies(uri cppnetlib-uri-parsers) @@ -25,9 +26,11 @@ if (Boost_FOUND) target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} ) target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) target_link_libraries(uri cppnetlib-uri-parsers) + target_link_libraries(uri_builder cppnetlib-uri-parsers) set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + set_target_properties(uri_builder PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) endif() diff --git a/libs/network/example/uri_builder.cpp b/libs/network/example/uri_builder.cpp new file mode 100644 index 000000000..e37160d0b --- /dev/null +++ b/libs/network/example/uri_builder.cpp @@ -0,0 +1,25 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include +#include +#include + + +using namespace boost::network; + + +int +main(int argc, char *argv[]) { + + uri::uri url; + url << uri::scheme("http") + << uri::host("www.github.com") + << uri::path("/cpp-netlib"); + std::cout << url << std::endl; + + return 0; +} diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index d1d666d7b..6135cc0b3 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -117,7 +117,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, tag_types) instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) << uri::host(string_type(boost::begin(host), boost::end(host))) << uri::port(8000) - << uri::path(string_type(boost::begin(decoded_path), boost::end(decoded_path))) + << uri::encoded_path(string_type(boost::begin(decoded_path), boost::end(decoded_path))) + //<< uri::path(uri::encoded(string_type(boost::begin(decoded_path), boost::end(decoded_path)))) ; BOOST_REQUIRE(uri::is_valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); @@ -203,3 +204,46 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, tag_types) BOOST_CHECK(boost::equal(uri::path(instance), path)); BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); } + +//BOOST_AUTO_TEST_CASE_TEMPLATE(scheme_test, T, tag_types) +//{ +// typedef uri::basic_uri uri_type; +// typedef typename uri_type::string_type string_type; +// +// const std::string scheme("http"); +// const std::string host("www.example.com"); +// const std::string path("/"); +// +// uri_type instance; +// //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); +// instance << uri::schemes::http +// << uri::host(string_type(boost::begin(host), boost::end(host))) +// << uri::path(string_type(boost::begin(path), boost::end(path))) +// ; +// BOOST_REQUIRE(uri::is_valid(instance)); +// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); +// BOOST_CHECK(boost::equal(uri::host(instance), host)); +// BOOST_CHECK(boost::equal(uri::path(instance), path)); +//} + +BOOST_AUTO_TEST_CASE(encoded_null_char_test) +{ + typedef uri::basic_uri uri_type; + typedef uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + + uri_type instance; + // there is a potential bug in the way we process ranges if the + // strings are null terminated. + instance << uri::scheme("http") + << uri::host("www.example.com") + << uri::encoded_path("/") + ; + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK_EQUAL(uri::scheme(instance), scheme); + BOOST_CHECK_EQUAL(uri::host(instance), host); + BOOST_CHECK_EQUAL(uri::path(instance), path); +} From e975db2fd42dda27c71ac446f08ba8b180483652 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Wed, 17 Aug 2011 22:11:14 +0200 Subject: [PATCH 182/768] Cleaned up example build file so that it can build on MSVC. --- .../protocol/http/message/async_message.hpp | 1 + libs/network/example/CMakeLists.txt | 54 ++++++++++--------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/boost/network/protocol/http/message/async_message.hpp b/boost/network/protocol/http/message/async_message.hpp index 493b474ba..f7580b1f7 100644 --- a/boost/network/protocol/http/message/async_message.hpp +++ b/boost/network/protocol/http/message/async_message.hpp @@ -11,6 +11,7 @@ #include #include +#include //FIXME move this out to a trait #include diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 5bf5d4510..a5693b2d2 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -6,31 +6,35 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) find_package( Boost 1.41.0 COMPONENTS program_options system regex date_time thread filesystem ) find_package( OpenSSL ) -include_directories(${OPENSSL_INCLUDE_DIR}) find_package( Threads ) -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_MULTITHREADED ON) if (Boost_FOUND) - add_executable(http_client http_client.cpp) - add_executable(simple_wget simple_wget.cpp) - add_executable(hello_world_server http/hello_world_server.cpp) - add_executable(fileserver http/fileserver.cpp) - add_executable(uri uri.cpp) - add_executable(uri_builder uri_builder.cpp) - add_dependencies(http_client cppnetlib-uri-parsers cppnetlib-client-connections) - add_dependencies(simple_wget cppnetlib-uri-parsers cppnetlib-client-connections) - add_dependencies(uri cppnetlib-uri-parsers) - target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers cppnetlib-client-connections) - target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers cppnetlib-client-connections) - target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} ) - target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) - target_link_libraries(uri cppnetlib-uri-parsers) - target_link_libraries(uri_builder cppnetlib-uri-parsers) - set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) - set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) - set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) - set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) - set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) - set_target_properties(uri_builder PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -endif() + set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_MULTITHREADED ON) +endif (Boost_FOUND) + +if (OPENSSL_FOUND) + include_directories(${OPENSSL_INCLUDE_DIR}) +endif (OPENSSL_FOUND) + +add_executable(http_client http_client.cpp) +add_executable(simple_wget simple_wget.cpp) +add_executable(hello_world_server http/hello_world_server.cpp) +add_executable(fileserver http/fileserver.cpp) +add_executable(uri uri.cpp) +add_executable(uri_builder uri_builder.cpp) +add_dependencies(http_client cppnetlib-uri-parsers) +add_dependencies(simple_wget cppnetlib-uri-parsers) +add_dependencies(uri cppnetlib-uri-parsers) +target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) +target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) +target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) +target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) +target_link_libraries(uri cppnetlib-uri-parsers) +target_link_libraries(uri_builder cppnetlib-uri-parsers) +set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(uri_builder PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) From f51911c98ea96a81b228763c6fd85d2d1f270d48 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 6 Aug 2011 18:40:42 +0200 Subject: [PATCH 183/768] Modified some code to get as much working on MSVC 10 as possible. There is still a compiler error in protocol/http/algorithms/linearize.hpp. --- CMakeLists.txt | 12 +++- .../http/policies/simple_connection.hpp | 8 +-- libs/network/example/CMakeLists.txt | 59 +++++++++++-------- libs/network/test/http/http_test_server.hpp | 24 ++++---- 4 files changed, 61 insertions(+), 42 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index eba49491b..cde6f5ef8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,13 @@ if (Boost_FOUND) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTI_THREADED ON) include_directories(${Boost_INCLUDE_DIRS}) -endif() +endif(Boost_FOUND) +if (MSVC) + add_definitions(-D_SCL_SECURE_NO_WARNINGS) +endif(MSVC) +if (WIN32) + add_definitions(-D_WIN32_WINNT=0x0501) +endif(WIN32) enable_testing() if (OPENSSL_FOUND) @@ -26,6 +32,8 @@ endif() add_subdirectory(libs/network/src) add_subdirectory(libs/network/test) -add_subdirectory(libs/mime/test) +if (NOT MSVC) + add_subdirectory(libs/mime/test) +endif(NOT_MSVC) add_subdirectory(libs/network/example) diff --git a/boost/network/protocol/http/policies/simple_connection.hpp b/boost/network/protocol/http/policies/simple_connection.hpp index 72f6a6974..16d9fd1a8 100644 --- a/boost/network/protocol/http/policies/simple_connection.hpp +++ b/boost/network/protocol/http/policies/simple_connection.hpp @@ -30,9 +30,9 @@ namespace boost { namespace network { namespace http { typedef function const &, system::error_code const &)> body_callback_function_type; struct connection_impl { - connection_impl(resolver_type & resolver, bool follow_redirect, string_type const & hostname, string_type const & port, resolver_function_type resolve, bool https, optional const & certificate_filename = optional(), optional const & verify_path = optional()) + connection_impl(resolver_type & resolver, bool follow_redirect, string_type const & hostname, string_type const & port, resolver_function_type resolve, bool https, optional const & certificate_filename = optional(), optional const & verify_path = optional()) : pimpl() - , follow_redirect_(follow_redirect) + , follow_redirect_(follow_redirect) { pimpl.reset(impl::sync_connection_base::new_connection(resolver, resolve, https, certificate_filename, verify_path)); } @@ -55,7 +55,7 @@ namespace boost { namespace network { namespace http { boost::uint16_t status = response_.status(); if (status >= 300 && status <= 307) { typename headers_range >::type location_range = headers(response_)["Location"]; - typename range_iterator >::type>::type location_header = boost::begin(location_range); + typename range_iterator >::type>::type location_header = boost::begin(location_range); if (location_header != boost::end(location_range)) { request_.uri(location_header->second); } else throw std::runtime_error("Location header not defined in redirect response."); @@ -98,7 +98,7 @@ namespace boost { namespace network { namespace http { void cleanup() { } - simple_connection_policy(bool cache_resolved, bool follow_redirect) + simple_connection_policy(bool cache_resolved, bool follow_redirect) : resolver_base(cache_resolved), follow_redirect_(follow_redirect) {} // member variables diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index a5693b2d2..e975c9902 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -9,32 +9,43 @@ find_package( OpenSSL ) find_package( Threads ) if (Boost_FOUND) - set(Boost_USE_STATIC_LIBS ON) - set(Boost_USE_MULTITHREADED ON) + set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_MULTITHREADED ON) endif (Boost_FOUND) if (OPENSSL_FOUND) - include_directories(${OPENSSL_INCLUDE_DIR}) + include_directories(${OPENSSL_INCLUDE_DIR}) endif (OPENSSL_FOUND) -add_executable(http_client http_client.cpp) -add_executable(simple_wget simple_wget.cpp) -add_executable(hello_world_server http/hello_world_server.cpp) -add_executable(fileserver http/fileserver.cpp) -add_executable(uri uri.cpp) -add_executable(uri_builder uri_builder.cpp) -add_dependencies(http_client cppnetlib-uri-parsers) -add_dependencies(simple_wget cppnetlib-uri-parsers) -add_dependencies(uri cppnetlib-uri-parsers) -target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) -target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) -target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) -target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) -target_link_libraries(uri cppnetlib-uri-parsers) -target_link_libraries(uri_builder cppnetlib-uri-parsers) -set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(uri_builder PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +if (Boost_FOUND) + add_executable(http_client http_client.cpp) + add_dependencies(http_client cppnetlib-uri-parsers) + target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + + add_executable(simple_wget simple_wget.cpp) + add_dependencies(simple_wget cppnetlib-uri-parsers) + target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + + add_executable(hello_world_server http/hello_world_server.cpp) + target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) + set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + + if (UNIX) + add_executable(fileserver http/fileserver.cpp) + target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) + set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + endif (UNIX) + + add_executable(uri uri.cpp) + add_dependencies(uri cppnetlib-uri-parsers) + target_link_libraries(uri cppnetlib-uri-parsers) + set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + + add_executable(uri_builder uri_builder.cpp) + add_dependencies(uri_builder cppnetlib-uri-parsers) + target_link_libraries(uri_builder cppnetlib-uri-parsers) + set_target_properties(uri_builder PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + +endif() diff --git a/libs/network/test/http/http_test_server.hpp b/libs/network/test/http/http_test_server.hpp index 0f19ce95c..293c9d9d8 100644 --- a/libs/network/test/http/http_test_server.hpp +++ b/libs/network/test/http/http_test_server.hpp @@ -1,4 +1,4 @@ -// +// // Copyright Kim Grasman 2008. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -16,14 +16,14 @@ #include // ShellExecuteEx - #include + #include #pragma comment( lib, "shell32" ) #else #include // fork, execlp etc. #include #include // for waitpid #include // for chmod - #include // for kill + #include // for kill #endif struct http_test_server @@ -61,7 +61,7 @@ struct http_test_server boost::filesystem::path get_server_path(const boost::filesystem::path& base_path) { using namespace boost::filesystem; - const path script_name = + const path script_name = #if defined(HTTPS_SERVER_TEST) "https_test_server.py" #else @@ -84,8 +84,8 @@ struct http_test_server script_handle_t launch_python_script(const boost::filesystem::path& python_script_path) { using namespace boost::filesystem; - path::string_type script_name = python_script_path.filename().string(); - path::string_type script_dir = python_script_path.parent_path().string(); + path::string_type script_name = python_script_path.filename().native(); + path::string_type script_dir = python_script_path.parent_path().native(); #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) SHELLEXECUTEINFOA sei = {0}; @@ -93,8 +93,8 @@ struct http_test_server sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI; sei.lpVerb = "open"; sei.lpFile = "python.exe"; - sei.lpParameters = script_name.c_str(); - sei.lpDirectory = script_dir.c_str(); + sei.lpParameters = reinterpret_cast(script_name.c_str()); + sei.lpDirectory = reinterpret_cast(script_dir.c_str()); sei.nShow = SW_SHOWNOACTIVATE; if (!ShellExecuteExA(&sei)) @@ -107,16 +107,16 @@ struct http_test_server if (child_process < 0) return false; - if (child_process == 0) { + if (child_process == 0) { // child process - + // cd into script dir and launch python script current_path(script_dir); if (execlp("python", "python", script_name.c_str(), (char*)NULL) == -1) return 0; - } - else { + } + else { // parent sleep(1); } From 680da3374ddd7a57f8626d547a28f0a31c65017d Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 6 Aug 2011 19:34:32 +0200 Subject: [PATCH 184/768] Minor fix in build script. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cde6f5ef8..e6449449e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,6 @@ add_subdirectory(libs/network/src) add_subdirectory(libs/network/test) if (NOT MSVC) add_subdirectory(libs/mime/test) -endif(NOT_MSVC) +endif(NOT MSVC) add_subdirectory(libs/network/example) From 1945ea87cecdfafb39937d4d7d9f279139deabce Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 7 Aug 2011 08:38:08 +0200 Subject: [PATCH 185/768] I added a couple of fixes to ensure compilation on MSVC 10. --- .../protocol/http/client/connection/sync_base.hpp | 6 +++--- .../protocol/http/policies/pooled_connection.hpp | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/boost/network/protocol/http/client/connection/sync_base.hpp b/boost/network/protocol/http/client/connection/sync_base.hpp index 8314363b8..290cf372f 100644 --- a/boost/network/protocol/http/client/connection/sync_base.hpp +++ b/boost/network/protocol/http/client/connection/sync_base.hpp @@ -130,7 +130,7 @@ namespace boost { namespace network { namespace http { namespace impl { } if (boost::iequals(boost::begin(transfer_encoding_range)->second, "chunked")) { bool stopping = false; - do { + do { std::size_t chunk_size_line = read_until(socket_, response_buffer, "\r\n", error); if ((chunk_size_line == 0) && (error != boost::asio::error::eof)) throw boost::system::system_error(error); std::size_t chunk_size = 0; @@ -163,7 +163,7 @@ namespace boost { namespace network { namespace http { namespace impl { if (chunk_size != 0) throw std::runtime_error("Size mismatch between tranfer encoding chunk data size and declared chunk size."); - } + } } while (!stopping); } else throw std::runtime_error("Unsupported Transfer-Encoding."); } else { @@ -177,7 +177,7 @@ namespace boost { namespace network { namespace http { namespace impl { while ((bytes_read = boost::asio::read(socket_, response_buffer, boost::asio::transfer_at_least(1), error))) { body_stream << &response_buffer; length -= bytes_read; - if ((length <= 0) or error) + if ((length <= 0) || error) break; } } diff --git a/boost/network/protocol/http/policies/pooled_connection.hpp b/boost/network/protocol/http/policies/pooled_connection.hpp index c90289e6f..31be06f8e 100644 --- a/boost/network/protocol/http/policies/pooled_connection.hpp +++ b/boost/network/protocol/http/policies/pooled_connection.hpp @@ -30,7 +30,7 @@ namespace boost { namespace network { namespace http { typedef typename resolver_base::resolver_type resolver_type; typedef function resolver_function_type; typedef function const &, system::error_code const &)> body_callback_function_type; - + void cleanup() { host_connection_map().swap(host_connections); } @@ -85,9 +85,9 @@ namespace boost { namespace network { namespace http { pimpl->read_headers(response_, response_buffer); if ( - get_body && response_.status() != 304 + get_body && response_.status() != 304 && (response_.status() != 204) - && not (response_.status() >= 100 && response_.status() <= 199) + && !(response_.status() >= 100 && response_.status() <= 199) ) { pimpl->read_body(response_, response_buffer); } @@ -125,7 +125,7 @@ namespace boost { namespace network { namespace http { }; typedef shared_ptr connection_ptr; - + typedef unordered_map host_connection_map; host_connection_map host_connections; bool follow_redirect_; @@ -164,7 +164,7 @@ namespace boost { namespace network { namespace http { pooled_connection_policy(bool cache_resolved, bool follow_redirect) : resolver_base(cache_resolved), host_connections(), follow_redirect_(follow_redirect) {} - + }; } // namespace http From 8a051662eb94e03a681a6d810647ed4ec31992a8 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Mon, 29 Aug 2011 23:00:48 +0200 Subject: [PATCH 186/768] Added a couple of extra tests to construct a URI from an existing root URI. --- boost/network/uri/accessors.hpp | 14 ++-- boost/network/uri/directives.hpp | 11 +++ boost/network/uri/directives/authority.hpp | 2 +- boost/network/uri/uri.hpp | 81 ++++++++++++++++------ libs/network/test/uri/url_builder_test.cpp | 24 +++++++ libs/network/test/uri/url_test.cpp | 12 ++++ 6 files changed, 116 insertions(+), 28 deletions(-) diff --git a/boost/network/uri/accessors.hpp b/boost/network/uri/accessors.hpp index 88ed97e16..6123ab898 100644 --- a/boost/network/uri/accessors.hpp +++ b/boost/network/uri/accessors.hpp @@ -23,9 +23,9 @@ template < typename Map > struct key_value_sequence - : spirit::qi::grammar + : spirit::qi::grammar { - typedef typename Uri::const_iterator_type const_iterator_type; + typedef typename Uri::const_iterator const_iterator; key_value_sequence() : key_value_sequence::base_type(query) @@ -36,9 +36,9 @@ struct key_value_sequence value = +spirit::qi::char_("a-zA-Z_0-9/%"); } - spirit::qi::rule query; - spirit::qi::rule()> pair; - spirit::qi::rule key, value; + spirit::qi::rule query; + spirit::qi::rule()> pair; + spirit::qi::rule key, value; }; } // namespace details @@ -59,7 +59,7 @@ template < > typename basic_uri::string_type username(const basic_uri &uri) { typename basic_uri::const_range_type user_info_range = uri.user_info_range(); - typename basic_uri::const_iterator_type it(boost::begin(user_info_range)), end(boost::end(user_info_range)); + typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); for (; it != end; ++it) { if (*it == ':') { break; @@ -73,7 +73,7 @@ template < > typename basic_uri::string_type password(const basic_uri &uri) { typename basic_uri::const_range_type user_info_range = uri.user_info_range(); - typename basic_uri::const_iterator_type it(boost::begin(user_info_range)), end(boost::end(user_info_range)); + typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); for (; it != end; ++it) { if (*it == ':') { ++it; diff --git a/boost/network/uri/directives.hpp b/boost/network/uri/directives.hpp index 233c630ca..6b47e77c3 100644 --- a/boost/network/uri/directives.hpp +++ b/boost/network/uri/directives.hpp @@ -16,6 +16,17 @@ namespace boost { namespace network { namespace uri { +template < + class Tag + > +inline +basic_uri &operator << (basic_uri &uri, const basic_uri &root_uri) { + if (root_uri.is_valid()) { + uri.append(boost::begin(root_uri), boost::end(root_uri)); + } + return uri; +} + template < class Tag , class Directive diff --git a/boost/network/uri/directives/authority.hpp b/boost/network/uri/directives/authority.hpp index 6e723cfe8..7d0830a0f 100644 --- a/boost/network/uri/directives/authority.hpp +++ b/boost/network/uri/directives/authority.hpp @@ -34,7 +34,7 @@ template < class T > inline -authority_directive authority(const T &value) { +authority_directive authority(const T &value) { return authority_directive(value); } } // namespace uri diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index fe7c8e264..ef1fc58c3 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -48,15 +48,24 @@ class basic_uri public: typedef typename string::type string_type; - typedef typename string_type::iterator iterator_type; - typedef boost::iterator_range range_type; - typedef typename string_type::const_iterator const_iterator_type; - typedef boost::iterator_range const_range_type; + typedef typename string_type::iterator iterator; + typedef boost::iterator_range range_type; + typedef typename string_type::const_iterator const_iterator; + typedef boost::iterator_range const_range_type; - basic_uri() : is_valid_(false) { + basic_uri() + : is_valid_(false) { } + template < + class FwdIter + > + basic_uri(const FwdIter &first, const FwdIter &last) + : uri_(first, last), is_valid_(false) { + parse(); + } + basic_uri(const string_type &uri) : uri_(uri), is_valid_(false) { parse(); @@ -88,19 +97,19 @@ class basic_uri parse(); } - iterator_type begin() { + iterator begin() { return uri_.begin(); } - const_iterator_type begin() const { + const_iterator begin() const { return uri_.begin(); } - iterator_type end() { + iterator end() { return uri_.end(); } - const_iterator_type end() const { + const_iterator end() const { return uri_.end(); } @@ -195,9 +204,9 @@ class basic_uri } template < - class Iterator + class FwdIter > - void append(Iterator first, Iterator last) { + void append(const FwdIter &first, const FwdIter &last) { uri_.append(first, last); parse(); } @@ -217,18 +226,10 @@ template < > inline void basic_uri::parse() { - const_iterator_type first(boost::begin(uri_)), last(boost::end(uri_)); + const_iterator first(boost::begin(uri_)), last(boost::end(uri_)); is_valid_ = detail::parse(first, last, uri_parts_); } -template < - class Tag - > -inline -void swap(basic_uri &lhs, basic_uri &rhs) { - lhs.swap(rhs); -} - template < class Tag > @@ -358,6 +359,46 @@ bool operator == (const basic_uri &lhs, const basic_uri &rhs) { } } // namespace uri } // namespace network + +template < + class Tag + > +inline +typename network::uri::basic_uri::iterator begin(network::uri::basic_uri &uri) { + return uri.begin(); +} + +template < + class Tag + > +inline +typename network::uri::basic_uri::iterator end(network::uri::basic_uri &uri) { + return uri.end(); +} + +template < + class Tag + > +inline +typename network::uri::basic_uri::const_iterator begin(const network::uri::basic_uri &uri) { + return uri.begin(); +} + +template < + class Tag + > +inline +typename network::uri::basic_uri::const_iterator end(const network::uri::basic_uri &uri) { + return uri.end(); +} + +template < + class Tag + > +inline +void swap(network::uri::basic_uri &lhs, network::uri::basic_uri &rhs) { + lhs.swap(rhs); +} } // namespace boost diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index 6135cc0b3..f6d7a138b 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -205,6 +205,30 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, tag_types) BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); } +BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string root("http://www.example.com/"); + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + const std::string fragment("fragment"); + + uri_type root_uri(boost::begin(root), boost::end(root)); + uri_type instance; + //instance << uri::uri("http://www.example.com/") << uri::path("/") << uri::fragment("fragment"); + instance << root_uri + << uri::path(string_type(boost::begin(path), boost::end(path))) + << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); +} + //BOOST_AUTO_TEST_CASE_TEMPLATE(scheme_test, T, tag_types) //{ // typedef uri::basic_uri uri_type; diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index b0a313168..10373428c 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -312,3 +312,15 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, tag_types) { BOOST_CHECK(boost::equal((++queries.begin())->first, key_2)); BOOST_CHECK(boost::equal((++queries.begin())->second, value_2)); } + +BOOST_AUTO_TEST_CASE_TEMPLATE(range_test, T, tag_types) +{ + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://www.example.com/"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(instance, url)); +} From 1f07337bef7212ccb2c3b0beb9c2ebae2c02b050 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Thu, 1 Sep 2011 19:36:53 +0200 Subject: [PATCH 187/768] Refactored unit tests in order to prepare for the new URI interface. --- libs/network/test/uri/url_builder_test.cpp | 45 ++++++------ libs/network/test/uri/url_test.cpp | 85 +++++++++++----------- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index f6d7a138b..d98dd893c 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -6,6 +6,7 @@ #define BOOST_TEST_MODULE URI builder test #include #include +#include #include #include #include @@ -19,14 +20,14 @@ using namespace boost::network; typedef boost::mpl::list< - tags::default_string - , tags::default_wstring - > tag_types; + uri::uri + , uri::wuri + > uri_types; -BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string scheme("http"); @@ -45,9 +46,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_builder_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_builder_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string scheme("http"); @@ -78,9 +79,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_builder_test, T, tag_types) BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(port_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(port_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string scheme("http"); @@ -102,9 +103,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(port_test, T, tag_types) BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string scheme("http"); @@ -128,9 +129,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, tag_types) BOOST_CHECK(boost::equal(uri::decoded_path(instance), decoded_path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(query_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(query_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string scheme("http"); @@ -154,9 +155,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(query_test, T, tag_types) BOOST_CHECK(boost::equal(uri::query(instance), query)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(query_2_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(query_2_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string scheme("http"); @@ -182,9 +183,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(query_2_test, T, tag_types) BOOST_CHECK(boost::equal(uri::query(instance), query)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string scheme("http"); @@ -205,9 +206,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, tag_types) BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string root("http://www.example.com/"); @@ -229,9 +230,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, tag_types) BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); } -//BOOST_AUTO_TEST_CASE_TEMPLATE(scheme_test, T, tag_types) +//BOOST_AUTO_TEST_CASE_TEMPLATE(scheme_test, T, uri_types) //{ -// typedef uri::basic_uri uri_type; +// typedef T uri_type; // typedef typename uri_type::string_type string_type; // // const std::string scheme("http"); @@ -252,7 +253,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, tag_types) BOOST_AUTO_TEST_CASE(encoded_null_char_test) { - typedef uri::basic_uri uri_type; + typedef uri::uri uri_type; typedef uri_type::string_type string_type; const std::string scheme("http"); diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index 10373428c..48e56556d 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -6,9 +6,9 @@ #define BOOST_TEST_MODULE URL Test #include #include +#include #include #include -#include #include #include #include @@ -18,15 +18,14 @@ using namespace boost::network; - typedef boost::mpl::list< - tags::default_string - , tags::default_wstring - > tag_types; + uri::uri + , uri::wuri + > uri_types; -BOOST_AUTO_TEST_CASE_TEMPLATE(uri_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(uri_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://www.example.com/"); @@ -41,8 +40,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(uri_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://user:password@www.example.com/path?query#fragment"); @@ -66,8 +65,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(mailto_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(mailto_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/mailto:john.doe@example.com"); @@ -81,8 +80,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(mailto_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(file_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(file_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/file:///bin/bash"); @@ -95,8 +94,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(file_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/xmpp:example-node@example.com?message;subject=Hello%20World"); @@ -112,8 +111,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::query(instance), query)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://129.79.245.252/"); @@ -128,8 +127,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_1, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_1, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://[1080::8:800:200c:417a]/"); @@ -144,8 +143,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_1, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_2, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_2, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/"); @@ -160,8 +159,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_2, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ftp_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(ftp_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/ftp://john.doe@ftp.example.com/"); @@ -178,8 +177,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ftp_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(news_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(news_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/news:comp.infosystems.www.servers.unix"); @@ -192,8 +191,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(news_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(tel_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(tel_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/tel:+1-816-555-1212"); @@ -206,8 +205,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(tel_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_uri_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_uri_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://www.example.com/Path%20With%20%28Some%29%20Encoded%20Characters%21"); @@ -224,8 +223,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_uri_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::decoded_path(instance), decoded_path)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(copy_constructor_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(copy_constructor_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://www.example.com/"); @@ -235,8 +234,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(copy_constructor_test, T, tag_types) { BOOST_CHECK(instance == copy); } -BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://www.example.com/"); @@ -248,8 +247,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, tag_types) { BOOST_CHECK(instance == copy); } -BOOST_AUTO_TEST_CASE_TEMPLATE(username_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(username_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/ftp://john.doe:password@ftp.example.com/"); @@ -263,8 +262,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(username_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::password(instance), password)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(authority_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(authority_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://user:password@www.example.com/path?query#fragment"); @@ -275,8 +274,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(authority_test, T, tag_types) { BOOST_CHECK(boost::equal(uri::authority(instance), authority)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(http_query_map_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(http_query_map_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://user:password@www.example.com/path?query#fragment"); @@ -293,8 +292,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_query_map_test, T, tag_types) { BOOST_CHECK(boost::equal(queries.begin()->second, value)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, tag_types) { - typedef uri::basic_uri uri_type; +BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, uri_types) { + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("/service/xmpp:example-node@example.com?message;subject=Hello%20World"); @@ -313,9 +312,9 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, tag_types) { BOOST_CHECK(boost::equal((++queries.begin())->second, value_2)); } -BOOST_AUTO_TEST_CASE_TEMPLATE(range_test, T, tag_types) +BOOST_AUTO_TEST_CASE_TEMPLATE(range_test, T, uri_types) { - typedef uri::basic_uri uri_type; + typedef T uri_type; typedef typename uri_type::string_type string_type; const std::string url("http://www.example.com/"); From 46601975fcac69621aab9a4af3c62e394c432741 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 3 Sep 2011 22:24:46 +0200 Subject: [PATCH 188/768] Removed tag dispatching from URI. --- boost/network/protocol/http/impl/request.hpp | 18 ++- .../protocol/http/message/wrappers/port.hpp | 2 +- .../protocol/http/message/wrappers/uri.hpp | 6 +- boost/network/uri.hpp | 15 +- boost/network/uri/accessors.hpp | 52 +++---- boost/network/uri/detail/uri_parts.hpp | 1 - boost/network/uri/directives.hpp | 10 +- boost/network/uri/directives/fragment.hpp | 6 +- boost/network/uri/directives/path.hpp | 6 +- boost/network/uri/directives/port.hpp | 10 +- boost/network/uri/directives/query.hpp | 12 +- boost/network/uri/http/uri.hpp | 101 -------------- boost/network/uri/mailto/uri.hpp | 80 ----------- boost/network/uri/uri.hpp | 131 ++++++++---------- boost/network/uri/uri_io.hpp | 11 +- libs/network/example/CMakeLists.txt | 8 +- libs/network/example/uri.cpp | 14 +- libs/network/test/uri/CMakeLists.txt | 2 - libs/network/test/uri/url_builder_test.cpp | 23 +-- libs/network/test/uri/url_test.cpp | 37 ++--- 20 files changed, 179 insertions(+), 366 deletions(-) delete mode 100644 boost/network/uri/http/uri.hpp delete mode 100644 boost/network/uri/mailto/uri.hpp diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index ca5a2c26a..763b09c67 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include @@ -50,7 +50,7 @@ namespace http { struct basic_request : public basic_message { - mutable boost::network::uri::http::basic_uri uri_; + mutable boost::network::uri::basic_uri::type> uri_; typedef basic_message base_type; public: @@ -80,11 +80,10 @@ namespace http { } void swap(basic_request & other) { - using boost::network::uri::swap; base_type & base_ref(other); basic_request & this_ref(*this); base_ref.swap(this_ref); - swap(other.uri_, this->uri_); + boost::swap(other.uri_, this->uri_); } string_type const host() const { @@ -92,7 +91,14 @@ namespace http { } port_type port() const { - return uri::port_us(uri_); + boost::optional port = uri::port_us(uri_); + if (!port) + { + typedef constants consts; + return boost::iequals(uri_.scheme_range(), + string_type(consts::https()))? 443 : 80; + } + return *port; } string_type const path() const { @@ -115,7 +121,7 @@ namespace http { uri_ = new_uri; } - boost::network::uri::http::basic_uri const & uri() const { + boost::network::uri::basic_uri::type> const & uri() const { return uri_; } diff --git a/boost/network/protocol/http/message/wrappers/port.hpp b/boost/network/protocol/http/message/wrappers/port.hpp index 9777ac277..786ce1e98 100644 --- a/boost/network/protocol/http/message/wrappers/port.hpp +++ b/boost/network/protocol/http/message/wrappers/port.hpp @@ -30,7 +30,7 @@ namespace boost { namespace network { namespace http { } operator boost::optional () { - return port_us(message_.uri()); + return uri::port_us(message_.uri()); } }; diff --git a/boost/network/protocol/http/message/wrappers/uri.hpp b/boost/network/protocol/http/message/wrappers/uri.hpp index 7d4be811a..622d53a4a 100644 --- a/boost/network/protocol/http/message/wrappers/uri.hpp +++ b/boost/network/protocol/http/message/wrappers/uri.hpp @@ -7,7 +7,7 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#include namespace boost { namespace network { namespace http { @@ -24,7 +24,7 @@ namespace boost { namespace network { namespace http { operator string_type() { return message_.uri().raw(); } - operator boost::network::uri::basic_uri () { + operator boost::network::uri::basic_uri::type> () { return message_.uri(); } }; @@ -40,6 +40,6 @@ namespace boost { namespace network { namespace http { } // namespace network -} // nmaespace boost +} // namespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_HPP_20100620 diff --git a/boost/network/uri.hpp b/boost/network/uri.hpp index 7472e8cbc..237818c65 100644 --- a/boost/network/uri.hpp +++ b/boost/network/uri.hpp @@ -8,19 +8,18 @@ #include #include -#include -#include +//#include +//#include namespace boost { namespace network { namespace uri { -typedef basic_uri uri; -typedef basic_uri wuri; - -namespace http { -typedef basic_uri uri; -} +typedef basic_uri uri; +typedef basic_uri wuri; +//namespace http { +//typedef basic_uri uri; +//} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/accessors.hpp b/boost/network/uri/accessors.hpp index 6123ab898..7281ec65d 100644 --- a/boost/network/uri/accessors.hpp +++ b/boost/network/uri/accessors.hpp @@ -43,72 +43,72 @@ struct key_value_sequence } // namespace details template < - class Tag, + class String, class Map > inline -Map &query_map(const basic_uri &uri, Map &map) { - typename basic_uri::const_range_type range = uri.query_range(); - details::key_value_sequence, Map> parser; +Map &query_map(const basic_uri &uri, Map &map) { + typename basic_uri::const_range_type range = uri.query_range(); + details::key_value_sequence, Map> parser; spirit::qi::parse(boost::begin(range), boost::end(range), parser, map); return map; } template < - class Tag + class String > -typename basic_uri::string_type username(const basic_uri &uri) { - typename basic_uri::const_range_type user_info_range = uri.user_info_range(); - typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); +String username(const basic_uri &uri) { + typename basic_uri::const_range_type user_info_range = uri.user_info_range(); + typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); for (; it != end; ++it) { if (*it == ':') { break; } } - return typename string::type(boost::begin(user_info_range), it); + return String(boost::begin(user_info_range), it); } template < - class Tag + class String > -typename basic_uri::string_type password(const basic_uri &uri) { - typename basic_uri::const_range_type user_info_range = uri.user_info_range(); - typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); +String password(const basic_uri &uri) { + typename basic_uri::const_range_type user_info_range = uri.user_info_range(); + typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); for (; it != end; ++it) { if (*it == ':') { ++it; break; } } - return typename string::type(it, boost::end(user_info_range)); + return String(it, boost::end(user_info_range)); } template < - class Tag + class String > -typename basic_uri::string_type decoded_path(const basic_uri &uri) { - typename basic_uri::const_range_type path_range = uri.path_range(); - typename basic_uri::string_type decoded_path; +String decoded_path(const basic_uri &uri) { + typename basic_uri::const_range_type path_range = uri.path_range(); + String decoded_path; decode(path_range, std::back_inserter(decoded_path)); return decoded_path; } template < - class Tag + class String > -typename basic_uri::string_type decoded_query(const basic_uri &uri) { - typename basic_uri::const_range_type query_range = uri.query_range(); - typename basic_uri::string_type decoded_query; +String decoded_query(const basic_uri &uri) { + typename basic_uri::const_range_type query_range = uri.query_range(); + String decoded_query; decode(query_range, std::back_inserter(decoded_query)); return decoded_query; } template < - class Tag + class String > -typename basic_uri::string_type decoded_fragment(const basic_uri &uri) { - typename basic_uri::const_range_type fragment_range = uri.fragment_range(); - typename basic_uri::string_type decoded_fragment; +String decoded_fragment(const basic_uri &uri) { + typename basic_uri::const_range_type fragment_range = uri.fragment_range(); + String decoded_fragment; decode(fragment_range, std::back_inserter(decoded_fragment)); return decoded_fragment; } diff --git a/boost/network/uri/detail/uri_parts.hpp b/boost/network/uri/detail/uri_parts.hpp index a2647e1ec..e069657ae 100644 --- a/boost/network/uri/detail/uri_parts.hpp +++ b/boost/network/uri/detail/uri_parts.hpp @@ -8,7 +8,6 @@ # include -# include namespace boost { diff --git a/boost/network/uri/directives.hpp b/boost/network/uri/directives.hpp index 6b47e77c3..e02a1a1da 100644 --- a/boost/network/uri/directives.hpp +++ b/boost/network/uri/directives.hpp @@ -17,22 +17,22 @@ namespace boost { namespace network { namespace uri { template < - class Tag + class String > inline -basic_uri &operator << (basic_uri &uri, const basic_uri &root_uri) { - if (root_uri.is_valid()) { +basic_uri &operator << (basic_uri &uri, const basic_uri &root_uri) { + if (empty(uri) && valid(root_uri)) { uri.append(boost::begin(root_uri), boost::end(root_uri)); } return uri; } template < - class Tag + class String , class Directive > inline -basic_uri &operator << (basic_uri &uri, const Directive &directive) { +basic_uri &operator << (basic_uri &uri, const Directive &directive) { directive(uri); return uri; } diff --git a/boost/network/uri/directives/fragment.hpp b/boost/network/uri/directives/fragment.hpp index 809f1f8a7..49d980530 100644 --- a/boost/network/uri/directives/fragment.hpp +++ b/boost/network/uri/directives/fragment.hpp @@ -20,11 +20,11 @@ struct fragment_directive { {} template < - class Tag + class String , template class Uri > - void operator () (Uri &uri) const { - typename string::type encoded_value; + void operator () (Uri &uri) const { + String encoded_value; static const char separator[] = {'#'}; uri.append(boost::begin(separator), boost::end(separator)); encode(boost::as_literal(value), std::back_inserter(encoded_value)); diff --git a/boost/network/uri/directives/path.hpp b/boost/network/uri/directives/path.hpp index d2b1afd5a..f4a4bd99c 100644 --- a/boost/network/uri/directives/path.hpp +++ b/boost/network/uri/directives/path.hpp @@ -49,11 +49,11 @@ struct encoded_path_directive { {} template < - class Tag + class StringT , template class Uri > - void operator () (Uri &uri) const { - typename string::type encoded_value; + void operator () (Uri &uri) const { + StringT encoded_value; encode(boost::as_literal(value), std::back_inserter(encoded_value)); uri.append(encoded_value); } diff --git a/boost/network/uri/directives/port.hpp b/boost/network/uri/directives/port.hpp index ae3a9bb88..567208d64 100644 --- a/boost/network/uri/directives/port.hpp +++ b/boost/network/uri/directives/port.hpp @@ -22,10 +22,10 @@ struct port_directive { {} template < - class Tag + class String , template class Uri > - void operator () (Uri &uri) const { + void operator () (Uri &uri) const { static const char separator[] = {':'}; uri.append(boost::begin(separator), boost::end(separator)); uri.append(value); @@ -43,13 +43,13 @@ struct port_directive_us { {} template < - class Tag + class String , template class Uri > - void operator () (Uri &uri) const { + void operator () (Uri &uri) const { static const char separator[] = {':'}; uri.append(boost::begin(separator), boost::end(separator)); - typename string::type port = boost::lexical_cast::type>(value); + String port = boost::lexical_cast(value); uri.append(port); } diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp index 59eb2ea06..bb4cb7a27 100644 --- a/boost/network/uri/directives/query.hpp +++ b/boost/network/uri/directives/query.hpp @@ -20,11 +20,11 @@ struct query_directive { {} template < - class Tag + class String , template class Uri > - void operator () (Uri &uri) const { - typename string::type encoded_value; + void operator () (Uri &uri) const { + String encoded_value; static const char separator[] = {'?'}; uri.append(boost::begin(separator), boost::end(separator)); uri.append(value); @@ -53,11 +53,11 @@ struct query_key_value_directive { {} template < - class Tag + class String , template class Uri > - void operator () (Uri &uri) const { - typename string::type encoded_key, encoded_value; + void operator () (Uri &uri) const { + String encoded_key, encoded_value; static const char qmark[] = {'?'}; static const char equal[] = {'='}; static const char scolon[] = {';'}; diff --git a/boost/network/uri/http/uri.hpp b/boost/network/uri/http/uri.hpp deleted file mode 100644 index ecee3f491..000000000 --- a/boost/network/uri/http/uri.hpp +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_HTTP_URI_INC__ -# define __BOOST_NETWORK_URI_HTTP_URI_INC__ - - -# include - - -namespace boost { -namespace network { -namespace uri { -namespace http { -template < - class Tag - > -class basic_uri - : public boost::network::uri::basic_uri { - - typedef boost::network::uri::basic_uri base_type; - -public: - - basic_uri() { - - } - - basic_uri(const typename base_type::string_type &uri) : base_type(uri) { - - } - - basic_uri &operator = (const typename base_type::string_type &uri) { - basic_uri(uri).swap(*this); - return *this; - } - -}; -} // namespace http - -template < - class Tag - > -bool is_http(const http::basic_uri &uri) { - static const char scheme_http[] = {'h', 't', 't', 'p'}; - return boost::equal(uri.scheme_range(), scheme_http); -} - -template < - class Tag - > -bool is_https(const http::basic_uri &uri) { - static const char scheme_https[] = {'h', 't', 't', 'p', 's'}; - return boost::equal(uri.scheme_range(), scheme_https); -} - -template < - class Tag - > -inline -bool is_valid(const http::basic_uri &uri) { - return is_http(uri) || is_https(uri); -} - -template < - class Tag - > -inline -typename basic_uri::string_type port(const http::basic_uri &uri) { - typedef typename basic_uri::range_type range_type; - typedef typename basic_uri::string_type string_type; - - static const char default_http_port[] = "80"; - static const char default_https_port[] = "443"; - - range_type scheme = uri.scheme_range(); - range_type port = uri.port_range(); - - if (boost::empty(port)) { - if (is_http(uri)) { - return string_type(boost::begin(default_http_port), - boost::end(default_http_port)); - } - else if (is_https(uri)) { - return string_type(boost::begin(default_https_port), - boost::end(default_https_port)); - } - } - return string_type(boost::begin(port), boost::end(port)); -} - -typedef basic_uri uri; -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_HTTP_URI_INC__ diff --git a/boost/network/uri/mailto/uri.hpp b/boost/network/uri/mailto/uri.hpp deleted file mode 100644 index 87490a502..000000000 --- a/boost/network/uri/mailto/uri.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef __BOOST_NETWORK_URI_MAILTO_URI_INC__ -# define __BOOST_NETWORK_URI_MAILTO_URI_INC__ - - -# include - - -namespace boost { -namespace network { -namespace uri { -namespace mailto { -namespace details { -template < - class String - > -struct uri_parts - : boost::fusion::vector< - iterator_range // to - // headers - > -{ }; -} // namespace details -} // namespace mailto -} // namespace uri -} // namespace network -} // namespace boost - - -namespace boost { -namespace network { -namespace uri { -namespace mailto { - -template < - class Tag - > -class basic_uri - : public boost::network::uri::basic_uri { - - typedef boost::network::uri::basic_uri base_type; - -public: - - basic_uri() { - - } - - basic_uri(const typename base_type::string_type &uri) : base_type(uri) { - - } - - basic_uri &operator = (const typename base_type::string_type &uri) { - basic_uri(uri).swap(*this); - return *this; - } - - - -}; -} // namespace mailto - -template < - class Tag - > -bool is_mailto(const mailto::basic_uri &uri) { - static const char scheme_mailto[] = {'m', 'a', 'i', 'l', 't', 'o'}; - return boost::equal(uri.scheme_range(), scheme_mailto); -} -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // __BOOST_NETWORK_URI_MAILTO_URI_INC__ diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index ef1fc58c3..0e5768794 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -9,13 +9,13 @@ # include -# include # include # include # ifdef BOOST_NETWORK_NO_LIB # include # endif // #ifdef BOOST_NETWORK_NO_LIB # include +# include # include # include # include @@ -40,14 +40,14 @@ bool parse(std::wstring::const_iterator first, template < - class Tag + class String > class basic_uri - : public boost::equality_comparable > { + : public boost::equality_comparable > { public: - typedef typename string::type string_type; + typedef String string_type; typedef typename string_type::iterator iterator; typedef boost::iterator_range range_type; typedef typename string_type::const_iterator const_iterator; @@ -216,187 +216,168 @@ class basic_uri void parse(); string_type uri_; - detail::uri_parts::type> uri_parts_; + detail::uri_parts uri_parts_; bool is_valid_; }; template < - class Tag + class String > inline -void basic_uri::parse() { +void basic_uri::parse() { const_iterator first(boost::begin(uri_)), last(boost::end(uri_)); is_valid_ = detail::parse(first, last, uri_parts_); } template < - class Tag + class String > inline -typename basic_uri::string_type scheme(const basic_uri &uri) { +String scheme(const basic_uri &uri) { return uri.scheme(); } template < - class Tag + class String > inline -typename basic_uri::string_type user_info(const basic_uri &uri) { +String user_info(const basic_uri &uri) { return uri.user_info(); } template < - class Tag + class String > inline -typename basic_uri::string_type host(const basic_uri &uri) { +String host(const basic_uri &uri) { return uri.host(); } template < - class Tag + class String > inline -typename basic_uri::string_type port(const basic_uri &uri) { +String port(const basic_uri &uri) { return uri.port(); } template < - class Tag - > -struct port_wrapper { - const basic_uri &uri; - - port_wrapper(const basic_uri &uri) : uri(uri) { - - } - - boost::optional to_optional() const { - typename basic_uri::string_type port = uri.port(); - return (port.empty())? - boost::optional() : - boost::optional(boost::lexical_cast(port)); - } - - operator boost::optional () const { - return to_optional(); - } - - operator unsigned short () const { - typedef typename string::type string_type; - typedef constants consts; - const boost::optional &port = to_optional(); - if (port) return *port; - return boost::iequals(uri.scheme_range(), string_type(consts::https())) ? 443 : 80; - } -}; - -template < - class Tag + class String > inline -port_wrapper port_us(const basic_uri &uri) { - return port_wrapper(uri); +boost::optional port_us(const basic_uri &uri) { + String port = uri.port(); + return (port.empty())? + boost::optional() : + boost::optional(boost::lexical_cast(port)); } template < - class Tag + class String > inline -typename basic_uri::string_type path(const basic_uri &uri) { +String path(const basic_uri &uri) { return uri.path(); } template < - class Tag + class String > inline -typename basic_uri::string_type query(const basic_uri &uri) { +String query(const basic_uri &uri) { return uri.query(); } template < - class Tag + class String > inline -typename basic_uri::string_type fragment(const basic_uri &uri) { +String fragment(const basic_uri &uri) { return uri.fragment(); } template < - class Tag + class String > inline -typename basic_uri::string_type authority(const basic_uri &uri) { - typename basic_uri::const_range_type user_info(uri.user_info_range()); - typename basic_uri::const_range_type port(uri.port_range()); - return typename basic_uri::string_type(user_info.begin(), port.end()); +String authority(const basic_uri &uri) { + typename basic_uri::const_range_type user_info(uri.user_info_range()); + typename basic_uri::const_range_type port(uri.port_range()); + return String(user_info.begin(), port.end()); } template < - class Tag + class String > inline -typename basic_uri::string_type netloc(const basic_uri &uri) { +String netloc(const basic_uri &uri) { return authority(uri); } template < - class Tag + class String > inline -bool is_valid(const basic_uri &uri) { +bool valid(const basic_uri &uri) { return uri.is_valid(); } template < - class Tag + class String + > +inline +bool is_valid(const basic_uri &uri) { + return valid(uri); +} + +template < + class String > inline -bool operator == (const basic_uri &lhs, const basic_uri &rhs) { +bool operator == (const basic_uri &lhs, const basic_uri &rhs) { return std::equal(lhs.begin(), lhs.end(), rhs.begin()); } } // namespace uri } // namespace network template < - class Tag + class String > inline -typename network::uri::basic_uri::iterator begin(network::uri::basic_uri &uri) { +typename network::uri::basic_uri::iterator begin(network::uri::basic_uri &uri) { return uri.begin(); } template < - class Tag + class String > inline -typename network::uri::basic_uri::iterator end(network::uri::basic_uri &uri) { +typename network::uri::basic_uri::iterator end(network::uri::basic_uri &uri) { return uri.end(); } template < - class Tag + class String > inline -typename network::uri::basic_uri::const_iterator begin(const network::uri::basic_uri &uri) { +typename network::uri::basic_uri::const_iterator begin(const network::uri::basic_uri &uri) { return uri.begin(); } template < - class Tag + class String > inline -typename network::uri::basic_uri::const_iterator end(const network::uri::basic_uri &uri) { +typename network::uri::basic_uri::const_iterator end(const network::uri::basic_uri &uri) { return uri.end(); } template < - class Tag + class String > inline -void swap(network::uri::basic_uri &lhs, network::uri::basic_uri &rhs) { +void swap(network::uri::basic_uri &lhs, network::uri::basic_uri &rhs) { lhs.swap(rhs); } } // namespace boost diff --git a/boost/network/uri/uri_io.hpp b/boost/network/uri/uri_io.hpp index efff221f4..1b1f6f2cb 100644 --- a/boost/network/uri/uri_io.hpp +++ b/boost/network/uri/uri_io.hpp @@ -3,16 +3,19 @@ # include +# include namespace boost { namespace network { namespace uri { -template < - class Tag - > inline -std::ostream &operator << (std::ostream &os, const basic_uri &uri) { +std::ostream &operator << (std::ostream &os, const basic_uri &uri) { + return os << uri.string(); +} + +inline +std::wostream &operator << (std::wostream &os, const basic_uri &uri) { return os << uri.string(); } } // namespace uri diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index e975c9902..b6592e00c 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -14,7 +14,7 @@ if (Boost_FOUND) endif (Boost_FOUND) if (OPENSSL_FOUND) - include_directories(${OPENSSL_INCLUDE_DIR}) + include_directories(${OPENSSL_INCLUDE_DIR}) endif (OPENSSL_FOUND) if (Boost_FOUND) @@ -22,11 +22,17 @@ if (Boost_FOUND) add_dependencies(http_client cppnetlib-uri-parsers) target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + if (OPENSSL_FOUND) + target_link_libraries(http_client ${OPENSSL_LIBRARIES}) + endif (OPENSSL_FOUND) add_executable(simple_wget simple_wget.cpp) add_dependencies(simple_wget cppnetlib-uri-parsers) target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + if (OPENSSL_FOUND) + target_link_libraries(simple_wget ${OPENSSL_LIBRARIES}) + endif (OPENSSL_FOUND) add_executable(hello_world_server http/hello_world_server.cpp) target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) diff --git a/libs/network/example/uri.cpp b/libs/network/example/uri.cpp index 72c46e205..412849a85 100644 --- a/libs/network/example/uri.cpp +++ b/libs/network/example/uri.cpp @@ -27,13 +27,13 @@ int main(int argc, char * argv[]) { std::string("a valid") : std::string("an invalid")) << " URI!" << std::endl; - /*<< Create a `boost::network::http::uri` object from the input. >>*/ - boost::network::uri::http::uri http_uri_(input); - /*<< Check if it's a valid HTTP URI. >>*/ - std::cout << "It's also " - << (boost::network::uri::is_valid(http_uri_)? - std::string("a valid HTTP URI") : std::string("an invalid HTTP URI.")) - << "!" << std::endl; + ///*<< Create a `boost::network::http::uri` object from the input. >>*/ + //boost::network::uri::http::uri http_uri_(input); + ///*<< Check if it's a valid HTTP URI. >>*/ + //std::cout << "It's also " + // << (boost::network::uri::is_valid(http_uri_)? + // std::string("a valid HTTP URI") : std::string("an invalid HTTP URI.")) + // << "!" << std::endl; return EXIT_SUCCESS; } diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index 5ca9fb1de..7afc6ea36 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -14,8 +14,6 @@ if (Boost_FOUND) set( TESTS url_test - url_http_test - url_mailto_test url_encoding_test url_builder_test ) diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index d98dd893c..512277a1f 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, uri_types) << uri::host(string_type(boost::begin(host), boost::end(host))) << uri::path(string_type(boost::begin(path), boost::end(path))) ; - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -68,11 +68,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_builder_test, T, uri_types) << uri::query(string_type(boost::begin(query), boost::end(query))) << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))) ; - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK_EQUAL(static_cast(uri::port_us(instance)), 80); + BOOST_CHECK(uri::port_us(instance)); + BOOST_CHECK_EQUAL(uri::port_us(instance).get(), 80); BOOST_CHECK(boost::equal(uri::port(instance), port)); BOOST_CHECK(boost::equal(uri::path(instance), path)); BOOST_CHECK(boost::equal(uri::query(instance), query)); @@ -96,7 +97,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(port_test, T, uri_types) << uri::port(8000) << uri::path(string_type(boost::begin(path), boost::end(path))) ; - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::port(instance), port)); @@ -121,7 +122,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, uri_types) << uri::encoded_path(string_type(boost::begin(decoded_path), boost::end(decoded_path))) //<< uri::path(uri::encoded(string_type(boost::begin(decoded_path), boost::end(decoded_path)))) ; - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::port(instance), port)); @@ -148,7 +149,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(query_test, T, uri_types) << uri::path(string_type(boost::begin(path), boost::end(path))) << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), string_type(boost::begin(query_value), boost::end(query_value))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -176,7 +177,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(query_2_test, T, uri_types) string_type(boost::begin(query_value), boost::end(query_value))) << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), string_type(boost::begin(query_value), boost::end(query_value))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -199,7 +200,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, uri_types) << uri::host(string_type(boost::begin(host), boost::end(host))) << uri::path(string_type(boost::begin(path), boost::end(path))) << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -223,7 +224,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, uri_types) instance << root_uri << uri::path(string_type(boost::begin(path), boost::end(path))) << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -245,7 +246,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, uri_types) // << uri::host(string_type(boost::begin(host), boost::end(host))) // << uri::path(string_type(boost::begin(path), boost::end(path))) // ; -// BOOST_REQUIRE(uri::is_valid(instance)); +// BOOST_REQUIRE(uri::valid(instance)); // BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); // BOOST_CHECK(boost::equal(uri::host(instance), host)); // BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -267,7 +268,7 @@ BOOST_AUTO_TEST_CASE(encoded_null_char_test) << uri::host("www.example.com") << uri::encoded_path("/") ; - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), scheme); BOOST_CHECK_EQUAL(uri::host(instance), host); BOOST_CHECK_EQUAL(uri::path(instance), path); diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index 48e56556d..091d96559 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -34,7 +34,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(uri_test, T, uri_types) { const std::string path("/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -54,11 +54,12 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, uri_types) { const std::string fragment("fragment"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK_EQUAL(static_cast(uri::port_us(instance)), 80); + BOOST_CHECK(uri::port_us(instance)); + BOOST_CHECK_EQUAL(uri::port_us(instance).get(), 80); BOOST_CHECK(boost::equal(uri::port(instance), port)); BOOST_CHECK(boost::equal(uri::path(instance), path)); BOOST_CHECK(boost::equal(uri::query(instance), query)); @@ -75,7 +76,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(mailto_test, T, uri_types) { const std::string path("john.doe@example.com"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::path(instance), path)); } @@ -89,7 +90,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(file_test, T, uri_types) { const std::string path("/bin/bash"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::path(instance), path)); } @@ -105,7 +106,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_test, T, uri_types) { const std::string query("message;subject=Hello%20World"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::path(instance), path)); BOOST_CHECK(boost::equal(uri::query(instance), query)); @@ -121,7 +122,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, uri_types) { const std::string path("/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -137,7 +138,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_1, T, uri_types) { const std::string path("/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -153,7 +154,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_2, T, uri_types) { const std::string path("/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), path)); @@ -170,7 +171,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(ftp_test, T, uri_types) { const std::string path("/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); BOOST_CHECK(boost::equal(uri::host(instance), host)); @@ -186,7 +187,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(news_test, T, uri_types) { const std::string path("comp.infosystems.www.servers.unix"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::path(instance), path)); } @@ -200,7 +201,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(tel_test, T, uri_types) { const std::string path("+1-816-555-1212"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::path(instance), path)); } @@ -216,7 +217,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_uri_test, T, uri_types) { const std::string decoded_path("/Path With (Some) Encoded Characters!"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); BOOST_CHECK(boost::equal(uri::host(instance), host)); BOOST_CHECK(boost::equal(uri::path(instance), encoded_path)); @@ -257,7 +258,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(username_test, T, uri_types) { const std::string password("password"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::username(instance), username)); BOOST_CHECK(boost::equal(uri::password(instance), password)); } @@ -270,7 +271,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(authority_test, T, uri_types) { const std::string authority("user:password@www.example.com:80"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(uri::authority(instance), authority)); } @@ -281,7 +282,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(http_query_map_test, T, uri_types) { const std::string url("http://user:password@www.example.com/path?query#fragment"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); const std::string key("query"); const std::string value; @@ -299,7 +300,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, uri_types) { const std::string url("/service/xmpp:example-node@example.com?message;subject=Hello%20World"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); const std::string key_1("message"), key_2("subject"); const std::string value_1, value_2("Hello%20World"); @@ -320,6 +321,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(range_test, T, uri_types) const std::string url("http://www.example.com/"); uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(instance, url)); } From 2d34606e6557d571641b6333112e679e87b1e487 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 10 Sep 2011 12:52:25 +0200 Subject: [PATCH 189/768] Refactor build and cleaned headers. --- boost/network/uri/accessors.hpp | 1 + boost/network/uri/detail/parse_uri.hpp | 274 ------------------------- boost/network/uri/uri.hpp | 4 - libs/network/build/CMakeLists.txt | 2 +- libs/network/build/Jamfile.v2 | 6 +- libs/network/example/CMakeLists.txt | 16 +- libs/network/example/Jamfile.v2 | 10 +- libs/network/src/CMakeLists.txt | 2 +- libs/network/src/parse_uri_impl.cpp | 13 -- libs/network/src/uri/parse.cpp | 252 ++++++++++++++++++++++- libs/network/test/CMakeLists.txt | 8 +- libs/network/test/Jamfile.v2 | 2 +- libs/network/test/http/CMakeLists.txt | 4 +- libs/network/test/http/Jamfile.v2 | 18 +- libs/network/test/uri/CMakeLists.txt | 4 +- 15 files changed, 285 insertions(+), 331 deletions(-) delete mode 100644 boost/network/uri/detail/parse_uri.hpp delete mode 100644 libs/network/src/parse_uri_impl.cpp diff --git a/boost/network/uri/accessors.hpp b/boost/network/uri/accessors.hpp index 7281ec65d..aa57c6f45 100644 --- a/boost/network/uri/accessors.hpp +++ b/boost/network/uri/accessors.hpp @@ -12,6 +12,7 @@ # include # include # include +# include namespace boost { diff --git a/boost/network/uri/detail/parse_uri.hpp b/boost/network/uri/detail/parse_uri.hpp deleted file mode 100644 index a4fa0969a..000000000 --- a/boost/network/uri/detail/parse_uri.hpp +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright 2009, 2010, 2011 Dean Michael Berris, Jeroen Habraken, Glyn Matthews. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#ifndef BOOST_NETWORK_URL_DETAIL_PARSE_URL_HPP_ -# define BOOST_NETWORK_URL_DETAIL_PARSE_URL_HPP_ - - -# ifdef BOOST_NETWORK_NO_LIB -# define BOOST_NETWORK_INLINE inline -# else -# define BOOST_NETWORK_INLINE -# endif // BOOST_NETWORK_NO_LIB - - -#include -#include -#include -#include -#include -#include - - -namespace boost { -namespace network { -namespace uri { -namespace detail { -namespace qi = boost::spirit::qi; - -template < - class String, - typename Iterator - > -struct uri_grammar : qi::grammar()> { - - uri_grammar() : uri_grammar::base_type(start, "uri") { - using boost::spirit::repository::qi::iter_pos; - - // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" - gen_delims %= qi::char_(":/?#[]@"); - // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" - sub_delims %= qi::char_("!$&'()*+,;="); - // reserved = gen-delims / sub-delims - reserved %= gen_delims | sub_delims; - // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - unreserved %= qi::alnum | qi::char_("-._~"); - // pct-encoded = "%" HEXDIG HEXDIG - pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; - - // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - pchar %= qi::raw[ - unreserved | pct_encoded | sub_delims | qi::char_(":@") - ]; - - // segment = *pchar - segment %= qi::raw[*pchar]; - // segment-nz = 1*pchar - segment_nz %= qi::raw[+pchar]; - // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) - segment_nz_nc %= qi::raw[ - +(unreserved | pct_encoded | sub_delims | qi::char_("@")) - ]; - // path-abempty = *( "/" segment ) - path_abempty %= - iter_pos - >> qi::omit[qi::raw[*(qi::char_("/") >> segment)]] - >> iter_pos - ; - // path-absolute = "/" [ segment-nz *( "/" segment ) ] - path_absolute %= - iter_pos - >> qi::omit[qi::raw[ - qi::char_("/") - >> -(segment_nz >> *(qi::char_("/") >> segment)) - ]] - >> iter_pos - ; - // path-rootless = segment-nz *( "/" segment ) - path_rootless %= - iter_pos - >> qi::omit[qi::raw[ - segment_nz >> *(qi::char_("/") >> segment) - ]] - >> iter_pos - ; - // path-empty = 0 - path_empty %= - iter_pos - >> qi::omit[qi::eps] - >> iter_pos - ; - - // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) - scheme %= - iter_pos - >> qi::omit[qi::alpha >> *(qi::alnum | qi::char_("+.-"))] - >> iter_pos - ; - - // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) - user_info %= - iter_pos - >> qi::omit[qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))]] - >> iter_pos - ; - - ip_literal %= - qi::lit('[') >> (ipv6address | ipvfuture) >> ']' - ; - - ipvfuture %= - qi::lit('v') >> +qi::xdigit >> '.' >> +( unreserved | sub_delims | ':') - ; - - ipv6address %= qi::raw[ - qi::repeat(6)[h16 >> ':'] >> ls32 - | "::" >> qi::repeat(5)[h16 >> ':'] >> ls32 - | qi::raw[ h16] >> "::" >> qi::repeat(4)[h16 >> ':'] >> ls32 - | qi::raw[ +(*(h16 >> ':')) >> h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 - | qi::raw[qi::repeat(2)[*(h16 >> ':')] >> h16] >> "::" >> qi::repeat(2)[h16 >> ':'] >> ls32 - | qi::raw[qi::repeat(3)[*(h16 >> ':')] >> h16] >> "::" >> h16 >> ':' >> ls32 - | qi::raw[qi::repeat(4)[*(h16 >> ':')] >> h16] >> "::" >> ls32 - | qi::raw[qi::repeat(5)[*(h16 >> ':')] >> h16] >> "::" >> h16 - | qi::raw[qi::repeat(6)[*(h16 >> ':')] >> h16] >> "::" - - ]; - - // ls32 = ( h16 ":" h16 ) / IPv4address - ls32 %= (h16 >> ':' >> h16) | ipv4address - ; - - // h16 = 1*4HEXDIG - h16 %= qi::repeat(1, 4)[qi::xdigit] - ; - - // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 - dec_octet %= - !(qi::lit('0') >> qi::digit) - >> qi::raw[ - qi::uint_parser() - ]; - - // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet - ipv4address %= qi::raw[ - dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] - ]; - - // reg-name = *( unreserved / pct-encoded / sub-delims ) - reg_name %= qi::raw[ - *(unreserved | pct_encoded | sub_delims) - ]; - - // TODO, host = IP-literal / IPv4address / reg-name - host %= - iter_pos - >> qi::omit[ip_literal | ipv4address | reg_name] - >> iter_pos - ; - - // port %= qi::ushort_; - port %= - iter_pos - >> qi::omit[*qi::digit] - >> iter_pos - ; - - // query = *( pchar / "/" / "?" ) - query %= - iter_pos - >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] - >> iter_pos - ; - - // fragment = *( pchar / "/" / "?" ) - fragment %= - iter_pos - >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] - >> iter_pos - ; - - // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty - // authority = [ userinfo "@" ] host [ ":" port ] - hier_part %= - ( - "//" - >> -(user_info >> '@') - >> host - >> -(':' >> port) - >> path_abempty - ) - | - ( - qi::attr(iterator_range()) - >> qi::attr(iterator_range()) - >> qi::attr(iterator_range()) - >> ( - path_absolute - | path_rootless - | path_empty - ) - ) - ; - - start %= - scheme >> ':' - >> hier_part - >> -('?' >> query) - >> -('#' >> fragment) - ; - } - - qi::rule - gen_delims, sub_delims, reserved, unreserved; - qi::rule - pct_encoded, pchar; - - qi::rule - segment, segment_nz, segment_nz_nc; - qi::rule()> - path_abempty, path_absolute, path_rootless, path_empty; - - qi::rule - dec_octet, ipv4address, reg_name, ipv6address, ipvfuture, ip_literal; - - qi::rule - h16, ls32; - - qi::rule()> - host, port; - - qi::rule()> - scheme, user_info, query, fragment; - - qi::rule, - iterator_range, - iterator_range, - iterator_range >()> - hier_part; - - // actual uri parser - qi::rule()> start; - -}; - - -BOOST_NETWORK_INLINE -bool parse(std::string::const_iterator first, - std::string::const_iterator last, - uri_parts &parts) { - namespace qi = boost::spirit::qi; - static detail::uri_grammar grammar; - bool is_valid = qi::parse(first, last, grammar, parts); - return is_valid && (first == last); -} - -BOOST_NETWORK_INLINE -bool parse(std::wstring::const_iterator first, - std::wstring::const_iterator last, - uri_parts &parts) { - namespace qi = boost::spirit::qi; - static uri_grammar grammar; - bool is_valid = qi::parse(first, last, grammar, parts); - return is_valid && (first == last); -} -} // namespace detail -} // namespace uri -} // namespace network -} // namespace boost - - -#endif // BOOST_NETWORK_URL_DETAIL_PARSE_URL_HPP_ - diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 0e5768794..c26a10f5e 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -11,10 +11,6 @@ # include # include # include -# ifdef BOOST_NETWORK_NO_LIB -# include -# endif // #ifdef BOOST_NETWORK_NO_LIB -# include # include # include # include diff --git a/libs/network/build/CMakeLists.txt b/libs/network/build/CMakeLists.txt index 3ed21b20d..8111a37b7 100644 --- a/libs/network/build/CMakeLists.txt +++ b/libs/network/build/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) find_package( Boost 1.43.0 COMPONENTS unit_test_framework system regex thread filesystem ) -add_library(cppnetlib-uri-parsers STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/parse_uri_impl.cpp) +add_library(cppnetlib-uri STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/parse_uri_impl.cpp) add_library(cppnetlib-server-parsers STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/server_request_parsers_impl.cpp) diff --git a/libs/network/build/Jamfile.v2 b/libs/network/build/Jamfile.v2 index 1a9e18906..f0fd0af91 100644 --- a/libs/network/build/Jamfile.v2 +++ b/libs/network/build/Jamfile.v2 @@ -18,13 +18,13 @@ project cpp-netlib : cpp-pch client : boost/network/include/http/client.hpp ; cpp-pch server : boost/network/include/http/server.hpp ; -lib cppnetlib-uri-parsers : libs/network/src/parse_uri_impl.cpp ; +lib cppnetlib-uri : libs/network/src/parse_uri_impl.cpp ; lib cppnetlib-server-parsers : libs/network/src/server_request_parsers_impl.cpp ; install headers : client server : ../../../boost/network/include/http ; -install libraries : cppnetlib-uri-parsers cppnetlib-server-parsers ; +install libraries : cppnetlib-uri cppnetlib-server-parsers ; -alias all : headers ; +alias all : headers ; diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index b6592e00c..912579e61 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -19,16 +19,16 @@ endif (OPENSSL_FOUND) if (Boost_FOUND) add_executable(http_client http_client.cpp) - add_dependencies(http_client cppnetlib-uri-parsers) - target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + add_dependencies(http_client cppnetlib-uri) + target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) if (OPENSSL_FOUND) target_link_libraries(http_client ${OPENSSL_LIBRARIES}) endif (OPENSSL_FOUND) add_executable(simple_wget simple_wget.cpp) - add_dependencies(simple_wget cppnetlib-uri-parsers) - target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + add_dependencies(simple_wget cppnetlib-uri) + target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) if (OPENSSL_FOUND) target_link_libraries(simple_wget ${OPENSSL_LIBRARIES}) @@ -45,13 +45,13 @@ if (Boost_FOUND) endif (UNIX) add_executable(uri uri.cpp) - add_dependencies(uri cppnetlib-uri-parsers) - target_link_libraries(uri cppnetlib-uri-parsers) + add_dependencies(uri cppnetlib-uri) + target_link_libraries(uri cppnetlib-uri) set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) add_executable(uri_builder uri_builder.cpp) - add_dependencies(uri_builder cppnetlib-uri-parsers) - target_link_libraries(uri_builder cppnetlib-uri-parsers) + add_dependencies(uri_builder cppnetlib-uri) + target_link_libraries(uri_builder cppnetlib-uri) set_target_properties(uri_builder PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) endif() diff --git a/libs/network/example/Jamfile.v2 b/libs/network/example/Jamfile.v2 index f09d9332c..df6ebde7c 100644 --- a/libs/network/example/Jamfile.v2 +++ b/libs/network/example/Jamfile.v2 @@ -21,19 +21,19 @@ project network_test : debug:BOOST_NETWORK_DEBUG ; -exe http_client : http_client.cpp /cpp-netlib//cppnetlib-uri-parsers ; +exe http_client : http_client.cpp /cpp-netlib//cppnetlib-uri ; # exe dispatch_table : dispatch_table.cpp ; -exe uri : uri.cpp /cpp-netlib//cppnetlib-uri-parsers ; +exe uri : uri.cpp /cpp-netlib//cppnetlib-uri ; -exe simple_wget : simple_wget.cpp /cpp-netlib//cppnetlib-uri-parsers ; +exe simple_wget : simple_wget.cpp /cpp-netlib//cppnetlib-uri ; exe hello_world_server : http/hello_world_server.cpp /cpp-netlib//cppnetlib-server-parsers ; -exe hello_world_client : http/hello_world_client.cpp /cpp-netlib//cppnetlib-uri-parsers ; +exe hello_world_client : http/hello_world_client.cpp /cpp-netlib//cppnetlib-uri ; -exe one_liner : http/one_liner.cpp /cpp-netlib//cppnetlib-uri-parsers ; +exe one_liner : http/one_liner.cpp /cpp-netlib//cppnetlib-uri ; exe fileserver : http/fileserver.cpp /cpp-netlib//cppnetlib-server-parsers ; diff --git a/libs/network/src/CMakeLists.txt b/libs/network/src/CMakeLists.txt index e06a58d1c..169a51bfd 100644 --- a/libs/network/src/CMakeLists.txt +++ b/libs/network/src/CMakeLists.txt @@ -8,7 +8,7 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) set(CPP-NETLIB_URI_SRCS uri/parse.cpp) -add_library(cppnetlib-uri-parsers ${CPP-NETLIB_URI_SRCS}) +add_library(cppnetlib-uri ${CPP-NETLIB_URI_SRCS}) set(CPP-NETLIB_HTTP_SERVER_SRCS server_request_parsers_impl.cpp) add_library(cppnetlib-server-parsers ${CPP-NETLIB_HTTP_SERVER_SRCS}) diff --git a/libs/network/src/parse_uri_impl.cpp b/libs/network/src/parse_uri_impl.cpp deleted file mode 100644 index 7de09346b..000000000 --- a/libs/network/src/parse_uri_impl.cpp +++ /dev/null @@ -1,13 +0,0 @@ - -// Copyright 2010-2011 Dean Michael Berris. -// Copyright 2009 Jeroen Habraken. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifdef BOOST_NETWORK_NO_LIB -#undef BOOST_NETWORK_NO_LIB -#endif - -#include - diff --git a/libs/network/src/uri/parse.cpp b/libs/network/src/uri/parse.cpp index 4aadb2628..972859b9b 100644 --- a/libs/network/src/uri/parse.cpp +++ b/libs/network/src/uri/parse.cpp @@ -4,9 +4,253 @@ // http://www.boost.org/LICENSE_1_0.txt) -#ifdef BOOST_NETWORK_NO_LIB -# undef BOOST_NETWORK_NO_LIB -#endif // BOOST_NETWORK_NO_LIB +#include +#include +#include +#include +#include +#include -#include +namespace boost { +namespace network { +namespace uri { +namespace detail { +namespace qi = boost::spirit::qi; + +template < + class String, + typename Iterator + > +struct uri_grammar : qi::grammar()> { + + uri_grammar() : uri_grammar::base_type(start, "uri") { + using boost::spirit::repository::qi::iter_pos; + + // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" + gen_delims %= qi::char_(":/?#[]@"); + // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + sub_delims %= qi::char_("!$&'()*+,;="); + // reserved = gen-delims / sub-delims + reserved %= gen_delims | sub_delims; + // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + unreserved %= qi::alnum | qi::char_("-._~"); + // pct-encoded = "%" HEXDIG HEXDIG + pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; + + // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + pchar %= qi::raw[ + unreserved | pct_encoded | sub_delims | qi::char_(":@") + ]; + + // segment = *pchar + segment %= qi::raw[*pchar]; + // segment-nz = 1*pchar + segment_nz %= qi::raw[+pchar]; + // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) + segment_nz_nc %= qi::raw[ + +(unreserved | pct_encoded | sub_delims | qi::char_("@")) + ]; + // path-abempty = *( "/" segment ) + path_abempty %= + iter_pos + >> qi::omit[qi::raw[*(qi::char_("/") >> segment)]] + >> iter_pos + ; + // path-absolute = "/" [ segment-nz *( "/" segment ) ] + path_absolute %= + iter_pos + >> qi::omit[qi::raw[ + qi::char_("/") + >> -(segment_nz >> *(qi::char_("/") >> segment)) + ]] + >> iter_pos + ; + // path-rootless = segment-nz *( "/" segment ) + path_rootless %= + iter_pos + >> qi::omit[qi::raw[ + segment_nz >> *(qi::char_("/") >> segment) + ]] + >> iter_pos + ; + // path-empty = 0 + path_empty %= + iter_pos + >> qi::omit[qi::eps] + >> iter_pos + ; + + // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + scheme %= + iter_pos + >> qi::omit[qi::alpha >> *(qi::alnum | qi::char_("+.-"))] + >> iter_pos + ; + + // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) + user_info %= + iter_pos + >> qi::omit[qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))]] + >> iter_pos + ; + + ip_literal %= + qi::lit('[') >> (ipv6address | ipvfuture) >> ']' + ; + + ipvfuture %= + qi::lit('v') >> +qi::xdigit >> '.' >> +( unreserved | sub_delims | ':') + ; + + ipv6address %= qi::raw[ + qi::repeat(6)[h16 >> ':'] >> ls32 + | "::" >> qi::repeat(5)[h16 >> ':'] >> ls32 + | qi::raw[ h16] >> "::" >> qi::repeat(4)[h16 >> ':'] >> ls32 + | qi::raw[ +(*(h16 >> ':')) >> h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 + | qi::raw[qi::repeat(2)[*(h16 >> ':')] >> h16] >> "::" >> qi::repeat(2)[h16 >> ':'] >> ls32 + | qi::raw[qi::repeat(3)[*(h16 >> ':')] >> h16] >> "::" >> h16 >> ':' >> ls32 + | qi::raw[qi::repeat(4)[*(h16 >> ':')] >> h16] >> "::" >> ls32 + | qi::raw[qi::repeat(5)[*(h16 >> ':')] >> h16] >> "::" >> h16 + | qi::raw[qi::repeat(6)[*(h16 >> ':')] >> h16] >> "::" + + ]; + + // ls32 = ( h16 ":" h16 ) / IPv4address + ls32 %= (h16 >> ':' >> h16) | ipv4address + ; + + // h16 = 1*4HEXDIG + h16 %= qi::repeat(1, 4)[qi::xdigit] + ; + + // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 + dec_octet %= + !(qi::lit('0') >> qi::digit) + >> qi::raw[ + qi::uint_parser() + ]; + + // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet + ipv4address %= qi::raw[ + dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] + ]; + + // reg-name = *( unreserved / pct-encoded / sub-delims ) + reg_name %= qi::raw[ + *(unreserved | pct_encoded | sub_delims) + ]; + + // TODO, host = IP-literal / IPv4address / reg-name + host %= + iter_pos + >> qi::omit[ip_literal | ipv4address | reg_name] + >> iter_pos + ; + + // port %= qi::ushort_; + port %= + iter_pos + >> qi::omit[*qi::digit] + >> iter_pos + ; + + // query = *( pchar / "/" / "?" ) + query %= + iter_pos + >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] + >> iter_pos + ; + + // fragment = *( pchar / "/" / "?" ) + fragment %= + iter_pos + >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] + >> iter_pos + ; + + // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty + // authority = [ userinfo "@" ] host [ ":" port ] + hier_part %= + ( + "//" + >> -(user_info >> '@') + >> host + >> -(':' >> port) + >> path_abempty + ) + | + ( + qi::attr(iterator_range()) + >> qi::attr(iterator_range()) + >> qi::attr(iterator_range()) + >> ( + path_absolute + | path_rootless + | path_empty + ) + ) + ; + + start %= + scheme >> ':' + >> hier_part + >> -('?' >> query) + >> -('#' >> fragment) + ; + } + + qi::rule + gen_delims, sub_delims, reserved, unreserved; + qi::rule + pct_encoded, pchar; + + qi::rule + segment, segment_nz, segment_nz_nc; + qi::rule()> + path_abempty, path_absolute, path_rootless, path_empty; + + qi::rule + dec_octet, ipv4address, reg_name, ipv6address, ipvfuture, ip_literal; + + qi::rule + h16, ls32; + + qi::rule()> + host, port; + + qi::rule()> + scheme, user_info, query, fragment; + + qi::rule, + iterator_range, + iterator_range, + iterator_range >()> + hier_part; + + // actual uri parser + qi::rule()> start; + +}; + +bool parse(std::string::const_iterator first, + std::string::const_iterator last, + uri_parts &parts) { + namespace qi = boost::spirit::qi; + static detail::uri_grammar grammar; + bool is_valid = qi::parse(first, last, grammar, parts); + return is_valid && (first == last); +} + +bool parse(std::wstring::const_iterator first, + std::wstring::const_iterator last, + uri_parts &parts) { + namespace qi = boost::spirit::qi; + static uri_grammar grammar; + bool is_valid = qi::parse(first, last, grammar, parts); + return is_valid && (first == last); +} +} // namespace detail +} // namespace uri +} // namespace network +} // namespace boost diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index 092499b5a..343cf5697 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -22,11 +22,11 @@ if (Boost_FOUND) set_source_files_properties(${test}.cpp PROPERTIES COMPILE_FLAGS "-Wall") add_executable(cpp-netlib-${test} ${test}.cpp) - add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) + add_dependencies(cpp-netlib-${test} cppnetlib-uri) - # add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) - # target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + # add_dependencies(cpp-netlib-${test} cppnetlib-uri) + # target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) + target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) endif() diff --git a/libs/network/test/Jamfile.v2 b/libs/network/test/Jamfile.v2 index f9ea75977..c04d04fbe 100644 --- a/libs/network/test/Jamfile.v2 +++ b/libs/network/test/Jamfile.v2 @@ -49,6 +49,6 @@ build-project http ; run message_test.cpp ; run message_transform_test.cpp ; -run url_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run url_test.cpp /cpp-netlib//cppnetlib-uri ; run client_server_include_failure.cpp ; diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index aa20424ba..dcc3749cb 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -31,8 +31,8 @@ if (Boost_FOUND) PROPERTIES COMPILE_FLAGS "-Wall") endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) - add_dependencies(cpp-netlib-http-${test} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers cppnetlib-client-connections) + add_dependencies(cpp-netlib-http-${test} cppnetlib-uri) + target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) endif() diff --git a/libs/network/test/http/Jamfile.v2 b/libs/network/test/http/Jamfile.v2 index b62c5b0f5..c5f317858 100644 --- a/libs/network/test/http/Jamfile.v2 +++ b/libs/network/test/http/Jamfile.v2 @@ -15,21 +15,21 @@ project network_test/http : debug:BOOST_NETWORK_DEBUG ; -run client_constructor_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; -run client_get_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; -run client_get_different_port_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; -run client_get_timeout_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run client_constructor_test.cpp /cpp-netlib//cppnetlib-uri ; +run client_get_test.cpp /cpp-netlib//cppnetlib-uri ; +run client_get_different_port_test.cpp /cpp-netlib//cppnetlib-uri ; +run client_get_timeout_test.cpp /cpp-netlib//cppnetlib-uri ; run client_include_inlined.cpp : BOOST_NETWORK_NO_LIB ; -run client_localhost_normal_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; -run client_localhost_ssl_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run client_localhost_normal_test.cpp /cpp-netlib//cppnetlib-uri ; +run client_localhost_ssl_test.cpp /cpp-netlib//cppnetlib-uri ; run message_async_ready_test.cpp ; -run message_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run message_test.cpp /cpp-netlib//cppnetlib-uri ; run request_incremental_parser_test.cpp ; -run request_linearize_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run request_linearize_test.cpp /cpp-netlib//cppnetlib-uri ; run response_incremental_parser_test.cpp /cpp-netlib//cppnetlib-server-parsers ; run server_constructor_test.cpp /cpp-netlib//cppnetlib-server-parsers ; run server_include_inlined.cpp : BOOST_NETWORK_NO_LIB ; -run url_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run url_test.cpp /cpp-netlib//cppnetlib-uri ; exe http_async_server : server_async.cpp /cpp-netlib//cppnetlib-server-parsers ; exe hello_world : server_hello_world.cpp /cpp-netlib//cppnetlib-server-parsers ; diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index 7afc6ea36..ab2f012a8 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -21,8 +21,8 @@ if (Boost_FOUND) set_source_files_properties(${test}.cpp PROPERTIES COMPILE_FLAGS "-Wall") add_executable(cpp-netlib-${test} ${test}.cpp) - add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + add_dependencies(cpp-netlib-${test} cppnetlib-uri) + target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) endif() From 316c8cf4eef20be82d8fdc0dfd55b9d65501a033 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 17 Sep 2011 20:33:04 +0200 Subject: [PATCH 190/768] template is now a class . No support for std::wstring. --- boost/network/uri.hpp | 16 - boost/network/uri/accessors.hpp | 67 ++-- boost/network/uri/directives.hpp | 20 +- boost/network/uri/directives/authority.hpp | 28 +- boost/network/uri/directives/fragment.hpp | 30 +- boost/network/uri/directives/host.hpp | 24 +- boost/network/uri/directives/path.hpp | 61 +--- boost/network/uri/directives/port.hpp | 53 ++-- boost/network/uri/directives/query.hpp | 74 ++--- boost/network/uri/directives/scheme.hpp | 54 +--- boost/network/uri/directives/user_info.hpp | 26 +- boost/network/uri/uri.hpp | 170 ++++------ boost/network/uri/uri_io.hpp | 9 +- libs/network/test/uri/url_builder_test.cpp | 301 ++++++------------ libs/network/test/uri/url_encoding_test.cpp | 27 +- libs/network/test/uri/url_http_test.cpp | 61 ---- libs/network/test/uri/url_mailto_test.cpp | 30 -- libs/network/test/uri/url_test.cpp | 330 ++++++-------------- 18 files changed, 380 insertions(+), 1001 deletions(-) delete mode 100644 libs/network/test/uri/url_http_test.cpp delete mode 100644 libs/network/test/uri/url_mailto_test.cpp diff --git a/boost/network/uri.hpp b/boost/network/uri.hpp index 237818c65..e9ad1ffea 100644 --- a/boost/network/uri.hpp +++ b/boost/network/uri.hpp @@ -6,23 +6,7 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include #include -//#include -//#include - - -namespace boost { namespace network { namespace uri { - -typedef basic_uri uri; -typedef basic_uri wuri; - -//namespace http { -//typedef basic_uri uri; -//} -} // namespace uri -} // namespace network -} // namespace boost #endif diff --git a/boost/network/uri/accessors.hpp b/boost/network/uri/accessors.hpp index aa57c6f45..7b71862b3 100644 --- a/boost/network/uri/accessors.hpp +++ b/boost/network/uri/accessors.hpp @@ -20,14 +20,11 @@ namespace network { namespace uri { namespace details { template < - typename Uri, typename Map > struct key_value_sequence - : spirit::qi::grammar + : spirit::qi::grammar { - typedef typename Uri::const_iterator const_iterator; - key_value_sequence() : key_value_sequence::base_type(query) { @@ -37,79 +34,63 @@ struct key_value_sequence value = +spirit::qi::char_("a-zA-Z_0-9/%"); } - spirit::qi::rule query; - spirit::qi::rule()> pair; - spirit::qi::rule key, value; + spirit::qi::rule query; + spirit::qi::rule()> pair; + spirit::qi::rule key, value; }; } // namespace details template < - class String, class Map > inline -Map &query_map(const basic_uri &uri, Map &map) { - typename basic_uri::const_range_type range = uri.query_range(); - details::key_value_sequence, Map> parser; +Map &query_map(const uri &uri_, Map &map) { + uri::const_range_type range = uri_.query_range(); + details::key_value_sequence parser; spirit::qi::parse(boost::begin(range), boost::end(range), parser, map); return map; } -template < - class String - > -String username(const basic_uri &uri) { - typename basic_uri::const_range_type user_info_range = uri.user_info_range(); - typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); +std::string username(const uri &uri_) { + uri::const_range_type user_info_range = uri_.user_info_range(); + uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); for (; it != end; ++it) { if (*it == ':') { break; } } - return String(boost::begin(user_info_range), it); + return std::string(boost::begin(user_info_range), it); } -template < - class String - > -String password(const basic_uri &uri) { - typename basic_uri::const_range_type user_info_range = uri.user_info_range(); - typename basic_uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); +std::string password(const uri &uri_) { + uri::const_range_type user_info_range = uri_.user_info_range(); + uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); for (; it != end; ++it) { if (*it == ':') { ++it; break; } } - return String(it, boost::end(user_info_range)); + return std::string(it, boost::end(user_info_range)); } -template < - class String - > -String decoded_path(const basic_uri &uri) { - typename basic_uri::const_range_type path_range = uri.path_range(); - String decoded_path; +std::string decoded_path(const uri &uri_) { + uri::const_range_type path_range = uri_.path_range(); + std::string decoded_path; decode(path_range, std::back_inserter(decoded_path)); return decoded_path; } -template < - class String - > -String decoded_query(const basic_uri &uri) { - typename basic_uri::const_range_type query_range = uri.query_range(); - String decoded_query; +std::string decoded_query(const uri &uri_) { + uri::const_range_type query_range = uri_.query_range(); + std::string decoded_query; decode(query_range, std::back_inserter(decoded_query)); return decoded_query; } -template < - class String - > -String decoded_fragment(const basic_uri &uri) { - typename basic_uri::const_range_type fragment_range = uri.fragment_range(); - String decoded_fragment; +std::string decoded_fragment(const uri &uri_) { + uri::const_range_type fragment_range = uri_.fragment_range(); + std::string decoded_fragment; decode(fragment_range, std::back_inserter(decoded_fragment)); return decoded_fragment; } diff --git a/boost/network/uri/directives.hpp b/boost/network/uri/directives.hpp index e02a1a1da..632cf44db 100644 --- a/boost/network/uri/directives.hpp +++ b/boost/network/uri/directives.hpp @@ -16,25 +16,21 @@ namespace boost { namespace network { namespace uri { -template < - class String - > inline -basic_uri &operator << (basic_uri &uri, const basic_uri &root_uri) { - if (empty(uri) && valid(root_uri)) { - uri.append(boost::begin(root_uri), boost::end(root_uri)); +uri &operator << (uri &uri_, const uri &root_uri) { + if (empty(uri_) && valid(root_uri)) { + uri_.append(boost::begin(root_uri), boost::end(root_uri)); } - return uri; + return uri_; } template < - class String - , class Directive + class Directive > inline -basic_uri &operator << (basic_uri &uri, const Directive &directive) { - directive(uri); - return uri; +uri &operator << (uri &uri_, const Directive &directive) { + directive(uri_); + return uri_; } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/authority.hpp b/boost/network/uri/directives/authority.hpp index 7d0830a0f..3d1295a40 100644 --- a/boost/network/uri/directives/authority.hpp +++ b/boost/network/uri/directives/authority.hpp @@ -2,40 +2,26 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ -# include - - - namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct authority_directive { - explicit authority_directive(const ValueType &value) - : value(value) + explicit authority_directive(const std::string &authority) + : authority(authority) {} - template < - class Tag - , template class Uri - > - void operator () (Uri &uri) const { - uri.append(value); + void operator () (uri &uri_) const { + uri_.append(authority); } - const ValueType &value; + std::string authority; }; -template < - class T - > inline -authority_directive authority(const T &value) { - return authority_directive(value); +authority_directive authority(const std::string &authority) { + return authority_directive(authority); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/fragment.hpp b/boost/network/uri/directives/fragment.hpp index 49d980530..33c57c2f1 100644 --- a/boost/network/uri/directives/fragment.hpp +++ b/boost/network/uri/directives/fragment.hpp @@ -10,37 +10,27 @@ namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct fragment_directive { - explicit fragment_directive(const ValueType &value) - : value(value) + explicit fragment_directive(const std::string &fragment) + : fragment(fragment) {} - template < - class String - , template class Uri - > - void operator () (Uri &uri) const { - String encoded_value; + void operator () (uri &uri_) const { + std::string encoded_fragment; static const char separator[] = {'#'}; - uri.append(boost::begin(separator), boost::end(separator)); - encode(boost::as_literal(value), std::back_inserter(encoded_value)); - uri.append(encoded_value); + uri_.append(boost::begin(separator), boost::end(separator)); + encode(fragment, std::back_inserter(encoded_fragment)); + uri_.append(encoded_fragment); } - const ValueType &value; + std::string fragment; }; -template < - class T - > inline -fragment_directive fragment(const T &value) { - return fragment_directive(value); +fragment_directive fragment(const std::string &fragment) { + return fragment_directive(fragment); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/host.hpp b/boost/network/uri/directives/host.hpp index e251edb84..a7f72efaa 100644 --- a/boost/network/uri/directives/host.hpp +++ b/boost/network/uri/directives/host.hpp @@ -9,33 +9,23 @@ namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct host_directive { - explicit host_directive(const ValueType &value) - : value(value) + explicit host_directive(const std::string &host) + : host(host) {} - template < - class Tag - , template class Uri - > - void operator () (Uri &uri) const { - uri.append(value); + void operator () (uri &uri_) const { + uri_.append(host); } - const ValueType &value; + std::string host; }; -template < - class T - > inline -host_directive host(const T &value) { - return host_directive(value); +host_directive host(const std::string &host) { + return host_directive(host); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/path.hpp b/boost/network/uri/directives/path.hpp index f4a4bd99c..241fe9e3d 100644 --- a/boost/network/uri/directives/path.hpp +++ b/boost/network/uri/directives/path.hpp @@ -9,73 +9,44 @@ namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct path_directive { - explicit path_directive(const ValueType &value) - : value(value) + explicit path_directive(const std::string &path) + : path(path) {} - template < - class Tag - , template class Uri - > - void operator () (Uri &uri) const { - (*this)(boost::as_literal(value), uri); + void operator () (uri &uri_) const { + uri_.append(path); } - template < - class Rng - , class Tag - , template class Uri - > - void operator () (const Rng &rng, Uri &uri) const { - uri.append(boost::begin(rng), boost::end(rng)); - } - - const ValueType &value; + std::string path; }; -template < - class ValueType - > struct encoded_path_directive { - explicit encoded_path_directive(const ValueType &value) - : value(value) + explicit encoded_path_directive(const std::string &path) + : path(path) {} - template < - class StringT - , template class Uri - > - void operator () (Uri &uri) const { - StringT encoded_value; - encode(boost::as_literal(value), std::back_inserter(encoded_value)); - uri.append(encoded_value); + void operator () (uri &uri_) const { + std::string encoded_path; + encode(path, std::back_inserter(encoded_path)); + uri_.append(encoded_path); } - const ValueType &value; + std::string path; }; -template < - class T - > inline -path_directive path(const T &value) { - return path_directive(value); +path_directive path(const std::string &path) { + return path_directive(path); } -template < - class T - > inline -encoded_path_directive encoded_path(const T &value) { - return encoded_path_directive(value); +encoded_path_directive encoded_path(const std::string &path) { + return encoded_path_directive(path); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/port.hpp b/boost/network/uri/directives/port.hpp index 567208d64..a31711dea 100644 --- a/boost/network/uri/directives/port.hpp +++ b/boost/network/uri/directives/port.hpp @@ -2,9 +2,8 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ -# include -# include # include +# include # include # include @@ -12,64 +11,48 @@ namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct port_directive { - explicit port_directive(const ValueType &value) - : value(value) + explicit port_directive(const std::string &port) + : port(port) {} - template < - class String - , template class Uri - > - void operator () (Uri &uri) const { + void operator () (uri &uri_) const { static const char separator[] = {':'}; - uri.append(boost::begin(separator), boost::end(separator)); - uri.append(value); + uri_.append(boost::begin(separator), boost::end(separator)); + uri_.append(port); } - const ValueType &value; + std::string port; }; struct port_directive_us { - explicit port_directive_us(boost::uint16_t value) - : value(value) + explicit port_directive_us(boost::uint16_t port) + : port(port) {} - template < - class String - , template class Uri - > - void operator () (Uri &uri) const { + void operator () (uri &uri_) const { static const char separator[] = {':'}; - uri.append(boost::begin(separator), boost::end(separator)); - String port = boost::lexical_cast(value); - uri.append(port); + uri_.append(boost::begin(separator), boost::end(separator)); + std::string port_ = boost::lexical_cast(port); + uri_.append(port_); } - boost::uint16_t value; + boost::uint16_t port; }; - -template < - class T - > inline -port_directive port(const T &value, - typename boost::disable_if::type>::type * = 0) { - return port_directive(value); +port_directive port(const std::string &port) { + return port_directive(port); } inline -port_directive_us port(boost::uint16_t value) { - return port_directive_us(value); +port_directive_us port(boost::uint16_t port) { + return port_directive_us(port); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp index bb4cb7a27..39520f1e0 100644 --- a/boost/network/uri/directives/query.hpp +++ b/boost/network/uri/directives/query.hpp @@ -10,84 +10,62 @@ namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct query_directive { - explicit query_directive(const ValueType &value) - : value(value) + explicit query_directive(const std::string &query) + : query(query) {} - template < - class String - , template class Uri - > - void operator () (Uri &uri) const { - String encoded_value; + void operator () (uri &uri_) const { + std::string encoded_query; static const char separator[] = {'?'}; - uri.append(boost::begin(separator), boost::end(separator)); - uri.append(value); + uri_.append(boost::begin(separator), boost::end(separator)); + uri_.append(query); } - const ValueType &value; + std::string query; }; -template < - class T - > inline -query_directive query(const T &value) { - return query_directive(value); +query_directive query(const std::string &query) { + return query_directive(query); } -template < - class KeyType - , class ValueType - > -struct query_key_value_directive { +struct query_key_query_directive { - query_key_value_directive(const KeyType &key, const ValueType &value) - : key(key), value(value) + query_key_query_directive(const std::string &key, const std::string &query) + : key(key), query(query) {} - template < - class String - , template class Uri - > - void operator () (Uri &uri) const { - String encoded_key, encoded_value; + void operator () (uri &uri_) const { + std::string encoded_key, encoded_query; static const char qmark[] = {'?'}; static const char equal[] = {'='}; static const char scolon[] = {';'}; - if (!uri.query_range()) + if (!uri_.query_range()) { - uri.append(boost::begin(qmark), boost::end(qmark)); + uri_.append(boost::begin(qmark), boost::end(qmark)); } else { - uri.append(boost::begin(scolon), boost::end(scolon)); + uri_.append(boost::begin(scolon), boost::end(scolon)); } - encode(boost::as_literal(key), std::back_inserter(encoded_key)); - uri.append(encoded_key); - uri.append(boost::begin(equal), boost::end(equal)); - encode(boost::as_literal(value), std::back_inserter(encoded_value)); - uri.append(encoded_value); + encode(key, std::back_inserter(encoded_key)); + uri_.append(encoded_key); + uri_.append(boost::begin(equal), boost::end(equal)); + encode(query, std::back_inserter(encoded_query)); + uri_.append(encoded_query); } - const KeyType &key; - const ValueType &value; + std::string key; + std::string query; }; -template < - class Key - , class Value - > inline -query_key_value_directive query(const Key &key, const Value &value) { - return query_key_value_directive(key, value); +query_key_query_directive query(const std::string &key, const std::string &query) { + return query_key_query_directive(key, query); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/scheme.hpp b/boost/network/uri/directives/scheme.hpp index 27726ac30..764265e2a 100644 --- a/boost/network/uri/directives/scheme.hpp +++ b/boost/network/uri/directives/scheme.hpp @@ -9,64 +9,26 @@ namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct scheme_directive { - explicit scheme_directive(const ValueType &value) - : value(value) + explicit scheme_directive(const std::string &scheme) + : scheme(scheme) {} - template < - class Tag - , template class Uri - > - void operator () (Uri &uri) const { + void operator () (uri &uri_) const { static const char separator[] = {':', '/', '/'}; - uri.append(value); - uri.append(boost::begin(separator), boost::end(separator)); + uri_.append(scheme); + uri_.append(boost::begin(separator), boost::end(separator)); } - const ValueType &value; + std::string scheme; }; -template < - class T - > inline -scheme_directive scheme(const T &value) { - return scheme_directive(value); +scheme_directive scheme(const std::string &scheme) { + return scheme_directive(scheme); } - -namespace schemes { -struct scheme_helper { - - scheme_helper(const char *scheme) - : scheme(scheme) { - - } - - template < - class Tag - , template class Uri - > - void operator () (Uri &uri) const { - static const char separator[] = {':', '/', '/'}; - uri.append(boost::begin(scheme), boost::end(scheme)); - uri.append(boost::begin(separator), boost::end(separator)); - } - - std::string scheme; - -}; - -//static scheme_helper http("http"); -//static scheme_helper https("https"); -//static scheme_helper ftp("ftp"); -//static scheme_helper mailto("mailto"); -} // namespace schemes } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/user_info.hpp b/boost/network/uri/directives/user_info.hpp index 881700a6a..a900eed93 100644 --- a/boost/network/uri/directives/user_info.hpp +++ b/boost/network/uri/directives/user_info.hpp @@ -9,35 +9,25 @@ namespace boost { namespace network { namespace uri { -template < - class ValueType - > struct user_info_directive { - explicit user_info_directive(const ValueType &value) - : value(value) + explicit user_info_directive(const std::string &user_info) + : user_info(user_info) {} - template < - class Tag - , template class Uri - > - void operator () (Uri &uri) const { + void operator () (uri &uri_) const { static const char separator[] = {'@'}; - uri.append(value); - uri.append(boost::begin(separator), boost::end(separator)); + uri_.append(user_info); + uri_.append(boost::begin(separator), boost::end(separator)); } - const ValueType &value; + std::string user_info; }; -template < - class T - > inline -user_info_directive user_info(const T &value) { - return user_info_directive(value); +user_info_directive user_info(const std::string &user_info) { + return user_info_directive(user_info); } } // namespace uri } // namespace network diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index c26a10f5e..c2c7013dd 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -28,28 +28,21 @@ namespace detail { bool parse(std::string::const_iterator first, std::string::const_iterator last, uri_parts &parts); - -bool parse(std::wstring::const_iterator first, - std::wstring::const_iterator last, - uri_parts &parts); } // namespace detail -template < - class String - > -class basic_uri - : public boost::equality_comparable > { +class uri + : public boost::equality_comparable { public: - typedef String string_type; - typedef typename string_type::iterator iterator; + typedef std::string string_type; + typedef string_type::iterator iterator; typedef boost::iterator_range range_type; - typedef typename string_type::const_iterator const_iterator; + typedef string_type::const_iterator const_iterator; typedef boost::iterator_range const_range_type; - basic_uri() + uri() : is_valid_(false) { } @@ -57,38 +50,38 @@ class basic_uri template < class FwdIter > - basic_uri(const FwdIter &first, const FwdIter &last) + uri(const FwdIter &first, const FwdIter &last) : uri_(first, last), is_valid_(false) { parse(); } - basic_uri(const string_type &uri) + uri(const string_type &uri) : uri_(uri), is_valid_(false) { parse(); } - basic_uri(const basic_uri &other) + uri(const uri &other) : uri_(other.uri_), uri_parts_(other.uri_parts_), is_valid_(other.is_valid_) { } - basic_uri &operator = (const basic_uri &other) { - basic_uri(other).swap(*this); + uri &operator = (const uri &other) { + uri(other).swap(*this); return *this; } - basic_uri &operator = (const string_type &uri) { - basic_uri(uri).swap(*this); + uri &operator = (const string_type &uri_) { + uri(uri_).swap(*this); return *this; } - ~basic_uri() { + ~uri() { } - void swap(basic_uri &other) { + void swap(uri &other) { boost::swap(uri_, other.uri_); parse(); } @@ -212,168 +205,111 @@ class basic_uri void parse(); string_type uri_; - detail::uri_parts uri_parts_; + detail::uri_parts uri_parts_; bool is_valid_; }; -template < - class String - > inline -void basic_uri::parse() { +void uri::parse() { const_iterator first(boost::begin(uri_)), last(boost::end(uri_)); is_valid_ = detail::parse(first, last, uri_parts_); } -template < - class String - > inline -String scheme(const basic_uri &uri) { - return uri.scheme(); +std::string scheme(const uri &uri_) { + return uri_.scheme(); } -template < - class String - > inline -String user_info(const basic_uri &uri) { - return uri.user_info(); +std::string user_info(const uri &uri_) { + return uri_.user_info(); } -template < - class String - > inline -String host(const basic_uri &uri) { - return uri.host(); +std::string host(const uri &uri_) { + return uri_.host(); } -template < - class String - > inline -String port(const basic_uri &uri) { - return uri.port(); +std::string port(const uri &uri_) { + return uri_.port(); } -template < - class String - > inline -boost::optional port_us(const basic_uri &uri) { - String port = uri.port(); +boost::optional port_us(const uri &uri_) { + std::string port = uri_.port(); return (port.empty())? boost::optional() : boost::optional(boost::lexical_cast(port)); } -template < - class String - > inline -String path(const basic_uri &uri) { - return uri.path(); +std::string path(const uri &uri_) { + return uri_.path(); } -template < - class String - > inline -String query(const basic_uri &uri) { - return uri.query(); +std::string query(const uri &uri_) { + return uri_.query(); } -template < - class String - > inline -String fragment(const basic_uri &uri) { - return uri.fragment(); +std::string fragment(const uri &uri_) { + return uri_.fragment(); } -template < - class String - > inline -String authority(const basic_uri &uri) { - typename basic_uri::const_range_type user_info(uri.user_info_range()); - typename basic_uri::const_range_type port(uri.port_range()); - return String(user_info.begin(), port.end()); +std::string authority(const uri &uri_) { + uri::const_range_type user_info(uri_.user_info_range()); + uri::const_range_type port(uri_.port_range()); + return std::string(user_info.begin(), port.end()); } -template < - class String - > inline -String netloc(const basic_uri &uri) { - return authority(uri); +std::string netloc(const uri &uri_) { + return authority(uri_); } -template < - class String - > inline -bool valid(const basic_uri &uri) { - return uri.is_valid(); +bool valid(const uri &uri_) { + return uri_.is_valid(); } -template < - class String - > inline -bool is_valid(const basic_uri &uri) { - return valid(uri); +bool is_valid(const uri &uri_) { + return valid(uri_); } -template < - class String - > inline -bool operator == (const basic_uri &lhs, const basic_uri &rhs) { +bool operator == (const uri &lhs, const uri &rhs) { return std::equal(lhs.begin(), lhs.end(), rhs.begin()); } } // namespace uri } // namespace network -template < - class String - > inline -typename network::uri::basic_uri::iterator begin(network::uri::basic_uri &uri) { - return uri.begin(); +network::uri::uri::iterator begin(network::uri::uri &uri_) { + return uri_.begin(); } -template < - class String - > inline -typename network::uri::basic_uri::iterator end(network::uri::basic_uri &uri) { - return uri.end(); +network::uri::uri::iterator end(network::uri::uri &uri_) { + return uri_.end(); } -template < - class String - > inline -typename network::uri::basic_uri::const_iterator begin(const network::uri::basic_uri &uri) { - return uri.begin(); +network::uri::uri::const_iterator begin(const network::uri::uri &uri_) { + return uri_.begin(); } -template < - class String - > inline -typename network::uri::basic_uri::const_iterator end(const network::uri::basic_uri &uri) { - return uri.end(); +network::uri::uri::const_iterator end(const network::uri::uri &uri_) { + return uri_.end(); } -template < - class String - > inline -void swap(network::uri::basic_uri &lhs, network::uri::basic_uri &rhs) { +void swap(network::uri::uri &lhs, network::uri::uri &rhs) { lhs.swap(rhs); } } // namespace boost diff --git a/boost/network/uri/uri_io.hpp b/boost/network/uri/uri_io.hpp index 1b1f6f2cb..f900953d8 100644 --- a/boost/network/uri/uri_io.hpp +++ b/boost/network/uri/uri_io.hpp @@ -10,13 +10,8 @@ namespace boost { namespace network { namespace uri { inline -std::ostream &operator << (std::ostream &os, const basic_uri &uri) { - return os << uri.string(); -} - -inline -std::wostream &operator << (std::wostream &os, const basic_uri &uri) { - return os << uri.string(); +std::ostream &operator << (std::ostream &os, const uri &uri_) { + return os << uri_.string(); } } // namespace uri } // namespace network diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index 512277a1f..b9a35e9b6 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -19,257 +19,146 @@ using namespace boost::network; -typedef boost::mpl::list< - uri::uri - , uri::wuri - > uri_types; - -BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, uri_types) +BOOST_AUTO_TEST_CASE(builder_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string path("/"); - - uri_type instance; - //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); - instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << uri::host(string_type(boost::begin(host), boost::end(host))) - << uri::path(string_type(boost::begin(path), boost::end(path))) - ; + uri::uri instance; + instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_builder_test, T, uri_types) +BOOST_AUTO_TEST_CASE(full_uri_builder_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string user_info("user:password"); - const std::string host("www.example.com"); - const std::string port("80"); - const std::string path("/path"); - const std::string query("query"); - const std::string fragment("fragment"); - - uri_type instance; - instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << uri::user_info(string_type(boost::begin(user_info), boost::end(user_info))) - << uri::host(string_type(boost::begin(host), boost::end(host))) - << uri::port(string_type(boost::begin(port), boost::end(port))) - << uri::path(string_type(boost::begin(path), boost::end(path))) - << uri::query(string_type(boost::begin(query), boost::end(query))) - << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))) + uri::uri instance; + instance << uri::scheme("http") + << uri::user_info("user:password") + << uri::host("www.example.com") + << uri::port("80") + << uri::path("/path") + << uri::query("query") + << uri::fragment("fragment") ; BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::user_info(instance), "user:password"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); BOOST_CHECK(uri::port_us(instance)); BOOST_CHECK_EQUAL(uri::port_us(instance).get(), 80); - BOOST_CHECK(boost::equal(uri::port(instance), port)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::query(instance), query)); - BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); + BOOST_CHECK_EQUAL(uri::port(instance), "80"); + BOOST_CHECK_EQUAL(uri::path(instance), "/path"); + BOOST_CHECK_EQUAL(uri::query(instance), "query"); + BOOST_CHECK_EQUAL(uri::fragment(instance), "fragment"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(port_test, T, uri_types) +BOOST_AUTO_TEST_CASE(port_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string port("8000"); - const std::string path("/"); - - uri_type instance; - //instance << uri::scheme("http") << uri::host("www.example.com") << uri::port(8000) << uri::path("/"); - instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << uri::host(string_type(boost::begin(host), boost::end(host))) - << uri::port(8000) - << uri::path(string_type(boost::begin(path), boost::end(path))) - ; + uri::uri instance; + instance << uri::scheme("http") << uri::host("www.example.com") << uri::port(8000) << uri::path("/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::port(instance), port)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::port(instance), "8000"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, uri_types) +BOOST_AUTO_TEST_CASE(encoded_path_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string port("8000"); - const std::string encoded_path("/Path%20With%20%28Some%29%20Encoded%20Characters%21"); - const std::string decoded_path("/Path With (Some) Encoded Characters!"); - - uri_type instance; - instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << uri::host(string_type(boost::begin(host), boost::end(host))) + uri::uri instance; + instance << uri::scheme("http") + << uri::host("www.example.com") << uri::port(8000) - << uri::encoded_path(string_type(boost::begin(decoded_path), boost::end(decoded_path))) - //<< uri::path(uri::encoded(string_type(boost::begin(decoded_path), boost::end(decoded_path)))) + << uri::encoded_path("/Path%20With%20%28Some%29%20Encoded%20Characters%21") + //<< uri::path(uri::encoded("/Path%20With%20%28Some%29%20Encoded%20Characters%21") ; + std::cout << instance << std::endl; BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::port(instance), port)); - BOOST_CHECK(boost::equal(uri::path(instance), encoded_path)); - BOOST_CHECK(boost::equal(uri::decoded_path(instance), decoded_path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::port(instance), "8000"); + BOOST_CHECK_EQUAL(uri::path(instance), "/Path%20With%20%28Some%29%20Encoded%20Characters%21"); + BOOST_CHECK_EQUAL(uri::decoded_path(instance), "/Path With (Some) Encoded Characters!"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(query_test, T, uri_types) +BOOST_AUTO_TEST_CASE(query_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string path("/"); - const std::string query("key=value"); - const std::string query_key("key"); - const std::string query_value("value"); - - uri_type instance; - //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); - instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << uri::host(string_type(boost::begin(host), boost::end(host))) - << uri::path(string_type(boost::begin(path), boost::end(path))) - << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), - string_type(boost::begin(query_value), boost::end(query_value))); + uri::uri instance; + instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") + << uri::query("key", "value") + ; BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::query(instance), query)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); + BOOST_CHECK_EQUAL(uri::query(instance), "key=value"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(query_2_test, T, uri_types) +BOOST_AUTO_TEST_CASE(query_2_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string path("/"); - const std::string query("key=value;key=value"); - const std::string query_key("key"); - const std::string query_value("value"); - - uri_type instance; - //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); - instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << uri::host(string_type(boost::begin(host), boost::end(host))) - << uri::path(string_type(boost::begin(path), boost::end(path))) - << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), - string_type(boost::begin(query_value), boost::end(query_value))) - << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), - string_type(boost::begin(query_value), boost::end(query_value))); + uri::uri instance; + instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") + << uri::query("key1", "value1") << uri::query("key2", "value2") + ; BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::query(instance), query)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); + BOOST_CHECK_EQUAL(uri::query(instance), "key1=value1;key2=value2"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, uri_types) +BOOST_AUTO_TEST_CASE(fragment_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string path("/"); - const std::string fragment("fragment"); - - uri_type instance; - //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") << uri::fragment("fragment"); - instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) - << uri::host(string_type(boost::begin(host), boost::end(host))) - << uri::path(string_type(boost::begin(path), boost::end(path))) - << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))); + uri::uri instance; + instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") << uri::fragment("fragment"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); + BOOST_CHECK_EQUAL(uri::fragment(instance), "fragment"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(from_root_test, T, uri_types) +BOOST_AUTO_TEST_CASE(from_root_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string root("http://www.example.com/"); - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string path("/"); - const std::string fragment("fragment"); - - uri_type root_uri(boost::begin(root), boost::end(root)); - uri_type instance; - //instance << uri::uri("http://www.example.com/") << uri::path("/") << uri::fragment("fragment"); - instance << root_uri - << uri::path(string_type(boost::begin(path), boost::end(path))) - << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))); + uri::uri root_uri("http://www.example.com/"); + uri::uri instance; + instance << root_uri << uri::path("/") << uri::fragment("fragment"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); + BOOST_CHECK_EQUAL(uri::fragment(instance), "fragment"); } -//BOOST_AUTO_TEST_CASE_TEMPLATE(scheme_test, T, uri_types) +//BOOST_AUTO_TEST_CASE(scheme_test) +//{ +// uri_type instance; +// instance << uri::schemes::http << uri::host("www.example.com") << uri::path("/"); +// BOOST_REQUIRE(uri::valid(instance)); +// BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); +// BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); +// BOOST_CHECK_EQUAL(uri::path(instance), "/"); +//} + +//BOOST_AUTO_TEST_CASE(encoded_null_char_test) //{ -// typedef T uri_type; -// typedef typename uri_type::string_type string_type; +// typedef uri::uri uri_type; +// typedef uri_type::string_type string_type; // // const std::string scheme("http"); // const std::string host("www.example.com"); // const std::string path("/"); // // uri_type instance; -// //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); -// instance << uri::schemes::http -// << uri::host(string_type(boost::begin(host), boost::end(host))) -// << uri::path(string_type(boost::begin(path), boost::end(path))) +// // there is a potential bug in the way we process ranges if the +// // strings are null terminated. +// instance << uri::scheme("http") +// << uri::host("www.example.com") +// << uri::encoded_path("/") // ; // BOOST_REQUIRE(uri::valid(instance)); -// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); -// BOOST_CHECK(boost::equal(uri::host(instance), host)); -// BOOST_CHECK(boost::equal(uri::path(instance), path)); +// BOOST_CHECK_EQUAL(uri::scheme(instance), scheme); +// BOOST_CHECK_EQUAL(uri::host(instance), host); +// BOOST_CHECK_EQUAL(uri::path(instance), path); //} - -BOOST_AUTO_TEST_CASE(encoded_null_char_test) -{ - typedef uri::uri uri_type; - typedef uri_type::string_type string_type; - - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string path("/"); - - uri_type instance; - // there is a potential bug in the way we process ranges if the - // strings are null terminated. - instance << uri::scheme("http") - << uri::host("www.example.com") - << uri::encoded_path("/") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), scheme); - BOOST_CHECK_EQUAL(uri::host(instance), host); - BOOST_CHECK_EQUAL(uri::path(instance), path); -} diff --git a/libs/network/test/uri/url_encoding_test.cpp b/libs/network/test/uri/url_encoding_test.cpp index bc08f8c1c..6ca37939b 100644 --- a/libs/network/test/uri/url_encoding_test.cpp +++ b/libs/network/test/uri/url_encoding_test.cpp @@ -8,41 +8,26 @@ #include #include #include -#include -#include -#include -#include -#include #include using namespace boost::network; -typedef boost::mpl::list< - tags::default_string - , tags::default_wstring - > tag_types; - - -BOOST_AUTO_TEST_CASE_TEMPLATE(encoding_test, T, tag_types) { - typedef typename string::type string_type; +BOOST_AUTO_TEST_CASE(encoding_test) { const std::string unencoded(" !\"#$%&\'()*"); const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A"); - string_type instance; + std::string instance; uri::encode(unencoded, std::back_inserter(instance)); - BOOST_CHECK(boost::equal(instance, encoded)); + BOOST_CHECK_EQUAL(instance, encoded); } - -BOOST_AUTO_TEST_CASE_TEMPLATE(decoding_test, T, tag_types) { - typedef typename string::type string_type; - +BOOST_AUTO_TEST_CASE(decoding_test) { const std::string unencoded(" !\"#$%&\'()*"); const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A"); - string_type instance; + std::string instance; uri::decode(encoded, std::back_inserter(instance)); - BOOST_CHECK(boost::equal(instance, unencoded)); + BOOST_CHECK_EQUAL(instance, unencoded); } diff --git a/libs/network/test/uri/url_http_test.cpp b/libs/network/test/uri/url_http_test.cpp deleted file mode 100644 index ed162df89..000000000 --- a/libs/network/test/uri/url_http_test.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#define BOOST_TEST_MODULE HTTP URL Test -#include -#include -#include -#include -#include - -using namespace boost::network; - -typedef boost::mpl::list< - tags::default_string - , tags::default_wstring - > tag_types; - - -BOOST_AUTO_TEST_CASE_TEMPLATE(valid_http, T, tag_types) -{ - typedef uri::http::basic_uri uri_type; - typedef typename uri_type::string_type string_type; - const std::string url("http://example.com/"); - uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_http(instance)); - BOOST_REQUIRE(uri::is_valid(instance)); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(valid_https, T, tag_types) -{ - typedef uri::http::basic_uri uri_type; - typedef typename uri_type::string_type string_type; - const std::string url("https://example.com/"); - uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_https(instance)); - BOOST_REQUIRE(uri::is_valid(instance)); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(invalid_https, T, tag_types) -{ - typedef uri::http::basic_uri uri_type; - typedef typename uri_type::string_type string_type; - const std::string url("http://example.com/"); - uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(!uri::is_https(instance)); - BOOST_REQUIRE(uri::is_valid(instance)); -} - -BOOST_AUTO_TEST_CASE_TEMPLATE(not_http, T, tag_types) -{ - typedef uri::http::basic_uri uri_type; - typedef typename uri_type::string_type string_type; - const std::string url("/service/mailto:john.doe@example.com"); - uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(!uri::is_http(instance)); - BOOST_REQUIRE(!uri::is_https(instance)); - BOOST_REQUIRE(!uri::is_valid(instance)); -} diff --git a/libs/network/test/uri/url_mailto_test.cpp b/libs/network/test/uri/url_mailto_test.cpp deleted file mode 100644 index 8765748fe..000000000 --- a/libs/network/test/uri/url_mailto_test.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Glyn Matthews 2011. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - - -#define BOOST_TEST_MODULE mailto URL Test -#include -#include -#include -#include -#include - -using namespace boost::network; - -typedef boost::mpl::list< - tags::default_string - , tags::default_wstring - > tag_types; - - -BOOST_AUTO_TEST_CASE_TEMPLATE(valid_mailto, T, tag_types) -{ - typedef uri::mailto::basic_uri uri_type; - typedef typename uri_type::string_type string_type; - const std::string url("/service/mailto:john.doe@example.com"); - uri_type instance(string_type(boost::begin(url), boost::end(url))); - BOOST_REQUIRE(uri::is_mailto(instance)); - BOOST_REQUIRE(uri::is_valid(instance)); -} diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index 091d96559..700cfc5f9 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -8,319 +8,173 @@ #include #include #include -#include -#include +#include #include -#include -#include #include using namespace boost::network; -typedef boost::mpl::list< - uri::uri - , uri::wuri - > uri_types; - -BOOST_AUTO_TEST_CASE_TEMPLATE(uri_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://www.example.com/"); - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string path("/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(uri_test) { + uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://user:password@www.example.com/path?query#fragment"); - const std::string scheme("http"); - const std::string user_info("user:password"); - const std::string host("www.example.com"); - const std::string port = "80"; - const std::string path("/path"); - const std::string query("query"); - const std::string fragment("fragment"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(full_uri_test) { + uri::uri instance("http://user:password@www.example.com/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::user_info(instance), "user:password"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); BOOST_CHECK(uri::port_us(instance)); BOOST_CHECK_EQUAL(uri::port_us(instance).get(), 80); - BOOST_CHECK(boost::equal(uri::port(instance), port)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::query(instance), query)); - BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); + BOOST_CHECK_EQUAL(uri::port(instance), "80"); + BOOST_CHECK_EQUAL(uri::path(instance), "/path"); + BOOST_CHECK_EQUAL(uri::query(instance), "query"); + BOOST_CHECK_EQUAL(uri::fragment(instance), "fragment"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(mailto_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/mailto:john.doe@example.com"); - const std::string scheme("mailto"); - // RFC 3986 interprets this as the path - const std::string path("john.doe@example.com"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(mailto_test) { + uri::uri instance("mailto:john.doe@example.com"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "mailto"); + BOOST_CHECK_EQUAL(uri::path(instance), "john.doe@example.com"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(file_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/file:///bin/bash"); - const std::string scheme("file"); - const std::string path("/bin/bash"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(file_test) { + uri::uri instance("file:///bin/bash"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "file"); + BOOST_CHECK_EQUAL(uri::path(instance), "/bin/bash"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/xmpp:example-node@example.com?message;subject=Hello%20World"); - const std::string scheme("xmpp"); - // RFC 3986 interprets this as the path - const std::string path("example-node@example.com"); - const std::string query("message;subject=Hello%20World"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(xmpp_test) { + uri::uri instance("xmpp:example-node@example.com?message;subject=Hello%20World"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); - BOOST_CHECK(boost::equal(uri::query(instance), query)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "xmpp"); + BOOST_CHECK_EQUAL(uri::path(instance), "example-node@example.com"); + BOOST_CHECK_EQUAL(uri::query(instance), "message;subject=Hello%20World"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://129.79.245.252/"); - const std::string scheme("http"); - const std::string host("129.79.245.252"); - const std::string path("/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(ipv4_address_test) { + uri::uri instance("http://129.79.245.252/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "129.79.245.252"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_1, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://[1080::8:800:200c:417a]/"); - const std::string scheme("http"); - const std::string host("[1080:0:0:0:8:800:200C:417A]"); - const std::string path("/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(ipv6_address_test_1) { + uri::uri instance("http://[1080::8:800:200c:417a]/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "[1080:0:0:0:8:800:200C:417A]"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_2, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/"); - const std::string scheme("http"); - const std::string host("[2001:db8:85a3:8d3:1319:8a2e:370:7348]"); - const std::string path("/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(ipv6_address_test_2) { + uri::uri instance("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "[2001:db8:85a3:8d3:1319:8a2e:370:7348]"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(ftp_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/ftp://john.doe@ftp.example.com/"); - const std::string scheme("ftp"); - const std::string user_info("john.doe"); - const std::string host("ftp.example.com"); - const std::string path("/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(ftp_test) { + uri::uri instance("ftp://john.doe@ftp.example.com/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "ftp"); + BOOST_CHECK_EQUAL(uri::user_info(instance), "john.doe"); + BOOST_CHECK_EQUAL(uri::host(instance), "ftp.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(news_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/news:comp.infosystems.www.servers.unix"); - const std::string scheme("news"); - const std::string path("comp.infosystems.www.servers.unix"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(news_test) { + uri::uri instance("news:comp.infosystems.www.servers.unix"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "news"); + BOOST_CHECK_EQUAL(uri::path(instance), "comp.infosystems.www.servers.unix"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(tel_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/tel:+1-816-555-1212"); - const std::string scheme("tel"); - const std::string path("+1-816-555-1212"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(tel_test) { + uri::uri instance("tel:+1-816-555-1212"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "tel"); + BOOST_CHECK_EQUAL(uri::path(instance), "+1-816-555-1212"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_uri_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://www.example.com/Path%20With%20%28Some%29%20Encoded%20Characters%21"); - const std::string scheme("http"); - const std::string host("www.example.com"); - const std::string encoded_path("/Path%20With%20%28Some%29%20Encoded%20Characters%21"); - const std::string decoded_path("/Path With (Some) Encoded Characters!"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(encoded_uri_test) { + uri::uri instance("http://www.example.com/Path%20With%20%28Some%29%20Encoded%20Characters%21"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); - BOOST_CHECK(boost::equal(uri::host(instance), host)); - BOOST_CHECK(boost::equal(uri::path(instance), encoded_path)); - BOOST_CHECK(boost::equal(uri::decoded_path(instance), decoded_path)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/Path%20With%20%28Some%29%20Encoded%20Characters%21"); + BOOST_CHECK_EQUAL(uri::decoded_path(instance), "/Path With (Some) Encoded Characters!"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(copy_constructor_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://www.example.com/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); - uri_type copy = instance; +BOOST_AUTO_TEST_CASE(copy_constructor_test) { + uri::uri instance("http://www.example.com/"); + uri::uri copy = instance; BOOST_CHECK(instance == copy); } -BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://www.example.com/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); - uri_type copy; +BOOST_AUTO_TEST_CASE(assignment_test) { + uri::uri instance("http://www.example.com/"); + uri::uri copy; copy = instance; - BOOST_CHECK(instance.string() == copy.string()); - BOOST_CHECK(instance == copy); + BOOST_CHECK_EQUAL(instance.string(), copy.string()); + BOOST_CHECK_EQUAL(instance, copy); } -BOOST_AUTO_TEST_CASE_TEMPLATE(username_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/ftp://john.doe:password@ftp.example.com/"); - const std::string scheme("http"); - const std::string username("john.doe"); - const std::string password("password"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(username_test) { + uri::uri instance("ftp://john.doe:password@ftp.example.com/"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::username(instance), username)); - BOOST_CHECK(boost::equal(uri::password(instance), password)); + BOOST_CHECK_EQUAL(uri::username(instance), "john.doe"); + BOOST_CHECK_EQUAL(uri::password(instance), "password"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(authority_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://user:password@www.example.com/path?query#fragment"); - const std::string authority("user:password@www.example.com:80"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(authority_test) { + uri::uri instance("http://user:password@www.example.com/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(uri::authority(instance), authority)); + BOOST_CHECK_EQUAL(uri::authority(instance), "user:password@www.example.com:80"); } -BOOST_AUTO_TEST_CASE_TEMPLATE(http_query_map_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("http://user:password@www.example.com/path?query#fragment"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(http_query_map_test) { + uri::uri instance("http://user:password@www.example.com/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); const std::string key("query"); const std::string value; - std::map queries; + std::map queries; uri::query_map(instance, queries); BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(1)); - BOOST_CHECK(boost::equal(queries.begin()->first, key)); - BOOST_CHECK(boost::equal(queries.begin()->second, value)); + BOOST_CHECK_EQUAL(queries.begin()->first, key); + BOOST_CHECK_EQUAL(queries.begin()->second, value); } -BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, uri_types) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - - const std::string url("/service/xmpp:example-node@example.com?message;subject=Hello%20World"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); +BOOST_AUTO_TEST_CASE(xmpp_query_map_test) { + uri::uri instance("xmpp:example-node@example.com?message;subject=Hello%20World"); BOOST_REQUIRE(uri::valid(instance)); const std::string key_1("message"), key_2("subject"); const std::string value_1, value_2("Hello%20World"); - std::map queries; + std::map queries; uri::query_map(instance, queries); BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(2)); - BOOST_CHECK(boost::equal(queries.begin()->first, key_1)); - BOOST_CHECK(boost::equal(queries.begin()->second, value_1)); - BOOST_CHECK(boost::equal((++queries.begin())->first, key_2)); - BOOST_CHECK(boost::equal((++queries.begin())->second, value_2)); + BOOST_CHECK_EQUAL(queries.begin()->first, key_1); + BOOST_CHECK_EQUAL(queries.begin()->second, value_1); + BOOST_CHECK_EQUAL((++queries.begin())->first, key_2); + BOOST_CHECK_EQUAL((++queries.begin())->second, value_2); } -BOOST_AUTO_TEST_CASE_TEMPLATE(range_test, T, uri_types) +BOOST_AUTO_TEST_CASE(range_test) { - typedef T uri_type; - typedef typename uri_type::string_type string_type; - const std::string url("http://www.example.com/"); - - uri_type instance(string_type(boost::begin(url), boost::end(url))); + uri::uri instance(url); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(instance, url)); } From 5b11b29e428e07e4650732d3b5e8317e678cd034 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 18 Sep 2011 10:25:08 +0200 Subject: [PATCH 191/768] Cleaned up the URI tests a little further. --- boost/network/uri/directives/authority.hpp | 7 +++- boost/network/uri/directives/fragment.hpp | 12 +++--- boost/network/uri/directives/host.hpp | 7 +++- boost/network/uri/directives/path.hpp | 7 +++- boost/network/uri/directives/port.hpp | 34 ++++++---------- boost/network/uri/directives/query.hpp | 33 ++++++++-------- boost/network/uri/directives/scheme.hpp | 10 +++-- boost/network/uri/directives/user_info.hpp | 10 +++-- boost/network/uri/uri.hpp | 15 +++++++ libs/network/test/uri/url_builder_test.cpp | 40 ++++++++----------- libs/network/test/uri/url_test.cpp | 46 ++++++++++++++++------ 11 files changed, 125 insertions(+), 96 deletions(-) diff --git a/boost/network/uri/directives/authority.hpp b/boost/network/uri/directives/authority.hpp index 3d1295a40..807de4af7 100644 --- a/boost/network/uri/directives/authority.hpp +++ b/boost/network/uri/directives/authority.hpp @@ -11,8 +11,11 @@ struct authority_directive { : authority(authority) {} - void operator () (uri &uri_) const { - uri_.append(authority); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append(authority); } std::string authority; diff --git a/boost/network/uri/directives/fragment.hpp b/boost/network/uri/directives/fragment.hpp index 33c57c2f1..0beadd421 100644 --- a/boost/network/uri/directives/fragment.hpp +++ b/boost/network/uri/directives/fragment.hpp @@ -16,12 +16,12 @@ struct fragment_directive { : fragment(fragment) {} - void operator () (uri &uri_) const { - std::string encoded_fragment; - static const char separator[] = {'#'}; - uri_.append(boost::begin(separator), boost::end(separator)); - encode(fragment, std::back_inserter(encoded_fragment)); - uri_.append(encoded_fragment); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append("#"); + uri.append(fragment); } std::string fragment; diff --git a/boost/network/uri/directives/host.hpp b/boost/network/uri/directives/host.hpp index a7f72efaa..75cf1d038 100644 --- a/boost/network/uri/directives/host.hpp +++ b/boost/network/uri/directives/host.hpp @@ -15,8 +15,11 @@ struct host_directive { : host(host) {} - void operator () (uri &uri_) const { - uri_.append(host); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append(host); } std::string host; diff --git a/boost/network/uri/directives/path.hpp b/boost/network/uri/directives/path.hpp index 241fe9e3d..4921a3eb2 100644 --- a/boost/network/uri/directives/path.hpp +++ b/boost/network/uri/directives/path.hpp @@ -15,8 +15,11 @@ struct path_directive { : path(path) {} - void operator () (uri &uri_) const { - uri_.append(path); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append(path); } std::string path; diff --git a/boost/network/uri/directives/port.hpp b/boost/network/uri/directives/port.hpp index a31711dea..9e561486b 100644 --- a/boost/network/uri/directives/port.hpp +++ b/boost/network/uri/directives/port.hpp @@ -17,31 +17,19 @@ struct port_directive { : port(port) {} - void operator () (uri &uri_) const { - static const char separator[] = {':'}; - uri_.append(boost::begin(separator), boost::end(separator)); - uri_.append(port); - } - - std::string port; - -}; - - -struct port_directive_us { - - explicit port_directive_us(boost::uint16_t port) - : port(port) + explicit port_directive(boost::uint16_t port) + : port(boost::lexical_cast(port)) {} - void operator () (uri &uri_) const { - static const char separator[] = {':'}; - uri_.append(boost::begin(separator), boost::end(separator)); - std::string port_ = boost::lexical_cast(port); - uri_.append(port_); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append(":"); + uri.append(port); } - boost::uint16_t port; + std::string port; }; @@ -51,8 +39,8 @@ port_directive port(const std::string &port) { } inline -port_directive_us port(boost::uint16_t port) { - return port_directive_us(port); +port_directive port(boost::uint16_t port) { + return port_directive(port); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp index 39520f1e0..d2afbcadf 100644 --- a/boost/network/uri/directives/query.hpp +++ b/boost/network/uri/directives/query.hpp @@ -16,11 +16,12 @@ struct query_directive { : query(query) {} - void operator () (uri &uri_) const { - std::string encoded_query; - static const char separator[] = {'?'}; - uri_.append(boost::begin(separator), boost::end(separator)); - uri_.append(query); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append("?"); + uri.append(query); } std::string query; @@ -38,24 +39,22 @@ struct query_key_query_directive { : key(key), query(query) {} - void operator () (uri &uri_) const { + template < + class Uri + > + void operator () (Uri &uri) const { std::string encoded_key, encoded_query; - static const char qmark[] = {'?'}; - static const char equal[] = {'='}; - static const char scolon[] = {';'}; - if (!uri_.query_range()) + if (!uri.query_range()) { - uri_.append(boost::begin(qmark), boost::end(qmark)); + uri.append("?"); } else { - uri_.append(boost::begin(scolon), boost::end(scolon)); + uri.append(";"); } - encode(key, std::back_inserter(encoded_key)); - uri_.append(encoded_key); - uri_.append(boost::begin(equal), boost::end(equal)); - encode(query, std::back_inserter(encoded_query)); - uri_.append(encoded_query); + uri.append(key); + uri.append("="); + uri.append(query); } std::string key; diff --git a/boost/network/uri/directives/scheme.hpp b/boost/network/uri/directives/scheme.hpp index 764265e2a..708436006 100644 --- a/boost/network/uri/directives/scheme.hpp +++ b/boost/network/uri/directives/scheme.hpp @@ -15,10 +15,12 @@ struct scheme_directive { : scheme(scheme) {} - void operator () (uri &uri_) const { - static const char separator[] = {':', '/', '/'}; - uri_.append(scheme); - uri_.append(boost::begin(separator), boost::end(separator)); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append(scheme); + uri.append("://"); } std::string scheme; diff --git a/boost/network/uri/directives/user_info.hpp b/boost/network/uri/directives/user_info.hpp index a900eed93..cd7e7e788 100644 --- a/boost/network/uri/directives/user_info.hpp +++ b/boost/network/uri/directives/user_info.hpp @@ -15,10 +15,12 @@ struct user_info_directive { : user_info(user_info) {} - void operator () (uri &uri_) const { - static const char separator[] = {'@'}; - uri_.append(user_info); - uri_.append(boost::begin(separator), boost::end(separator)); + template < + class Uri + > + void operator () (Uri &uri) const { + uri.append(user_info); + uri.append("@"); } std::string user_info; diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index c2c7013dd..3332d86a6 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -281,6 +281,21 @@ bool is_valid(const uri &uri_) { return valid(uri_); } +inline +bool is_hierarchical(const uri &uri_) { + //uri::const_range_type scheme = uri_.scheme_range(); + //uri::const_range_type user_info = uri_.user_info_range(); + //return is_valid(uri_) && + // boost::equal(std::make_pair(boost::end(scheme), + // boost::begin(user_info)), + // boost::as_literal("://")); + return false; +} + +bool is_opaque(const uri &uri_) { + return false; +} + inline bool operator == (const uri &lhs, const uri &rhs) { return std::equal(lhs.begin(), lhs.end(), rhs.begin()); diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index b9a35e9b6..fb55e96ad 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -70,10 +70,9 @@ BOOST_AUTO_TEST_CASE(encoded_path_test) instance << uri::scheme("http") << uri::host("www.example.com") << uri::port(8000) - << uri::encoded_path("/Path%20With%20%28Some%29%20Encoded%20Characters%21") - //<< uri::path(uri::encoded("/Path%20With%20%28Some%29%20Encoded%20Characters%21") + << uri::encoded_path("/Path With (Some) Encoded Characters!") + ; ; - std::cout << instance << std::endl; BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); @@ -141,24 +140,17 @@ BOOST_AUTO_TEST_CASE(from_root_test) // BOOST_CHECK_EQUAL(uri::path(instance), "/"); //} -//BOOST_AUTO_TEST_CASE(encoded_null_char_test) -//{ -// typedef uri::uri uri_type; -// typedef uri_type::string_type string_type; -// -// const std::string scheme("http"); -// const std::string host("www.example.com"); -// const std::string path("/"); -// -// uri_type instance; -// // there is a potential bug in the way we process ranges if the -// // strings are null terminated. -// instance << uri::scheme("http") -// << uri::host("www.example.com") -// << uri::encoded_path("/") -// ; -// BOOST_REQUIRE(uri::valid(instance)); -// BOOST_CHECK_EQUAL(uri::scheme(instance), scheme); -// BOOST_CHECK_EQUAL(uri::host(instance), host); -// BOOST_CHECK_EQUAL(uri::path(instance), path); -//} +BOOST_AUTO_TEST_CASE(encoded_null_char_test) +{ + // there is a potential bug in the way we process ranges if the + // strings are null terminated. + uri::uri instance; + instance << uri::scheme("http") + << uri::host("www.example.com") + << uri::encoded_path("/") + ; + BOOST_REQUIRE(uri::valid(instance)); + BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::path(instance), "/"); +} diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index 700cfc5f9..e48146a49 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -16,9 +16,35 @@ using namespace boost::network; -BOOST_AUTO_TEST_CASE(uri_test) { +BOOST_AUTO_TEST_CASE(basic_uri_range_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); + BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); + BOOST_CHECK(boost::equal(instance.user_info_range(), boost::as_literal(""))); + BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); + BOOST_CHECK(boost::equal(instance.port_range(), boost::as_literal(""))); + BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/"))); + BOOST_CHECK(boost::equal(instance.query_range(), boost::as_literal(""))); + BOOST_CHECK(boost::equal(instance.fragment_range(), boost::as_literal(""))); +} + +BOOST_AUTO_TEST_CASE(full_uri_range_test) { + uri::uri instance("http://user:password@www.example.com/path?query#fragment"); + BOOST_REQUIRE(uri::valid(instance)); + BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); + BOOST_CHECK(boost::equal(instance.user_info_range(), boost::as_literal("user:password"))); + BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); + BOOST_CHECK(boost::equal(instance.port_range(), boost::as_literal("80"))); + BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/path"))); + BOOST_CHECK(boost::equal(instance.query_range(), boost::as_literal("query"))); + BOOST_CHECK(boost::equal(instance.fragment_range(), boost::as_literal("fragment"))); +} + +BOOST_AUTO_TEST_CASE(basic_uri_test) { + uri::uri instance("http://www.example.com/"); + uri::uri::const_range_type scheme = instance.scheme_range(); + uri::uri::const_range_type user_info = instance.host_range(); + BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); BOOST_CHECK_EQUAL(uri::path(instance), "/"); @@ -144,31 +170,27 @@ BOOST_AUTO_TEST_CASE(authority_test) { } BOOST_AUTO_TEST_CASE(http_query_map_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); + uri::uri instance("http://user:password@www.example.com/path?query=something#fragment"); BOOST_REQUIRE(uri::valid(instance)); - const std::string key("query"); - const std::string value; std::map queries; uri::query_map(instance, queries); BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(1)); - BOOST_CHECK_EQUAL(queries.begin()->first, key); - BOOST_CHECK_EQUAL(queries.begin()->second, value); + BOOST_CHECK_EQUAL(queries.begin()->first, "query"); + BOOST_CHECK_EQUAL(queries.begin()->second, "something"); } BOOST_AUTO_TEST_CASE(xmpp_query_map_test) { uri::uri instance("xmpp:example-node@example.com?message;subject=Hello%20World"); BOOST_REQUIRE(uri::valid(instance)); - const std::string key_1("message"), key_2("subject"); - const std::string value_1, value_2("Hello%20World"); std::map queries; uri::query_map(instance, queries); BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(2)); - BOOST_CHECK_EQUAL(queries.begin()->first, key_1); - BOOST_CHECK_EQUAL(queries.begin()->second, value_1); - BOOST_CHECK_EQUAL((++queries.begin())->first, key_2); - BOOST_CHECK_EQUAL((++queries.begin())->second, value_2); + BOOST_CHECK_EQUAL(queries.begin()->first, "message"); + BOOST_CHECK_EQUAL(queries.begin()->second, ""); + BOOST_CHECK_EQUAL((++queries.begin())->first, "subject"); + BOOST_CHECK_EQUAL((++queries.begin())->second, "Hello%20World"); } BOOST_AUTO_TEST_CASE(range_test) From d4091d3a447a7288abce9ef6279a9ffcf9883b44 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 18 Sep 2011 16:47:36 +0200 Subject: [PATCH 192/768] Minor clarifications in URI test. --- libs/network/test/uri/url_test.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index e48146a49..a6ab8e125 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -20,12 +20,12 @@ BOOST_AUTO_TEST_CASE(basic_uri_range_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); - BOOST_CHECK(boost::equal(instance.user_info_range(), boost::as_literal(""))); + BOOST_CHECK(boost::empty(instance.user_info_range())); BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); - BOOST_CHECK(boost::equal(instance.port_range(), boost::as_literal(""))); + BOOST_CHECK(boost::empty(instance.port_range())); BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/"))); - BOOST_CHECK(boost::equal(instance.query_range(), boost::as_literal(""))); - BOOST_CHECK(boost::equal(instance.fragment_range(), boost::as_literal(""))); + BOOST_CHECK(boost::empty(instance.query_range())); + BOOST_CHECK(boost::empty(instance.fragment_range())); } BOOST_AUTO_TEST_CASE(full_uri_range_test) { @@ -42,8 +42,6 @@ BOOST_AUTO_TEST_CASE(full_uri_range_test) { BOOST_AUTO_TEST_CASE(basic_uri_test) { uri::uri instance("http://www.example.com/"); - uri::uri::const_range_type scheme = instance.scheme_range(); - uri::uri::const_range_type user_info = instance.host_range(); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); From fdfeeb8aac9518d380a56cf78d47eb54477038d7 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Tue, 27 Sep 2011 22:16:16 +0200 Subject: [PATCH 193/768] Added test and applied fix for issue #67. --- boost/network/uri/uri.hpp | 5 +++-- libs/network/test/uri/url_test.cpp | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 3332d86a6..0e6371d81 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -72,8 +72,9 @@ class uri return *this; } - uri &operator = (const string_type &uri_) { - uri(uri_).swap(*this); + uri &operator = (const string_type &uri) { + uri_ = uri; + parse(); return *this; } diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index a6ab8e125..e56f4a327 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -198,3 +198,13 @@ BOOST_AUTO_TEST_CASE(range_test) BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK(boost::equal(instance, url)); } + +BOOST_AUTO_TEST_CASE(issue_67_test) +{ + const std::string site_name("http://www.google.com/"); + uri::uri bar0; + uri::uri bar1 = site_name; + bar0 = site_name; + BOOST_CHECK(uri::is_valid(bar0)); + BOOST_CHECK(uri::is_valid(bar1)); +} From 553ecede12e390cbba9d59ff395333aca31878cf Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 15 Oct 2011 09:19:49 +0200 Subject: [PATCH 194/768] Add one_liner to build script to make sure it compiles and runs on MSVC 10. --- boost/network/protocol/http/impl/request.hpp | 4 ++-- boost/network/protocol/http/message/wrappers/uri.hpp | 2 +- libs/network/example/CMakeLists.txt | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index 763b09c67..3a6c05296 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -50,7 +50,7 @@ namespace http { struct basic_request : public basic_message { - mutable boost::network::uri::basic_uri::type> uri_; + mutable boost::network::uri::uri uri_; typedef basic_message base_type; public: @@ -121,7 +121,7 @@ namespace http { uri_ = new_uri; } - boost::network::uri::basic_uri::type> const & uri() const { + boost::network::uri::uri const & uri() const { return uri_; } diff --git a/boost/network/protocol/http/message/wrappers/uri.hpp b/boost/network/protocol/http/message/wrappers/uri.hpp index 622d53a4a..7ff9d9b02 100644 --- a/boost/network/protocol/http/message/wrappers/uri.hpp +++ b/boost/network/protocol/http/message/wrappers/uri.hpp @@ -24,7 +24,7 @@ namespace boost { namespace network { namespace http { operator string_type() { return message_.uri().raw(); } - operator boost::network::uri::basic_uri::type> () { + operator boost::network::uri::uri () { return message_.uri(); } }; diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 912579e61..96dab26b3 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -34,6 +34,10 @@ if (Boost_FOUND) target_link_libraries(simple_wget ${OPENSSL_LIBRARIES}) endif (OPENSSL_FOUND) + add_executable(one_liner http/one_liner.cpp) + target_link_libraries(one_liner ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) + set_target_properties(one_liner PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + add_executable(hello_world_server http/hello_world_server.cpp) target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) From 5a346487a119e6480a3b20974b599dc962528ca2 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 26 Nov 2011 09:17:01 +0100 Subject: [PATCH 195/768] Updated build scripts to ensure the minimum Boost version is 1.45. --- CMakeLists.txt | 8 +++--- boost/network/uri/uri.hpp | 25 ----------------- libs/network/build/CMakeLists.txt | 2 +- libs/network/example/CMakeLists.txt | 11 +++++--- libs/network/example/simple_wget.cpp | 5 +--- libs/network/test/CMakeLists.txt | 5 +--- libs/network/test/http/CMakeLists.txt | 40 +++++++++++++-------------- libs/network/test/uri/CMakeLists.txt | 2 +- 8 files changed, 35 insertions(+), 63 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e6449449e..934f257cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 2.6) project(CPP-NETLIB) -find_package( Boost 1.41.0 ) +find_package( Boost 1.45.0 ) find_package( OpenSSL ) find_package( Threads ) set(CMAKE_VERBOSE_MAKEFILE true) @@ -32,8 +32,8 @@ endif() add_subdirectory(libs/network/src) add_subdirectory(libs/network/test) -if (NOT MSVC) - add_subdirectory(libs/mime/test) -endif(NOT MSVC) +#if (NOT MSVC) +# add_subdirectory(libs/mime/test) +#endif(NOT MSVC) add_subdirectory(libs/network/example) diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 0e6371d81..f99262a5b 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -303,31 +303,6 @@ bool operator == (const uri &lhs, const uri &rhs) { } } // namespace uri } // namespace network - -inline -network::uri::uri::iterator begin(network::uri::uri &uri_) { - return uri_.begin(); -} - -inline -network::uri::uri::iterator end(network::uri::uri &uri_) { - return uri_.end(); -} - -inline -network::uri::uri::const_iterator begin(const network::uri::uri &uri_) { - return uri_.begin(); -} - -inline -network::uri::uri::const_iterator end(const network::uri::uri &uri_) { - return uri_.end(); -} - -inline -void swap(network::uri::uri &lhs, network::uri::uri &rhs) { - lhs.swap(rhs); -} } // namespace boost diff --git a/libs/network/build/CMakeLists.txt b/libs/network/build/CMakeLists.txt index 8111a37b7..dc1c0d0be 100644 --- a/libs/network/build/CMakeLists.txt +++ b/libs/network/build/CMakeLists.txt @@ -1,5 +1,5 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) -find_package( Boost 1.43.0 COMPONENTS unit_test_framework system regex thread filesystem ) +find_package( Boost 1.45.0 COMPONENTS unit_test_framework system regex thread filesystem ) add_library(cppnetlib-uri STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/parse_uri_impl.cpp) add_library(cppnetlib-server-parsers STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/server_request_parsers_impl.cpp) diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 96dab26b3..57b106696 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -4,7 +4,7 @@ # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) -find_package( Boost 1.41.0 COMPONENTS program_options system regex date_time thread filesystem ) +find_package( Boost 1.45.0 COMPONENTS program_options system regex date_time thread filesystem ) find_package( OpenSSL ) find_package( Threads ) @@ -20,7 +20,7 @@ endif (OPENSSL_FOUND) if (Boost_FOUND) add_executable(http_client http_client.cpp) add_dependencies(http_client cppnetlib-uri) - target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) + target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) if (OPENSSL_FOUND) target_link_libraries(http_client ${OPENSSL_LIBRARIES}) @@ -28,15 +28,18 @@ if (Boost_FOUND) add_executable(simple_wget simple_wget.cpp) add_dependencies(simple_wget cppnetlib-uri) - target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) + target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) if (OPENSSL_FOUND) target_link_libraries(simple_wget ${OPENSSL_LIBRARIES}) endif (OPENSSL_FOUND) add_executable(one_liner http/one_liner.cpp) - target_link_libraries(one_liner ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) + target_link_libraries(one_liner ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) set_target_properties(one_liner PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) + if (OPENSSL_FOUND) + target_link_libraries(one_liner ${OPENSSL_LIBRARIES}) + endif (OPENSSL_FOUND) add_executable(hello_world_server http/hello_world_server.cpp) target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) diff --git a/libs/network/example/simple_wget.cpp b/libs/network/example/simple_wget.cpp index 45821f447..2fda68008 100644 --- a/libs/network/example/simple_wget.cpp +++ b/libs/network/example/simple_wget.cpp @@ -26,10 +26,7 @@ namespace uri = boost::network::uri; namespace { -template < - class Tag - > -std::string get_filename(const uri::basic_uri &url) { +std::string get_filename(const uri::uri &url) { std::string path = uri::path(url); std::size_t index = path.find_last_of('/'); std::string filename = path.substr(index + 1); diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index 343cf5697..b0d631668 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -4,7 +4,7 @@ # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) -find_package( Boost 1.41.0 COMPONENTS unit_test_framework system regex date_time thread filesystem ) +find_package( Boost 1.45.0 COMPONENTS unit_test_framework system regex date_time thread filesystem ) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) @@ -23,9 +23,6 @@ if (Boost_FOUND) PROPERTIES COMPILE_FLAGS "-Wall") add_executable(cpp-netlib-${test} ${test}.cpp) add_dependencies(cpp-netlib-${test} cppnetlib-uri) - - # add_dependencies(cpp-netlib-${test} cppnetlib-uri) - # target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index dcc3749cb..94def170d 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -5,7 +5,7 @@ # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) -find_package( Boost 1.43.0 REQUIRED unit_test_framework system regex thread filesystem ) +find_package( Boost 1.45.0 REQUIRED unit_test_framework system regex thread filesystem ) find_package( OpenSSL ) if (OPENSSL_FOUND) @@ -86,24 +86,24 @@ if (Boost_FOUND) math (EXPR PORT "${PORT} + 1") endforeach (test) - set ( INLINED_TESTS - client_include_inlined - server_include_inlined - ) - foreach ( test ${INLINED_TESTS} ) - if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) - set_source_files_properties(${test}.cpp - PROPERTIES COMPILE_FLAGS "-Wall") - endif() - add_executable(cpp-netlib-http-inlined-${test} ${test}.cpp) - target_link_libraries(cpp-netlib-http-inlined-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) - if (OPENSSL_FOUND) - target_link_libraries(cpp-netlib-http-inlined-${test} ${OPENSSL_LIBRARIES}) - endif() - set_target_properties(cpp-netlib-http-inlined-${test} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) - add_test(cpp-netlib-http-inlined-${test} - ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-inlined-${test}) - endforeach (test) + #set ( INLINED_TESTS + # client_include_inlined + # server_include_inlined + # ) + #foreach ( test ${INLINED_TESTS} ) + # if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) + # set_source_files_properties(${test}.cpp + # PROPERTIES COMPILE_FLAGS "-Wall") + # endif() + # add_executable(cpp-netlib-http-inlined-${test} ${test}.cpp) + # target_link_libraries(cpp-netlib-http-inlined-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + # if (OPENSSL_FOUND) + # target_link_libraries(cpp-netlib-http-inlined-${test} ${OPENSSL_LIBRARIES}) + # endif() + # set_target_properties(cpp-netlib-http-inlined-${test} + # PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + # add_test(cpp-netlib-http-inlined-${test} + # ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-inlined-${test}) + #endforeach (test) endif() diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index ab2f012a8..6e69508c7 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -4,7 +4,7 @@ # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) -find_package( Boost 1.41.0 COMPONENTS unit_test_framework system regex date_time filesystem ) +find_package( Boost 1.45.0 COMPONENTS unit_test_framework system regex date_time filesystem ) find_package( OpenSSL ) find_package( Threads ) From 9a7f1d95d6c80071b09138e8ce367b1adfbc1bb9 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 27 Nov 2011 09:34:13 +0100 Subject: [PATCH 196/768] Updated linearize function because of a compilation failure on MSVC 2010. --- .../protocol/http/algorithms/linearize.hpp | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/boost/network/protocol/http/algorithms/linearize.hpp b/boost/network/protocol/http/algorithms/linearize.hpp index c53305ae2..975e86136 100644 --- a/boost/network/protocol/http/algorithms/linearize.hpp +++ b/boost/network/protocol/http/algorithms/linearize.hpp @@ -38,8 +38,8 @@ namespace boost { namespace network { namespace http { typedef typename ostringstream::type output_stream; typedef constants consts; output_stream header_line; - header_line << name(header) - << consts::colon() << consts::space() + header_line << name(header) + << consts::colon() << consts::space() << value(header) << consts::crlf(); return header_line.str(); } @@ -50,17 +50,17 @@ namespace boost { namespace network { namespace http { ((ClientRequest)), (OutputIterator) ) linearize( - Request const & request, + Request const & request, typename Request::string_type const & method, - unsigned version_major, - unsigned version_minor, + unsigned version_major, + unsigned version_minor, OutputIterator oi - ) + ) { typedef typename Request::tag Tag; typedef constants consts; typedef typename string::type string_type; - static string_type + static string_type http_slash = consts::http_slash() , accept = consts::accept() , accept_mime = consts::default_accept_mime() @@ -73,7 +73,7 @@ namespace boost { namespace network { namespace http { ; boost::copy(method, oi); *oi = consts::space_char(); - if (request.path().empty() || request.path()[0] != consts::slash_char()) + if (request.path().empty() || request.path()[0] != consts::slash_char()) *oi = consts::slash_char(); boost::copy(request.path(), oi); if (!request.query().empty()) { @@ -116,13 +116,11 @@ namespace boost { namespace network { namespace http { boost::copy(crlf, oi); } typedef typename headers_range::type headers_range; - typedef typename range_iterator::type headers_iterator; - headers_range request_headers = headers(request); - headers_iterator iterator = boost::begin(request_headers), - end = boost::end(request_headers); - for (; iterator != end; ++iterator) { - string_type header_name = name(*iterator), - header_value = value(*iterator); + typedef typename range_value::type headers_value; + BOOST_FOREACH(const headers_value &header, headers(request)) + { + string_type header_name = name(header), + header_value = value(header); boost::copy(header_name, oi); *oi = consts::colon_char(); *oi = consts::space_char(); @@ -140,11 +138,11 @@ namespace boost { namespace network { namespace http { typename body_range::type body_data = body(request).range(); return boost::copy(body_data, oi); } - + } /* http */ - + } /* net */ - + } /* boost */ #endif /* BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 */ From 25745d558ba63ad1374262bfc266c791953eba15 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 27 Nov 2011 14:50:54 +0100 Subject: [PATCH 197/768] Line endings. --- .../protocol/http/algorithms/linearize.hpp | 298 +++++++++--------- 1 file changed, 149 insertions(+), 149 deletions(-) diff --git a/boost/network/protocol/http/algorithms/linearize.hpp b/boost/network/protocol/http/algorithms/linearize.hpp index 975e86136..703a7cf7f 100644 --- a/boost/network/protocol/http/algorithms/linearize.hpp +++ b/boost/network/protocol/http/algorithms/linearize.hpp @@ -1,149 +1,149 @@ -#ifndef BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 -#define BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 - -// Copyright 2010 Dean Michael Berris. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace boost { namespace network { namespace http { - - template - struct linearize_header { - typedef typename string::type string_type; - - template - struct result; - - template - struct result { - typedef string_type type; - }; - - template - BOOST_CONCEPT_REQUIRES( - ((Header)), - (string_type) - ) operator()(ValueType & header) { - typedef typename ostringstream::type output_stream; - typedef constants consts; - output_stream header_line; - header_line << name(header) - << consts::colon() << consts::space() - << value(header) << consts::crlf(); - return header_line.str(); - } - }; - - template - BOOST_CONCEPT_REQUIRES( - ((ClientRequest)), - (OutputIterator) - ) linearize( - Request const & request, - typename Request::string_type const & method, - unsigned version_major, - unsigned version_minor, - OutputIterator oi - ) - { - typedef typename Request::tag Tag; - typedef constants consts; - typedef typename string::type string_type; - static string_type - http_slash = consts::http_slash() - , accept = consts::accept() - , accept_mime = consts::default_accept_mime() - , accept_encoding = consts::accept_encoding() - , default_accept_encoding = consts::default_accept_encoding() - , crlf = consts::crlf() - , host = consts::host() - , connection = consts::connection() - , close = consts::close() - ; - boost::copy(method, oi); - *oi = consts::space_char(); - if (request.path().empty() || request.path()[0] != consts::slash_char()) - *oi = consts::slash_char(); - boost::copy(request.path(), oi); - if (!request.query().empty()) { - *oi = consts::question_mark_char(); - boost::copy(request.query(), oi); - } - if (!request.anchor().empty()) { - *oi = consts::hash_char(); - boost::copy(request.anchor(), oi); - } - *oi = consts::space_char(); - boost::copy(http_slash, oi); - string_type version_major_str = boost::lexical_cast(version_major), - version_minor_str = boost::lexical_cast(version_minor); - boost::copy(version_major_str, oi); - *oi = consts::dot_char(); - boost::copy(version_minor_str, oi); - boost::copy(crlf, oi); - boost::copy(host, oi); - *oi = consts::colon_char(); - *oi = consts::space_char(); - boost::copy(request.host(), oi); - boost::optional port_ = port(request); - if (port_) { - string_type port_str = boost::lexical_cast(*port_); - *oi = consts::colon_char(); - boost::copy(port_str, oi); - } - boost::copy(crlf, oi); - boost::copy(accept, oi); - *oi = consts::colon_char(); - *oi = consts::space_char(); - boost::copy(accept_mime, oi); - boost::copy(crlf, oi); - if (version_major == 1u && version_minor == 1u) { - boost::copy(accept_encoding, oi); - *oi = consts::colon_char(); - *oi = consts::space_char(); - boost::copy(default_accept_encoding, oi); - boost::copy(crlf, oi); - } - typedef typename headers_range::type headers_range; - typedef typename range_value::type headers_value; - BOOST_FOREACH(const headers_value &header, headers(request)) - { - string_type header_name = name(header), - header_value = value(header); - boost::copy(header_name, oi); - *oi = consts::colon_char(); - *oi = consts::space_char(); - boost::copy(header_value, oi); - boost::copy(crlf, oi); - } - if (!connection_keepalive::value) { - boost::copy(connection, oi); - *oi = consts::colon_char(); - *oi = consts::space_char(); - boost::copy(close, oi); - boost::copy(crlf, oi); - } - boost::copy(crlf, oi); - typename body_range::type body_data = body(request).range(); - return boost::copy(body_data, oi); - } - -} /* http */ - -} /* net */ - -} /* boost */ - -#endif /* BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 */ - +#ifndef BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 +#define BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 + +// Copyright 2010 Dean Michael Berris. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace network { namespace http { + + template + struct linearize_header { + typedef typename string::type string_type; + + template + struct result; + + template + struct result { + typedef string_type type; + }; + + template + BOOST_CONCEPT_REQUIRES( + ((Header)), + (string_type) + ) operator()(ValueType & header) { + typedef typename ostringstream::type output_stream; + typedef constants consts; + output_stream header_line; + header_line << name(header) + << consts::colon() << consts::space() + << value(header) << consts::crlf(); + return header_line.str(); + } + }; + + template + BOOST_CONCEPT_REQUIRES( + ((ClientRequest)), + (OutputIterator) + ) linearize( + Request const & request, + typename Request::string_type const & method, + unsigned version_major, + unsigned version_minor, + OutputIterator oi + ) + { + typedef typename Request::tag Tag; + typedef constants consts; + typedef typename string::type string_type; + static string_type + http_slash = consts::http_slash() + , accept = consts::accept() + , accept_mime = consts::default_accept_mime() + , accept_encoding = consts::accept_encoding() + , default_accept_encoding = consts::default_accept_encoding() + , crlf = consts::crlf() + , host = consts::host() + , connection = consts::connection() + , close = consts::close() + ; + boost::copy(method, oi); + *oi = consts::space_char(); + if (request.path().empty() || request.path()[0] != consts::slash_char()) + *oi = consts::slash_char(); + boost::copy(request.path(), oi); + if (!request.query().empty()) { + *oi = consts::question_mark_char(); + boost::copy(request.query(), oi); + } + if (!request.anchor().empty()) { + *oi = consts::hash_char(); + boost::copy(request.anchor(), oi); + } + *oi = consts::space_char(); + boost::copy(http_slash, oi); + string_type version_major_str = boost::lexical_cast(version_major), + version_minor_str = boost::lexical_cast(version_minor); + boost::copy(version_major_str, oi); + *oi = consts::dot_char(); + boost::copy(version_minor_str, oi); + boost::copy(crlf, oi); + boost::copy(host, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + boost::copy(request.host(), oi); + boost::optional port_ = port(request); + if (port_) { + string_type port_str = boost::lexical_cast(*port_); + *oi = consts::colon_char(); + boost::copy(port_str, oi); + } + boost::copy(crlf, oi); + boost::copy(accept, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + boost::copy(accept_mime, oi); + boost::copy(crlf, oi); + if (version_major == 1u && version_minor == 1u) { + boost::copy(accept_encoding, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + boost::copy(default_accept_encoding, oi); + boost::copy(crlf, oi); + } + typedef typename headers_range::type headers_range; + typedef typename range_value::type headers_value; + BOOST_FOREACH(const headers_value &header, headers(request)) + { + string_type header_name = name(header), + header_value = value(header); + boost::copy(header_name, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + boost::copy(header_value, oi); + boost::copy(crlf, oi); + } + if (!connection_keepalive::value) { + boost::copy(connection, oi); + *oi = consts::colon_char(); + *oi = consts::space_char(); + boost::copy(close, oi); + boost::copy(crlf, oi); + } + boost::copy(crlf, oi); + typename body_range::type body_data = body(request).range(); + return boost::copy(body_data, oi); + } + +} /* http */ + +} /* net */ + +} /* boost */ + +#endif /* BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 */ + From 8e6237c001daf99564dcbf2ed203e2ab1c5ba4dc Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Wed, 30 Nov 2011 21:59:44 +0100 Subject: [PATCH 198/768] Added test for python when running HTTP server unit tests. --- libs/network/test/http/CMakeLists.txt | 32 ++++++++++++++++----------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 94def170d..6de7015db 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -7,6 +7,7 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) find_package( Boost 1.45.0 REQUIRED unit_test_framework system regex thread filesystem ) find_package( OpenSSL ) +find_package( PythonInterp ) if (OPENSSL_FOUND) include_directories( ${OPENSSL_INCLUDE_DIR} ) @@ -60,31 +61,36 @@ if (Boost_FOUND) ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) endforeach (test) - set ( SERVER_TESTS + if ( PYTHONINTERP_FOUND ) + set ( SERVER_TESTS server_hello_world server_async server_async_less_copy ) - set ( PORT 8000 ) - foreach ( test ${SERVER_TESTS} ) + set ( PORT 8000 ) + foreach ( test ${SERVER_TESTS} ) if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) - set_source_files_properties(${test}.cpp - PROPERTIES COMPILE_FLAGS "-Wall") + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) add_dependencies(cpp-netlib-http-${test} cppnetlib-server-parsers) target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) set_target_properties(cpp-netlib-http-${test} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY - ${CPP-NETLIB_BINARY_DIR}/tests) + PROPERTIES RUNTIME_OUTPUT_DIRECTORY + ${CPP-NETLIB_BINARY_DIR}/tests) add_test(cpp-netlib-${test} - python - ${CPP-NETLIB_SOURCE_DIR}/libs/network/test/httplib_acceptance.py - ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test} - ${PORT} - ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}.passed) + ${PYTHON_EXECUTABLE} + ${CPP-NETLIB_SOURCE_DIR}/libs/network/test/httplib_acceptance.py + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test} + ${PORT} + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}.passed) math (EXPR PORT "${PORT} + 1") - endforeach (test) + endforeach (test) + #else() + # message(STATUS "Python not found, won't run server tests." + endif( PYTHONINTERP_FOUND ) + #set ( INLINED_TESTS # client_include_inlined From 01589b64c8b0918f96fecdd15d663603fa447de8 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 5 Dec 2011 17:09:59 +1100 Subject: [PATCH 199/768] Simplifying the CMakeLists files. --- CMakeLists.txt | 6 +++++- libs/network/example/CMakeLists.txt | 5 ----- libs/network/test/CMakeLists.txt | 15 +++++---------- libs/network/test/http/CMakeLists.txt | 6 ------ 4 files changed, 10 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1475321ce..bfe59a71d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,11 @@ cmake_minimum_required(VERSION 2.6) project(CPP-NETLIB) -find_package( Boost 1.41.0 ) +find_package( Boost 1.43.0 REQUIRED unit_test_framework system regex date_time thread filesystem ) +find_package( OpenSSL ) +find_package( Threads ) +set(Boost_USE_STATIC_LIBS ON) +set(Boost_USE_MULTITHREADED ON) set(CMAKE_VERBOSE_MAKEFILE true) if (CMAKE_BUILD_TYPE MATCHES Debug) diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 293a6ad30..6ebffa5fd 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -4,12 +4,7 @@ # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) -find_package( Boost 1.41.0 COMPONENTS program_options system regex date_time thread filesystem ) -find_package( OpenSSL ) include_directories(${OPENSSL_INCLUDE_DIR}) -find_package( Threads ) -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_MULTITHREADED ON) if (Boost_FOUND) add_executable(http_client http_client.cpp) diff --git a/libs/network/test/CMakeLists.txt b/libs/network/test/CMakeLists.txt index 190affb4a..0c3d841a8 100644 --- a/libs/network/test/CMakeLists.txt +++ b/libs/network/test/CMakeLists.txt @@ -4,11 +4,6 @@ # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) -find_package( Boost 1.41.0 COMPONENTS unit_test_framework system regex date_time thread filesystem ) -find_package( OpenSSL ) -find_package( Threads ) -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_MULTITHREADED ON) add_subdirectory(uri) add_subdirectory(http) @@ -24,17 +19,17 @@ if (Boost_FOUND) set_source_files_properties(${test}.cpp PROPERTIES COMPILE_FLAGS "-Wall") add_executable(cpp-netlib-${test} ${test}.cpp) - add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) + add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) - # add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) - # target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + target_link_libraries(cpp-netlib-${test} + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) endif() set_target_properties(cpp-netlib-${test} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) - add_test(cpp-netlib-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) + add_test(cpp-netlib-${test} + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) endforeach (test) endif() diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 018993729..b60a83789 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -5,18 +5,12 @@ # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) -find_package( Boost 1.43.0 REQUIRED unit_test_framework system regex thread filesystem ) -find_package( OpenSSL ) if (OPENSSL_FOUND) include_directories( ${OPENSSL_INCLUDE_DIR} ) add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) endif() -find_package( Threads ) -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_MULTITHREADED ON) - if (Boost_FOUND) set ( TESTS client_constructor_test From 6aead42c76dbc7be9cedcf14f9f038e816b590f9 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 5 Dec 2011 17:18:48 +1100 Subject: [PATCH 200/768] More CMakeLists twiddling. --- CMakeLists.txt | 5 +---- libs/network/test/uri/CMakeLists.txt | 14 +++++--------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bfe59a71d..d8b17a49a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,14 +8,12 @@ project(CPP-NETLIB) find_package( Boost 1.43.0 REQUIRED unit_test_framework system regex date_time thread filesystem ) find_package( OpenSSL ) find_package( Threads ) -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_MULTITHREADED ON) set(CMAKE_VERBOSE_MAKEFILE true) if (CMAKE_BUILD_TYPE MATCHES Debug) add_definitions(-DBOOST_NETWORK_DEBUG) endif() - + if (Boost_FOUND) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTI_THREADED ON) @@ -26,4 +24,3 @@ add_subdirectory(libs/network/src) add_subdirectory(libs/network/test) add_subdirectory(libs/mime/test) add_subdirectory(libs/network/example) - diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index 0c1e48a5a..e6faeec83 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -4,12 +4,6 @@ # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) -find_package( Boost 1.41.0 COMPONENTS unit_test_framework system regex date_time filesystem ) -find_package( OpenSSL ) -find_package( Threads ) -set(Boost_USE_STATIC_LIBS ON) -set(Boost_USE_MULTITHREADED ON) - if (Boost_FOUND) set( @@ -22,14 +16,16 @@ if (Boost_FOUND) set_source_files_properties(${test}.cpp PROPERTIES COMPILE_FLAGS "-Wall") add_executable(cpp-netlib-${test} ${test}.cpp) - add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) + target_link_libraries(cpp-netlib-${test} + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) endif() set_target_properties(cpp-netlib-${test} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) - add_test(cpp-netlib-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) + add_test(cpp-netlib-${test} + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) endforeach (test) endif() From e6d63356462dc6b2b1d9bec022233b9785aa875a Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 5 Dec 2011 17:23:03 +1100 Subject: [PATCH 201/768] Final twiddling for Boost search. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d8b17a49a..e5be84757 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,8 @@ cmake_minimum_required(VERSION 2.6) project(CPP-NETLIB) +set(Boost_USE_STATIC_LIBS ON) +set(Boost_USE_MULTI_THREADED ON) find_package( Boost 1.43.0 REQUIRED unit_test_framework system regex date_time thread filesystem ) find_package( OpenSSL ) find_package( Threads ) @@ -15,8 +17,6 @@ if (CMAKE_BUILD_TYPE MATCHES Debug) endif() if (Boost_FOUND) - set(Boost_USE_STATIC_LIBS ON) - set(Boost_USE_MULTI_THREADED ON) include_directories(${Boost_INCLUDE_DIRS}) endif() enable_testing() From 9dacc036c77f6b64a002fc5b280a3809dc36aea4 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 5 Dec 2011 17:46:55 +1100 Subject: [PATCH 202/768] Fiddling yet again with CMakeLists.txt files. --- CMakeLists.txt | 7 ++++++- libs/network/src/CMakeLists.txt | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e5be84757..cd0fe51ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ cmake_minimum_required(VERSION 2.6) project(CPP-NETLIB) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTI_THREADED ON) -find_package( Boost 1.43.0 REQUIRED unit_test_framework system regex date_time thread filesystem ) +find_package( Boost 1.45.0 REQUIRED unit_test_framework system regex date_time thread filesystem program_options) find_package( OpenSSL ) find_package( Threads ) set(CMAKE_VERBOSE_MAKEFILE true) @@ -19,6 +19,11 @@ endif() if (Boost_FOUND) include_directories(${Boost_INCLUDE_DIRS}) endif() + +if (OpenSSL_FOUND) + add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) +endif() + enable_testing() add_subdirectory(libs/network/src) add_subdirectory(libs/network/test) diff --git a/libs/network/src/CMakeLists.txt b/libs/network/src/CMakeLists.txt index dae683daf..c2cf98b15 100644 --- a/libs/network/src/CMakeLists.txt +++ b/libs/network/src/CMakeLists.txt @@ -6,6 +6,7 @@ # boost_network_uri include_directories(${CPP-NETLIB_SOURCE_DIR}) + set(CPP-NETLIB_URI_SRCS uri/parse.cpp) add_library(cppnetlib-uri-parsers ${CPP-NETLIB_URI_SRCS}) From 2d3952060ea8da31aa991f458da682e0f7fffd83 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 5 Dec 2011 18:23:34 +1100 Subject: [PATCH 203/768] More CMakeLists fudging around. --- CMakeLists.txt | 19 ++++---- libs/network/example/CMakeLists.txt | 69 +++++++++++++++++++-------- libs/network/src/CMakeLists.txt | 4 ++ libs/network/test/http/CMakeLists.txt | 12 +++-- 4 files changed, 72 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cd0fe51ab..55abd9423 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ cmake_minimum_required(VERSION 2.6) project(CPP-NETLIB) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTI_THREADED ON) -find_package( Boost 1.45.0 REQUIRED unit_test_framework system regex date_time thread filesystem program_options) +find_package( Boost 1.45.0 REQUIRED unit_test_framework system regex date_time thread filesystem program_options ) find_package( OpenSSL ) find_package( Threads ) set(CMAKE_VERBOSE_MAKEFILE true) @@ -16,16 +16,17 @@ if (CMAKE_BUILD_TYPE MATCHES Debug) add_definitions(-DBOOST_NETWORK_DEBUG) endif() +if (OpenSSL_FOUND) + add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) +endif() + if (Boost_FOUND) include_directories(${Boost_INCLUDE_DIRS}) + enable_testing() + add_subdirectory(libs/network/src) + add_subdirectory(libs/network/test) + add_subdirectory(libs/mime/test) + add_subdirectory(libs/network/example) endif() -if (OpenSSL_FOUND) - add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) -endif() -enable_testing() -add_subdirectory(libs/network/src) -add_subdirectory(libs/network/test) -add_subdirectory(libs/mime/test) -add_subdirectory(libs/network/example) diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 6ebffa5fd..d20475002 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -6,23 +6,54 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) include_directories(${OPENSSL_INCLUDE_DIR}) -if (Boost_FOUND) - add_executable(http_client http_client.cpp) - add_executable(simple_wget simple_wget.cpp) - add_executable(hello_world_server http/hello_world_server.cpp) - add_executable(fileserver http/fileserver.cpp) - add_executable(uri uri.cpp) - add_dependencies(http_client cppnetlib-uri-parsers) - add_dependencies(simple_wget cppnetlib-uri-parsers) - add_dependencies(uri cppnetlib-uri-parsers) - target_link_libraries(http_client ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers) - target_link_libraries(simple_wget ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} cppnetlib-uri-parsers) - target_link_libraries(hello_world_server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} ) - target_link_libraries(fileserver ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) - target_link_libraries(uri cppnetlib-uri-parsers) - set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) - set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) - set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) - set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) - set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +if (OPENSSL_FOUND) + add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) endif() + +add_executable(http_client http_client.cpp) +add_executable(simple_wget simple_wget.cpp) +add_executable(hello_world_server http/hello_world_server.cpp) +add_executable(fileserver http/fileserver.cpp) +add_executable(uri uri.cpp) +add_dependencies(http_client cppnetlib-uri-parsers) +add_dependencies(simple_wget cppnetlib-uri-parsers) +add_dependencies(uri cppnetlib-uri-parsers) +set(BOOST_CLIENT_LIBS + ${Boost_PROGRAM_OPTIONS_LIBRARY} + ${Boost_THREAD_LIBRARY} + ${Boost_SYSTEM_LIBRARY}) + +set(BOOST_SERVER_LIBS + ${Boost_THREAD_LIBRARY} + ${Boost_SYSTEM_LIBRARY} + ${Boost_PROGRAM_OPTIONS_LIBRARY}) + +target_link_libraries(http_client + ${BOOST_CLIENT_LIBS} + ${CMAKE_THREAD_LIBS_INIT} + ${OPENSSL_LIBRARIES} + cppnetlib-uri-parsers) + +target_link_libraries(simple_wget + ${BOOST_CLIENT_LIBS} + ${CMAKE_THREAD_LIBS_INIT} + ${OPENSSL_LIBRARIES} + cppnetlib-uri-parsers) + +target_link_libraries(hello_world_server + ${BOOST_SERVER_LIBS} + ${CMAKE_THREAD_LIBS_INIT} + ${OPENSSL_LIBRARIES}) + +target_link_libraries(fileserver + ${BOOST_SERVER_LIBS} + ${Boost_FILESYSTEM_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + cppnetlib-server-parsers) + +target_link_libraries(uri cppnetlib-uri-parsers) +set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) diff --git a/libs/network/src/CMakeLists.txt b/libs/network/src/CMakeLists.txt index c2cf98b15..7bf2ca648 100644 --- a/libs/network/src/CMakeLists.txt +++ b/libs/network/src/CMakeLists.txt @@ -7,6 +7,10 @@ # boost_network_uri include_directories(${CPP-NETLIB_SOURCE_DIR}) +if (OPENSSL_FOUND) + add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) +endif() + set(CPP-NETLIB_URI_SRCS uri/parse.cpp) add_library(cppnetlib-uri-parsers ${CPP-NETLIB_URI_SRCS}) diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index b60a83789..c48432b18 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -12,6 +12,10 @@ if (OPENSSL_FOUND) endif() if (Boost_FOUND) + set ( BOOST_LIBS + ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} + ${Boost_THREAD_LIBRARY} + ${Boost_SYSTEM_LIBRARY}) set ( TESTS client_constructor_test client_get_test @@ -32,7 +36,7 @@ if (Boost_FOUND) endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) add_dependencies(cpp-netlib-http-${test} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + target_link_libraries(cpp-netlib-http-${test} ${BOOST_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) endif() @@ -53,7 +57,7 @@ if (Boost_FOUND) endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) add_dependencies(cpp-netlib-http-${test} cppnetlib-server-parsers) - target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) + target_link_libraries(cpp-netlib-http-${test} ${BOOST_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) set_target_properties(cpp-netlib-http-${test} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) add_test(cpp-netlib-http-${test} @@ -73,7 +77,7 @@ if (Boost_FOUND) endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) add_dependencies(cpp-netlib-http-${test} cppnetlib-server-parsers) - target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) + target_link_libraries(cpp-netlib-http-${test} ${BOOST_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) set_target_properties(cpp-netlib-http-${test} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) @@ -96,7 +100,7 @@ if (Boost_FOUND) PROPERTIES COMPILE_FLAGS "-Wall") endif() add_executable(cpp-netlib-http-inlined-${test} ${test}.cpp) - target_link_libraries(cpp-netlib-http-inlined-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(cpp-netlib-http-inlined-${test} ${BOOST_LIBS} ${CMAKE_THREAD_LIBS_INIT}) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-inlined-${test} ${OPENSSL_LIBRARIES}) endif() From b46df4ed40fca48c3c71564c7f7d58ad5edb5d5b Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 5 Dec 2011 18:24:07 +1100 Subject: [PATCH 204/768] Fixes #82 -- simplifying header printing. --- libs/network/example/http_client.cpp | 47 +++++++++++----------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/libs/network/example/http_client.cpp b/libs/network/example/http_client.cpp index 76c246aa3..1f8264a04 100644 --- a/libs/network/example/http_client.cpp +++ b/libs/network/example/http_client.cpp @@ -11,30 +11,21 @@ */ #include #include -#include #include +#include #include namespace po = boost::program_options; -using namespace std; - -struct header_printer { - std::ostream & os; - header_printer(std::ostream & os_) : os(os_) {} - template - void operator()(Pair const & p) { - os << p.first << ": " << p.second << endl; - } -}; int main(int argc, char * argv[]) { + using namespace boost::network; po::options_description options("Allowed options"); - string output_filename, source; + std::string output_filename, source; bool show_headers; options.add_options() ("help,h", "produce help message") ("headers,H", "print headers") - ("source,s", po::value(&source), "source URL") + ("source,s", po::value(&source), "source URL") ; po::positional_options_description positional_options; @@ -44,47 +35,47 @@ int main(int argc, char * argv[]) { po::store(po::command_line_parser(argc, argv).options(options).positional(positional_options).run(), vm); po::notify(vm); - } catch(exception & e) { - cout << "Error: " << e.what() << endl; - cout << options << endl; + } catch(std::exception & e) { + std::cout << "Error: " << e.what() << std::endl; + std::cout << options << std::endl; return EXIT_FAILURE; }; if (vm.count("help")) { - cout << options << endl; + std::cout << options << std::endl; return EXIT_SUCCESS; }; if (vm.count("source") < 1) { - cout << "Error: Source URL required." << endl; - cout << options << endl; + std::cout << "Error: Source URL required." << std::endl; + std::cout << options << std::endl; return EXIT_FAILURE; }; show_headers = vm.count("headers") ? true : false ; - using namespace boost::network; typedef http::basic_client http_client; - + http_client::request request(source); http_client::string_type destination_ = host(request); - + request << ::boost::network::header("Connection", "close"); http_client client(http::_follow_redirects=true); http_client::response response = client.get(request); if (show_headers) { headers_range::type headers_ = response.headers(); - std::copy(headers_.begin(), headers_.end(), - boost::make_function_output_iterator(header_printer(cout))); - cout << endl; + typedef std::pair header_type; + BOOST_FOREACH(header_type const & header, headers_) { + std::cout << header.first << ": " << header.second << std::endl; + } + std::cout << std::endl; }; - + body_range::type body_ = body(response).range(); - boost::copy(body_, std::ostream_iterator::type>(cout)); - + boost::copy(body_, std::ostream_iterator::type>(std::cout)); return EXIT_SUCCESS; } //] From fb05e2aa53f8acd6efac54ec1d3aa2c312d7f6aa Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 5 Dec 2011 18:42:04 +1100 Subject: [PATCH 205/768] Fixing booboos. --- libs/network/test/http/CMakeLists.txt | 5 ---- libs/network/test/uri/CMakeLists.txt | 42 +++++++++++++-------------- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 59738ece5..3490a36fd 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -29,13 +29,8 @@ if (Boost_FOUND) PROPERTIES COMPILE_FLAGS "-Wall") endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) -<<<<<<< HEAD add_dependencies(cpp-netlib-http-${test} cppnetlib-uri-parsers) target_link_libraries(cpp-netlib-http-${test} ${BOOST_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) -======= - add_dependencies(cpp-netlib-http-${test} cppnetlib-uri) - target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) ->>>>>>> cd5b00337224ee166982f4ce954d2d55b906d7da if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) endif() diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index c433232cd..512dd7503 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -6,25 +6,23 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) if (Boost_FOUND) - set( - TESTS - url_test - url_http_test - url_mailto_test - ) - foreach (test ${TESTS}) - set_source_files_properties(${test}.cpp - PROPERTIES COMPILE_FLAGS "-Wall") - add_executable(cpp-netlib-${test} ${test}.cpp) - add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-${test} - ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) - if (OPENSSL_FOUND) - target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) - endif() - set_target_properties(cpp-netlib-${test} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) - add_test(cpp-netlib-${test} - ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) - endforeach (test) -endif() + set( + TESTS + url_test + url_encoding_test + url_builder_test + ) + foreach (test ${TESTS}) + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") + add_executable(cpp-netlib-${test} ${test}.cpp) + add_dependencies(cpp-netlib-${test} cppnetlib-uri) + target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) + if (OPENSSL_FOUND) + target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) + endif() + set_target_properties(cpp-netlib-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) + endforeach (test) +endif(Boost_FOUND) From b8c28a5aed9a55d82d78e685c752b004d0be8a4d Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 5 Dec 2011 18:44:33 +1100 Subject: [PATCH 206/768] Revert "Fixing booboos." This reverts commit fb05e2aa53f8acd6efac54ec1d3aa2c312d7f6aa. --- libs/network/test/http/CMakeLists.txt | 5 ++++ libs/network/test/uri/CMakeLists.txt | 42 ++++++++++++++------------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 3490a36fd..59738ece5 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -29,8 +29,13 @@ if (Boost_FOUND) PROPERTIES COMPILE_FLAGS "-Wall") endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) +<<<<<<< HEAD add_dependencies(cpp-netlib-http-${test} cppnetlib-uri-parsers) target_link_libraries(cpp-netlib-http-${test} ${BOOST_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) +======= + add_dependencies(cpp-netlib-http-${test} cppnetlib-uri) + target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) +>>>>>>> cd5b00337224ee166982f4ce954d2d55b906d7da if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) endif() diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index 512dd7503..c433232cd 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -6,23 +6,25 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) if (Boost_FOUND) - set( - TESTS - url_test - url_encoding_test - url_builder_test - ) - foreach (test ${TESTS}) - set_source_files_properties(${test}.cpp - PROPERTIES COMPILE_FLAGS "-Wall") - add_executable(cpp-netlib-${test} ${test}.cpp) - add_dependencies(cpp-netlib-${test} cppnetlib-uri) - target_link_libraries(cpp-netlib-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri) - if (OPENSSL_FOUND) - target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) - endif() - set_target_properties(cpp-netlib-${test} - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) - add_test(cpp-netlib-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) - endforeach (test) -endif(Boost_FOUND) + set( + TESTS + url_test + url_http_test + url_mailto_test + ) + foreach (test ${TESTS}) + set_source_files_properties(${test}.cpp + PROPERTIES COMPILE_FLAGS "-Wall") + add_executable(cpp-netlib-${test} ${test}.cpp) + add_dependencies(cpp-netlib-${test} cppnetlib-uri-parsers) + target_link_libraries(cpp-netlib-${test} + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + if (OPENSSL_FOUND) + target_link_libraries(cpp-netlib-${test} ${OPENSSL_LIBRARIES}) + endif() + set_target_properties(cpp-netlib-${test} + PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) + add_test(cpp-netlib-${test} + ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) + endforeach (test) +endif() From e92fe0400c4d24c8c67ed48c9a8bf08afceb3ab3 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 5 Dec 2011 18:46:03 +1100 Subject: [PATCH 207/768] Revert "Merge branch '0.9-devel' of github.com:deanberris/cpp-netlib into canonical-0.9-devel" This reverts commit 9ab0cace12ccf26c81ec1c2c0b0d46622bfcdb6e, reversing changes made to 79d3fd67e202f4aa4b5e2a5d5837419616b56eba. --- boost/network/protocol/http/impl/request.hpp | 18 +- .../protocol/http/message/wrappers/port.hpp | 2 +- .../protocol/http/message/wrappers/uri.hpp | 6 +- boost/network/uri.hpp | 17 + boost/network/uri/accessors.hpp | 68 ++- boost/network/uri/detail/parse_uri.hpp | 274 +++++++++++ boost/network/uri/detail/uri_parts.hpp | 1 + boost/network/uri/directives.hpp | 17 +- boost/network/uri/directives/authority.hpp | 27 +- boost/network/uri/directives/fragment.hpp | 28 +- boost/network/uri/directives/host.hpp | 23 +- boost/network/uri/directives/path.hpp | 60 ++- boost/network/uri/directives/port.hpp | 55 ++- boost/network/uri/directives/query.hpp | 71 ++- boost/network/uri/directives/scheme.hpp | 54 ++- boost/network/uri/directives/user_info.hpp | 26 +- boost/network/uri/http/uri.hpp | 101 ++++ boost/network/uri/mailto/uri.hpp | 80 ++++ boost/network/uri/uri.hpp | 236 +++++---- boost/network/uri/uri_io.hpp | 8 +- libs/network/build/CMakeLists.txt | 2 +- libs/network/build/Jamfile.v2 | 6 +- libs/network/example/Jamfile.v2 | 10 +- libs/network/example/uri.cpp | 14 +- libs/network/src/CMakeLists.txt | 2 +- libs/network/src/parse_uri_impl.cpp | 13 + libs/network/src/uri/parse.cpp | 252 +--------- libs/network/test/Jamfile.v2 | 2 +- libs/network/test/http/CMakeLists.txt | 5 - libs/network/test/http/Jamfile.v2 | 18 +- libs/network/test/uri/CMakeLists.txt | 1 + libs/network/test/uri/url_builder_test.cpp | 285 +++++++---- libs/network/test/uri/url_encoding_test.cpp | 27 +- libs/network/test/uri/url_http_test.cpp | 61 +++ libs/network/test/uri/url_mailto_test.cpp | 30 ++ libs/network/test/uri/url_test.cpp | 452 +++++++++++------- 36 files changed, 1540 insertions(+), 812 deletions(-) create mode 100644 boost/network/uri/detail/parse_uri.hpp create mode 100644 boost/network/uri/http/uri.hpp create mode 100644 boost/network/uri/mailto/uri.hpp create mode 100644 libs/network/src/parse_uri_impl.cpp create mode 100644 libs/network/test/uri/url_http_test.cpp create mode 100644 libs/network/test/uri/url_mailto_test.cpp diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index 763b09c67..ca5a2c26a 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include @@ -50,7 +50,7 @@ namespace http { struct basic_request : public basic_message { - mutable boost::network::uri::basic_uri::type> uri_; + mutable boost::network::uri::http::basic_uri uri_; typedef basic_message base_type; public: @@ -80,10 +80,11 @@ namespace http { } void swap(basic_request & other) { + using boost::network::uri::swap; base_type & base_ref(other); basic_request & this_ref(*this); base_ref.swap(this_ref); - boost::swap(other.uri_, this->uri_); + swap(other.uri_, this->uri_); } string_type const host() const { @@ -91,14 +92,7 @@ namespace http { } port_type port() const { - boost::optional port = uri::port_us(uri_); - if (!port) - { - typedef constants consts; - return boost::iequals(uri_.scheme_range(), - string_type(consts::https()))? 443 : 80; - } - return *port; + return uri::port_us(uri_); } string_type const path() const { @@ -121,7 +115,7 @@ namespace http { uri_ = new_uri; } - boost::network::uri::basic_uri::type> const & uri() const { + boost::network::uri::http::basic_uri const & uri() const { return uri_; } diff --git a/boost/network/protocol/http/message/wrappers/port.hpp b/boost/network/protocol/http/message/wrappers/port.hpp index 786ce1e98..9777ac277 100644 --- a/boost/network/protocol/http/message/wrappers/port.hpp +++ b/boost/network/protocol/http/message/wrappers/port.hpp @@ -30,7 +30,7 @@ namespace boost { namespace network { namespace http { } operator boost::optional () { - return uri::port_us(message_.uri()); + return port_us(message_.uri()); } }; diff --git a/boost/network/protocol/http/message/wrappers/uri.hpp b/boost/network/protocol/http/message/wrappers/uri.hpp index 622d53a4a..7d4be811a 100644 --- a/boost/network/protocol/http/message/wrappers/uri.hpp +++ b/boost/network/protocol/http/message/wrappers/uri.hpp @@ -7,7 +7,7 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include +#include namespace boost { namespace network { namespace http { @@ -24,7 +24,7 @@ namespace boost { namespace network { namespace http { operator string_type() { return message_.uri().raw(); } - operator boost::network::uri::basic_uri::type> () { + operator boost::network::uri::basic_uri () { return message_.uri(); } }; @@ -40,6 +40,6 @@ namespace boost { namespace network { namespace http { } // namespace network -} // namespace boost +} // nmaespace boost #endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPERS_URI_HPP_20100620 diff --git a/boost/network/uri.hpp b/boost/network/uri.hpp index e9ad1ffea..7472e8cbc 100644 --- a/boost/network/uri.hpp +++ b/boost/network/uri.hpp @@ -6,7 +6,24 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include #include +#include +#include + + +namespace boost { namespace network { namespace uri { + +typedef basic_uri uri; +typedef basic_uri wuri; + +namespace http { +typedef basic_uri uri; +} + +} // namespace uri +} // namespace network +} // namespace boost #endif diff --git a/boost/network/uri/accessors.hpp b/boost/network/uri/accessors.hpp index 7b71862b3..88ed97e16 100644 --- a/boost/network/uri/accessors.hpp +++ b/boost/network/uri/accessors.hpp @@ -12,7 +12,6 @@ # include # include # include -# include namespace boost { @@ -20,11 +19,14 @@ namespace network { namespace uri { namespace details { template < + typename Uri, typename Map > struct key_value_sequence - : spirit::qi::grammar + : spirit::qi::grammar { + typedef typename Uri::const_iterator_type const_iterator_type; + key_value_sequence() : key_value_sequence::base_type(query) { @@ -34,63 +36,79 @@ struct key_value_sequence value = +spirit::qi::char_("a-zA-Z_0-9/%"); } - spirit::qi::rule query; - spirit::qi::rule()> pair; - spirit::qi::rule key, value; + spirit::qi::rule query; + spirit::qi::rule()> pair; + spirit::qi::rule key, value; }; } // namespace details template < + class Tag, class Map > inline -Map &query_map(const uri &uri_, Map &map) { - uri::const_range_type range = uri_.query_range(); - details::key_value_sequence parser; +Map &query_map(const basic_uri &uri, Map &map) { + typename basic_uri::const_range_type range = uri.query_range(); + details::key_value_sequence, Map> parser; spirit::qi::parse(boost::begin(range), boost::end(range), parser, map); return map; } -std::string username(const uri &uri_) { - uri::const_range_type user_info_range = uri_.user_info_range(); - uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); +template < + class Tag + > +typename basic_uri::string_type username(const basic_uri &uri) { + typename basic_uri::const_range_type user_info_range = uri.user_info_range(); + typename basic_uri::const_iterator_type it(boost::begin(user_info_range)), end(boost::end(user_info_range)); for (; it != end; ++it) { if (*it == ':') { break; } } - return std::string(boost::begin(user_info_range), it); + return typename string::type(boost::begin(user_info_range), it); } -std::string password(const uri &uri_) { - uri::const_range_type user_info_range = uri_.user_info_range(); - uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); +template < + class Tag + > +typename basic_uri::string_type password(const basic_uri &uri) { + typename basic_uri::const_range_type user_info_range = uri.user_info_range(); + typename basic_uri::const_iterator_type it(boost::begin(user_info_range)), end(boost::end(user_info_range)); for (; it != end; ++it) { if (*it == ':') { ++it; break; } } - return std::string(it, boost::end(user_info_range)); + return typename string::type(it, boost::end(user_info_range)); } -std::string decoded_path(const uri &uri_) { - uri::const_range_type path_range = uri_.path_range(); - std::string decoded_path; +template < + class Tag + > +typename basic_uri::string_type decoded_path(const basic_uri &uri) { + typename basic_uri::const_range_type path_range = uri.path_range(); + typename basic_uri::string_type decoded_path; decode(path_range, std::back_inserter(decoded_path)); return decoded_path; } -std::string decoded_query(const uri &uri_) { - uri::const_range_type query_range = uri_.query_range(); - std::string decoded_query; +template < + class Tag + > +typename basic_uri::string_type decoded_query(const basic_uri &uri) { + typename basic_uri::const_range_type query_range = uri.query_range(); + typename basic_uri::string_type decoded_query; decode(query_range, std::back_inserter(decoded_query)); return decoded_query; } -std::string decoded_fragment(const uri &uri_) { - uri::const_range_type fragment_range = uri_.fragment_range(); - std::string decoded_fragment; +template < + class Tag + > +typename basic_uri::string_type decoded_fragment(const basic_uri &uri) { + typename basic_uri::const_range_type fragment_range = uri.fragment_range(); + typename basic_uri::string_type decoded_fragment; decode(fragment_range, std::back_inserter(decoded_fragment)); return decoded_fragment; } diff --git a/boost/network/uri/detail/parse_uri.hpp b/boost/network/uri/detail/parse_uri.hpp new file mode 100644 index 000000000..a4fa0969a --- /dev/null +++ b/boost/network/uri/detail/parse_uri.hpp @@ -0,0 +1,274 @@ +// Copyright 2009, 2010, 2011 Dean Michael Berris, Jeroen Habraken, Glyn Matthews. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_NETWORK_URL_DETAIL_PARSE_URL_HPP_ +# define BOOST_NETWORK_URL_DETAIL_PARSE_URL_HPP_ + + +# ifdef BOOST_NETWORK_NO_LIB +# define BOOST_NETWORK_INLINE inline +# else +# define BOOST_NETWORK_INLINE +# endif // BOOST_NETWORK_NO_LIB + + +#include +#include +#include +#include +#include +#include + + +namespace boost { +namespace network { +namespace uri { +namespace detail { +namespace qi = boost::spirit::qi; + +template < + class String, + typename Iterator + > +struct uri_grammar : qi::grammar()> { + + uri_grammar() : uri_grammar::base_type(start, "uri") { + using boost::spirit::repository::qi::iter_pos; + + // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" + gen_delims %= qi::char_(":/?#[]@"); + // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" + sub_delims %= qi::char_("!$&'()*+,;="); + // reserved = gen-delims / sub-delims + reserved %= gen_delims | sub_delims; + // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + unreserved %= qi::alnum | qi::char_("-._~"); + // pct-encoded = "%" HEXDIG HEXDIG + pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; + + // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + pchar %= qi::raw[ + unreserved | pct_encoded | sub_delims | qi::char_(":@") + ]; + + // segment = *pchar + segment %= qi::raw[*pchar]; + // segment-nz = 1*pchar + segment_nz %= qi::raw[+pchar]; + // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) + segment_nz_nc %= qi::raw[ + +(unreserved | pct_encoded | sub_delims | qi::char_("@")) + ]; + // path-abempty = *( "/" segment ) + path_abempty %= + iter_pos + >> qi::omit[qi::raw[*(qi::char_("/") >> segment)]] + >> iter_pos + ; + // path-absolute = "/" [ segment-nz *( "/" segment ) ] + path_absolute %= + iter_pos + >> qi::omit[qi::raw[ + qi::char_("/") + >> -(segment_nz >> *(qi::char_("/") >> segment)) + ]] + >> iter_pos + ; + // path-rootless = segment-nz *( "/" segment ) + path_rootless %= + iter_pos + >> qi::omit[qi::raw[ + segment_nz >> *(qi::char_("/") >> segment) + ]] + >> iter_pos + ; + // path-empty = 0 + path_empty %= + iter_pos + >> qi::omit[qi::eps] + >> iter_pos + ; + + // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + scheme %= + iter_pos + >> qi::omit[qi::alpha >> *(qi::alnum | qi::char_("+.-"))] + >> iter_pos + ; + + // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) + user_info %= + iter_pos + >> qi::omit[qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))]] + >> iter_pos + ; + + ip_literal %= + qi::lit('[') >> (ipv6address | ipvfuture) >> ']' + ; + + ipvfuture %= + qi::lit('v') >> +qi::xdigit >> '.' >> +( unreserved | sub_delims | ':') + ; + + ipv6address %= qi::raw[ + qi::repeat(6)[h16 >> ':'] >> ls32 + | "::" >> qi::repeat(5)[h16 >> ':'] >> ls32 + | qi::raw[ h16] >> "::" >> qi::repeat(4)[h16 >> ':'] >> ls32 + | qi::raw[ +(*(h16 >> ':')) >> h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 + | qi::raw[qi::repeat(2)[*(h16 >> ':')] >> h16] >> "::" >> qi::repeat(2)[h16 >> ':'] >> ls32 + | qi::raw[qi::repeat(3)[*(h16 >> ':')] >> h16] >> "::" >> h16 >> ':' >> ls32 + | qi::raw[qi::repeat(4)[*(h16 >> ':')] >> h16] >> "::" >> ls32 + | qi::raw[qi::repeat(5)[*(h16 >> ':')] >> h16] >> "::" >> h16 + | qi::raw[qi::repeat(6)[*(h16 >> ':')] >> h16] >> "::" + + ]; + + // ls32 = ( h16 ":" h16 ) / IPv4address + ls32 %= (h16 >> ':' >> h16) | ipv4address + ; + + // h16 = 1*4HEXDIG + h16 %= qi::repeat(1, 4)[qi::xdigit] + ; + + // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 + dec_octet %= + !(qi::lit('0') >> qi::digit) + >> qi::raw[ + qi::uint_parser() + ]; + + // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet + ipv4address %= qi::raw[ + dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] + ]; + + // reg-name = *( unreserved / pct-encoded / sub-delims ) + reg_name %= qi::raw[ + *(unreserved | pct_encoded | sub_delims) + ]; + + // TODO, host = IP-literal / IPv4address / reg-name + host %= + iter_pos + >> qi::omit[ip_literal | ipv4address | reg_name] + >> iter_pos + ; + + // port %= qi::ushort_; + port %= + iter_pos + >> qi::omit[*qi::digit] + >> iter_pos + ; + + // query = *( pchar / "/" / "?" ) + query %= + iter_pos + >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] + >> iter_pos + ; + + // fragment = *( pchar / "/" / "?" ) + fragment %= + iter_pos + >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] + >> iter_pos + ; + + // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty + // authority = [ userinfo "@" ] host [ ":" port ] + hier_part %= + ( + "//" + >> -(user_info >> '@') + >> host + >> -(':' >> port) + >> path_abempty + ) + | + ( + qi::attr(iterator_range()) + >> qi::attr(iterator_range()) + >> qi::attr(iterator_range()) + >> ( + path_absolute + | path_rootless + | path_empty + ) + ) + ; + + start %= + scheme >> ':' + >> hier_part + >> -('?' >> query) + >> -('#' >> fragment) + ; + } + + qi::rule + gen_delims, sub_delims, reserved, unreserved; + qi::rule + pct_encoded, pchar; + + qi::rule + segment, segment_nz, segment_nz_nc; + qi::rule()> + path_abempty, path_absolute, path_rootless, path_empty; + + qi::rule + dec_octet, ipv4address, reg_name, ipv6address, ipvfuture, ip_literal; + + qi::rule + h16, ls32; + + qi::rule()> + host, port; + + qi::rule()> + scheme, user_info, query, fragment; + + qi::rule, + iterator_range, + iterator_range, + iterator_range >()> + hier_part; + + // actual uri parser + qi::rule()> start; + +}; + + +BOOST_NETWORK_INLINE +bool parse(std::string::const_iterator first, + std::string::const_iterator last, + uri_parts &parts) { + namespace qi = boost::spirit::qi; + static detail::uri_grammar grammar; + bool is_valid = qi::parse(first, last, grammar, parts); + return is_valid && (first == last); +} + +BOOST_NETWORK_INLINE +bool parse(std::wstring::const_iterator first, + std::wstring::const_iterator last, + uri_parts &parts) { + namespace qi = boost::spirit::qi; + static uri_grammar grammar; + bool is_valid = qi::parse(first, last, grammar, parts); + return is_valid && (first == last); +} +} // namespace detail +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // BOOST_NETWORK_URL_DETAIL_PARSE_URL_HPP_ + diff --git a/boost/network/uri/detail/uri_parts.hpp b/boost/network/uri/detail/uri_parts.hpp index e069657ae..a2647e1ec 100644 --- a/boost/network/uri/detail/uri_parts.hpp +++ b/boost/network/uri/detail/uri_parts.hpp @@ -8,6 +8,7 @@ # include +# include namespace boost { diff --git a/boost/network/uri/directives.hpp b/boost/network/uri/directives.hpp index 632cf44db..233c630ca 100644 --- a/boost/network/uri/directives.hpp +++ b/boost/network/uri/directives.hpp @@ -16,21 +16,14 @@ namespace boost { namespace network { namespace uri { -inline -uri &operator << (uri &uri_, const uri &root_uri) { - if (empty(uri_) && valid(root_uri)) { - uri_.append(boost::begin(root_uri), boost::end(root_uri)); - } - return uri_; -} - template < - class Directive + class Tag + , class Directive > inline -uri &operator << (uri &uri_, const Directive &directive) { - directive(uri_); - return uri_; +basic_uri &operator << (basic_uri &uri, const Directive &directive) { + directive(uri); + return uri; } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/authority.hpp b/boost/network/uri/directives/authority.hpp index 807de4af7..6e723cfe8 100644 --- a/boost/network/uri/directives/authority.hpp +++ b/boost/network/uri/directives/authority.hpp @@ -2,29 +2,40 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_AUTHORITY_INC__ +# include + + + namespace boost { namespace network { namespace uri { +template < + class ValueType + > struct authority_directive { - explicit authority_directive(const std::string &authority) - : authority(authority) + explicit authority_directive(const ValueType &value) + : value(value) {} template < - class Uri + class Tag + , template class Uri > - void operator () (Uri &uri) const { - uri.append(authority); + void operator () (Uri &uri) const { + uri.append(value); } - std::string authority; + const ValueType &value; }; +template < + class T + > inline -authority_directive authority(const std::string &authority) { - return authority_directive(authority); +authority_directive authority(const T &value) { + return authority_directive(value); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/fragment.hpp b/boost/network/uri/directives/fragment.hpp index 0beadd421..809f1f8a7 100644 --- a/boost/network/uri/directives/fragment.hpp +++ b/boost/network/uri/directives/fragment.hpp @@ -10,27 +10,37 @@ namespace boost { namespace network { namespace uri { +template < + class ValueType + > struct fragment_directive { - explicit fragment_directive(const std::string &fragment) - : fragment(fragment) + explicit fragment_directive(const ValueType &value) + : value(value) {} template < - class Uri + class Tag + , template class Uri > - void operator () (Uri &uri) const { - uri.append("#"); - uri.append(fragment); + void operator () (Uri &uri) const { + typename string::type encoded_value; + static const char separator[] = {'#'}; + uri.append(boost::begin(separator), boost::end(separator)); + encode(boost::as_literal(value), std::back_inserter(encoded_value)); + uri.append(encoded_value); } - std::string fragment; + const ValueType &value; }; +template < + class T + > inline -fragment_directive fragment(const std::string &fragment) { - return fragment_directive(fragment); +fragment_directive fragment(const T &value) { + return fragment_directive(value); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/host.hpp b/boost/network/uri/directives/host.hpp index 75cf1d038..e251edb84 100644 --- a/boost/network/uri/directives/host.hpp +++ b/boost/network/uri/directives/host.hpp @@ -9,26 +9,33 @@ namespace boost { namespace network { namespace uri { +template < + class ValueType + > struct host_directive { - explicit host_directive(const std::string &host) - : host(host) + explicit host_directive(const ValueType &value) + : value(value) {} template < - class Uri + class Tag + , template class Uri > - void operator () (Uri &uri) const { - uri.append(host); + void operator () (Uri &uri) const { + uri.append(value); } - std::string host; + const ValueType &value; }; +template < + class T + > inline -host_directive host(const std::string &host) { - return host_directive(host); +host_directive host(const T &value) { + return host_directive(value); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/path.hpp b/boost/network/uri/directives/path.hpp index 4921a3eb2..d2b1afd5a 100644 --- a/boost/network/uri/directives/path.hpp +++ b/boost/network/uri/directives/path.hpp @@ -9,47 +9,73 @@ namespace boost { namespace network { namespace uri { +template < + class ValueType + > struct path_directive { - explicit path_directive(const std::string &path) - : path(path) + explicit path_directive(const ValueType &value) + : value(value) {} template < - class Uri + class Tag + , template class Uri > - void operator () (Uri &uri) const { - uri.append(path); + void operator () (Uri &uri) const { + (*this)(boost::as_literal(value), uri); } - std::string path; + template < + class Rng + , class Tag + , template class Uri + > + void operator () (const Rng &rng, Uri &uri) const { + uri.append(boost::begin(rng), boost::end(rng)); + } + + const ValueType &value; }; +template < + class ValueType + > struct encoded_path_directive { - explicit encoded_path_directive(const std::string &path) - : path(path) + explicit encoded_path_directive(const ValueType &value) + : value(value) {} - void operator () (uri &uri_) const { - std::string encoded_path; - encode(path, std::back_inserter(encoded_path)); - uri_.append(encoded_path); + template < + class Tag + , template class Uri + > + void operator () (Uri &uri) const { + typename string::type encoded_value; + encode(boost::as_literal(value), std::back_inserter(encoded_value)); + uri.append(encoded_value); } - std::string path; + const ValueType &value; }; +template < + class T + > inline -path_directive path(const std::string &path) { - return path_directive(path); +path_directive path(const T &value) { + return path_directive(value); } +template < + class T + > inline -encoded_path_directive encoded_path(const std::string &path) { - return encoded_path_directive(path); +encoded_path_directive encoded_path(const T &value) { + return encoded_path_directive(value); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/port.hpp b/boost/network/uri/directives/port.hpp index 9e561486b..ae3a9bb88 100644 --- a/boost/network/uri/directives/port.hpp +++ b/boost/network/uri/directives/port.hpp @@ -2,8 +2,9 @@ # define __BOOST_NETWORK_URI_DIRECTIVES_PORT_INC__ +# include +# include # include -# include # include # include @@ -11,36 +12,64 @@ namespace boost { namespace network { namespace uri { +template < + class ValueType + > struct port_directive { - explicit port_directive(const std::string &port) - : port(port) + explicit port_directive(const ValueType &value) + : value(value) {} - explicit port_directive(boost::uint16_t port) - : port(boost::lexical_cast(port)) + template < + class Tag + , template class Uri + > + void operator () (Uri &uri) const { + static const char separator[] = {':'}; + uri.append(boost::begin(separator), boost::end(separator)); + uri.append(value); + } + + const ValueType &value; + +}; + + +struct port_directive_us { + + explicit port_directive_us(boost::uint16_t value) + : value(value) {} template < - class Uri + class Tag + , template class Uri > - void operator () (Uri &uri) const { - uri.append(":"); + void operator () (Uri &uri) const { + static const char separator[] = {':'}; + uri.append(boost::begin(separator), boost::end(separator)); + typename string::type port = boost::lexical_cast::type>(value); uri.append(port); } - std::string port; + boost::uint16_t value; }; + +template < + class T + > inline -port_directive port(const std::string &port) { - return port_directive(port); +port_directive port(const T &value, + typename boost::disable_if::type>::type * = 0) { + return port_directive(value); } inline -port_directive port(boost::uint16_t port) { - return port_directive(port); +port_directive_us port(boost::uint16_t value) { + return port_directive_us(value); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp index d2afbcadf..59eb2ea06 100644 --- a/boost/network/uri/directives/query.hpp +++ b/boost/network/uri/directives/query.hpp @@ -10,61 +10,84 @@ namespace boost { namespace network { namespace uri { +template < + class ValueType + > struct query_directive { - explicit query_directive(const std::string &query) - : query(query) + explicit query_directive(const ValueType &value) + : value(value) {} template < - class Uri + class Tag + , template class Uri > - void operator () (Uri &uri) const { - uri.append("?"); - uri.append(query); + void operator () (Uri &uri) const { + typename string::type encoded_value; + static const char separator[] = {'?'}; + uri.append(boost::begin(separator), boost::end(separator)); + uri.append(value); } - std::string query; + const ValueType &value; }; +template < + class T + > inline -query_directive query(const std::string &query) { - return query_directive(query); +query_directive query(const T &value) { + return query_directive(value); } -struct query_key_query_directive { +template < + class KeyType + , class ValueType + > +struct query_key_value_directive { - query_key_query_directive(const std::string &key, const std::string &query) - : key(key), query(query) + query_key_value_directive(const KeyType &key, const ValueType &value) + : key(key), value(value) {} template < - class Uri + class Tag + , template class Uri > - void operator () (Uri &uri) const { - std::string encoded_key, encoded_query; + void operator () (Uri &uri) const { + typename string::type encoded_key, encoded_value; + static const char qmark[] = {'?'}; + static const char equal[] = {'='}; + static const char scolon[] = {';'}; if (!uri.query_range()) { - uri.append("?"); + uri.append(boost::begin(qmark), boost::end(qmark)); } else { - uri.append(";"); + uri.append(boost::begin(scolon), boost::end(scolon)); } - uri.append(key); - uri.append("="); - uri.append(query); + encode(boost::as_literal(key), std::back_inserter(encoded_key)); + uri.append(encoded_key); + uri.append(boost::begin(equal), boost::end(equal)); + encode(boost::as_literal(value), std::back_inserter(encoded_value)); + uri.append(encoded_value); } - std::string key; - std::string query; + const KeyType &key; + const ValueType &value; }; +template < + class Key + , class Value + > inline -query_key_query_directive query(const std::string &key, const std::string &query) { - return query_key_query_directive(key, query); +query_key_value_directive query(const Key &key, const Value &value) { + return query_key_value_directive(key, value); } } // namespace uri } // namespace network diff --git a/boost/network/uri/directives/scheme.hpp b/boost/network/uri/directives/scheme.hpp index 708436006..27726ac30 100644 --- a/boost/network/uri/directives/scheme.hpp +++ b/boost/network/uri/directives/scheme.hpp @@ -9,28 +9,64 @@ namespace boost { namespace network { namespace uri { +template < + class ValueType + > struct scheme_directive { - explicit scheme_directive(const std::string &scheme) - : scheme(scheme) + explicit scheme_directive(const ValueType &value) + : value(value) {} template < - class Uri + class Tag + , template class Uri > - void operator () (Uri &uri) const { - uri.append(scheme); - uri.append("://"); + void operator () (Uri &uri) const { + static const char separator[] = {':', '/', '/'}; + uri.append(value); + uri.append(boost::begin(separator), boost::end(separator)); } - std::string scheme; + const ValueType &value; }; +template < + class T + > inline -scheme_directive scheme(const std::string &scheme) { - return scheme_directive(scheme); +scheme_directive scheme(const T &value) { + return scheme_directive(value); } + +namespace schemes { +struct scheme_helper { + + scheme_helper(const char *scheme) + : scheme(scheme) { + + } + + template < + class Tag + , template class Uri + > + void operator () (Uri &uri) const { + static const char separator[] = {':', '/', '/'}; + uri.append(boost::begin(scheme), boost::end(scheme)); + uri.append(boost::begin(separator), boost::end(separator)); + } + + std::string scheme; + +}; + +//static scheme_helper http("http"); +//static scheme_helper https("https"); +//static scheme_helper ftp("ftp"); +//static scheme_helper mailto("mailto"); +} // namespace schemes } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/directives/user_info.hpp b/boost/network/uri/directives/user_info.hpp index cd7e7e788..881700a6a 100644 --- a/boost/network/uri/directives/user_info.hpp +++ b/boost/network/uri/directives/user_info.hpp @@ -9,27 +9,35 @@ namespace boost { namespace network { namespace uri { +template < + class ValueType + > struct user_info_directive { - explicit user_info_directive(const std::string &user_info) - : user_info(user_info) + explicit user_info_directive(const ValueType &value) + : value(value) {} template < - class Uri + class Tag + , template class Uri > - void operator () (Uri &uri) const { - uri.append(user_info); - uri.append("@"); + void operator () (Uri &uri) const { + static const char separator[] = {'@'}; + uri.append(value); + uri.append(boost::begin(separator), boost::end(separator)); } - std::string user_info; + const ValueType &value; }; +template < + class T + > inline -user_info_directive user_info(const std::string &user_info) { - return user_info_directive(user_info); +user_info_directive user_info(const T &value) { + return user_info_directive(value); } } // namespace uri } // namespace network diff --git a/boost/network/uri/http/uri.hpp b/boost/network/uri/http/uri.hpp new file mode 100644 index 000000000..ecee3f491 --- /dev/null +++ b/boost/network/uri/http/uri.hpp @@ -0,0 +1,101 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef __BOOST_NETWORK_URI_HTTP_URI_INC__ +# define __BOOST_NETWORK_URI_HTTP_URI_INC__ + + +# include + + +namespace boost { +namespace network { +namespace uri { +namespace http { +template < + class Tag + > +class basic_uri + : public boost::network::uri::basic_uri { + + typedef boost::network::uri::basic_uri base_type; + +public: + + basic_uri() { + + } + + basic_uri(const typename base_type::string_type &uri) : base_type(uri) { + + } + + basic_uri &operator = (const typename base_type::string_type &uri) { + basic_uri(uri).swap(*this); + return *this; + } + +}; +} // namespace http + +template < + class Tag + > +bool is_http(const http::basic_uri &uri) { + static const char scheme_http[] = {'h', 't', 't', 'p'}; + return boost::equal(uri.scheme_range(), scheme_http); +} + +template < + class Tag + > +bool is_https(const http::basic_uri &uri) { + static const char scheme_https[] = {'h', 't', 't', 'p', 's'}; + return boost::equal(uri.scheme_range(), scheme_https); +} + +template < + class Tag + > +inline +bool is_valid(const http::basic_uri &uri) { + return is_http(uri) || is_https(uri); +} + +template < + class Tag + > +inline +typename basic_uri::string_type port(const http::basic_uri &uri) { + typedef typename basic_uri::range_type range_type; + typedef typename basic_uri::string_type string_type; + + static const char default_http_port[] = "80"; + static const char default_https_port[] = "443"; + + range_type scheme = uri.scheme_range(); + range_type port = uri.port_range(); + + if (boost::empty(port)) { + if (is_http(uri)) { + return string_type(boost::begin(default_http_port), + boost::end(default_http_port)); + } + else if (is_https(uri)) { + return string_type(boost::begin(default_https_port), + boost::end(default_https_port)); + } + } + return string_type(boost::begin(port), boost::end(port)); +} + +typedef basic_uri uri; +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_HTTP_URI_INC__ diff --git a/boost/network/uri/mailto/uri.hpp b/boost/network/uri/mailto/uri.hpp new file mode 100644 index 000000000..87490a502 --- /dev/null +++ b/boost/network/uri/mailto/uri.hpp @@ -0,0 +1,80 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef __BOOST_NETWORK_URI_MAILTO_URI_INC__ +# define __BOOST_NETWORK_URI_MAILTO_URI_INC__ + + +# include + + +namespace boost { +namespace network { +namespace uri { +namespace mailto { +namespace details { +template < + class String + > +struct uri_parts + : boost::fusion::vector< + iterator_range // to + // headers + > +{ }; +} // namespace details +} // namespace mailto +} // namespace uri +} // namespace network +} // namespace boost + + +namespace boost { +namespace network { +namespace uri { +namespace mailto { + +template < + class Tag + > +class basic_uri + : public boost::network::uri::basic_uri { + + typedef boost::network::uri::basic_uri base_type; + +public: + + basic_uri() { + + } + + basic_uri(const typename base_type::string_type &uri) : base_type(uri) { + + } + + basic_uri &operator = (const typename base_type::string_type &uri) { + basic_uri(uri).swap(*this); + return *this; + } + + + +}; +} // namespace mailto + +template < + class Tag + > +bool is_mailto(const mailto::basic_uri &uri) { + static const char scheme_mailto[] = {'m', 'a', 'i', 'l', 't', 'o'}; + return boost::equal(uri.scheme_range(), scheme_mailto); +} +} // namespace uri +} // namespace network +} // namespace boost + + +#endif // __BOOST_NETWORK_URI_MAILTO_URI_INC__ diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 0e6371d81..fe7c8e264 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -9,9 +9,13 @@ # include +# include # include # include -# include +# ifdef BOOST_NETWORK_NO_LIB +# include +# endif // #ifdef BOOST_NETWORK_NO_LIB +# include # include # include # include @@ -28,78 +32,75 @@ namespace detail { bool parse(std::string::const_iterator first, std::string::const_iterator last, uri_parts &parts); + +bool parse(std::wstring::const_iterator first, + std::wstring::const_iterator last, + uri_parts &parts); } // namespace detail -class uri - : public boost::equality_comparable { +template < + class Tag + > +class basic_uri + : public boost::equality_comparable > { public: - typedef std::string string_type; - typedef string_type::iterator iterator; - typedef boost::iterator_range range_type; - typedef string_type::const_iterator const_iterator; - typedef boost::iterator_range const_range_type; + typedef typename string::type string_type; + typedef typename string_type::iterator iterator_type; + typedef boost::iterator_range range_type; + typedef typename string_type::const_iterator const_iterator_type; + typedef boost::iterator_range const_range_type; - uri() - : is_valid_(false) { + basic_uri() : is_valid_(false) { } - template < - class FwdIter - > - uri(const FwdIter &first, const FwdIter &last) - : uri_(first, last), is_valid_(false) { - parse(); - } - - uri(const string_type &uri) + basic_uri(const string_type &uri) : uri_(uri), is_valid_(false) { parse(); } - uri(const uri &other) + basic_uri(const basic_uri &other) : uri_(other.uri_), uri_parts_(other.uri_parts_), is_valid_(other.is_valid_) { } - uri &operator = (const uri &other) { - uri(other).swap(*this); + basic_uri &operator = (const basic_uri &other) { + basic_uri(other).swap(*this); return *this; } - uri &operator = (const string_type &uri) { - uri_ = uri; - parse(); + basic_uri &operator = (const string_type &uri) { + basic_uri(uri).swap(*this); return *this; } - ~uri() { + ~basic_uri() { } - void swap(uri &other) { + void swap(basic_uri &other) { boost::swap(uri_, other.uri_); parse(); } - iterator begin() { + iterator_type begin() { return uri_.begin(); } - const_iterator begin() const { + const_iterator_type begin() const { return uri_.begin(); } - iterator end() { + iterator_type end() { return uri_.end(); } - const_iterator end() const { + const_iterator_type end() const { return uri_.end(); } @@ -194,9 +195,9 @@ class uri } template < - class FwdIter + class Iterator > - void append(const FwdIter &first, const FwdIter &last) { + void append(Iterator first, Iterator last) { uri_.append(first, last); parse(); } @@ -206,128 +207,157 @@ class uri void parse(); string_type uri_; - detail::uri_parts uri_parts_; + detail::uri_parts::type> uri_parts_; bool is_valid_; }; +template < + class Tag + > inline -void uri::parse() { - const_iterator first(boost::begin(uri_)), last(boost::end(uri_)); +void basic_uri::parse() { + const_iterator_type first(boost::begin(uri_)), last(boost::end(uri_)); is_valid_ = detail::parse(first, last, uri_parts_); } +template < + class Tag + > inline -std::string scheme(const uri &uri_) { - return uri_.scheme(); +void swap(basic_uri &lhs, basic_uri &rhs) { + lhs.swap(rhs); } +template < + class Tag + > inline -std::string user_info(const uri &uri_) { - return uri_.user_info(); +typename basic_uri::string_type scheme(const basic_uri &uri) { + return uri.scheme(); } +template < + class Tag + > inline -std::string host(const uri &uri_) { - return uri_.host(); +typename basic_uri::string_type user_info(const basic_uri &uri) { + return uri.user_info(); } +template < + class Tag + > inline -std::string port(const uri &uri_) { - return uri_.port(); +typename basic_uri::string_type host(const basic_uri &uri) { + return uri.host(); } +template < + class Tag + > inline -boost::optional port_us(const uri &uri_) { - std::string port = uri_.port(); - return (port.empty())? - boost::optional() : - boost::optional(boost::lexical_cast(port)); +typename basic_uri::string_type port(const basic_uri &uri) { + return uri.port(); } -inline -std::string path(const uri &uri_) { - return uri_.path(); -} +template < + class Tag + > +struct port_wrapper { + const basic_uri &uri; -inline -std::string query(const uri &uri_) { - return uri_.query(); -} + port_wrapper(const basic_uri &uri) : uri(uri) { -inline -std::string fragment(const uri &uri_) { - return uri_.fragment(); -} + } -inline -std::string authority(const uri &uri_) { - uri::const_range_type user_info(uri_.user_info_range()); - uri::const_range_type port(uri_.port_range()); - return std::string(user_info.begin(), port.end()); -} + boost::optional to_optional() const { + typename basic_uri::string_type port = uri.port(); + return (port.empty())? + boost::optional() : + boost::optional(boost::lexical_cast(port)); + } -inline -std::string netloc(const uri &uri_) { - return authority(uri_); -} + operator boost::optional () const { + return to_optional(); + } -inline -bool valid(const uri &uri_) { - return uri_.is_valid(); -} + operator unsigned short () const { + typedef typename string::type string_type; + typedef constants consts; + const boost::optional &port = to_optional(); + if (port) return *port; + return boost::iequals(uri.scheme_range(), string_type(consts::https())) ? 443 : 80; + } +}; +template < + class Tag + > inline -bool is_valid(const uri &uri_) { - return valid(uri_); +port_wrapper port_us(const basic_uri &uri) { + return port_wrapper(uri); } +template < + class Tag + > inline -bool is_hierarchical(const uri &uri_) { - //uri::const_range_type scheme = uri_.scheme_range(); - //uri::const_range_type user_info = uri_.user_info_range(); - //return is_valid(uri_) && - // boost::equal(std::make_pair(boost::end(scheme), - // boost::begin(user_info)), - // boost::as_literal("://")); - return false; -} - -bool is_opaque(const uri &uri_) { - return false; +typename basic_uri::string_type path(const basic_uri &uri) { + return uri.path(); } +template < + class Tag + > inline -bool operator == (const uri &lhs, const uri &rhs) { - return std::equal(lhs.begin(), lhs.end(), rhs.begin()); +typename basic_uri::string_type query(const basic_uri &uri) { + return uri.query(); } -} // namespace uri -} // namespace network +template < + class Tag + > inline -network::uri::uri::iterator begin(network::uri::uri &uri_) { - return uri_.begin(); +typename basic_uri::string_type fragment(const basic_uri &uri) { + return uri.fragment(); } +template < + class Tag + > inline -network::uri::uri::iterator end(network::uri::uri &uri_) { - return uri_.end(); +typename basic_uri::string_type authority(const basic_uri &uri) { + typename basic_uri::const_range_type user_info(uri.user_info_range()); + typename basic_uri::const_range_type port(uri.port_range()); + return typename basic_uri::string_type(user_info.begin(), port.end()); } +template < + class Tag + > inline -network::uri::uri::const_iterator begin(const network::uri::uri &uri_) { - return uri_.begin(); +typename basic_uri::string_type netloc(const basic_uri &uri) { + return authority(uri); } +template < + class Tag + > inline -network::uri::uri::const_iterator end(const network::uri::uri &uri_) { - return uri_.end(); +bool is_valid(const basic_uri &uri) { + return uri.is_valid(); } +template < + class Tag + > inline -void swap(network::uri::uri &lhs, network::uri::uri &rhs) { - lhs.swap(rhs); +bool operator == (const basic_uri &lhs, const basic_uri &rhs) { + return std::equal(lhs.begin(), lhs.end(), rhs.begin()); } +} // namespace uri +} // namespace network } // namespace boost diff --git a/boost/network/uri/uri_io.hpp b/boost/network/uri/uri_io.hpp index f900953d8..efff221f4 100644 --- a/boost/network/uri/uri_io.hpp +++ b/boost/network/uri/uri_io.hpp @@ -3,15 +3,17 @@ # include -# include namespace boost { namespace network { namespace uri { +template < + class Tag + > inline -std::ostream &operator << (std::ostream &os, const uri &uri_) { - return os << uri_.string(); +std::ostream &operator << (std::ostream &os, const basic_uri &uri) { + return os << uri.string(); } } // namespace uri } // namespace network diff --git a/libs/network/build/CMakeLists.txt b/libs/network/build/CMakeLists.txt index 8111a37b7..3ed21b20d 100644 --- a/libs/network/build/CMakeLists.txt +++ b/libs/network/build/CMakeLists.txt @@ -1,6 +1,6 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) find_package( Boost 1.43.0 COMPONENTS unit_test_framework system regex thread filesystem ) -add_library(cppnetlib-uri STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/parse_uri_impl.cpp) +add_library(cppnetlib-uri-parsers STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/parse_uri_impl.cpp) add_library(cppnetlib-server-parsers STATIC ${CPP-NETLIB_SOURCE_DIR}/libs/network/src/server_request_parsers_impl.cpp) diff --git a/libs/network/build/Jamfile.v2 b/libs/network/build/Jamfile.v2 index f0fd0af91..1a9e18906 100644 --- a/libs/network/build/Jamfile.v2 +++ b/libs/network/build/Jamfile.v2 @@ -18,13 +18,13 @@ project cpp-netlib : cpp-pch client : boost/network/include/http/client.hpp ; cpp-pch server : boost/network/include/http/server.hpp ; -lib cppnetlib-uri : libs/network/src/parse_uri_impl.cpp ; +lib cppnetlib-uri-parsers : libs/network/src/parse_uri_impl.cpp ; lib cppnetlib-server-parsers : libs/network/src/server_request_parsers_impl.cpp ; install headers : client server : ../../../boost/network/include/http ; -install libraries : cppnetlib-uri cppnetlib-server-parsers ; +install libraries : cppnetlib-uri-parsers cppnetlib-server-parsers ; -alias all : headers ; +alias all : headers ; diff --git a/libs/network/example/Jamfile.v2 b/libs/network/example/Jamfile.v2 index df6ebde7c..f09d9332c 100644 --- a/libs/network/example/Jamfile.v2 +++ b/libs/network/example/Jamfile.v2 @@ -21,19 +21,19 @@ project network_test : debug:BOOST_NETWORK_DEBUG ; -exe http_client : http_client.cpp /cpp-netlib//cppnetlib-uri ; +exe http_client : http_client.cpp /cpp-netlib//cppnetlib-uri-parsers ; # exe dispatch_table : dispatch_table.cpp ; -exe uri : uri.cpp /cpp-netlib//cppnetlib-uri ; +exe uri : uri.cpp /cpp-netlib//cppnetlib-uri-parsers ; -exe simple_wget : simple_wget.cpp /cpp-netlib//cppnetlib-uri ; +exe simple_wget : simple_wget.cpp /cpp-netlib//cppnetlib-uri-parsers ; exe hello_world_server : http/hello_world_server.cpp /cpp-netlib//cppnetlib-server-parsers ; -exe hello_world_client : http/hello_world_client.cpp /cpp-netlib//cppnetlib-uri ; +exe hello_world_client : http/hello_world_client.cpp /cpp-netlib//cppnetlib-uri-parsers ; -exe one_liner : http/one_liner.cpp /cpp-netlib//cppnetlib-uri ; +exe one_liner : http/one_liner.cpp /cpp-netlib//cppnetlib-uri-parsers ; exe fileserver : http/fileserver.cpp /cpp-netlib//cppnetlib-server-parsers ; diff --git a/libs/network/example/uri.cpp b/libs/network/example/uri.cpp index 412849a85..72c46e205 100644 --- a/libs/network/example/uri.cpp +++ b/libs/network/example/uri.cpp @@ -27,13 +27,13 @@ int main(int argc, char * argv[]) { std::string("a valid") : std::string("an invalid")) << " URI!" << std::endl; - ///*<< Create a `boost::network::http::uri` object from the input. >>*/ - //boost::network::uri::http::uri http_uri_(input); - ///*<< Check if it's a valid HTTP URI. >>*/ - //std::cout << "It's also " - // << (boost::network::uri::is_valid(http_uri_)? - // std::string("a valid HTTP URI") : std::string("an invalid HTTP URI.")) - // << "!" << std::endl; + /*<< Create a `boost::network::http::uri` object from the input. >>*/ + boost::network::uri::http::uri http_uri_(input); + /*<< Check if it's a valid HTTP URI. >>*/ + std::cout << "It's also " + << (boost::network::uri::is_valid(http_uri_)? + std::string("a valid HTTP URI") : std::string("an invalid HTTP URI.")) + << "!" << std::endl; return EXIT_SUCCESS; } diff --git a/libs/network/src/CMakeLists.txt b/libs/network/src/CMakeLists.txt index 7a840a609..8506a5a2c 100644 --- a/libs/network/src/CMakeLists.txt +++ b/libs/network/src/CMakeLists.txt @@ -13,7 +13,7 @@ if (OPENSSL_FOUND) endif() set(CPP-NETLIB_URI_SRCS uri/parse.cpp) -add_library(cppnetlib-uri ${CPP-NETLIB_URI_SRCS}) +add_library(cppnetlib-uri-parsers ${CPP-NETLIB_URI_SRCS}) set(CPP-NETLIB_HTTP_SERVER_SRCS server_request_parsers_impl.cpp) add_library(cppnetlib-server-parsers ${CPP-NETLIB_HTTP_SERVER_SRCS}) diff --git a/libs/network/src/parse_uri_impl.cpp b/libs/network/src/parse_uri_impl.cpp new file mode 100644 index 000000000..7de09346b --- /dev/null +++ b/libs/network/src/parse_uri_impl.cpp @@ -0,0 +1,13 @@ + +// Copyright 2010-2011 Dean Michael Berris. +// Copyright 2009 Jeroen Habraken. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifdef BOOST_NETWORK_NO_LIB +#undef BOOST_NETWORK_NO_LIB +#endif + +#include + diff --git a/libs/network/src/uri/parse.cpp b/libs/network/src/uri/parse.cpp index 972859b9b..4aadb2628 100644 --- a/libs/network/src/uri/parse.cpp +++ b/libs/network/src/uri/parse.cpp @@ -4,253 +4,9 @@ // http://www.boost.org/LICENSE_1_0.txt) -#include -#include -#include -#include -#include -#include +#ifdef BOOST_NETWORK_NO_LIB +# undef BOOST_NETWORK_NO_LIB +#endif // BOOST_NETWORK_NO_LIB -namespace boost { -namespace network { -namespace uri { -namespace detail { -namespace qi = boost::spirit::qi; - -template < - class String, - typename Iterator - > -struct uri_grammar : qi::grammar()> { - - uri_grammar() : uri_grammar::base_type(start, "uri") { - using boost::spirit::repository::qi::iter_pos; - - // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" - gen_delims %= qi::char_(":/?#[]@"); - // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" - sub_delims %= qi::char_("!$&'()*+,;="); - // reserved = gen-delims / sub-delims - reserved %= gen_delims | sub_delims; - // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - unreserved %= qi::alnum | qi::char_("-._~"); - // pct-encoded = "%" HEXDIG HEXDIG - pct_encoded %= qi::char_("%") >> qi::repeat(2)[qi::xdigit]; - - // pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - pchar %= qi::raw[ - unreserved | pct_encoded | sub_delims | qi::char_(":@") - ]; - - // segment = *pchar - segment %= qi::raw[*pchar]; - // segment-nz = 1*pchar - segment_nz %= qi::raw[+pchar]; - // segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) - segment_nz_nc %= qi::raw[ - +(unreserved | pct_encoded | sub_delims | qi::char_("@")) - ]; - // path-abempty = *( "/" segment ) - path_abempty %= - iter_pos - >> qi::omit[qi::raw[*(qi::char_("/") >> segment)]] - >> iter_pos - ; - // path-absolute = "/" [ segment-nz *( "/" segment ) ] - path_absolute %= - iter_pos - >> qi::omit[qi::raw[ - qi::char_("/") - >> -(segment_nz >> *(qi::char_("/") >> segment)) - ]] - >> iter_pos - ; - // path-rootless = segment-nz *( "/" segment ) - path_rootless %= - iter_pos - >> qi::omit[qi::raw[ - segment_nz >> *(qi::char_("/") >> segment) - ]] - >> iter_pos - ; - // path-empty = 0 - path_empty %= - iter_pos - >> qi::omit[qi::eps] - >> iter_pos - ; - - // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) - scheme %= - iter_pos - >> qi::omit[qi::alpha >> *(qi::alnum | qi::char_("+.-"))] - >> iter_pos - ; - - // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) - user_info %= - iter_pos - >> qi::omit[qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))]] - >> iter_pos - ; - - ip_literal %= - qi::lit('[') >> (ipv6address | ipvfuture) >> ']' - ; - - ipvfuture %= - qi::lit('v') >> +qi::xdigit >> '.' >> +( unreserved | sub_delims | ':') - ; - - ipv6address %= qi::raw[ - qi::repeat(6)[h16 >> ':'] >> ls32 - | "::" >> qi::repeat(5)[h16 >> ':'] >> ls32 - | qi::raw[ h16] >> "::" >> qi::repeat(4)[h16 >> ':'] >> ls32 - | qi::raw[ +(*(h16 >> ':')) >> h16] >> "::" >> qi::repeat(3)[h16 >> ':'] >> ls32 - | qi::raw[qi::repeat(2)[*(h16 >> ':')] >> h16] >> "::" >> qi::repeat(2)[h16 >> ':'] >> ls32 - | qi::raw[qi::repeat(3)[*(h16 >> ':')] >> h16] >> "::" >> h16 >> ':' >> ls32 - | qi::raw[qi::repeat(4)[*(h16 >> ':')] >> h16] >> "::" >> ls32 - | qi::raw[qi::repeat(5)[*(h16 >> ':')] >> h16] >> "::" >> h16 - | qi::raw[qi::repeat(6)[*(h16 >> ':')] >> h16] >> "::" - - ]; - - // ls32 = ( h16 ":" h16 ) / IPv4address - ls32 %= (h16 >> ':' >> h16) | ipv4address - ; - - // h16 = 1*4HEXDIG - h16 %= qi::repeat(1, 4)[qi::xdigit] - ; - - // dec-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35 - dec_octet %= - !(qi::lit('0') >> qi::digit) - >> qi::raw[ - qi::uint_parser() - ]; - - // IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet - ipv4address %= qi::raw[ - dec_octet >> qi::repeat(3)[qi::lit('.') >> dec_octet] - ]; - - // reg-name = *( unreserved / pct-encoded / sub-delims ) - reg_name %= qi::raw[ - *(unreserved | pct_encoded | sub_delims) - ]; - - // TODO, host = IP-literal / IPv4address / reg-name - host %= - iter_pos - >> qi::omit[ip_literal | ipv4address | reg_name] - >> iter_pos - ; - - // port %= qi::ushort_; - port %= - iter_pos - >> qi::omit[*qi::digit] - >> iter_pos - ; - - // query = *( pchar / "/" / "?" ) - query %= - iter_pos - >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] - >> iter_pos - ; - - // fragment = *( pchar / "/" / "?" ) - fragment %= - iter_pos - >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] - >> iter_pos - ; - - // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty - // authority = [ userinfo "@" ] host [ ":" port ] - hier_part %= - ( - "//" - >> -(user_info >> '@') - >> host - >> -(':' >> port) - >> path_abempty - ) - | - ( - qi::attr(iterator_range()) - >> qi::attr(iterator_range()) - >> qi::attr(iterator_range()) - >> ( - path_absolute - | path_rootless - | path_empty - ) - ) - ; - - start %= - scheme >> ':' - >> hier_part - >> -('?' >> query) - >> -('#' >> fragment) - ; - } - - qi::rule - gen_delims, sub_delims, reserved, unreserved; - qi::rule - pct_encoded, pchar; - - qi::rule - segment, segment_nz, segment_nz_nc; - qi::rule()> - path_abempty, path_absolute, path_rootless, path_empty; - - qi::rule - dec_octet, ipv4address, reg_name, ipv6address, ipvfuture, ip_literal; - - qi::rule - h16, ls32; - - qi::rule()> - host, port; - - qi::rule()> - scheme, user_info, query, fragment; - - qi::rule, - iterator_range, - iterator_range, - iterator_range >()> - hier_part; - - // actual uri parser - qi::rule()> start; - -}; - -bool parse(std::string::const_iterator first, - std::string::const_iterator last, - uri_parts &parts) { - namespace qi = boost::spirit::qi; - static detail::uri_grammar grammar; - bool is_valid = qi::parse(first, last, grammar, parts); - return is_valid && (first == last); -} - -bool parse(std::wstring::const_iterator first, - std::wstring::const_iterator last, - uri_parts &parts) { - namespace qi = boost::spirit::qi; - static uri_grammar grammar; - bool is_valid = qi::parse(first, last, grammar, parts); - return is_valid && (first == last); -} -} // namespace detail -} // namespace uri -} // namespace network -} // namespace boost +#include diff --git a/libs/network/test/Jamfile.v2 b/libs/network/test/Jamfile.v2 index c04d04fbe..f9ea75977 100644 --- a/libs/network/test/Jamfile.v2 +++ b/libs/network/test/Jamfile.v2 @@ -49,6 +49,6 @@ build-project http ; run message_test.cpp ; run message_transform_test.cpp ; -run url_test.cpp /cpp-netlib//cppnetlib-uri ; +run url_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; run client_server_include_failure.cpp ; diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 59738ece5..3490a36fd 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -29,13 +29,8 @@ if (Boost_FOUND) PROPERTIES COMPILE_FLAGS "-Wall") endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) -<<<<<<< HEAD add_dependencies(cpp-netlib-http-${test} cppnetlib-uri-parsers) target_link_libraries(cpp-netlib-http-${test} ${BOOST_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) -======= - add_dependencies(cpp-netlib-http-${test} cppnetlib-uri) - target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) ->>>>>>> cd5b00337224ee166982f4ce954d2d55b906d7da if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) endif() diff --git a/libs/network/test/http/Jamfile.v2 b/libs/network/test/http/Jamfile.v2 index c5f317858..b62c5b0f5 100644 --- a/libs/network/test/http/Jamfile.v2 +++ b/libs/network/test/http/Jamfile.v2 @@ -15,21 +15,21 @@ project network_test/http : debug:BOOST_NETWORK_DEBUG ; -run client_constructor_test.cpp /cpp-netlib//cppnetlib-uri ; -run client_get_test.cpp /cpp-netlib//cppnetlib-uri ; -run client_get_different_port_test.cpp /cpp-netlib//cppnetlib-uri ; -run client_get_timeout_test.cpp /cpp-netlib//cppnetlib-uri ; +run client_constructor_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run client_get_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run client_get_different_port_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run client_get_timeout_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; run client_include_inlined.cpp : BOOST_NETWORK_NO_LIB ; -run client_localhost_normal_test.cpp /cpp-netlib//cppnetlib-uri ; -run client_localhost_ssl_test.cpp /cpp-netlib//cppnetlib-uri ; +run client_localhost_normal_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; +run client_localhost_ssl_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; run message_async_ready_test.cpp ; -run message_test.cpp /cpp-netlib//cppnetlib-uri ; +run message_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; run request_incremental_parser_test.cpp ; -run request_linearize_test.cpp /cpp-netlib//cppnetlib-uri ; +run request_linearize_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; run response_incremental_parser_test.cpp /cpp-netlib//cppnetlib-server-parsers ; run server_constructor_test.cpp /cpp-netlib//cppnetlib-server-parsers ; run server_include_inlined.cpp : BOOST_NETWORK_NO_LIB ; -run url_test.cpp /cpp-netlib//cppnetlib-uri ; +run url_test.cpp /cpp-netlib//cppnetlib-uri-parsers ; exe http_async_server : server_async.cpp /cpp-netlib//cppnetlib-server-parsers ; exe hello_world : server_hello_world.cpp /cpp-netlib//cppnetlib-server-parsers ; diff --git a/libs/network/test/uri/CMakeLists.txt b/libs/network/test/uri/CMakeLists.txt index c433232cd..e6faeec83 100644 --- a/libs/network/test/uri/CMakeLists.txt +++ b/libs/network/test/uri/CMakeLists.txt @@ -27,4 +27,5 @@ if (Boost_FOUND) add_test(cpp-netlib-${test} ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-${test}) endforeach (test) + endif() diff --git a/libs/network/test/uri/url_builder_test.cpp b/libs/network/test/uri/url_builder_test.cpp index fb55e96ad..6135cc0b3 100644 --- a/libs/network/test/uri/url_builder_test.cpp +++ b/libs/network/test/uri/url_builder_test.cpp @@ -6,7 +6,6 @@ #define BOOST_TEST_MODULE URI builder test #include #include -#include #include #include #include @@ -19,138 +18,232 @@ using namespace boost::network; +typedef boost::mpl::list< + tags::default_string + , tags::default_wstring + > tag_types; -BOOST_AUTO_TEST_CASE(builder_test) -{ - uri::uri instance; - instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); -} -BOOST_AUTO_TEST_CASE(full_uri_builder_test) +BOOST_AUTO_TEST_CASE_TEMPLATE(builder_test, T, tag_types) { - uri::uri instance; - instance << uri::scheme("http") - << uri::user_info("user:password") - << uri::host("www.example.com") - << uri::port("80") - << uri::path("/path") - << uri::query("query") - << uri::fragment("fragment") + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + + uri_type instance; + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::path(string_type(boost::begin(path), boost::end(path))) ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::user_info(instance), "user:password"); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); - BOOST_CHECK(uri::port_us(instance)); - BOOST_CHECK_EQUAL(uri::port_us(instance).get(), 80); - BOOST_CHECK_EQUAL(uri::port(instance), "80"); - BOOST_CHECK_EQUAL(uri::path(instance), "/path"); - BOOST_CHECK_EQUAL(uri::query(instance), "query"); - BOOST_CHECK_EQUAL(uri::fragment(instance), "fragment"); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE(port_test) +BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_builder_test, T, tag_types) { - uri::uri instance; - instance << uri::scheme("http") << uri::host("www.example.com") << uri::port(8000) << uri::path("/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); - BOOST_CHECK_EQUAL(uri::port(instance), "8000"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string user_info("user:password"); + const std::string host("www.example.com"); + const std::string port("80"); + const std::string path("/path"); + const std::string query("query"); + const std::string fragment("fragment"); + + uri_type instance; + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::user_info(string_type(boost::begin(user_info), boost::end(user_info))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::port(string_type(boost::begin(port), boost::end(port))) + << uri::path(string_type(boost::begin(path), boost::end(path))) + << uri::query(string_type(boost::begin(query), boost::end(query))) + << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))) + ; + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK_EQUAL(static_cast(uri::port_us(instance)), 80); + BOOST_CHECK(boost::equal(uri::port(instance), port)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::query(instance), query)); + BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); } -BOOST_AUTO_TEST_CASE(encoded_path_test) +BOOST_AUTO_TEST_CASE_TEMPLATE(port_test, T, tag_types) { - uri::uri instance; - instance << uri::scheme("http") - << uri::host("www.example.com") + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string port("8000"); + const std::string path("/"); + + uri_type instance; + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::port(8000) << uri::path("/"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) << uri::port(8000) - << uri::encoded_path("/Path With (Some) Encoded Characters!") + << uri::path(string_type(boost::begin(path), boost::end(path))) ; - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); - BOOST_CHECK_EQUAL(uri::port(instance), "8000"); - BOOST_CHECK_EQUAL(uri::path(instance), "/Path%20With%20%28Some%29%20Encoded%20Characters%21"); - BOOST_CHECK_EQUAL(uri::decoded_path(instance), "/Path With (Some) Encoded Characters!"); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::port(instance), port)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); } -BOOST_AUTO_TEST_CASE(query_test) +BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_path_test, T, tag_types) { - uri::uri instance; - instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") - << uri::query("key", "value") + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string port("8000"); + const std::string encoded_path("/Path%20With%20%28Some%29%20Encoded%20Characters%21"); + const std::string decoded_path("/Path With (Some) Encoded Characters!"); + + uri_type instance; + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::port(8000) + << uri::encoded_path(string_type(boost::begin(decoded_path), boost::end(decoded_path))) + //<< uri::path(uri::encoded(string_type(boost::begin(decoded_path), boost::end(decoded_path)))) ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); - BOOST_CHECK_EQUAL(uri::query(instance), "key=value"); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::port(instance), port)); + BOOST_CHECK(boost::equal(uri::path(instance), encoded_path)); + BOOST_CHECK(boost::equal(uri::decoded_path(instance), decoded_path)); } -BOOST_AUTO_TEST_CASE(query_2_test) +BOOST_AUTO_TEST_CASE_TEMPLATE(query_test, T, tag_types) { - uri::uri instance; - instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") - << uri::query("key1", "value1") << uri::query("key2", "value2") - ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); - BOOST_CHECK_EQUAL(uri::query(instance), "key1=value1;key2=value2"); + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + const std::string query("key=value"); + const std::string query_key("key"); + const std::string query_value("value"); + + uri_type instance; + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::path(string_type(boost::begin(path), boost::end(path))) + << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), + string_type(boost::begin(query_value), boost::end(query_value))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::query(instance), query)); } -BOOST_AUTO_TEST_CASE(fragment_test) +BOOST_AUTO_TEST_CASE_TEMPLATE(query_2_test, T, tag_types) { - uri::uri instance; - instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") << uri::fragment("fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); - BOOST_CHECK_EQUAL(uri::fragment(instance), "fragment"); + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + const std::string query("key=value;key=value"); + const std::string query_key("key"); + const std::string query_value("value"); + + uri_type instance; + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::path(string_type(boost::begin(path), boost::end(path))) + << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), + string_type(boost::begin(query_value), boost::end(query_value))) + << uri::query(string_type(boost::begin(query_key), boost::end(query_key)), + string_type(boost::begin(query_value), boost::end(query_value))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::query(instance), query)); } -BOOST_AUTO_TEST_CASE(from_root_test) +BOOST_AUTO_TEST_CASE_TEMPLATE(fragment_test, T, tag_types) { - uri::uri root_uri("http://www.example.com/"); - uri::uri instance; - instance << root_uri << uri::path("/") << uri::fragment("fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); - BOOST_CHECK_EQUAL(uri::fragment(instance), "fragment"); + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + const std::string fragment("fragment"); + + uri_type instance; + //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/") << uri::fragment("fragment"); + instance << uri::scheme(string_type(boost::begin(scheme), boost::end(scheme))) + << uri::host(string_type(boost::begin(host), boost::end(host))) + << uri::path(string_type(boost::begin(path), boost::end(path))) + << uri::fragment(string_type(boost::begin(fragment), boost::end(fragment))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); } -//BOOST_AUTO_TEST_CASE(scheme_test) +//BOOST_AUTO_TEST_CASE_TEMPLATE(scheme_test, T, tag_types) //{ +// typedef uri::basic_uri uri_type; +// typedef typename uri_type::string_type string_type; +// +// const std::string scheme("http"); +// const std::string host("www.example.com"); +// const std::string path("/"); +// // uri_type instance; -// instance << uri::schemes::http << uri::host("www.example.com") << uri::path("/"); -// BOOST_REQUIRE(uri::valid(instance)); -// BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); -// BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); -// BOOST_CHECK_EQUAL(uri::path(instance), "/"); +// //instance << uri::scheme("http") << uri::host("www.example.com") << uri::path("/"); +// instance << uri::schemes::http +// << uri::host(string_type(boost::begin(host), boost::end(host))) +// << uri::path(string_type(boost::begin(path), boost::end(path))) +// ; +// BOOST_REQUIRE(uri::is_valid(instance)); +// BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); +// BOOST_CHECK(boost::equal(uri::host(instance), host)); +// BOOST_CHECK(boost::equal(uri::path(instance), path)); //} BOOST_AUTO_TEST_CASE(encoded_null_char_test) { + typedef uri::basic_uri uri_type; + typedef uri_type::string_type string_type; + + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + + uri_type instance; // there is a potential bug in the way we process ranges if the // strings are null terminated. - uri::uri instance; instance << uri::scheme("http") << uri::host("www.example.com") << uri::encoded_path("/") ; - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK_EQUAL(uri::scheme(instance), scheme); + BOOST_CHECK_EQUAL(uri::host(instance), host); + BOOST_CHECK_EQUAL(uri::path(instance), path); } diff --git a/libs/network/test/uri/url_encoding_test.cpp b/libs/network/test/uri/url_encoding_test.cpp index 6ca37939b..bc08f8c1c 100644 --- a/libs/network/test/uri/url_encoding_test.cpp +++ b/libs/network/test/uri/url_encoding_test.cpp @@ -8,26 +8,41 @@ #include #include #include +#include +#include +#include +#include +#include #include using namespace boost::network; +typedef boost::mpl::list< + tags::default_string + , tags::default_wstring + > tag_types; + + +BOOST_AUTO_TEST_CASE_TEMPLATE(encoding_test, T, tag_types) { + typedef typename string::type string_type; -BOOST_AUTO_TEST_CASE(encoding_test) { const std::string unencoded(" !\"#$%&\'()*"); const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A"); - std::string instance; + string_type instance; uri::encode(unencoded, std::back_inserter(instance)); - BOOST_CHECK_EQUAL(instance, encoded); + BOOST_CHECK(boost::equal(instance, encoded)); } -BOOST_AUTO_TEST_CASE(decoding_test) { + +BOOST_AUTO_TEST_CASE_TEMPLATE(decoding_test, T, tag_types) { + typedef typename string::type string_type; + const std::string unencoded(" !\"#$%&\'()*"); const std::string encoded("%20%21%22%23%24%25%26%27%28%29%2A"); - std::string instance; + string_type instance; uri::decode(encoded, std::back_inserter(instance)); - BOOST_CHECK_EQUAL(instance, unencoded); + BOOST_CHECK(boost::equal(instance, unencoded)); } diff --git a/libs/network/test/uri/url_http_test.cpp b/libs/network/test/uri/url_http_test.cpp new file mode 100644 index 000000000..ed162df89 --- /dev/null +++ b/libs/network/test/uri/url_http_test.cpp @@ -0,0 +1,61 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#define BOOST_TEST_MODULE HTTP URL Test +#include +#include +#include +#include +#include + +using namespace boost::network; + +typedef boost::mpl::list< + tags::default_string + , tags::default_wstring + > tag_types; + + +BOOST_AUTO_TEST_CASE_TEMPLATE(valid_http, T, tag_types) +{ + typedef uri::http::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + const std::string url("http://example.com/"); + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_http(instance)); + BOOST_REQUIRE(uri::is_valid(instance)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(valid_https, T, tag_types) +{ + typedef uri::http::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + const std::string url("https://example.com/"); + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_https(instance)); + BOOST_REQUIRE(uri::is_valid(instance)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(invalid_https, T, tag_types) +{ + typedef uri::http::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + const std::string url("http://example.com/"); + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(!uri::is_https(instance)); + BOOST_REQUIRE(uri::is_valid(instance)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(not_http, T, tag_types) +{ + typedef uri::http::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + const std::string url("/service/mailto:john.doe@example.com"); + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(!uri::is_http(instance)); + BOOST_REQUIRE(!uri::is_https(instance)); + BOOST_REQUIRE(!uri::is_valid(instance)); +} diff --git a/libs/network/test/uri/url_mailto_test.cpp b/libs/network/test/uri/url_mailto_test.cpp new file mode 100644 index 000000000..8765748fe --- /dev/null +++ b/libs/network/test/uri/url_mailto_test.cpp @@ -0,0 +1,30 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#define BOOST_TEST_MODULE mailto URL Test +#include +#include +#include +#include +#include + +using namespace boost::network; + +typedef boost::mpl::list< + tags::default_string + , tags::default_wstring + > tag_types; + + +BOOST_AUTO_TEST_CASE_TEMPLATE(valid_mailto, T, tag_types) +{ + typedef uri::mailto::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + const std::string url("/service/mailto:john.doe@example.com"); + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_mailto(instance)); + BOOST_REQUIRE(uri::is_valid(instance)); +} diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index e56f4a327..b0a313168 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -6,205 +6,309 @@ #define BOOST_TEST_MODULE URL Test #include #include -#include #include -#include +#include +#include +#include #include +#include +#include #include using namespace boost::network; -BOOST_AUTO_TEST_CASE(basic_uri_range_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); - BOOST_CHECK(boost::empty(instance.user_info_range())); - BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); - BOOST_CHECK(boost::empty(instance.port_range())); - BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/"))); - BOOST_CHECK(boost::empty(instance.query_range())); - BOOST_CHECK(boost::empty(instance.fragment_range())); -} - -BOOST_AUTO_TEST_CASE(full_uri_range_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); - BOOST_CHECK(boost::equal(instance.user_info_range(), boost::as_literal("user:password"))); - BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); - BOOST_CHECK(boost::equal(instance.port_range(), boost::as_literal("80"))); - BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/path"))); - BOOST_CHECK(boost::equal(instance.query_range(), boost::as_literal("query"))); - BOOST_CHECK(boost::equal(instance.fragment_range(), boost::as_literal("fragment"))); -} - -BOOST_AUTO_TEST_CASE(basic_uri_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); -} - -BOOST_AUTO_TEST_CASE(full_uri_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::user_info(instance), "user:password"); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); - BOOST_CHECK(uri::port_us(instance)); - BOOST_CHECK_EQUAL(uri::port_us(instance).get(), 80); - BOOST_CHECK_EQUAL(uri::port(instance), "80"); - BOOST_CHECK_EQUAL(uri::path(instance), "/path"); - BOOST_CHECK_EQUAL(uri::query(instance), "query"); - BOOST_CHECK_EQUAL(uri::fragment(instance), "fragment"); -} - -BOOST_AUTO_TEST_CASE(mailto_test) { - uri::uri instance("mailto:john.doe@example.com"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "mailto"); - BOOST_CHECK_EQUAL(uri::path(instance), "john.doe@example.com"); -} - -BOOST_AUTO_TEST_CASE(file_test) { - uri::uri instance("file:///bin/bash"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "file"); - BOOST_CHECK_EQUAL(uri::path(instance), "/bin/bash"); -} - -BOOST_AUTO_TEST_CASE(xmpp_test) { - uri::uri instance("xmpp:example-node@example.com?message;subject=Hello%20World"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "xmpp"); - BOOST_CHECK_EQUAL(uri::path(instance), "example-node@example.com"); - BOOST_CHECK_EQUAL(uri::query(instance), "message;subject=Hello%20World"); -} - -BOOST_AUTO_TEST_CASE(ipv4_address_test) { - uri::uri instance("http://129.79.245.252/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "129.79.245.252"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); -} - -BOOST_AUTO_TEST_CASE(ipv6_address_test_1) { - uri::uri instance("http://[1080::8:800:200c:417a]/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "[1080:0:0:0:8:800:200C:417A]"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); -} - -BOOST_AUTO_TEST_CASE(ipv6_address_test_2) { - uri::uri instance("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "[2001:db8:85a3:8d3:1319:8a2e:370:7348]"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); -} - -BOOST_AUTO_TEST_CASE(ftp_test) { - uri::uri instance("ftp://john.doe@ftp.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "ftp"); - BOOST_CHECK_EQUAL(uri::user_info(instance), "john.doe"); - BOOST_CHECK_EQUAL(uri::host(instance), "ftp.example.com"); - BOOST_CHECK_EQUAL(uri::path(instance), "/"); -} - -BOOST_AUTO_TEST_CASE(news_test) { - uri::uri instance("news:comp.infosystems.www.servers.unix"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "news"); - BOOST_CHECK_EQUAL(uri::path(instance), "comp.infosystems.www.servers.unix"); -} - -BOOST_AUTO_TEST_CASE(tel_test) { - uri::uri instance("tel:+1-816-555-1212"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "tel"); - BOOST_CHECK_EQUAL(uri::path(instance), "+1-816-555-1212"); -} - -BOOST_AUTO_TEST_CASE(encoded_uri_test) { - uri::uri instance("http://www.example.com/Path%20With%20%28Some%29%20Encoded%20Characters%21"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); - BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); - BOOST_CHECK_EQUAL(uri::path(instance), "/Path%20With%20%28Some%29%20Encoded%20Characters%21"); - BOOST_CHECK_EQUAL(uri::decoded_path(instance), "/Path With (Some) Encoded Characters!"); +typedef boost::mpl::list< + tags::default_string + , tags::default_wstring + > tag_types; + + +BOOST_AUTO_TEST_CASE_TEMPLATE(uri_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://www.example.com/"); + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string path("/"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(full_uri_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://user:password@www.example.com/path?query#fragment"); + const std::string scheme("http"); + const std::string user_info("user:password"); + const std::string host("www.example.com"); + const std::string port = "80"; + const std::string path("/path"); + const std::string query("query"); + const std::string fragment("fragment"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK_EQUAL(static_cast(uri::port_us(instance)), 80); + BOOST_CHECK(boost::equal(uri::port(instance), port)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::query(instance), query)); + BOOST_CHECK(boost::equal(uri::fragment(instance), fragment)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(mailto_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("/service/mailto:john.doe@example.com"); + const std::string scheme("mailto"); + // RFC 3986 interprets this as the path + const std::string path("john.doe@example.com"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(file_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("/service/file:///bin/bash"); + const std::string scheme("file"); + const std::string path("/bin/bash"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("/service/xmpp:example-node@example.com?message;subject=Hello%20World"); + const std::string scheme("xmpp"); + // RFC 3986 interprets this as the path + const std::string path("example-node@example.com"); + const std::string query("message;subject=Hello%20World"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); + BOOST_CHECK(boost::equal(uri::query(instance), query)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(ipv4_address_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://129.79.245.252/"); + const std::string scheme("http"); + const std::string host("129.79.245.252"); + const std::string path("/"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_1, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://[1080::8:800:200c:417a]/"); + const std::string scheme("http"); + const std::string host("[1080:0:0:0:8:800:200C:417A]"); + const std::string path("/"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(ipv6_address_test_2, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://[2001:db8:85a3:8d3:1319:8a2e:370:7348]/"); + const std::string scheme("http"); + const std::string host("[2001:db8:85a3:8d3:1319:8a2e:370:7348]"); + const std::string path("/"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(ftp_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("/service/ftp://john.doe@ftp.example.com/"); + const std::string scheme("ftp"); + const std::string user_info("john.doe"); + const std::string host("ftp.example.com"); + const std::string path("/"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::user_info(instance), user_info)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); } - -BOOST_AUTO_TEST_CASE(copy_constructor_test) { - uri::uri instance("http://www.example.com/"); - uri::uri copy = instance; + +BOOST_AUTO_TEST_CASE_TEMPLATE(news_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("/service/news:comp.infosystems.www.servers.unix"); + const std::string scheme("news"); + const std::string path("comp.infosystems.www.servers.unix"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(tel_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("/service/tel:+1-816-555-1212"); + const std::string scheme("tel"); + const std::string path("+1-816-555-1212"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::path(instance), path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(encoded_uri_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://www.example.com/Path%20With%20%28Some%29%20Encoded%20Characters%21"); + const std::string scheme("http"); + const std::string host("www.example.com"); + const std::string encoded_path("/Path%20With%20%28Some%29%20Encoded%20Characters%21"); + const std::string decoded_path("/Path With (Some) Encoded Characters!"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::scheme(instance), scheme)); + BOOST_CHECK(boost::equal(uri::host(instance), host)); + BOOST_CHECK(boost::equal(uri::path(instance), encoded_path)); + BOOST_CHECK(boost::equal(uri::decoded_path(instance), decoded_path)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(copy_constructor_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://www.example.com/"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + uri_type copy = instance; BOOST_CHECK(instance == copy); } -BOOST_AUTO_TEST_CASE(assignment_test) { - uri::uri instance("http://www.example.com/"); - uri::uri copy; +BOOST_AUTO_TEST_CASE_TEMPLATE(assignment_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://www.example.com/"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + uri_type copy; copy = instance; - BOOST_CHECK_EQUAL(instance.string(), copy.string()); - BOOST_CHECK_EQUAL(instance, copy); + BOOST_CHECK(instance.string() == copy.string()); + BOOST_CHECK(instance == copy); } -BOOST_AUTO_TEST_CASE(username_test) { - uri::uri instance("ftp://john.doe:password@ftp.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::username(instance), "john.doe"); - BOOST_CHECK_EQUAL(uri::password(instance), "password"); +BOOST_AUTO_TEST_CASE_TEMPLATE(username_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("/service/ftp://john.doe:password@ftp.example.com/"); + const std::string scheme("http"); + const std::string username("john.doe"); + const std::string password("password"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::username(instance), username)); + BOOST_CHECK(boost::equal(uri::password(instance), password)); } -BOOST_AUTO_TEST_CASE(authority_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK_EQUAL(uri::authority(instance), "user:password@www.example.com:80"); +BOOST_AUTO_TEST_CASE_TEMPLATE(authority_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://user:password@www.example.com/path?query#fragment"); + const std::string authority("user:password@www.example.com:80"); + + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + BOOST_CHECK(boost::equal(uri::authority(instance), authority)); } -BOOST_AUTO_TEST_CASE(http_query_map_test) { - uri::uri instance("http://user:password@www.example.com/path?query=something#fragment"); - BOOST_REQUIRE(uri::valid(instance)); +BOOST_AUTO_TEST_CASE_TEMPLATE(http_query_map_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("http://user:password@www.example.com/path?query#fragment"); - std::map queries; + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + const std::string key("query"); + const std::string value; + + std::map queries; uri::query_map(instance, queries); BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(1)); - BOOST_CHECK_EQUAL(queries.begin()->first, "query"); - BOOST_CHECK_EQUAL(queries.begin()->second, "something"); + BOOST_CHECK(boost::equal(queries.begin()->first, key)); + BOOST_CHECK(boost::equal(queries.begin()->second, value)); } -BOOST_AUTO_TEST_CASE(xmpp_query_map_test) { - uri::uri instance("xmpp:example-node@example.com?message;subject=Hello%20World"); - BOOST_REQUIRE(uri::valid(instance)); +BOOST_AUTO_TEST_CASE_TEMPLATE(xmpp_query_map_test, T, tag_types) { + typedef uri::basic_uri uri_type; + typedef typename uri_type::string_type string_type; + + const std::string url("/service/xmpp:example-node@example.com?message;subject=Hello%20World"); - std::map queries; + uri_type instance(string_type(boost::begin(url), boost::end(url))); + BOOST_REQUIRE(uri::is_valid(instance)); + const std::string key_1("message"), key_2("subject"); + const std::string value_1, value_2("Hello%20World"); + + std::map queries; uri::query_map(instance, queries); BOOST_REQUIRE_EQUAL(queries.size(), std::size_t(2)); - BOOST_CHECK_EQUAL(queries.begin()->first, "message"); - BOOST_CHECK_EQUAL(queries.begin()->second, ""); - BOOST_CHECK_EQUAL((++queries.begin())->first, "subject"); - BOOST_CHECK_EQUAL((++queries.begin())->second, "Hello%20World"); -} - -BOOST_AUTO_TEST_CASE(range_test) -{ - const std::string url("http://www.example.com/"); - uri::uri instance(url); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(instance, url)); -} - -BOOST_AUTO_TEST_CASE(issue_67_test) -{ - const std::string site_name("http://www.google.com/"); - uri::uri bar0; - uri::uri bar1 = site_name; - bar0 = site_name; - BOOST_CHECK(uri::is_valid(bar0)); - BOOST_CHECK(uri::is_valid(bar1)); + BOOST_CHECK(boost::equal(queries.begin()->first, key_1)); + BOOST_CHECK(boost::equal(queries.begin()->second, value_1)); + BOOST_CHECK(boost::equal((++queries.begin())->first, key_2)); + BOOST_CHECK(boost::equal((++queries.begin())->second, value_2)); } From 7e21d0f8c705255ce5ffd46d5549c243a9f5ca4e Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Mon, 5 Dec 2011 19:28:32 +1100 Subject: [PATCH 208/768] Final tweaks to get things going again. --- CMakeLists.txt | 2 +- libs/network/example/CMakeLists.txt | 14 ++++++-------- libs/network/src/CMakeLists.txt | 4 ---- libs/network/test/http/CMakeLists.txt | 9 +++++++-- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc0ffc19b..052e5c2f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ if (CMAKE_BUILD_TYPE MATCHES Debug) add_definitions(-DBOOST_NETWORK_DEBUG) endif() -if (OpenSSL_FOUND) +if (OPENSSL_FOUND) add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) endif() diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index d20475002..78ef6d487 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -6,17 +6,13 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) include_directories(${OPENSSL_INCLUDE_DIR}) -if (OPENSSL_FOUND) - add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) -endif() - add_executable(http_client http_client.cpp) add_executable(simple_wget simple_wget.cpp) add_executable(hello_world_server http/hello_world_server.cpp) add_executable(fileserver http/fileserver.cpp) add_executable(uri uri.cpp) -add_dependencies(http_client cppnetlib-uri-parsers) -add_dependencies(simple_wget cppnetlib-uri-parsers) +add_dependencies(http_client cppnetlib-uri-parsers cppnetlib-client-connections) +add_dependencies(simple_wget cppnetlib-uri-parsers cppnetlib-client-connections) add_dependencies(uri cppnetlib-uri-parsers) set(BOOST_CLIENT_LIBS ${Boost_PROGRAM_OPTIONS_LIBRARY} @@ -32,13 +28,15 @@ target_link_libraries(http_client ${BOOST_CLIENT_LIBS} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} - cppnetlib-uri-parsers) + cppnetlib-uri-parsers + cppnetlib-client-connections) target_link_libraries(simple_wget ${BOOST_CLIENT_LIBS} ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES} - cppnetlib-uri-parsers) + cppnetlib-uri-parsers + cppnetlib-client-connections) target_link_libraries(hello_world_server ${BOOST_SERVER_LIBS} diff --git a/libs/network/src/CMakeLists.txt b/libs/network/src/CMakeLists.txt index 8506a5a2c..be27107a1 100644 --- a/libs/network/src/CMakeLists.txt +++ b/libs/network/src/CMakeLists.txt @@ -8,10 +8,6 @@ include_directories(${CPP-NETLIB_SOURCE_DIR}) -if (OPENSSL_FOUND) - add_definitions(-DBOOST_NETWORK_ENABLE_HTTPS) -endif() - set(CPP-NETLIB_URI_SRCS uri/parse.cpp) add_library(cppnetlib-uri-parsers ${CPP-NETLIB_URI_SRCS}) diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 3490a36fd..ab8dc7035 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -29,8 +29,13 @@ if (Boost_FOUND) PROPERTIES COMPILE_FLAGS "-Wall") endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) - add_dependencies(cpp-netlib-http-${test} cppnetlib-uri-parsers) - target_link_libraries(cpp-netlib-http-${test} ${BOOST_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri-parsers) + add_dependencies(cpp-netlib-http-${test} + cppnetlib-uri-parsers + cppnetlib-client-connections) + target_link_libraries(cpp-netlib-http-${test} + ${BOOST_LIBS} ${CMAKE_THREAD_LIBS_INIT} + cppnetlib-uri-parsers + cppnetlib-client-connections) if (OPENSSL_FOUND) target_link_libraries(cpp-netlib-http-${test} ${OPENSSL_LIBRARIES}) endif() From e2c257ffbc1f94c0b5161bd304c486c7f4144144 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Tue, 6 Dec 2011 23:18:50 +0100 Subject: [PATCH 209/768] Fixed CMake scripts for MSVC 10.0 --- libs/network/example/CMakeLists.txt | 15 ++++++++++++--- libs/network/test/http/CMakeLists.txt | 10 +++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index c0e3b3eef..7f901ea27 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -11,7 +11,9 @@ endif (OPENSSL_FOUND) add_executable(http_client http_client.cpp) add_executable(simple_wget simple_wget.cpp) add_executable(hello_world_server http/hello_world_server.cpp) -add_executable(fileserver http/fileserver.cpp) +if (UNIX) + add_executable(fileserver http/fileserver.cpp) +endif (UNIX) add_executable(uri uri.cpp) add_dependencies(http_client cppnetlib-uri cppnetlib-client-connections) add_dependencies(simple_wget cppnetlib-uri cppnetlib-client-connections) @@ -19,11 +21,14 @@ add_dependencies(uri cppnetlib-uri) set(BOOST_CLIENT_LIBS ${Boost_PROGRAM_OPTIONS_LIBRARY} ${Boost_THREAD_LIBRARY} + ${Boost_DATE_TIME_LIBRARY} + ${Boost_REGEX_LIBRARY} ${Boost_SYSTEM_LIBRARY}) set(BOOST_SERVER_LIBS ${Boost_THREAD_LIBRARY} ${Boost_SYSTEM_LIBRARY} + ${Boost_DATE_TIME_LIBRARY} ${Boost_PROGRAM_OPTIONS_LIBRARY}) target_link_libraries(http_client @@ -48,15 +53,19 @@ if (OPENSSL_FOUND) target_link_libraries(hello_world_server ${OPENSSL_LIBRARIES}) endif (OPENSSL_FOUND) -target_link_libraries(fileserver +if (UNIX) + target_link_libraries(fileserver ${BOOST_SERVER_LIBS} ${Boost_FILESYSTEM_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) +endif (UNIX) target_link_libraries(uri cppnetlib-uri) set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) -set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +if (UNIX) + set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +endif (UNIX) set_target_properties(uri PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index 3a2432d5c..b06a2a12a 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -13,10 +13,6 @@ if (OPENSSL_FOUND) endif() if (Boost_FOUND) - set ( BOOST_LIBS - ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} - ${Boost_THREAD_LIBRARY} - ${Boost_SYSTEM_LIBRARY}) set ( TESTS client_constructor_test client_get_test @@ -34,7 +30,7 @@ if (Boost_FOUND) cppnetlib-uri cppnetlib-client-connections) target_link_libraries(cpp-netlib-http-${test} - ${BOOST_LIBS} ${CMAKE_THREAD_LIBS_INIT} + ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-uri cppnetlib-client-connections) if (OPENSSL_FOUND) @@ -57,7 +53,7 @@ if (Boost_FOUND) endif() add_executable(cpp-netlib-http-${test} ${test}.cpp) add_dependencies(cpp-netlib-http-${test} cppnetlib-server-parsers) - target_link_libraries(cpp-netlib-http-${test} ${BOOST_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) + target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) set_target_properties(cpp-netlib-http-${test} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) add_test(cpp-netlib-http-${test} @@ -78,7 +74,7 @@ if (Boost_FOUND) # endif() # add_executable(cpp-netlib-http-${test} ${test}.cpp) # add_dependencies(cpp-netlib-http-${test} cppnetlib-server-parsers) - # target_link_libraries(cpp-netlib-http-${test} ${BOOST_LIBS} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) + # target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) # set_target_properties(cpp-netlib-http-${test} # PROPERTIES RUNTIME_OUTPUT_DIRECTORY # ${CPP-NETLIB_BINARY_DIR}/tests) From 4fbe263747a305dbf76fb2b52294eccf03d5c4b1 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Wed, 7 Dec 2011 22:12:50 +0100 Subject: [PATCH 210/768] Cleaned up URI parts. --- boost/network/uri/detail/uri_parts.hpp | 33 ++++++++++--------- boost/network/uri/uri.hpp | 36 ++++++++------------- libs/network/src/uri/parse.cpp | 44 ++++++++++++++++++-------- 3 files changed, 61 insertions(+), 52 deletions(-) diff --git a/boost/network/uri/detail/uri_parts.hpp b/boost/network/uri/detail/uri_parts.hpp index e069657ae..9bc04bda6 100644 --- a/boost/network/uri/detail/uri_parts.hpp +++ b/boost/network/uri/detail/uri_parts.hpp @@ -7,7 +7,7 @@ # define BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ -# include +# include namespace boost { @@ -18,29 +18,28 @@ template < class String > struct iterator_range - : boost::fusion::vector< + : std::pair< typename String::const_iterator - , typename String::const_iterator - > -{ }; + , typename String::const_iterator> { +}; template < class String > -struct uri_parts - : boost::fusion::vector< - iterator_range // scheme - , boost::fusion::vector< - iterator_range // user_info - , iterator_range // host - , iterator_range // port - , iterator_range // path - > - , iterator_range // query - , iterator_range // fragment +struct hierarchical_part { + iterator_range user_info, host, port, path; +}; + +template < + class String > -{ }; +struct uri_parts { + iterator_range scheme; + hierarchical_part hier_part; + iterator_range query; + iterator_range fragment; +}; } // namespace detail } // namespace uri } // namespace network diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index f99262a5b..0bf4cae07 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -11,7 +11,6 @@ # include # include # include -# include # include # include # include @@ -104,45 +103,38 @@ class uri } const_range_type scheme_range() const { - using boost::fusion::at_c; - return const_range_type(at_c<0>(at_c<0>(uri_parts_)), - at_c<1>(at_c<0>(uri_parts_))); + return const_range_type(uri_parts_.scheme.first, + uri_parts_.scheme.second); } const_range_type user_info_range() const { - using boost::fusion::at_c; - return const_range_type(at_c<0>(at_c<0>(at_c<1>(uri_parts_))), - at_c<1>(at_c<0>(at_c<1>(uri_parts_)))); + return const_range_type(uri_parts_.hier_part.user_info.first, + uri_parts_.hier_part.user_info.second); } const_range_type host_range() const { - using boost::fusion::at_c; - return const_range_type(at_c<0>(at_c<1>(at_c<1>(uri_parts_))), - at_c<1>(at_c<1>(at_c<1>(uri_parts_)))); + return const_range_type(uri_parts_.hier_part.host.first, + uri_parts_.hier_part.host.second); } const_range_type port_range() const { - using boost::fusion::at_c; - return const_range_type(at_c<0>(at_c<2>(at_c<1>(uri_parts_))), - at_c<1>(at_c<2>(at_c<1>(uri_parts_)))); + return const_range_type(uri_parts_.hier_part.port.first, + uri_parts_.hier_part.port.second); } const_range_type path_range() const { - using boost::fusion::at_c; - return const_range_type(at_c<0>(at_c<3>(at_c<1>(uri_parts_))), - at_c<1>(at_c<3>(at_c<1>(uri_parts_)))); + return const_range_type(uri_parts_.hier_part.path.first, + uri_parts_.hier_part.path.second); } const_range_type query_range() const { - using boost::fusion::at_c; - return const_range_type(at_c<0>(at_c<2>(uri_parts_)), - at_c<1>(at_c<2>(uri_parts_))); + return const_range_type(uri_parts_.query.first, + uri_parts_.query.second); } const_range_type fragment_range() const { - using boost::fusion::at_c; - return const_range_type(at_c<0>(at_c<3>(uri_parts_)), - at_c<1>(at_c<3>(uri_parts_))); + return const_range_type(uri_parts_.fragment.first, + uri_parts_.fragment.second); } string_type scheme() const { diff --git a/libs/network/src/uri/parse.cpp b/libs/network/src/uri/parse.cpp index 972859b9b..87d86a2b4 100644 --- a/libs/network/src/uri/parse.cpp +++ b/libs/network/src/uri/parse.cpp @@ -10,6 +10,36 @@ #include #include #include +#include + + +BOOST_FUSION_ADAPT_TPL_STRUCT +( + (String), + (boost::network::uri::detail::iterator_range)(String), + (typename String::const_iterator, first) + (typename String::const_iterator, second) + ); + +BOOST_FUSION_ADAPT_TPL_STRUCT +( + (String), + (boost::network::uri::detail::hierarchical_part)(String), + (boost::network::uri::detail::iterator_range, user_info) + (boost::network::uri::detail::iterator_range, host) + (boost::network::uri::detail::iterator_range, port) + (boost::network::uri::detail::iterator_range, path) + ); + +BOOST_FUSION_ADAPT_TPL_STRUCT +( + (String), + (boost::network::uri::detail::uri_parts)(String), + (boost::network::uri::detail::iterator_range, scheme) + (boost::network::uri::detail::hierarchical_part, hier_part) + (boost::network::uri::detail::iterator_range, query) + (boost::network::uri::detail::iterator_range, fragment) + ); namespace boost { @@ -222,10 +252,7 @@ struct uri_grammar : qi::grammar()> { qi::rule()> scheme, user_info, query, fragment; - qi::rule, - iterator_range, - iterator_range, - iterator_range >()> + qi::rule()> hier_part; // actual uri parser @@ -241,15 +268,6 @@ bool parse(std::string::const_iterator first, bool is_valid = qi::parse(first, last, grammar, parts); return is_valid && (first == last); } - -bool parse(std::wstring::const_iterator first, - std::wstring::const_iterator last, - uri_parts &parts) { - namespace qi = boost::spirit::qi; - static uri_grammar grammar; - bool is_valid = qi::parse(first, last, grammar, parts); - return is_valid && (first == last); -} } // namespace detail } // namespace uri } // namespace network From b9d61eed3126791ee69945804c63fc14ae7bf272 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Thu, 8 Dec 2011 21:40:20 +0100 Subject: [PATCH 211/768] Cleaned up further the implementation of the URI parts and parser. --- boost/network/protocol/http/impl/request.hpp | 1 + boost/network/uri/detail/uri_parts.hpp | 44 ++++--- boost/network/uri/uri.hpp | 32 ++--- libs/network/src/uri/parse.cpp | 121 +++++++------------ 4 files changed, 83 insertions(+), 115 deletions(-) diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index 3a6c05296..707ee175a 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -17,6 +17,7 @@ #include #include +#include #include #include diff --git a/boost/network/uri/detail/uri_parts.hpp b/boost/network/uri/detail/uri_parts.hpp index 9bc04bda6..48a88d238 100644 --- a/boost/network/uri/detail/uri_parts.hpp +++ b/boost/network/uri/detail/uri_parts.hpp @@ -7,7 +7,7 @@ # define BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ -# include +# include namespace boost { @@ -15,30 +15,40 @@ namespace network { namespace uri { namespace detail { template < - class String + class FwdIter > -struct iterator_range - : std::pair< - typename String::const_iterator - , typename String::const_iterator> { +struct hierarchical_part { + iterator_range user_info, host, port, path; -}; + hierarchical_part() + {} -template < - class String - > -struct hierarchical_part { - iterator_range user_info, host, port, path; + hierarchical_part(FwdIter begin, FwdIter end) + : user_info(begin, end) + , host(begin, end) + , port(begin, end) + , path(begin, end) + { } }; template < - class String + class FwdIter > struct uri_parts { - iterator_range scheme; - hierarchical_part hier_part; - iterator_range query; - iterator_range fragment; + iterator_range scheme; + hierarchical_part hier_part; + iterator_range query; + iterator_range fragment; + + uri_parts() + {} + + uri_parts(FwdIter begin, FwdIter end) + : scheme(begin, end) + , hier_part(begin, end) + , query(begin, end) + , fragment(begin, end) + { } }; } // namespace detail } // namespace uri diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 0bf4cae07..fd8e17e3a 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -7,12 +7,7 @@ #ifndef __BOOST_NETWORK_URI_INC__ # define __BOOST_NETWORK_URI_INC__ - -# include -# include # include -# include -# include # include # include # include @@ -26,7 +21,7 @@ namespace uri { namespace detail { bool parse(std::string::const_iterator first, std::string::const_iterator last, - uri_parts &parts); + uri_parts &parts); } // namespace detail @@ -50,7 +45,7 @@ class uri class FwdIter > uri(const FwdIter &first, const FwdIter &last) - : uri_(first, last), is_valid_(false) { + : uri_(first, last), uri_parts_(first, first), is_valid_(false) { parse(); } @@ -103,38 +98,31 @@ class uri } const_range_type scheme_range() const { - return const_range_type(uri_parts_.scheme.first, - uri_parts_.scheme.second); + return uri_parts_.scheme; } const_range_type user_info_range() const { - return const_range_type(uri_parts_.hier_part.user_info.first, - uri_parts_.hier_part.user_info.second); + return uri_parts_.hier_part.user_info; } const_range_type host_range() const { - return const_range_type(uri_parts_.hier_part.host.first, - uri_parts_.hier_part.host.second); + return uri_parts_.hier_part.host; } const_range_type port_range() const { - return const_range_type(uri_parts_.hier_part.port.first, - uri_parts_.hier_part.port.second); + return uri_parts_.hier_part.port; } const_range_type path_range() const { - return const_range_type(uri_parts_.hier_part.path.first, - uri_parts_.hier_part.path.second); + return uri_parts_.hier_part.path; } const_range_type query_range() const { - return const_range_type(uri_parts_.query.first, - uri_parts_.query.second); + return uri_parts_.query; } const_range_type fragment_range() const { - return const_range_type(uri_parts_.fragment.first, - uri_parts_.fragment.second); + return uri_parts_.fragment; } string_type scheme() const { @@ -198,7 +186,7 @@ class uri void parse(); string_type uri_; - detail::uri_parts uri_parts_; + detail::uri_parts uri_parts_; bool is_valid_; }; diff --git a/libs/network/src/uri/parse.cpp b/libs/network/src/uri/parse.cpp index 87d86a2b4..8392eed38 100644 --- a/libs/network/src/uri/parse.cpp +++ b/libs/network/src/uri/parse.cpp @@ -6,42 +6,29 @@ #include #include -#include -#include -#include -#include +#include #include - -BOOST_FUSION_ADAPT_TPL_STRUCT -( - (String), - (boost::network::uri::detail::iterator_range)(String), - (typename String::const_iterator, first) - (typename String::const_iterator, second) - ); - BOOST_FUSION_ADAPT_TPL_STRUCT ( - (String), - (boost::network::uri::detail::hierarchical_part)(String), - (boost::network::uri::detail::iterator_range, user_info) - (boost::network::uri::detail::iterator_range, host) - (boost::network::uri::detail::iterator_range, port) - (boost::network::uri::detail::iterator_range, path) + (FwdIter), + (boost::network::uri::detail::hierarchical_part)(FwdIter), + (boost::iterator_range, user_info) + (boost::iterator_range, host) + (boost::iterator_range, port) + (boost::iterator_range, path) ); BOOST_FUSION_ADAPT_TPL_STRUCT ( - (String), - (boost::network::uri::detail::uri_parts)(String), - (boost::network::uri::detail::iterator_range, scheme) - (boost::network::uri::detail::hierarchical_part, hier_part) - (boost::network::uri::detail::iterator_range, query) - (boost::network::uri::detail::iterator_range, fragment) + (FwdIter), + (boost::network::uri::detail::uri_parts)(FwdIter), + (boost::iterator_range, scheme) + (boost::network::uri::detail::hierarchical_part, hier_part) + (boost::iterator_range, query) + (boost::iterator_range, fragment) ); - namespace boost { namespace network { namespace uri { @@ -49,14 +36,16 @@ namespace detail { namespace qi = boost::spirit::qi; template < - class String, - typename Iterator + class String > -struct uri_grammar : qi::grammar()> { +struct uri_grammar : qi::grammar< + typename String::const_iterator + , detail::uri_parts()> { - uri_grammar() : uri_grammar::base_type(start, "uri") { - using boost::spirit::repository::qi::iter_pos; + typedef String string_type; + typedef typename String::const_iterator const_iterator; + uri_grammar() : uri_grammar::base_type(start, "uri") { // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" gen_delims %= qi::char_(":/?#[]@"); // sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "=" @@ -83,46 +72,34 @@ struct uri_grammar : qi::grammar()> { ]; // path-abempty = *( "/" segment ) path_abempty %= - iter_pos - >> qi::omit[qi::raw[*(qi::char_("/") >> segment)]] - >> iter_pos + qi::raw[qi::raw[*(qi::char_("/") >> segment)]] ; // path-absolute = "/" [ segment-nz *( "/" segment ) ] path_absolute %= - iter_pos - >> qi::omit[qi::raw[ + qi::raw[qi::raw[ qi::char_("/") >> -(segment_nz >> *(qi::char_("/") >> segment)) ]] - >> iter_pos ; // path-rootless = segment-nz *( "/" segment ) path_rootless %= - iter_pos - >> qi::omit[qi::raw[ + qi::raw[qi::raw[ segment_nz >> *(qi::char_("/") >> segment) ]] - >> iter_pos ; // path-empty = 0 path_empty %= - iter_pos - >> qi::omit[qi::eps] - >> iter_pos + qi::raw[qi::eps] ; // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) scheme %= - iter_pos - >> qi::omit[qi::alpha >> *(qi::alnum | qi::char_("+.-"))] - >> iter_pos + qi::raw[qi::alpha >> *(qi::alnum | qi::char_("+.-"))] ; // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) user_info %= - iter_pos - >> qi::omit[qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))]] - >> iter_pos + qi::raw[qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))]] ; ip_literal %= @@ -173,30 +150,22 @@ struct uri_grammar : qi::grammar()> { // TODO, host = IP-literal / IPv4address / reg-name host %= - iter_pos - >> qi::omit[ip_literal | ipv4address | reg_name] - >> iter_pos + qi::raw[ip_literal | ipv4address | reg_name] ; // port %= qi::ushort_; port %= - iter_pos - >> qi::omit[*qi::digit] - >> iter_pos + qi::raw[*qi::digit] ; // query = *( pchar / "/" / "?" ) query %= - iter_pos - >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] - >> iter_pos + qi::raw[qi::raw[*(pchar | qi::char_("/?"))]] ; // fragment = *( pchar / "/" / "?" ) fragment %= - iter_pos - >> qi::omit[qi::raw[*(pchar | qi::char_("/?"))]] - >> iter_pos + qi::raw[qi::raw[*(pchar | qi::char_("/?"))]] ; // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty @@ -211,9 +180,9 @@ struct uri_grammar : qi::grammar()> { ) | ( - qi::attr(iterator_range()) - >> qi::attr(iterator_range()) - >> qi::attr(iterator_range()) + qi::attr(iterator_range()) + >> qi::attr(iterator_range()) + >> qi::attr(iterator_range()) >> ( path_absolute | path_rootless @@ -230,41 +199,41 @@ struct uri_grammar : qi::grammar()> { ; } - qi::rule + qi::rule gen_delims, sub_delims, reserved, unreserved; - qi::rule + qi::rule pct_encoded, pchar; - qi::rule + qi::rule segment, segment_nz, segment_nz_nc; - qi::rule()> + qi::rule()> path_abempty, path_absolute, path_rootless, path_empty; - qi::rule + qi::rule dec_octet, ipv4address, reg_name, ipv6address, ipvfuture, ip_literal; - qi::rule + qi::rule h16, ls32; - qi::rule()> + qi::rule()> host, port; - qi::rule()> + qi::rule()> scheme, user_info, query, fragment; - qi::rule()> + qi::rule()> hier_part; // actual uri parser - qi::rule()> start; + qi::rule()> start; }; bool parse(std::string::const_iterator first, std::string::const_iterator last, - uri_parts &parts) { + uri_parts &parts) { namespace qi = boost::spirit::qi; - static detail::uri_grammar grammar; + static detail::uri_grammar grammar; bool is_valid = qi::parse(first, last, grammar, parts); return is_valid && (first == last); } From 6183a0c761f526f493e4cb1c04e7615a9552665d Mon Sep 17 00:00:00 2001 From: Matt Trentini Date: Sat, 10 Dec 2011 07:20:50 -0500 Subject: [PATCH 212/768] Changed the line endings of the mime test files to CRLF which will allow the tests to pass. Also removed the reference to the mime test file "TestMessages/00001136". That file had been removed awhile ago by Dean as it caused false positives in some virus checkers. --- libs/mime/test/TestMessages/00000001 | 80 +++--- libs/mime/test/TestMessages/00000019 | 162 +++++------ libs/mime/test/TestMessages/00000431 | 280 ++++++++++---------- libs/mime/test/TestMessages/00000975 | 230 ++++++++-------- libs/mime/test/TestMessages/0019-NoBoundary | 160 +++++------ libs/mime/test/mime-roundtrip.cpp | 4 +- 6 files changed, 459 insertions(+), 457 deletions(-) diff --git a/libs/mime/test/TestMessages/00000001 b/libs/mime/test/TestMessages/00000001 index 4f6cf531f..b6c9dd6c1 100644 --- a/libs/mime/test/TestMessages/00000001 +++ b/libs/mime/test/TestMessages/00000001 @@ -1,40 +1,40 @@ -Resent-To: mail.app@flagg2.qualcomm.com -Resent-From: win-eudora-bugs@flagg2.qualcomm.com -Resent-Message-Id: -Resent-Date: Mon, 1 Nov 2004 15:38:13 -0800 -Received: from flagg2.qualcomm.com [129.46.154.229] - by localhost with IMAP (fetchmail-6.2.5) - for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:38:25 -0800 (PST) -Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com - (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; - Mon, 1 Nov 2004 15:38:13 -0800 -Received: from sabrina.qualcomm.com (sabrina.qualcomm.com [129.46.61.150]) - by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA1NcAcH015308 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); - Mon, 1 Nov 2004 15:38:11 -0800 (PST) -Received: from moria.qualcomm.com (qualcomm.com [199.106.114.68]) - by sabrina.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA1Nc8HJ019370 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) - for ; Mon, 1 Nov 2004 15:38:09 -0800 (PST) -Received: from isengard.qualcomm.com (isengard.qualcomm.com [199.106.114.75]) by moria.qualcomm.com (qualnet-external) with ESMTP id iA1Nc7Rg028808 for ; Mon, 1 Nov 2004 15:38:07 -0800 (PST) -Received: from coyote.rain.org (coyote.rain.org [198.68.144.2]) by isengard.qualcomm.com with ESMTP id iA1Nc7uA020987 for ; Mon, 1 Nov 2004 15:38:07 -0800 (PST) -Received: from sanders.rain.org (maxmp-189.rain.org [198.68.144.189]) - by coyote.rain.org (Postfix) with ESMTP id 648227775 - for ; Mon, 1 Nov 2004 15:38:06 -0800 (PST) -Message-Id: <5.0.2.1.2.20041101153017.00a26ec0@rain.org> -X-Sender: maia3@rain.org -X-Mailer: QUALCOMM Windows Eudora Version 5.0.2 -Date: Mon, 01 Nov 2004 15:31:46 -0800 -To: win-eudora6-bugs@qualcomm.com -From: Maia -Subject: New Bugs -Mime-Version: 1.0 -Content-Type: text/plain; charset="us-ascii"; format=flowed -X-PMX-Version: 4.6.0.97784, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.3 - -Just now, without any reason, an email of mine was turned into a mixture of -text and directions and numbers and letters and is now unusable. Do you -know why this is happening? - Thanks, Maia - - +Resent-To: mail.app@flagg2.qualcomm.com +Resent-From: win-eudora-bugs@flagg2.qualcomm.com +Resent-Message-Id: +Resent-Date: Mon, 1 Nov 2004 15:38:13 -0800 +Received: from flagg2.qualcomm.com [129.46.154.229] + by localhost with IMAP (fetchmail-6.2.5) + for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:38:25 -0800 (PST) +Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com + (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; + Mon, 1 Nov 2004 15:38:13 -0800 +Received: from sabrina.qualcomm.com (sabrina.qualcomm.com [129.46.61.150]) + by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA1NcAcH015308 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); + Mon, 1 Nov 2004 15:38:11 -0800 (PST) +Received: from moria.qualcomm.com (qualcomm.com [199.106.114.68]) + by sabrina.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA1Nc8HJ019370 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) + for ; Mon, 1 Nov 2004 15:38:09 -0800 (PST) +Received: from isengard.qualcomm.com (isengard.qualcomm.com [199.106.114.75]) by moria.qualcomm.com (qualnet-external) with ESMTP id iA1Nc7Rg028808 for ; Mon, 1 Nov 2004 15:38:07 -0800 (PST) +Received: from coyote.rain.org (coyote.rain.org [198.68.144.2]) by isengard.qualcomm.com with ESMTP id iA1Nc7uA020987 for ; Mon, 1 Nov 2004 15:38:07 -0800 (PST) +Received: from sanders.rain.org (maxmp-189.rain.org [198.68.144.189]) + by coyote.rain.org (Postfix) with ESMTP id 648227775 + for ; Mon, 1 Nov 2004 15:38:06 -0800 (PST) +Message-Id: <5.0.2.1.2.20041101153017.00a26ec0@rain.org> +X-Sender: maia3@rain.org +X-Mailer: QUALCOMM Windows Eudora Version 5.0.2 +Date: Mon, 01 Nov 2004 15:31:46 -0800 +To: win-eudora6-bugs@qualcomm.com +From: Maia +Subject: New Bugs +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii"; format=flowed +X-PMX-Version: 4.6.0.97784, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.3 + +Just now, without any reason, an email of mine was turned into a mixture of +text and directions and numbers and letters and is now unusable. Do you +know why this is happening? + Thanks, Maia + + diff --git a/libs/mime/test/TestMessages/00000019 b/libs/mime/test/TestMessages/00000019 index d47d1158e..479618763 100644 --- a/libs/mime/test/TestMessages/00000019 +++ b/libs/mime/test/TestMessages/00000019 @@ -1,81 +1,81 @@ -Resent-To: mail.app@flagg2.qualcomm.com -Resent-From: win-eudora-bugs@flagg2.qualcomm.com -Resent-Message-Id: -Resent-Date: Mon, 1 Nov 2004 16:01:16 -0800 -Received: from flagg2.qualcomm.com [129.46.154.229] - by localhost with IMAP (fetchmail-6.2.5) - for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:38:27 -0800 (PST) -Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com - (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; - Mon, 1 Nov 2004 16:01:16 -0800 -Received: from neophyte.qualcomm.com (neophyte.qualcomm.com [129.46.61.149]) - by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA201FcH022189 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); - Mon, 1 Nov 2004 16:01:15 -0800 (PST) -Received: from hobbiton.qualcomm.com (hobbiton.qualcomm.com [199.106.114.69]) - by neophyte.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA201D9A029029 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) - for ; Mon, 1 Nov 2004 16:01:13 -0800 (PST) -Received: from isengard.qualcomm.com (isengard.qualcomm.com [199.106.114.75]) by hobbiton.qualcomm.com (qualnet-external) with ESMTP id iA201BhJ016885 for ; Mon, 1 Nov 2004 16:01:12 -0800 (PST) -Received: from localhost (localhost) by isengard.qualcomm.com id iA201CuA023535; Mon, 1 Nov 2004 16:01:12 -0800 (PST) -Date: Mon, 1 Nov 2004 16:01:12 -0800 (PST) -From: Mail Delivery Subsystem -Message-Id: <200411020001.iA201CuA023535@isengard.qualcomm.com> -To: -MIME-Version: 1.0 -Content-Type: multipart/report; report-type=delivery-status; - boundary="iA201CuA023535.1099353672/isengard.qualcomm.com" -Subject: Returned mail: see transcript for details -Auto-Submitted: auto-generated (failure) -X-PMX-Version: 4.6.0.99824, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.3 - -This is a MIME-encapsulated message - ---iA201CuA023535.1099353672/isengard.qualcomm.com - -The original message was received at Mon, 1 Nov 2004 16:01:09 -0800 (PST) -from [210.193.18.250] - - ----- The following addresses had permanent fatal errors ----- - - (reason: 550 5.6.1 Prohibited attachment type) - - ----- Transcript of session follows ----- -... while talking to hobbiton.qualcomm.com.: ->>> DATA -<<< 550 5.6.1 Prohibited attachment type -554 5.0.0 Service unavailable - ---iA201CuA023535.1099353672/isengard.qualcomm.com -Content-Type: message/delivery-status - -Reporting-MTA: dns; isengard.qualcomm.com -Received-From-MTA: DNS; [210.193.18.250] -Arrival-Date: Mon, 1 Nov 2004 16:01:09 -0800 (PST) - -Final-Recipient: RFC822; win-eudora6-bugs@eudora.com -Action: failed -Status: 5.6.1 -Remote-MTA: DNS; hobbiton.qualcomm.com -Diagnostic-Code: SMTP; 550 5.6.1 Prohibited attachment type -Last-Attempt-Date: Mon, 1 Nov 2004 16:01:12 -0800 (PST) - ---iA201CuA023535.1099353672/isengard.qualcomm.com -Content-Type: text/rfc822-headers - -Return-Path: -Received: from eudora.com ([210.193.18.250]) by isengard.qualcomm.com with ESMTP id iA2018uA023523 for ; Mon, 1 Nov 2004 16:01:09 -0800 (PST) -Message-Id: <200411020001.iA2018uA023523@isengard.qualcomm.com> -From: win-eudora6-bugs@eudora.com -To: win-eudora6-bugs@eudora.com -Subject: Re: Excel file -Date: Tue, 2 Nov 2004 08:00:34 +0800 -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_0001_00000AE6.000070CC" -X-Priority: 3 -X-MSMail-Priority: Normal - ---iA201CuA023535.1099353672/isengard.qualcomm.com-- - - +Resent-To: mail.app@flagg2.qualcomm.com +Resent-From: win-eudora-bugs@flagg2.qualcomm.com +Resent-Message-Id: +Resent-Date: Mon, 1 Nov 2004 16:01:16 -0800 +Received: from flagg2.qualcomm.com [129.46.154.229] + by localhost with IMAP (fetchmail-6.2.5) + for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:38:27 -0800 (PST) +Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com + (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; + Mon, 1 Nov 2004 16:01:16 -0800 +Received: from neophyte.qualcomm.com (neophyte.qualcomm.com [129.46.61.149]) + by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA201FcH022189 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); + Mon, 1 Nov 2004 16:01:15 -0800 (PST) +Received: from hobbiton.qualcomm.com (hobbiton.qualcomm.com [199.106.114.69]) + by neophyte.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA201D9A029029 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) + for ; Mon, 1 Nov 2004 16:01:13 -0800 (PST) +Received: from isengard.qualcomm.com (isengard.qualcomm.com [199.106.114.75]) by hobbiton.qualcomm.com (qualnet-external) with ESMTP id iA201BhJ016885 for ; Mon, 1 Nov 2004 16:01:12 -0800 (PST) +Received: from localhost (localhost) by isengard.qualcomm.com id iA201CuA023535; Mon, 1 Nov 2004 16:01:12 -0800 (PST) +Date: Mon, 1 Nov 2004 16:01:12 -0800 (PST) +From: Mail Delivery Subsystem +Message-Id: <200411020001.iA201CuA023535@isengard.qualcomm.com> +To: +MIME-Version: 1.0 +Content-Type: multipart/report; report-type=delivery-status; + boundary="iA201CuA023535.1099353672/isengard.qualcomm.com" +Subject: Returned mail: see transcript for details +Auto-Submitted: auto-generated (failure) +X-PMX-Version: 4.6.0.99824, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.3 + +This is a MIME-encapsulated message + +--iA201CuA023535.1099353672/isengard.qualcomm.com + +The original message was received at Mon, 1 Nov 2004 16:01:09 -0800 (PST) +from [210.193.18.250] + + ----- The following addresses had permanent fatal errors ----- + + (reason: 550 5.6.1 Prohibited attachment type) + + ----- Transcript of session follows ----- +... while talking to hobbiton.qualcomm.com.: +>>> DATA +<<< 550 5.6.1 Prohibited attachment type +554 5.0.0 Service unavailable + +--iA201CuA023535.1099353672/isengard.qualcomm.com +Content-Type: message/delivery-status + +Reporting-MTA: dns; isengard.qualcomm.com +Received-From-MTA: DNS; [210.193.18.250] +Arrival-Date: Mon, 1 Nov 2004 16:01:09 -0800 (PST) + +Final-Recipient: RFC822; win-eudora6-bugs@eudora.com +Action: failed +Status: 5.6.1 +Remote-MTA: DNS; hobbiton.qualcomm.com +Diagnostic-Code: SMTP; 550 5.6.1 Prohibited attachment type +Last-Attempt-Date: Mon, 1 Nov 2004 16:01:12 -0800 (PST) + +--iA201CuA023535.1099353672/isengard.qualcomm.com +Content-Type: text/rfc822-headers + +Return-Path: +Received: from eudora.com ([210.193.18.250]) by isengard.qualcomm.com with ESMTP id iA2018uA023523 for ; Mon, 1 Nov 2004 16:01:09 -0800 (PST) +Message-Id: <200411020001.iA2018uA023523@isengard.qualcomm.com> +From: win-eudora6-bugs@eudora.com +To: win-eudora6-bugs@eudora.com +Subject: Re: Excel file +Date: Tue, 2 Nov 2004 08:00:34 +0800 +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="----=_NextPart_000_0001_00000AE6.000070CC" +X-Priority: 3 +X-MSMail-Priority: Normal + +--iA201CuA023535.1099353672/isengard.qualcomm.com-- + + diff --git a/libs/mime/test/TestMessages/00000431 b/libs/mime/test/TestMessages/00000431 index 88a21c386..7559066c3 100644 --- a/libs/mime/test/TestMessages/00000431 +++ b/libs/mime/test/TestMessages/00000431 @@ -1,140 +1,140 @@ -Marshall-Sez: This message has nested multiparts; with the last part of a - multipart being another multipart -Resent-To: mail.app@flagg2.qualcomm.com -Resent-From: eudora-suggest@flagg2.qualcomm.com -Resent-Message-Id: -Resent-Date: Mon, 1 Nov 2004 22:33:29 -0800 -Received: from flagg2.qualcomm.com [129.46.154.229] - by localhost with IMAP (fetchmail-6.2.5) - for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:39:31 -0800 (PST) -Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com - (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; - Mon, 1 Nov 2004 22:33:29 -0800 -Received: from sabrina.qualcomm.com (sabrina.qualcomm.com [129.46.61.150]) - by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA26XQcH013328 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL) - for ; Mon, 1 Nov 2004 22:33:26 -0800 (PST) -Received: from moria.qualcomm.com (qualcomm.com [199.106.114.68]) - by sabrina.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA26XNHJ013973 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) - for ; Mon, 1 Nov 2004 22:33:24 -0800 (PST) -Received: from isengard.qualcomm.com (isengard.qualcomm.com [199.106.114.75]) by moria.qualcomm.com (qualnet-external) with ESMTP id iA26XMha015651 for ; Mon, 1 Nov 2004 22:33:22 -0800 (PST) -Received: from d60-65-159-220.col.wideopenwest.com (d60-65-159-220.col.wideopenwest.com [65.60.220.159]) by isengard.qualcomm.com with ESMTP id iA26XFuA029259 for ; Mon, 1 Nov 2004 22:33:16 -0800 (PST) -Received: from lopezclub.com (lopezclub-com.mr.outblaze.com [205.158.62.177]) - by d60-65-159-220.col.wideopenwest.com with esmtp - id 1F1D2A4AC2 for ; Tue, 02 Nov 2004 00:35:33 -0600 -Message-ID: <010001c4c0a6$2e00ef5b$f3fa62fd@lopezclub.com> -From: "Coarsest A. Spading" -To: Eudora -Subject: =?windows-1251?B?zeUg5OD+8iDv8O717uTgIOru4uDr5fD7Pw==?= -Date: Tue, 02 Nov 2004 00:35:33 -0600 -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_0036_D092C96B.3CE29AF1" -X-Priority: 3 -X-MSMail-Priority: Normal -X-Mailer: Microsoft Outlook Express 6.00.2800.1106 -X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 -X-RAV-Antivirus: This e-mail has been scanned for viruses on host: d60-65-159-220.col.wideopenwest.com -X-PMX-Version: 4.6.0.97784, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.6 -X-PerlMx-Spam: Gauge=XXXXXXXXXIIIIII, Probability=96%, Report='MR_OUTBLAZE 5, IMGSPAM_BODY 3.2, RCVD_IN_CBL 3, __SANE_MSGID 0, __TO_MALFORMED_2 0, __MIME_VERSION 0, __NEXTPART_NORMAL 0, __NEXTPART_ALL 0, __CT 0, __CTYPE_HAS_BOUNDARY 0, __CTYPE_MULTIPART 0, __HAS_X_PRIORITY 0, __HAS_MSMAIL_PRI 0, __OUTLOOK_MUA_1 0, __HAS_X_MAILER 0, SUBJ_FULL_OF_8BITS 0, __HIGHBITS 0, __IMGSPAM_BODY 0, __TAG_EXISTS_BODY 0, __TAG_EXISTS_META 0, __TAG_EXISTS_HTML 0, HTML_FONT_COLOR_BLUE 0, __TAG_EXISTS_HEAD 0, __IMGSPAM_BODY_1 0, HTML_90_100 0, __HAS_MSGID 0, __OUTLOOK_MUA 0, IMGSPAM_BODY_1 0, __OUTLOOK_MSGID_1 0' -X-Maybe-Spam: X-Maybe-Spam - -This is a multi-part message in MIME format. - -------=_NextPart_000_0036_D092C96B.3CE29AF1 -Content-Type: multipart/related; - type="multipart/alternative"; - boundary="----=_NextPart_001_0037_D092C96B.3CE29AF1" - -------=_NextPart_001_0037_D092C96B.3CE29AF1 -Content-Type: image/gif; - name="ani.gif" -Content-Transfer-Encoding: base64 -Content-Disposition: attachment; - filename="ani.gif" -Content-ID: - -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 -QRGG5TIy0SsEL4v5zGiOWwgAADs= - -------=_NextPart_001_0037_D092C96B.3CE29AF1 -Content-Type: multipart/alternative; - boundary="----=_NextPart_002_0038_D092C96B.3CE29AF1" - -------=_NextPart_002_0038_D092C96B.3CE29AF1 -Content-Type: text/plain; - charset=windows-1251 -Content-Transfer-Encoding: quoted-printable - -=c2=e4=ee=e1=e0=e2=ee=ea =ea =f0=e0=f1=f1=ea=e0=e7=e0=ec =ee =f1=f2=f0= -=e0=ed=ed=fb=f5 =ef=f0=ee=e8=f1=f8=e5=f1=f2=e2=e8=ff=f5 -------=_NextPart_002_0038_D092C96B.3CE29AF1 -Content-Type: text/html; - charset=windows-1251 -Content-Transfer-Encoding: quoted-printable - - - - - - - - - -
     
    -
     
    -
    =f1=ee=e2=f0=e5=ec=e5=ed=ed=e0=ff =ed=e0=f3=ea=e0=2e = -=c8=ed=ee=e3=e4=e0 =f2=e0=ea=ee=e9 =ea=eb=fe=f7 =e1=fc=e5=f2 =e8=e7
    - -------=_NextPart_002_0038_D092C96B.3CE29AF1-- - -------=_NextPart_001_0037_D092C96B.3CE29AF1-- - -------=_NextPart_000_0036_D092C96B.3CE29AF1-- - - - +Marshall-Sez: This message has nested multiparts; with the last part of a + multipart being another multipart +Resent-To: mail.app@flagg2.qualcomm.com +Resent-From: eudora-suggest@flagg2.qualcomm.com +Resent-Message-Id: +Resent-Date: Mon, 1 Nov 2004 22:33:29 -0800 +Received: from flagg2.qualcomm.com [129.46.154.229] + by localhost with IMAP (fetchmail-6.2.5) + for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:39:31 -0800 (PST) +Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com + (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; + Mon, 1 Nov 2004 22:33:29 -0800 +Received: from sabrina.qualcomm.com (sabrina.qualcomm.com [129.46.61.150]) + by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA26XQcH013328 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL) + for ; Mon, 1 Nov 2004 22:33:26 -0800 (PST) +Received: from moria.qualcomm.com (qualcomm.com [199.106.114.68]) + by sabrina.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA26XNHJ013973 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) + for ; Mon, 1 Nov 2004 22:33:24 -0800 (PST) +Received: from isengard.qualcomm.com (isengard.qualcomm.com [199.106.114.75]) by moria.qualcomm.com (qualnet-external) with ESMTP id iA26XMha015651 for ; Mon, 1 Nov 2004 22:33:22 -0800 (PST) +Received: from d60-65-159-220.col.wideopenwest.com (d60-65-159-220.col.wideopenwest.com [65.60.220.159]) by isengard.qualcomm.com with ESMTP id iA26XFuA029259 for ; Mon, 1 Nov 2004 22:33:16 -0800 (PST) +Received: from lopezclub.com (lopezclub-com.mr.outblaze.com [205.158.62.177]) + by d60-65-159-220.col.wideopenwest.com with esmtp + id 1F1D2A4AC2 for ; Tue, 02 Nov 2004 00:35:33 -0600 +Message-ID: <010001c4c0a6$2e00ef5b$f3fa62fd@lopezclub.com> +From: "Coarsest A. Spading" +To: Eudora +Subject: =?windows-1251?B?zeUg5OD+8iDv8O717uTgIOru4uDr5fD7Pw==?= +Date: Tue, 02 Nov 2004 00:35:33 -0600 +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="----=_NextPart_000_0036_D092C96B.3CE29AF1" +X-Priority: 3 +X-MSMail-Priority: Normal +X-Mailer: Microsoft Outlook Express 6.00.2800.1106 +X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 +X-RAV-Antivirus: This e-mail has been scanned for viruses on host: d60-65-159-220.col.wideopenwest.com +X-PMX-Version: 4.6.0.97784, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.6 +X-PerlMx-Spam: Gauge=XXXXXXXXXIIIIII, Probability=96%, Report='MR_OUTBLAZE 5, IMGSPAM_BODY 3.2, RCVD_IN_CBL 3, __SANE_MSGID 0, __TO_MALFORMED_2 0, __MIME_VERSION 0, __NEXTPART_NORMAL 0, __NEXTPART_ALL 0, __CT 0, __CTYPE_HAS_BOUNDARY 0, __CTYPE_MULTIPART 0, __HAS_X_PRIORITY 0, __HAS_MSMAIL_PRI 0, __OUTLOOK_MUA_1 0, __HAS_X_MAILER 0, SUBJ_FULL_OF_8BITS 0, __HIGHBITS 0, __IMGSPAM_BODY 0, __TAG_EXISTS_BODY 0, __TAG_EXISTS_META 0, __TAG_EXISTS_HTML 0, HTML_FONT_COLOR_BLUE 0, __TAG_EXISTS_HEAD 0, __IMGSPAM_BODY_1 0, HTML_90_100 0, __HAS_MSGID 0, __OUTLOOK_MUA 0, IMGSPAM_BODY_1 0, __OUTLOOK_MSGID_1 0' +X-Maybe-Spam: X-Maybe-Spam + +This is a multi-part message in MIME format. + +------=_NextPart_000_0036_D092C96B.3CE29AF1 +Content-Type: multipart/related; + type="multipart/alternative"; + boundary="----=_NextPart_001_0037_D092C96B.3CE29AF1" + +------=_NextPart_001_0037_D092C96B.3CE29AF1 +Content-Type: image/gif; + name="ani.gif" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; + filename="ani.gif" +Content-ID: + +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 +QRGG5TIy0SsEL4v5zGiOWwgAADs= + +------=_NextPart_001_0037_D092C96B.3CE29AF1 +Content-Type: multipart/alternative; + boundary="----=_NextPart_002_0038_D092C96B.3CE29AF1" + +------=_NextPart_002_0038_D092C96B.3CE29AF1 +Content-Type: text/plain; + charset=windows-1251 +Content-Transfer-Encoding: quoted-printable + +=c2=e4=ee=e1=e0=e2=ee=ea =ea =f0=e0=f1=f1=ea=e0=e7=e0=ec =ee =f1=f2=f0= +=e0=ed=ed=fb=f5 =ef=f0=ee=e8=f1=f8=e5=f1=f2=e2=e8=ff=f5 +------=_NextPart_002_0038_D092C96B.3CE29AF1 +Content-Type: text/html; + charset=windows-1251 +Content-Transfer-Encoding: quoted-printable + + + + + + + + +
    +
     
    +
     
    +
    =f1=ee=e2=f0=e5=ec=e5=ed=ed=e0=ff =ed=e0=f3=ea=e0=2e = +=c8=ed=ee=e3=e4=e0 =f2=e0=ea=ee=e9 =ea=eb=fe=f7 =e1=fc=e5=f2 =e8=e7
    + +------=_NextPart_002_0038_D092C96B.3CE29AF1-- + +------=_NextPart_001_0037_D092C96B.3CE29AF1-- + +------=_NextPart_000_0036_D092C96B.3CE29AF1-- + + + diff --git a/libs/mime/test/TestMessages/00000975 b/libs/mime/test/TestMessages/00000975 index e5110689d..7b3ef638f 100644 --- a/libs/mime/test/TestMessages/00000975 +++ b/libs/mime/test/TestMessages/00000975 @@ -1,115 +1,115 @@ -Resent-To: mail.app@flagg2.qualcomm.com -Resent-From: eudora-suggest@flagg2.qualcomm.com -Resent-Message-Id: -Resent-Date: Tue, 2 Nov 2004 08:05:31 -0800 -Received: from flagg2.qualcomm.com [129.46.154.229] - by localhost with IMAP (fetchmail-6.2.5) - for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:40:47 -0800 (PST) -Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com - (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; - Tue, 2 Nov 2004 08:05:31 -0800 -Received: from neophyte.qualcomm.com (neophyte.qualcomm.com [129.46.61.149]) - by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA2G5TcH006140 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL) - for ; Tue, 2 Nov 2004 08:05:30 -0800 (PST) -Received: from hobbiton.qualcomm.com (hobbiton.qualcomm.com [199.106.114.69]) - by neophyte.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA2G5R9A004119 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) - for ; Tue, 2 Nov 2004 08:05:28 -0800 (PST) -Received: from mailserver.internal.evanstech.com ([216.235.152.49]) by hobbiton.qualcomm.com (qualnet-external) with ESMTP id iA2G5QBU029487 for ; Tue, 2 Nov 2004 08:05:26 -0800 (PST) -From: postmaster@evanstech.com -To: eudora-suggest@qualcomm.com -Date: Tue, 2 Nov 2004 11:04:00 -0500 -MIME-Version: 1.0 -Content-Type: multipart/report; report-type=delivery-status; - boundary="9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter" -X-DSNContext: 335a7efd - 4457 - 00000001 - 80040546 -Message-ID: -Subject: Delivery Status Notification (Failure) -X-PMX-Version: 4.6.0.99824, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.8 -X-PerlMx-Spam: Gauge=XXXXX, Probability=50%, Report='VBOUNCE 5, __TO_MALFORMED_2 0, __MIME_VERSION 0, __CT 0, __CTYPE_HAS_BOUNDARY 0, __CTYPE_MULTIPART 0, __HAS_MSGID 0, __SANE_MSGID 0, __UNUSABLE_MSGID 0, __VIRUS_MYDOOM_1 0, NO_REAL_NAME 0' - -This is a MIME-formatted message. -Portions of this message may be unreadable without a MIME-capable mail program. - ---9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - ------------------- Virus Warning Message (on echelon) - -Found virus WORM_SWASH.A in file message.pif (in message.zip) -The uncleanable file is deleted. - -Visit http://qualnet.qualcomm.com/it/virus for more information - ---------------------------------------------------------- - ---9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter -Content-Type: text/plain; charset=unicode-1-1-utf-7 - -This is an automatically generated Delivery Status Notification. - -Delivery to the following recipients failed. - - john@evanstech.com - - - - ---9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter -Content-Type: message/delivery-status - -Reporting-MTA: dns;mailserver.internal.evanstech.com -Received-From-MTA: dns;qualcomm.com -Arrival-Date: Tue, 2 Nov 2004 11:03:49 -0500 - -Final-Recipient: rfc822;john@evanstech.com -Action: failed -Status: 5.1.1 - ---9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter -Content-Type: message/rfc822 - -Received: from qualcomm.com ([80.231.132.37] RDNS failed) by mailserver.internal.evanstech.com with Microsoft SMTPSVC(5.0.2195.6713); - Tue, 2 Nov 2004 11:03:49 -0500 -From: eudora-suggest@qualcomm.com -To: john@evanstech.com -Subject: Status -Date: Tue, 2 Nov 2004 17:03:42 +0100 -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_0007_BF11B844.031F7FC2" -X-Priority: 3 -X-MSMail-Priority: Normal -Return-Path: eudora-suggest@qualcomm.com -Message-ID: -X-OriginalArrivalTime: 02 Nov 2004 16:03:50.0928 (UTC) FILETIME=[8B44D100:01C4C0F5] - -This is a multi-part message in MIME format. - -------=_NextPart_000_0007_BF11B844.031F7FC2 -Content-Type: text/html; - charset="Windows-1252" -Content-Transfer-Encoding: 7bit - -The message cannot be represented in 7-bit ASCII encoding and has been sent as a binary attachment. - - -------=_NextPart_000_0007_BF11B844.031F7FC2 -Content-Type: text/plain; charset=us-ascii -Content-Transfer-Encoding: 7bit - - ------------------- Virus Warning Message (on echelon) - -message.zip is removed from here because it contains a virus. - ---------------------------------------------------------- -------=_NextPart_000_0007_BF11B844.031F7FC2-- - - - - ---9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter-- - +Resent-To: mail.app@flagg2.qualcomm.com +Resent-From: eudora-suggest@flagg2.qualcomm.com +Resent-Message-Id: +Resent-Date: Tue, 2 Nov 2004 08:05:31 -0800 +Received: from flagg2.qualcomm.com [129.46.154.229] + by localhost with IMAP (fetchmail-6.2.5) + for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:40:47 -0800 (PST) +Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com + (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; + Tue, 2 Nov 2004 08:05:31 -0800 +Received: from neophyte.qualcomm.com (neophyte.qualcomm.com [129.46.61.149]) + by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA2G5TcH006140 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL) + for ; Tue, 2 Nov 2004 08:05:30 -0800 (PST) +Received: from hobbiton.qualcomm.com (hobbiton.qualcomm.com [199.106.114.69]) + by neophyte.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA2G5R9A004119 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) + for ; Tue, 2 Nov 2004 08:05:28 -0800 (PST) +Received: from mailserver.internal.evanstech.com ([216.235.152.49]) by hobbiton.qualcomm.com (qualnet-external) with ESMTP id iA2G5QBU029487 for ; Tue, 2 Nov 2004 08:05:26 -0800 (PST) +From: postmaster@evanstech.com +To: eudora-suggest@qualcomm.com +Date: Tue, 2 Nov 2004 11:04:00 -0500 +MIME-Version: 1.0 +Content-Type: multipart/report; report-type=delivery-status; + boundary="9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter" +X-DSNContext: 335a7efd - 4457 - 00000001 - 80040546 +Message-ID: +Subject: Delivery Status Notification (Failure) +X-PMX-Version: 4.6.0.99824, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.8 +X-PerlMx-Spam: Gauge=XXXXX, Probability=50%, Report='VBOUNCE 5, __TO_MALFORMED_2 0, __MIME_VERSION 0, __CT 0, __CTYPE_HAS_BOUNDARY 0, __CTYPE_MULTIPART 0, __HAS_MSGID 0, __SANE_MSGID 0, __UNUSABLE_MSGID 0, __VIRUS_MYDOOM_1 0, NO_REAL_NAME 0' + +This is a MIME-formatted message. +Portions of this message may be unreadable without a MIME-capable mail program. + +--9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit + +------------------ Virus Warning Message (on echelon) + +Found virus WORM_SWASH.A in file message.pif (in message.zip) +The uncleanable file is deleted. + +Visit http://qualnet.qualcomm.com/it/virus for more information + +--------------------------------------------------------- + +--9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter +Content-Type: text/plain; charset=unicode-1-1-utf-7 + +This is an automatically generated Delivery Status Notification. + +Delivery to the following recipients failed. + + john@evanstech.com + + + + +--9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter +Content-Type: message/delivery-status + +Reporting-MTA: dns;mailserver.internal.evanstech.com +Received-From-MTA: dns;qualcomm.com +Arrival-Date: Tue, 2 Nov 2004 11:03:49 -0500 + +Final-Recipient: rfc822;john@evanstech.com +Action: failed +Status: 5.1.1 + +--9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter +Content-Type: message/rfc822 + +Received: from qualcomm.com ([80.231.132.37] RDNS failed) by mailserver.internal.evanstech.com with Microsoft SMTPSVC(5.0.2195.6713); + Tue, 2 Nov 2004 11:03:49 -0500 +From: eudora-suggest@qualcomm.com +To: john@evanstech.com +Subject: Status +Date: Tue, 2 Nov 2004 17:03:42 +0100 +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="----=_NextPart_000_0007_BF11B844.031F7FC2" +X-Priority: 3 +X-MSMail-Priority: Normal +Return-Path: eudora-suggest@qualcomm.com +Message-ID: +X-OriginalArrivalTime: 02 Nov 2004 16:03:50.0928 (UTC) FILETIME=[8B44D100:01C4C0F5] + +This is a multi-part message in MIME format. + +------=_NextPart_000_0007_BF11B844.031F7FC2 +Content-Type: text/html; + charset="Windows-1252" +Content-Transfer-Encoding: 7bit + +The message cannot be represented in 7-bit ASCII encoding and has been sent as a binary attachment. + + +------=_NextPart_000_0007_BF11B844.031F7FC2 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit + + +------------------ Virus Warning Message (on echelon) + +message.zip is removed from here because it contains a virus. + +--------------------------------------------------------- +------=_NextPart_000_0007_BF11B844.031F7FC2-- + + + + +--9B095B5ADSN=_01C4A240558054EB0030F626mailserver.inter-- + diff --git a/libs/mime/test/TestMessages/0019-NoBoundary b/libs/mime/test/TestMessages/0019-NoBoundary index ec0c237f4..df297920f 100644 --- a/libs/mime/test/TestMessages/0019-NoBoundary +++ b/libs/mime/test/TestMessages/0019-NoBoundary @@ -1,80 +1,80 @@ -Resent-To: mail.app@flagg2.qualcomm.com -Resent-From: win-eudora-bugs@flagg2.qualcomm.com -Resent-Message-Id: -Resent-Date: Mon, 1 Nov 2004 16:01:16 -0800 -Received: from flagg2.qualcomm.com [129.46.154.229] - by localhost with IMAP (fetchmail-6.2.5) - for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:38:27 -0800 (PST) -Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com - (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; - Mon, 1 Nov 2004 16:01:16 -0800 -Received: from neophyte.qualcomm.com (neophyte.qualcomm.com [129.46.61.149]) - by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA201FcH022189 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); - Mon, 1 Nov 2004 16:01:15 -0800 (PST) -Received: from hobbiton.qualcomm.com (hobbiton.qualcomm.com [199.106.114.69]) - by neophyte.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA201D9A029029 - (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) - for ; Mon, 1 Nov 2004 16:01:13 -0800 (PST) -Received: from isengard.qualcomm.com (isengard.qualcomm.com [199.106.114.75]) by hobbiton.qualcomm.com (qualnet-external) with ESMTP id iA201BhJ016885 for ; Mon, 1 Nov 2004 16:01:12 -0800 (PST) -Received: from localhost (localhost) by isengard.qualcomm.com id iA201CuA023535; Mon, 1 Nov 2004 16:01:12 -0800 (PST) -Date: Mon, 1 Nov 2004 16:01:12 -0800 (PST) -From: Mail Delivery Subsystem -Message-Id: <200411020001.iA201CuA023535@isengard.qualcomm.com> -To: -MIME-Version: 1.0 -Content-Type: multipart/report; report-type=delivery-status -Subject: Returned mail: see transcript for details -Auto-Submitted: auto-generated (failure) -X-PMX-Version: 4.6.0.99824, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.3 - -This is a MIME-encapsulated message - ---iA201CuA023535.1099353672/isengard.qualcomm.com - -The original message was received at Mon, 1 Nov 2004 16:01:09 -0800 (PST) -from [210.193.18.250] - - ----- The following addresses had permanent fatal errors ----- - - (reason: 550 5.6.1 Prohibited attachment type) - - ----- Transcript of session follows ----- -... while talking to hobbiton.qualcomm.com.: ->>> DATA -<<< 550 5.6.1 Prohibited attachment type -554 5.0.0 Service unavailable - ---iA201CuA023535.1099353672/isengard.qualcomm.com -Content-Type: message/delivery-status - -Reporting-MTA: dns; isengard.qualcomm.com -Received-From-MTA: DNS; [210.193.18.250] -Arrival-Date: Mon, 1 Nov 2004 16:01:09 -0800 (PST) - -Final-Recipient: RFC822; win-eudora6-bugs@eudora.com -Action: failed -Status: 5.6.1 -Remote-MTA: DNS; hobbiton.qualcomm.com -Diagnostic-Code: SMTP; 550 5.6.1 Prohibited attachment type -Last-Attempt-Date: Mon, 1 Nov 2004 16:01:12 -0800 (PST) - ---iA201CuA023535.1099353672/isengard.qualcomm.com -Content-Type: text/rfc822-headers - -Return-Path: -Received: from eudora.com ([210.193.18.250]) by isengard.qualcomm.com with ESMTP id iA2018uA023523 for ; Mon, 1 Nov 2004 16:01:09 -0800 (PST) -Message-Id: <200411020001.iA2018uA023523@isengard.qualcomm.com> -From: win-eudora6-bugs@eudora.com -To: win-eudora6-bugs@eudora.com -Subject: Re: Excel file -Date: Tue, 2 Nov 2004 08:00:34 +0800 -MIME-Version: 1.0 -Content-Type: multipart/mixed; - boundary="----=_NextPart_000_0001_00000AE6.000070CC" -X-Priority: 3 -X-MSMail-Priority: Normal - ---iA201CuA023535.1099353672/isengard.qualcomm.com-- - - +Resent-To: mail.app@flagg2.qualcomm.com +Resent-From: win-eudora-bugs@flagg2.qualcomm.com +Resent-Message-Id: +Resent-Date: Mon, 1 Nov 2004 16:01:16 -0800 +Received: from flagg2.qualcomm.com [129.46.154.229] + by localhost with IMAP (fetchmail-6.2.5) + for marshall@localhost (single-drop); Tue, 02 Nov 2004 11:38:27 -0800 (PST) +Received: from snape.qualcomm.com (unverified [129.46.132.184]) (using TLSv1 with Cipher RC4(128), Exch RSA_SIGN(1024), Hash MD5(128)) by flagg2.qualcomm.com + (Rockliffe SMTPRA 6.1.16) with ESMTP id for ; + Mon, 1 Nov 2004 16:01:16 -0800 +Received: from neophyte.qualcomm.com (neophyte.qualcomm.com [129.46.61.149]) + by snape.qualcomm.com (8.12.10/8.12.3/1.0) with ESMTP id iA201FcH022189 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); + Mon, 1 Nov 2004 16:01:15 -0800 (PST) +Received: from hobbiton.qualcomm.com (hobbiton.qualcomm.com [199.106.114.69]) + by neophyte.qualcomm.com (8.12.10/8.12.5/1.0) with ESMTP id iA201D9A029029 + (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT) + for ; Mon, 1 Nov 2004 16:01:13 -0800 (PST) +Received: from isengard.qualcomm.com (isengard.qualcomm.com [199.106.114.75]) by hobbiton.qualcomm.com (qualnet-external) with ESMTP id iA201BhJ016885 for ; Mon, 1 Nov 2004 16:01:12 -0800 (PST) +Received: from localhost (localhost) by isengard.qualcomm.com id iA201CuA023535; Mon, 1 Nov 2004 16:01:12 -0800 (PST) +Date: Mon, 1 Nov 2004 16:01:12 -0800 (PST) +From: Mail Delivery Subsystem +Message-Id: <200411020001.iA201CuA023535@isengard.qualcomm.com> +To: +MIME-Version: 1.0 +Content-Type: multipart/report; report-type=delivery-status +Subject: Returned mail: see transcript for details +Auto-Submitted: auto-generated (failure) +X-PMX-Version: 4.6.0.99824, Antispam-Core: 4.6.0.97340, Antispam-Data: 2004.11.1.3 + +This is a MIME-encapsulated message + +--iA201CuA023535.1099353672/isengard.qualcomm.com + +The original message was received at Mon, 1 Nov 2004 16:01:09 -0800 (PST) +from [210.193.18.250] + + ----- The following addresses had permanent fatal errors ----- + + (reason: 550 5.6.1 Prohibited attachment type) + + ----- Transcript of session follows ----- +... while talking to hobbiton.qualcomm.com.: +>>> DATA +<<< 550 5.6.1 Prohibited attachment type +554 5.0.0 Service unavailable + +--iA201CuA023535.1099353672/isengard.qualcomm.com +Content-Type: message/delivery-status + +Reporting-MTA: dns; isengard.qualcomm.com +Received-From-MTA: DNS; [210.193.18.250] +Arrival-Date: Mon, 1 Nov 2004 16:01:09 -0800 (PST) + +Final-Recipient: RFC822; win-eudora6-bugs@eudora.com +Action: failed +Status: 5.6.1 +Remote-MTA: DNS; hobbiton.qualcomm.com +Diagnostic-Code: SMTP; 550 5.6.1 Prohibited attachment type +Last-Attempt-Date: Mon, 1 Nov 2004 16:01:12 -0800 (PST) + +--iA201CuA023535.1099353672/isengard.qualcomm.com +Content-Type: text/rfc822-headers + +Return-Path: +Received: from eudora.com ([210.193.18.250]) by isengard.qualcomm.com with ESMTP id iA2018uA023523 for ; Mon, 1 Nov 2004 16:01:09 -0800 (PST) +Message-Id: <200411020001.iA2018uA023523@isengard.qualcomm.com> +From: win-eudora6-bugs@eudora.com +To: win-eudora6-bugs@eudora.com +Subject: Re: Excel file +Date: Tue, 2 Nov 2004 08:00:34 +0800 +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="----=_NextPart_000_0001_00000AE6.000070CC" +X-Priority: 3 +X-MSMail-Priority: Normal + +--iA201CuA023535.1099353672/isengard.qualcomm.com-- + + diff --git a/libs/mime/test/mime-roundtrip.cpp b/libs/mime/test/mime-roundtrip.cpp index c4f6aa34e..d09166076 100644 --- a/libs/mime/test/mime-roundtrip.cpp +++ b/libs/mime/test/mime-roundtrip.cpp @@ -87,7 +87,9 @@ init_unit_test_suite( int argc, char* argv[] ) framework::master_test_suite().add ( BOOST_TEST_CASE( boost::bind ( test_roundtrip, "TestMessages/00000019" ))); framework::master_test_suite().add ( BOOST_TEST_CASE( boost::bind ( test_roundtrip, "TestMessages/00000431" ))); framework::master_test_suite().add ( BOOST_TEST_CASE( boost::bind ( test_roundtrip, "TestMessages/00000975" ))); - framework::master_test_suite().add ( BOOST_TEST_CASE( boost::bind ( test_roundtrip, "TestMessages/00001136" ))); + +// Following test is removed because the file it used often tripped false-positives when scanned by virus checkers. +// framework::master_test_suite().add ( BOOST_TEST_CASE( boost::bind ( test_roundtrip, "TestMessages/00001136" ))); // test cases that fail // framework::master_test_suite().add ( BOOST_TEST_CASE( boost::bind ( test_roundtrip, "TestMessages/0019-NoBoundary" ))); From f67705f21222ee79d819319c0ab571d793d121ec Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 10 Dec 2011 17:30:23 +0100 Subject: [PATCH 213/768] URI no longer uses ranges internally, but strings because of inconsistencies in the parser that I couldn't solve. --- boost/network/protocol/http/impl/request.hpp | 2 +- boost/network/uri/accessors.hpp | 26 +++--- boost/network/uri/detail/uri_parts.hpp | 52 +++++------- boost/network/uri/directives/query.hpp | 2 +- boost/network/uri/uri.hpp | 86 +++++++------------- libs/network/src/uri/parse.cpp | 67 +++++++-------- libs/network/test/uri/url_test.cpp | 47 +++++------ 7 files changed, 121 insertions(+), 161 deletions(-) diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index 707ee175a..b777e8b4d 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -96,7 +96,7 @@ namespace http { if (!port) { typedef constants consts; - return boost::iequals(uri_.scheme_range(), + return boost::iequals(uri_.scheme(), string_type(consts::https()))? 443 : 80; } return *port; diff --git a/boost/network/uri/accessors.hpp b/boost/network/uri/accessors.hpp index 7b71862b3..56b50dfbb 100644 --- a/boost/network/uri/accessors.hpp +++ b/boost/network/uri/accessors.hpp @@ -45,53 +45,53 @@ template < > inline Map &query_map(const uri &uri_, Map &map) { - uri::const_range_type range = uri_.query_range(); + std::string range = uri_.query(); details::key_value_sequence parser; spirit::qi::parse(boost::begin(range), boost::end(range), parser, map); return map; } std::string username(const uri &uri_) { - uri::const_range_type user_info_range = uri_.user_info_range(); - uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); + std::string user_info = uri_.user_info(); + uri::const_iterator it(boost::begin(user_info)), end(boost::end(user_info)); for (; it != end; ++it) { if (*it == ':') { break; } } - return std::string(boost::begin(user_info_range), it); + return std::string(boost::begin(user_info), it); } std::string password(const uri &uri_) { - uri::const_range_type user_info_range = uri_.user_info_range(); - uri::const_iterator it(boost::begin(user_info_range)), end(boost::end(user_info_range)); + std::string user_info = uri_.user_info(); + uri::const_iterator it(boost::begin(user_info)), end(boost::end(user_info)); for (; it != end; ++it) { if (*it == ':') { ++it; break; } } - return std::string(it, boost::end(user_info_range)); + return std::string(it, boost::end(user_info)); } std::string decoded_path(const uri &uri_) { - uri::const_range_type path_range = uri_.path_range(); + std::string path = uri_.path(); std::string decoded_path; - decode(path_range, std::back_inserter(decoded_path)); + decode(path, std::back_inserter(decoded_path)); return decoded_path; } std::string decoded_query(const uri &uri_) { - uri::const_range_type query_range = uri_.query_range(); + std::string query = uri_.query(); std::string decoded_query; - decode(query_range, std::back_inserter(decoded_query)); + decode(query, std::back_inserter(decoded_query)); return decoded_query; } std::string decoded_fragment(const uri &uri_) { - uri::const_range_type fragment_range = uri_.fragment_range(); + std::string fragment = uri_.fragment(); std::string decoded_fragment; - decode(fragment_range, std::back_inserter(decoded_fragment)); + decode(fragment, std::back_inserter(decoded_fragment)); return decoded_fragment; } } // namespace uri diff --git a/boost/network/uri/detail/uri_parts.hpp b/boost/network/uri/detail/uri_parts.hpp index 48a88d238..985a9ede3 100644 --- a/boost/network/uri/detail/uri_parts.hpp +++ b/boost/network/uri/detail/uri_parts.hpp @@ -7,48 +7,36 @@ # define BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ -# include +# include namespace boost { namespace network { namespace uri { namespace detail { -template < - class FwdIter - > struct hierarchical_part { - iterator_range user_info, host, port, path; - - hierarchical_part() - {} - - hierarchical_part(FwdIter begin, FwdIter end) - : user_info(begin, end) - , host(begin, end) - , port(begin, end) - , path(begin, end) - { } + std::string user_info, host, port, path; + + void clear() { + user_info.clear(); + host.clear(); + port.clear(); + path.clear(); + } }; -template < - class FwdIter - > struct uri_parts { - iterator_range scheme; - hierarchical_part hier_part; - iterator_range query; - iterator_range fragment; - - uri_parts() - {} - - uri_parts(FwdIter begin, FwdIter end) - : scheme(begin, end) - , hier_part(begin, end) - , query(begin, end) - , fragment(begin, end) - { } + std::string scheme; + hierarchical_part hier_part; + std::string query; + std::string fragment; + + void clear() { + scheme.clear(); + hier_part.clear(); + query.clear(); + fragment.clear(); + } }; } // namespace detail } // namespace uri diff --git a/boost/network/uri/directives/query.hpp b/boost/network/uri/directives/query.hpp index d2afbcadf..c4692f44c 100644 --- a/boost/network/uri/directives/query.hpp +++ b/boost/network/uri/directives/query.hpp @@ -44,7 +44,7 @@ struct query_key_query_directive { > void operator () (Uri &uri) const { std::string encoded_key, encoded_query; - if (!uri.query_range()) + if (boost::empty(uri.query())) { uri.append("?"); } diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index fd8e17e3a..41e053b8e 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -10,6 +10,7 @@ # include # include # include +# include # include # include # include @@ -21,7 +22,7 @@ namespace uri { namespace detail { bool parse(std::string::const_iterator first, std::string::const_iterator last, - uri_parts &parts); + uri_parts &parts); } // namespace detail @@ -32,9 +33,7 @@ class uri typedef std::string string_type; typedef string_type::iterator iterator; - typedef boost::iterator_range range_type; typedef string_type::const_iterator const_iterator; - typedef boost::iterator_range const_range_type; uri() : is_valid_(false) { @@ -45,7 +44,7 @@ class uri class FwdIter > uri(const FwdIter &first, const FwdIter &last) - : uri_(first, last), uri_parts_(first, first), is_valid_(false) { + : uri_(first, last), is_valid_(false) { parse(); } @@ -97,67 +96,32 @@ class uri return uri_.end(); } - const_range_type scheme_range() const { - return uri_parts_.scheme; - } - - const_range_type user_info_range() const { - return uri_parts_.hier_part.user_info; - } - - const_range_type host_range() const { - return uri_parts_.hier_part.host; - } - - const_range_type port_range() const { - return uri_parts_.hier_part.port; - } - - const_range_type path_range() const { - return uri_parts_.hier_part.path; - } - - const_range_type query_range() const { - return uri_parts_.query; - } - - const_range_type fragment_range() const { - return uri_parts_.fragment; - } - string_type scheme() const { - const_range_type range = scheme_range(); - return string_type(boost::begin(range), boost::end(range)); + return uri_parts_.scheme; } string_type user_info() const { - const_range_type range = user_info_range(); - return string_type(boost::begin(range), boost::end(range)); + return uri_parts_.hier_part.user_info; } string_type host() const { - const_range_type range = host_range(); - return string_type(boost::begin(range), boost::end(range)); + return uri_parts_.hier_part.host; } string_type port() const { - const_range_type range = port_range(); - return string_type(boost::begin(range), boost::end(range)); + return uri_parts_.hier_part.port; } string_type path() const { - const_range_type range = path_range(); - return string_type(boost::begin(range), boost::end(range)); + return uri_parts_.hier_part.path; } string_type query() const { - const_range_type range = query_range(); - return string_type(boost::begin(range), boost::end(range)); + return uri_parts_.query; } string_type fragment() const { - const_range_type range = fragment_range(); - return string_type(boost::begin(range), boost::end(range)); + return uri_parts_.fragment; } string_type string() const { @@ -186,13 +150,14 @@ class uri void parse(); string_type uri_; - detail::uri_parts uri_parts_; + detail::uri_parts uri_parts_; bool is_valid_; }; inline void uri::parse() { + uri_parts_.clear(); const_iterator first(boost::begin(uri_)), last(boost::end(uri_)); is_valid_ = detail::parse(first, last, uri_parts_); } @@ -242,14 +207,25 @@ std::string fragment(const uri &uri_) { inline std::string authority(const uri &uri_) { - uri::const_range_type user_info(uri_.user_info_range()); - uri::const_range_type port(uri_.port_range()); - return std::string(user_info.begin(), port.end()); -} - -inline -std::string netloc(const uri &uri_) { - return authority(uri_); + std::string user_info(uri_.user_info()); + std::string host(uri_.host()); + std::string port(uri_.port()); + std::string authority; + if (!boost::empty(user_info)) + { + std::copy(boost::begin(user_info), boost::end(user_info), std::back_inserter(authority)); + authority.push_back('@'); + } + if (!boost::empty(host)) + { + std::copy(boost::begin(host), boost::end(host), std::back_inserter(authority)); + } + if (!boost::empty(port)) + { + authority.push_back(':'); + std::copy(boost::begin(port), boost::end(port), std::back_inserter(authority)); + } + return authority; } inline diff --git a/libs/network/src/uri/parse.cpp b/libs/network/src/uri/parse.cpp index 8392eed38..bbad450a3 100644 --- a/libs/network/src/uri/parse.cpp +++ b/libs/network/src/uri/parse.cpp @@ -9,24 +9,22 @@ #include #include -BOOST_FUSION_ADAPT_TPL_STRUCT +BOOST_FUSION_ADAPT_STRUCT ( - (FwdIter), - (boost::network::uri::detail::hierarchical_part)(FwdIter), - (boost::iterator_range, user_info) - (boost::iterator_range, host) - (boost::iterator_range, port) - (boost::iterator_range, path) + boost::network::uri::detail::hierarchical_part, + (std::string, user_info) + (std::string, host) + (std::string, port) + (std::string, path) ); -BOOST_FUSION_ADAPT_TPL_STRUCT +BOOST_FUSION_ADAPT_STRUCT ( - (FwdIter), - (boost::network::uri::detail::uri_parts)(FwdIter), - (boost::iterator_range, scheme) - (boost::network::uri::detail::hierarchical_part, hier_part) - (boost::iterator_range, query) - (boost::iterator_range, fragment) + boost::network::uri::detail::uri_parts, + (std::string, scheme) + (boost::network::uri::detail::hierarchical_part, hier_part) + (std::string, query) + (std::string, fragment) ); namespace boost { @@ -40,7 +38,7 @@ template < > struct uri_grammar : qi::grammar< typename String::const_iterator - , detail::uri_parts()> { + , detail::uri_parts()> { typedef String string_type; typedef typename String::const_iterator const_iterator; @@ -72,20 +70,18 @@ struct uri_grammar : qi::grammar< ]; // path-abempty = *( "/" segment ) path_abempty %= - qi::raw[qi::raw[*(qi::char_("/") >> segment)]] + qi::raw[*(qi::char_("/") >> segment)] ; // path-absolute = "/" [ segment-nz *( "/" segment ) ] path_absolute %= - qi::raw[qi::raw[ - qi::char_("/") - >> -(segment_nz >> *(qi::char_("/") >> segment)) - ]] + qi::raw[ + qi::char_("/") + >> -(segment_nz >> *(qi::char_("/") >> segment)) + ] ; // path-rootless = segment-nz *( "/" segment ) path_rootless %= - qi::raw[qi::raw[ - segment_nz >> *(qi::char_("/") >> segment) - ]] + qi::raw[segment_nz >> *(qi::char_("/") >> segment)] ; // path-empty = 0 path_empty %= @@ -99,7 +95,7 @@ struct uri_grammar : qi::grammar< // user_info = *( unreserved / pct-encoded / sub-delims / ":" ) user_info %= - qi::raw[qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))]] + qi::raw[*(unreserved | pct_encoded | sub_delims | qi::char_(":"))] ; ip_literal %= @@ -120,7 +116,6 @@ struct uri_grammar : qi::grammar< | qi::raw[qi::repeat(4)[*(h16 >> ':')] >> h16] >> "::" >> ls32 | qi::raw[qi::repeat(5)[*(h16 >> ':')] >> h16] >> "::" >> h16 | qi::raw[qi::repeat(6)[*(h16 >> ':')] >> h16] >> "::" - ]; // ls32 = ( h16 ":" h16 ) / IPv4address @@ -160,12 +155,12 @@ struct uri_grammar : qi::grammar< // query = *( pchar / "/" / "?" ) query %= - qi::raw[qi::raw[*(pchar | qi::char_("/?"))]] + qi::raw[*(pchar | qi::char_("/?"))] ; // fragment = *( pchar / "/" / "?" ) fragment %= - qi::raw[qi::raw[*(pchar | qi::char_("/?"))]] + qi::raw[*(pchar | qi::char_("/?"))] ; // hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty @@ -180,9 +175,9 @@ struct uri_grammar : qi::grammar< ) | ( - qi::attr(iterator_range()) - >> qi::attr(iterator_range()) - >> qi::attr(iterator_range()) + qi::attr(string_type()) + >> qi::attr(string_type()) + >> qi::attr(string_type()) >> ( path_absolute | path_rootless @@ -206,7 +201,7 @@ struct uri_grammar : qi::grammar< qi::rule segment, segment_nz, segment_nz_nc; - qi::rule()> + qi::rule path_abempty, path_absolute, path_rootless, path_empty; qi::rule @@ -215,23 +210,23 @@ struct uri_grammar : qi::grammar< qi::rule h16, ls32; - qi::rule()> + qi::rule host, port; - qi::rule()> + qi::rule scheme, user_info, query, fragment; - qi::rule()> + qi::rule hier_part; // actual uri parser - qi::rule()> start; + qi::rule start; }; bool parse(std::string::const_iterator first, std::string::const_iterator last, - uri_parts &parts) { + uri_parts &parts) { namespace qi = boost::spirit::qi; static detail::uri_grammar grammar; bool is_valid = qi::parse(first, last, grammar, parts); diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index e56f4a327..fdca7014f 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -16,29 +16,29 @@ using namespace boost::network; -BOOST_AUTO_TEST_CASE(basic_uri_range_test) { - uri::uri instance("http://www.example.com/"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); - BOOST_CHECK(boost::empty(instance.user_info_range())); - BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); - BOOST_CHECK(boost::empty(instance.port_range())); - BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/"))); - BOOST_CHECK(boost::empty(instance.query_range())); - BOOST_CHECK(boost::empty(instance.fragment_range())); -} - -BOOST_AUTO_TEST_CASE(full_uri_range_test) { - uri::uri instance("http://user:password@www.example.com/path?query#fragment"); - BOOST_REQUIRE(uri::valid(instance)); - BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); - BOOST_CHECK(boost::equal(instance.user_info_range(), boost::as_literal("user:password"))); - BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); - BOOST_CHECK(boost::equal(instance.port_range(), boost::as_literal("80"))); - BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/path"))); - BOOST_CHECK(boost::equal(instance.query_range(), boost::as_literal("query"))); - BOOST_CHECK(boost::equal(instance.fragment_range(), boost::as_literal("fragment"))); -} +//BOOST_AUTO_TEST_CASE(basic_uri_range_test) { +// uri::uri instance("http://www.example.com/"); +// BOOST_REQUIRE(uri::valid(instance)); +// BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); +// BOOST_CHECK(boost::empty(instance.user_info_range())); +// BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); +// BOOST_CHECK(boost::empty(instance.port_range())); +// BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/"))); +// BOOST_CHECK(boost::empty(instance.query_range())); +// BOOST_CHECK(boost::empty(instance.fragment_range())); +//} +// +//BOOST_AUTO_TEST_CASE(full_uri_range_test) { +// uri::uri instance("http://user:password@www.example.com/path?query#fragment"); +// BOOST_REQUIRE(uri::valid(instance)); +// BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); +// BOOST_CHECK(boost::equal(instance.user_info_range(), boost::as_literal("user:password"))); +// BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); +// BOOST_CHECK(boost::equal(instance.port_range(), boost::as_literal("80"))); +// BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/path"))); +// BOOST_CHECK(boost::equal(instance.query_range(), boost::as_literal("query"))); +// BOOST_CHECK(boost::equal(instance.fragment_range(), boost::as_literal("fragment"))); +//} BOOST_AUTO_TEST_CASE(basic_uri_test) { uri::uri instance("http://www.example.com/"); @@ -164,6 +164,7 @@ BOOST_AUTO_TEST_CASE(username_test) { BOOST_AUTO_TEST_CASE(authority_test) { uri::uri instance("http://user:password@www.example.com/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); + std::cout << uri::authority(instance) << std::endl; BOOST_CHECK_EQUAL(uri::authority(instance), "user:password@www.example.com:80"); } From 064b0bb5652997ea59c0e3c70fbc5ce1e1c023a7 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 10 Dec 2011 18:17:11 +0100 Subject: [PATCH 214/768] Fixes for compilation on Linux/GCC 4.4. --- boost/network/uri/accessors.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/boost/network/uri/accessors.hpp b/boost/network/uri/accessors.hpp index 56b50dfbb..41d92c5d2 100644 --- a/boost/network/uri/accessors.hpp +++ b/boost/network/uri/accessors.hpp @@ -45,14 +45,14 @@ template < > inline Map &query_map(const uri &uri_, Map &map) { - std::string range = uri_.query(); + const std::string range = uri_.query(); details::key_value_sequence parser; spirit::qi::parse(boost::begin(range), boost::end(range), parser, map); return map; } std::string username(const uri &uri_) { - std::string user_info = uri_.user_info(); + const std::string user_info = uri_.user_info(); uri::const_iterator it(boost::begin(user_info)), end(boost::end(user_info)); for (; it != end; ++it) { if (*it == ':') { @@ -63,7 +63,7 @@ std::string username(const uri &uri_) { } std::string password(const uri &uri_) { - std::string user_info = uri_.user_info(); + const std::string user_info = uri_.user_info(); uri::const_iterator it(boost::begin(user_info)), end(boost::end(user_info)); for (; it != end; ++it) { if (*it == ':') { @@ -75,21 +75,21 @@ std::string password(const uri &uri_) { } std::string decoded_path(const uri &uri_) { - std::string path = uri_.path(); + const std::string path = uri_.path(); std::string decoded_path; decode(path, std::back_inserter(decoded_path)); return decoded_path; } std::string decoded_query(const uri &uri_) { - std::string query = uri_.query(); + const std::string query = uri_.query(); std::string decoded_query; decode(query, std::back_inserter(decoded_query)); return decoded_query; } std::string decoded_fragment(const uri &uri_) { - std::string fragment = uri_.fragment(); + const std::string fragment = uri_.fragment(); std::string decoded_fragment; decode(fragment, std::back_inserter(decoded_fragment)); return decoded_fragment; From f45f21ae01720f784c654ac4dd16e01c26492fb2 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 11 Dec 2011 11:12:49 +0100 Subject: [PATCH 215/768] Added an atom feed example. --- boost/network/uri/accessors.hpp | 5 + boost/network/uri/uri.hpp | 15 - libs/network/example/CMakeLists.txt | 10 + libs/network/example/atom/atom.cpp | 97 + libs/network/example/atom/atom.hpp | 177 ++ libs/network/example/atom/main.cpp | 36 + libs/network/example/rapidxml/license.txt | 52 + libs/network/example/rapidxml/manual.html | 406 +++ libs/network/example/rapidxml/rapidxml.hpp | 2596 +++++++++++++++++ .../example/rapidxml/rapidxml_iterators.hpp | 174 ++ .../example/rapidxml/rapidxml_print.hpp | 421 +++ .../example/rapidxml/rapidxml_utils.hpp | 122 + 12 files changed, 4096 insertions(+), 15 deletions(-) create mode 100644 libs/network/example/atom/atom.cpp create mode 100644 libs/network/example/atom/atom.hpp create mode 100644 libs/network/example/atom/main.cpp create mode 100644 libs/network/example/rapidxml/license.txt create mode 100644 libs/network/example/rapidxml/manual.html create mode 100644 libs/network/example/rapidxml/rapidxml.hpp create mode 100644 libs/network/example/rapidxml/rapidxml_iterators.hpp create mode 100644 libs/network/example/rapidxml/rapidxml_print.hpp create mode 100644 libs/network/example/rapidxml/rapidxml_utils.hpp diff --git a/boost/network/uri/accessors.hpp b/boost/network/uri/accessors.hpp index 41d92c5d2..22810d70a 100644 --- a/boost/network/uri/accessors.hpp +++ b/boost/network/uri/accessors.hpp @@ -51,6 +51,7 @@ Map &query_map(const uri &uri_, Map &map) { return map; } +inline std::string username(const uri &uri_) { const std::string user_info = uri_.user_info(); uri::const_iterator it(boost::begin(user_info)), end(boost::end(user_info)); @@ -62,6 +63,7 @@ std::string username(const uri &uri_) { return std::string(boost::begin(user_info), it); } +inline std::string password(const uri &uri_) { const std::string user_info = uri_.user_info(); uri::const_iterator it(boost::begin(user_info)), end(boost::end(user_info)); @@ -74,6 +76,7 @@ std::string password(const uri &uri_) { return std::string(it, boost::end(user_info)); } +inline std::string decoded_path(const uri &uri_) { const std::string path = uri_.path(); std::string decoded_path; @@ -81,6 +84,7 @@ std::string decoded_path(const uri &uri_) { return decoded_path; } +inline std::string decoded_query(const uri &uri_) { const std::string query = uri_.query(); std::string decoded_query; @@ -88,6 +92,7 @@ std::string decoded_query(const uri &uri_) { return decoded_query; } +inline std::string decoded_fragment(const uri &uri_) { const std::string fragment = uri_.fragment(); std::string decoded_fragment; diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 41e053b8e..a89bf6afa 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -238,21 +238,6 @@ bool is_valid(const uri &uri_) { return valid(uri_); } -inline -bool is_hierarchical(const uri &uri_) { - //uri::const_range_type scheme = uri_.scheme_range(); - //uri::const_range_type user_info = uri_.user_info_range(); - //return is_valid(uri_) && - // boost::equal(std::make_pair(boost::end(scheme), - // boost::begin(user_info)), - // boost::as_literal("://")); - return false; -} - -bool is_opaque(const uri &uri_) { - return false; -} - inline bool operator == (const uri &lhs, const uri &rhs) { return std::equal(lhs.begin(), lhs.end(), rhs.begin()); diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 7f901ea27..30ce40ae9 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -10,6 +10,7 @@ endif (OPENSSL_FOUND) add_executable(http_client http_client.cpp) add_executable(simple_wget simple_wget.cpp) +add_executable(atom_reader atom/atom.cpp atom/main.cpp) add_executable(hello_world_server http/hello_world_server.cpp) if (UNIX) add_executable(fileserver http/fileserver.cpp) @@ -17,6 +18,7 @@ endif (UNIX) add_executable(uri uri.cpp) add_dependencies(http_client cppnetlib-uri cppnetlib-client-connections) add_dependencies(simple_wget cppnetlib-uri cppnetlib-client-connections) +add_dependencies(atom_reader cppnetlib-uri cppnetlib-client-connections) add_dependencies(uri cppnetlib-uri) set(BOOST_CLIENT_LIBS ${Boost_PROGRAM_OPTIONS_LIBRARY} @@ -43,6 +45,12 @@ target_link_libraries(simple_wget cppnetlib-uri cppnetlib-client-connections) +target_link_libraries(atom_reader + ${BOOST_CLIENT_LIBS} + ${CMAKE_THREAD_LIBS_INIT} + cppnetlib-uri + cppnetlib-client-connections) + target_link_libraries(hello_world_server ${BOOST_SERVER_LIBS} ${CMAKE_THREAD_LIBS_INIT}) @@ -50,6 +58,7 @@ target_link_libraries(hello_world_server if (OPENSSL_FOUND) target_link_libraries(http_client ${OPENSSL_LIBRARIES}) target_link_libraries(simple_wget ${OPENSSL_LIBRARIES}) + target_link_libraries(atom_reader ${OPENSSL_LIBRARIES}) target_link_libraries(hello_world_server ${OPENSSL_LIBRARIES}) endif (OPENSSL_FOUND) @@ -64,6 +73,7 @@ endif (UNIX) target_link_libraries(uri cppnetlib-uri) set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(atom_reader PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) if (UNIX) set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) diff --git a/libs/network/example/atom/atom.cpp b/libs/network/example/atom/atom.cpp new file mode 100644 index 000000000..4c729b6ba --- /dev/null +++ b/libs/network/example/atom/atom.cpp @@ -0,0 +1,97 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include "atom.hpp" +#include "../rapidxml/rapidxml.hpp" +#include +#include + + +namespace boost { +namespace network { +namespace atom { +feed::feed(const http::client::response &response) { + std::string response_body = body(response); + rapidxml::xml_document<> doc; + doc.parse<0>(const_cast(response_body.c_str())); + + rapidxml::xml_node<> *feed = doc.first_node("feed"); + if (!feed) { + throw std::runtime_error("Invalid atom feed."); + } + + rapidxml::xml_node<> *title = feed->first_node("title"); + if (title) { + title_ = title->first_node()->value(); + } + + rapidxml::xml_node<> *subtitle = feed->first_node("subtitle"); + if (subtitle) { + subtitle_ = subtitle->first_node()->value(); + } + + rapidxml::xml_node<> *id = feed->first_node("id"); + if (id) { + id_ = id->first_node()->value(); + } + + rapidxml::xml_node<> *updated = feed->first_node("updated"); + if (updated) { + updated_ = updated->first_node()->value(); + } + + rapidxml::xml_node<> *author = feed->first_node("author"); + if (author) { + rapidxml::xml_node<> *name = author->first_node("name"); + rapidxml::xml_node<> *email = author->first_node("email"); + if (name && email) { + author_ = atom::author(name->first_node()->value(), email->first_node()->value()); + } + else if (name) { + author_ = atom::author(name->first_node()->value()); + } + } + + rapidxml::xml_node<> *entry = feed->first_node("entry"); + while (entry) { + entries_.push_back(atom::entry()); + + rapidxml::xml_node<> *title = entry->first_node("title"); + if (title) { + entries_.back().set_title(title->first_node()->value()); + } + + rapidxml::xml_node<> *id = entry->first_node("id"); + if (id) { + entries_.back().set_id(id->first_node()->value()); + } + + rapidxml::xml_node<> *published = entry->first_node("published"); + if (published) { + entries_.back().set_published(published->first_node()->value()); + } + + rapidxml::xml_node<> *updated = entry->first_node("updated"); + if (updated) { + entries_.back().set_updated(updated->first_node()->value()); + } + + rapidxml::xml_node<> *summary = entry->first_node("summary"); + if (summary) { + entries_.back().set_summary(summary->first_node()->value()); + } + + rapidxml::xml_node<> *content = entry->first_node("content"); + if (content) { + entries_.back().set_content(content->first_node()->value()); + } + + entry = entry->next_sibling(); + } +} +} // namespace atom +} // namespace network +} // namespace boost diff --git a/libs/network/example/atom/atom.hpp b/libs/network/example/atom/atom.hpp new file mode 100644 index 000000000..b19e4146a --- /dev/null +++ b/libs/network/example/atom/atom.hpp @@ -0,0 +1,177 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef ___ATOM_INC__ +# define ___ATOM_INC__ + + +# include +# include +# include + + +namespace boost { +namespace network { +namespace atom { +class entry { + +public: + + void set_title(const std::string &title) { + title_ = title; + } + + std::string title() const { + return title_; + } + + void set_id(const std::string &id) { + id_ = id; + } + + std::string id() const { + return id_; + } + + void set_published(const std::string &published) { + published_ = published; + } + + std::string published() const { + return published_; + } + + void set_updated(const std::string &updated) { + updated_ = updated; + } + + std::string updated() const { + return updated_; + } + + void set_summary(const std::string &summary) { + summary_ = summary; + } + + std::string summary() const { + return summary_; + } + + void set_content(const std::string &content) { + content_ = content; + } + + std::string content() const { + return content_; + } + +private: + + std::string title_; + std::string id_; + std::string published_; + std::string updated_; + std::string summary_; + std::string content_; + +}; + +class author { + +public: + + author() { + + } + + author(const std::string &name) + : name_(name) { + + } + + author(const std::string &name, const std::string &email) + : name_(name), email_(email) { + + } + + std::string name() const { + return name_; + } + + std::string email() const { + return email_; + } + +private: + + std::string name_; + std::string email_; + +}; + +class feed { + +public: + typedef entry value_type; + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + + feed(const http::client::response &response); + + std::string title() const { + return title_; + } + + std::string subtitle() const { + return subtitle_; + } + + std::string id() const { + return id_; + } + + std::string updated() const { + return updated_; + } + + atom::author author() const { + return author_; + } + + unsigned int entry_count() const { + return entries_.size(); + } + + iterator begin() { + return entries_.begin(); + } + + iterator end() { + return entries_.end(); + } + + const_iterator begin() const { + return entries_.begin(); + } + + const_iterator end() const { + return entries_.end(); + } + +private: + + std::string title_; + std::string subtitle_; + std::string id_; + std::string updated_; + atom::author author_; + std::vector entries_; + +}; +} // namespace atom +} // namespace network +} // namespace boost + +#endif // ___ATOM_INC__ diff --git a/libs/network/example/atom/main.cpp b/libs/network/example/atom/main.cpp new file mode 100644 index 000000000..f4636e979 --- /dev/null +++ b/libs/network/example/atom/main.cpp @@ -0,0 +1,36 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include "atom.hpp" +#include +#include + +int main(int argc, char * argv[]) { + using namespace boost::network; + + if (argc != 2) { + std::cout << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + + try { + http::client client; + http::client::request request(argv[1]); + request << header("Connection", "close"); + http::client::response response = client.get(request); + atom::feed feed(response); + + std::cout << "Feed: " << feed.title() << " (" << feed.subtitle() << ")" << std::endl; + BOOST_FOREACH(const atom::entry &entry, feed) { + std::cout << entry.title() << " (" << entry.published() << ")" << std::endl; + } + } + catch (std::exception &e) { + std::cerr << e.what() << std::endl; + } + + return 0; +} diff --git a/libs/network/example/rapidxml/license.txt b/libs/network/example/rapidxml/license.txt new file mode 100644 index 000000000..140983180 --- /dev/null +++ b/libs/network/example/rapidxml/license.txt @@ -0,0 +1,52 @@ +Use of this software is granted under one of the following two licenses, +to be chosen freely by the user. + +1. Boost Software License - Version 1.0 - August 17th, 2003 +=============================================================================== + +Copyright (c) 2006, 2007 Marcin Kalicinski + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + +2. The MIT License +=============================================================================== + +Copyright (c) 2006, 2007 Marcin Kalicinski + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/libs/network/example/rapidxml/manual.html b/libs/network/example/rapidxml/manual.html new file mode 100644 index 000000000..2c422703f --- /dev/null +++ b/libs/network/example/rapidxml/manual.html @@ -0,0 +1,406 @@ +

    RAPIDXML Manual

    Version 1.13

    Copyright (C) 2006, 2009 Marcin Kalicinski
    See accompanying file license.txt for license information.

    Table of Contents

    1. What is RapidXml?
    1.1 Dependencies And Compatibility
    1.2 Character Types And Encodings
    1.3 Error Handling
    1.4 Memory Allocation
    1.5 W3C Compliance
    1.6 API Design
    1.7 Reliability
    1.8 Acknowledgements
    2. Two Minute Tutorial
    2.1 Parsing
    2.2 Accessing The DOM Tree
    2.3 Modifying The DOM Tree
    2.4 Printing XML
    3. Differences From Regular XML Parsers
    3.1 Lifetime Of Source Text
    3.2 Ownership Of Strings
    3.3 Destructive Vs Non-Destructive Mode
    4. Performance
    4.1 Comparison With Other Parsers
    5. Reference

    1. What is RapidXml?

    RapidXml is an attempt to create the fastest XML DOM parser possible, while retaining useability, portability and reasonable W3C compatibility. It is an in-situ parser written in C++, with parsing speed approaching that of strlen() function executed on the same data.

    + Entire parser is contained in a single header file, so no building or linking is neccesary. To use it you just need to copy rapidxml.hpp file to a convenient place (such as your project directory), and include it where needed. You may also want to use printing functions contained in header rapidxml_print.hpp.

    1.1 Dependencies And Compatibility

    RapidXml has no dependencies other than a very small subset of standard C++ library (<cassert>, <cstdlib>, <new> and <exception>, unless exceptions are disabled). It should compile on any reasonably conformant compiler, and was tested on Visual C++ 2003, Visual C++ 2005, Visual C++ 2008, gcc 3, gcc 4, and Comeau 4.3.3. Care was taken that no warnings are produced on these compilers, even with highest warning levels enabled.

    1.2 Character Types And Encodings

    RapidXml is character type agnostic, and can work both with narrow and wide characters. Current version does not fully support UTF-16 or UTF-32, so use of wide characters is somewhat incapacitated. However, it should succesfully parse wchar_t strings containing UTF-16 or UTF-32 if endianness of the data matches that of the machine. UTF-8 is fully supported, including all numeric character references, which are expanded into appropriate UTF-8 byte sequences (unless you enable parse_no_utf8 flag).

    + Note that RapidXml performs no decoding - strings returned by name() and value() functions will contain text encoded using the same encoding as source file. Rapidxml understands and expands the following character references: &apos; &amp; &quot; &lt; &gt; &#...; Other character references are not expanded.

    1.3 Error Handling

    By default, RapidXml uses C++ exceptions to report errors. If this behaviour is undesirable, RAPIDXML_NO_EXCEPTIONS can be defined to suppress exception code. See parse_error class and parse_error_handler() function for more information.

    1.4 Memory Allocation

    RapidXml uses a special memory pool object to allocate nodes and attributes, because direct allocation using new operator would be far too slow. Underlying memory allocations performed by the pool can be customized by use of memory_pool::set_allocator() function. See class memory_pool for more information.

    1.5 W3C Compliance

    RapidXml is not a W3C compliant parser, primarily because it ignores DOCTYPE declarations. There is a number of other, minor incompatibilities as well. Still, it can successfully parse and produce complete trees of all valid XML files in W3C conformance suite (over 1000 files specially designed to find flaws in XML processors). In destructive mode it performs whitespace normalization and character entity substitution for a small set of built-in entities.

    1.6 API Design

    RapidXml API is minimalistic, to reduce code size as much as possible, and facilitate use in embedded environments. Additional convenience functions are provided in separate headers: rapidxml_utils.hpp and rapidxml_print.hpp. Contents of these headers is not an essential part of the library, and is currently not documented (otherwise than with comments in code).

    1.7 Reliability

    RapidXml is very robust and comes with a large harness of unit tests. Special care has been taken to ensure stability of the parser no matter what source text is thrown at it. One of the unit tests produces 100,000 randomly corrupted variants of XML document, which (when uncorrupted) contains all constructs recognized by RapidXml. RapidXml passes this test when it correctly recognizes that errors have been introduced, and does not crash or loop indefinitely.

    + Another unit test puts RapidXml head-to-head with another, well estabilished XML parser, and verifies that their outputs match across a wide variety of small and large documents.

    + Yet another test feeds RapidXml with over 1000 test files from W3C compliance suite, and verifies that correct results are obtained. There are also additional tests that verify each API function separately, and test that various parsing modes work as expected.

    1.8 Acknowledgements

    I would like to thank Arseny Kapoulkine for his work on pugixml, which was an inspiration for this project. Additional thanks go to Kristen Wegner for creating pugxml, from which pugixml was derived. Janusz Wohlfeil kindly ran RapidXml speed tests on hardware that I did not have access to, allowing me to expand performance comparison table.

    2. Two Minute Tutorial

    2.1 Parsing

    The following code causes RapidXml to parse a zero-terminated string named text:
    using namespace rapidxml;
    +xml_document<> doc;    // character type defaults to char
    +doc.parse<0>(text);    // 0 means default parse flags
    +
    doc object is now a root of DOM tree containing representation of the parsed XML. Because all RapidXml interface is contained inside namespace rapidxml, users must either bring contents of this namespace into scope, or fully qualify all the names. Class xml_document represents a root of the DOM hierarchy. By means of public inheritance, it is also an xml_node and a memory_pool. Template parameter of xml_document::parse() function is used to specify parsing flags, with which you can fine-tune behaviour of the parser. Note that flags must be a compile-time constant.

    2.2 Accessing The DOM Tree

    To access the DOM tree, use methods of xml_node and xml_attribute classes:
    cout << "Name of my first node is: " << doc.first_node()->name() << "\n";
    +xml_node<> *node = doc.first_node("foobar");
    +cout << "Node foobar has value " << node->value() << "\n";
    +for (xml_attribute<> *attr = node->first_attribute();
    +     attr; attr = attr->next_attribute())
    +{
    +    cout << "Node foobar has attribute " << attr->name() << " ";
    +    cout << "with value " << attr->value() << "\n";
    +}
    +

    2.3 Modifying The DOM Tree

    DOM tree produced by the parser is fully modifiable. Nodes and attributes can be added/removed, and their contents changed. The below example creates a HTML document, whose sole contents is a link to google.com website:
    xml_document<> doc;
    +xml_node<> *node = doc.allocate_node(node_element, "a", "Google");
    +doc.append_node(node);
    +xml_attribute<> *attr = doc.allocate_attribute("href", "google.com");
    +node->append_attribute(attr);
    +
    One quirk is that nodes and attributes do not own the text of their names and values. This is because normally they only store pointers to the source text. So, when assigning a new name or value to the node, care must be taken to ensure proper lifetime of the string. The easiest way to achieve it is to allocate the string from the xml_document memory pool. In the above example this is not necessary, because we are only assigning character constants. But the code below uses memory_pool::allocate_string() function to allocate node name (which will have the same lifetime as the document), and assigns it to a new node:
    xml_document<> doc;
    +char *node_name = doc.allocate_string(name);        // Allocate string and copy name into it
    +xml_node<> *node = doc.allocate_node(node_element, node_name);  // Set node name to node_name
    +
    Check Reference section for description of the entire interface.

    2.4 Printing XML

    You can print xml_document and xml_node objects into an XML string. Use print() function or operator <<, which are defined in rapidxml_print.hpp header.
    using namespace rapidxml;
    +xml_document<> doc;    // character type defaults to char
    +// ... some code to fill the document
    +
    +// Print to stream using operator <<
    +std::cout << doc;   
    +
    +// Print to stream using print function, specifying printing flags
    +print(std::cout, doc, 0);   // 0 means default printing flags
    +
    +// Print to string using output iterator
    +std::string s;
    +print(std::back_inserter(s), doc, 0);
    +
    +// Print to memory buffer using output iterator
    +char buffer[4096];                      // You are responsible for making the buffer large enough!
    +char *end = print(buffer, doc, 0);      // end contains pointer to character after last printed character
    +*end = 0;                               // Add string terminator after XML
    +

    3. Differences From Regular XML Parsers

    RapidXml is an in-situ parser, which allows it to achieve very high parsing speed. In-situ means that parser does not make copies of strings. Instead, it places pointers to the source text in the DOM hierarchy.

    3.1 Lifetime Of Source Text

    In-situ parsing requires that source text lives at least as long as the document object. If source text is destroyed, names and values of nodes in DOM tree will become destroyed as well. Additionally, whitespace processing, character entity translation, and zero-termination of strings require that source text be modified during parsing (but see non-destructive mode). This makes the text useless for further processing once it was parsed by RapidXml.

    + In many cases however, these are not serious issues.

    3.2 Ownership Of Strings

    Nodes and attributes produced by RapidXml do not own their name and value strings. They merely hold the pointers to them. This means you have to be careful when setting these values manually, by using xml_base::name(const Ch *) or xml_base::value(const Ch *) functions. Care must be taken to ensure that lifetime of the string passed is at least as long as lifetime of the node/attribute. The easiest way to achieve it is to allocate the string from memory_pool owned by the document. Use memory_pool::allocate_string() function for this purpose.

    3.3 Destructive Vs Non-Destructive Mode

    By default, the parser modifies source text during the parsing process. This is required to achieve character entity translation, whitespace normalization, and zero-termination of strings.

    + In some cases this behaviour may be undesirable, for example if source text resides in read only memory, or is mapped to memory directly from file. By using appropriate parser flags (parse_non_destructive), source text modifications can be disabled. However, because RapidXml does in-situ parsing, it obviously has the following side-effects:

    4. Performance

    RapidXml achieves its speed through use of several techniques:
    • In-situ parsing. When building DOM tree, RapidXml does not make copies of string data, such as node names and values. Instead, it stores pointers to interior of the source text.
    • Use of template metaprogramming techniques. This allows it to move much of the work to compile time. Through magic of the templates, C++ compiler generates a separate copy of parsing code for any combination of parser flags you use. In each copy, all possible decisions are made at compile time and all unused code is omitted.
    • Extensive use of lookup tables for parsing.
    • Hand-tuned C++ with profiling done on several most popular CPUs.
    This results in a very small and fast code: a parser which is custom tailored to exact needs with each invocation.

    4.1 Comparison With Other Parsers

    The table below compares speed of RapidXml to some other parsers, and to strlen() function executed on the same data. On a modern CPU (as of 2007), you can expect parsing throughput to be close to 1 GB/s. As a rule of thumb, parsing speed is about 50-100x faster than Xerces DOM, 30-60x faster than TinyXml, 3-12x faster than pugxml, and about 5% - 30% faster than pugixml, the fastest XML parser I know of.
    • The test file is a real-world, 50kB large, moderately dense XML file.
    • All timing is done by using RDTSC instruction present in Pentium-compatible CPUs.
    • No profile-guided optimizations are used.
    • All parsers are running in their fastest modes.
    • The results are given in CPU cycles per character, so frequency of CPUs is irrelevant.
    • The results are minimum values from a large number of runs, to minimize effects of operating system activity, task switching, interrupt handling etc.
    • A single parse of the test file takes about 1/10th of a millisecond, so with large number of runs there is a good chance of hitting at least one no-interrupt streak, and obtaining undisturbed results.
    Platform
    Compiler
    strlen() RapidXml pugixml 0.3 pugxml TinyXml
    Pentium 4
    MSVC 8.0
    2.5
    5.4
    7.0
    61.7
    298.8
    Pentium 4
    gcc 4.1.1
    0.8
    6.1
    9.5
    67.0
    413.2
    Core 2
    MSVC 8.0
    1.0
    4.5
    5.0
    24.6
    154.8
    Core 2
    gcc 4.1.1
    0.6
    4.6
    5.4
    28.3
    229.3
    Athlon XP
    MSVC 8.0
    3.1
    7.7
    8.0
    25.5
    182.6
    Athlon XP
    gcc 4.1.1
    0.9
    8.2
    9.2
    33.7
    265.2
    Pentium 3
    MSVC 8.0
    2.0
    6.3
    7.0
    30.9
    211.9
    Pentium 3
    gcc 4.1.1
    1.0
    6.7
    8.9
    35.3
    316.0
    (*) All results are in CPU cycles per character of source text

    5. Reference

    This section lists all classes, functions, constants etc. and describes them in detail.
    class + template + rapidxml::memory_pool
    + constructor + memory_pool()
    + destructor + ~memory_pool()
    function allocate_node(node_type type, const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0)
    function allocate_attribute(const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0)
    function allocate_string(const Ch *source=0, std::size_t size=0)
    function clone_node(const xml_node< Ch > *source, xml_node< Ch > *result=0)
    function clear()
    function set_allocator(alloc_func *af, free_func *ff)

    class rapidxml::parse_error
    + constructor + parse_error(const char *what, void *where)
    function what() const
    function where() const

    class + template + rapidxml::xml_attribute
    + constructor + xml_attribute()
    function document() const
    function previous_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
    function next_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const

    class + template + rapidxml::xml_base
    + constructor + xml_base()
    function name() const
    function name_size() const
    function value() const
    function value_size() const
    function name(const Ch *name, std::size_t size)
    function name(const Ch *name)
    function value(const Ch *value, std::size_t size)
    function value(const Ch *value)
    function parent() const

    class + template + rapidxml::xml_document
    + constructor + xml_document()
    function parse(Ch *text)
    function clear()

    class + template + rapidxml::xml_node
    + constructor + xml_node(node_type type)
    function type() const
    function document() const
    function first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
    function last_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
    function previous_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
    function next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
    function first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
    function last_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const
    function type(node_type type)
    function prepend_node(xml_node< Ch > *child)
    function append_node(xml_node< Ch > *child)
    function insert_node(xml_node< Ch > *where, xml_node< Ch > *child)
    function remove_first_node()
    function remove_last_node()
    function remove_node(xml_node< Ch > *where)
    function remove_all_nodes()
    function prepend_attribute(xml_attribute< Ch > *attribute)
    function append_attribute(xml_attribute< Ch > *attribute)
    function insert_attribute(xml_attribute< Ch > *where, xml_attribute< Ch > *attribute)
    function remove_first_attribute()
    function remove_last_attribute()
    function remove_attribute(xml_attribute< Ch > *where)
    function remove_all_attributes()

    namespace rapidxml
    enum node_type
    function parse_error_handler(const char *what, void *where)
    function print(OutIt out, const xml_node< Ch > &node, int flags=0)
    function print(std::basic_ostream< Ch > &out, const xml_node< Ch > &node, int flags=0)
    function operator<<(std::basic_ostream< Ch > &out, const xml_node< Ch > &node)
    + constant + parse_no_data_nodes
    + constant + parse_no_element_values
    + constant + parse_no_string_terminators
    + constant + parse_no_entity_translation
    + constant + parse_no_utf8
    + constant + parse_declaration_node
    + constant + parse_comment_nodes
    + constant + parse_doctype_node
    + constant + parse_pi_nodes
    + constant + parse_validate_closing_tags
    + constant + parse_trim_whitespace
    + constant + parse_normalize_whitespace
    + constant + parse_default
    + constant + parse_non_destructive
    + constant + parse_fastest
    + constant + parse_full
    + constant + print_no_indenting


    class + template + rapidxml::memory_pool

    + + Defined in rapidxml.hpp
    + Base class for + xml_document

    Description

    This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. In most cases, you will not need to use this class directly. However, if you need to create nodes manually or modify names/values of nodes, you are encouraged to use memory_pool of relevant xml_document to allocate the memory. Not only is this faster than allocating them by using new operator, but also their lifetime will be tied to the lifetime of document, possibly simplyfing memory management.

    + Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. You can also call allocate_string() function to allocate strings. Such strings can then be used as names or values of nodes without worrying about their lifetime. Note that there is no free() function -- all allocations are freed at once when clear() function is called, or when the pool is destroyed.

    + It is also possible to create a standalone memory_pool, and use it to allocate nodes, whose lifetime will not be tied to any document.

    + Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. Until static memory is exhausted, no dynamic memory allocations are done. When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, by using global new[] and delete[] operators. This behaviour can be changed by setting custom allocation routines. Use set_allocator() function to set them.

    + Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. This value defaults to the size of pointer on target architecture.

    + To obtain absolutely top performance from the parser, it is important that all nodes are allocated from a single, contiguous block of memory. Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT to obtain best wasted memory to performance compromise. To do it, define their values before rapidxml.hpp file is included.

    Parameters

    Ch
    Character type of created nodes.

    + constructor + memory_pool::memory_pool

    Synopsis

    memory_pool(); +

    Description

    Constructs empty pool with default allocator functions.

    + destructor + memory_pool::~memory_pool

    Synopsis

    ~memory_pool(); +

    Description

    Destroys pool and frees all the memory. This causes memory occupied by nodes allocated by the pool to be freed. Nodes allocated from the pool are no longer valid.

    function memory_pool::allocate_node

    Synopsis

    xml_node<Ch>* allocate_node(node_type type, const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0); +

    Description

    Allocates a new node from the pool, and optionally assigns name and value to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

    Parameters

    type
    Type of node to create.
    name
    Name to assign to the node, or 0 to assign no name.
    value
    Value to assign to the node, or 0 to assign no value.
    name_size
    Size of name to assign, or 0 to automatically calculate size from name string.
    value_size
    Size of value to assign, or 0 to automatically calculate size from value string.

    Returns

    Pointer to allocated node. This pointer will never be NULL.

    function memory_pool::allocate_attribute

    Synopsis

    xml_attribute<Ch>* allocate_attribute(const Ch *name=0, const Ch *value=0, std::size_t name_size=0, std::size_t value_size=0); +

    Description

    Allocates a new attribute from the pool, and optionally assigns name and value to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

    Parameters

    name
    Name to assign to the attribute, or 0 to assign no name.
    value
    Value to assign to the attribute, or 0 to assign no value.
    name_size
    Size of name to assign, or 0 to automatically calculate size from name string.
    value_size
    Size of value to assign, or 0 to automatically calculate size from value string.

    Returns

    Pointer to allocated attribute. This pointer will never be NULL.

    function memory_pool::allocate_string

    Synopsis

    Ch* allocate_string(const Ch *source=0, std::size_t size=0); +

    Description

    Allocates a char array of given size from the pool, and optionally copies a given string to it. If the allocation request cannot be accomodated, this function will throw std::bad_alloc. If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function will call rapidxml::parse_error_handler() function.

    Parameters

    source
    String to initialize the allocated memory with, or 0 to not initialize it.
    size
    Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.

    Returns

    Pointer to allocated char array. This pointer will never be NULL.

    function memory_pool::clone_node

    Synopsis

    xml_node<Ch>* clone_node(const xml_node< Ch > *source, xml_node< Ch > *result=0); +

    Description

    Clones an xml_node and its hierarchy of child nodes and attributes. Nodes and attributes are allocated from this memory pool. Names and values are not cloned, they are shared between the clone and the source. Result node can be optionally specified as a second parameter, in which case its contents will be replaced with cloned source node. This is useful when you want to clone entire document.

    Parameters

    source
    Node to clone.
    result
    Node to put results in, or 0 to automatically allocate result node

    Returns

    Pointer to cloned node. This pointer will never be NULL.

    function memory_pool::clear

    Synopsis

    void clear(); +

    Description

    Clears the pool. This causes memory occupied by nodes allocated by the pool to be freed. Any nodes or strings allocated from the pool will no longer be valid.

    function memory_pool::set_allocator

    Synopsis

    void set_allocator(alloc_func *af, free_func *ff); +

    Description

    Sets or resets the user-defined memory allocation functions for the pool. This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. Allocation function must not return invalid pointer on failure. It should either throw, stop the program, or use longjmp() function to pass control to other place of program. If it returns invalid pointer, results are undefined.

    + User defined allocation functions must have the following forms:

    +void *allocate(std::size_t size);
    +void free(void *pointer);

    Parameters

    af
    Allocation function, or 0 to restore default function
    ff
    Free function, or 0 to restore default function

    class rapidxml::parse_error

    + + Defined in rapidxml.hpp

    Description

    Parse error exception. This exception is thrown by the parser when an error occurs. Use what() function to get human-readable error message. Use where() function to get a pointer to position within source text where error was detected.

    + If throwing exceptions by the parser is undesirable, it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. This function must be defined by the user.

    + This class derives from std::exception class.

    + constructor + parse_error::parse_error

    Synopsis

    parse_error(const char *what, void *where); +

    Description

    Constructs parse error.

    function parse_error::what

    Synopsis

    virtual const char* what() const; +

    Description

    Gets human readable description of error.

    Returns

    Pointer to null terminated description of the error.

    function parse_error::where

    Synopsis

    Ch* where() const; +

    Description

    Gets pointer to character data where error happened. Ch should be the same as char type of xml_document that produced the error.

    Returns

    Pointer to location within the parsed string where error occured.

    class + template + rapidxml::xml_attribute

    + + Defined in rapidxml.hpp
    + Inherits from + xml_base

    Description

    Class representing attribute node of XML document. Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). Note that after parse, both name and value of attribute will point to interior of source text used for parsing. Thus, this text must persist in memory for the lifetime of attribute.

    Parameters

    Ch
    Character type to use.

    + constructor + xml_attribute::xml_attribute

    Synopsis

    xml_attribute(); +

    Description

    Constructs an empty attribute with the specified type. Consider using memory_pool of appropriate xml_document if allocating attributes manually.

    function xml_attribute::document

    Synopsis

    xml_document<Ch>* document() const; +

    Description

    Gets document of which attribute is a child.

    Returns

    Pointer to document that contains this attribute, or 0 if there is no parent document.

    function xml_attribute::previous_attribute

    Synopsis

    xml_attribute<Ch>* previous_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets previous attribute, optionally matching attribute name.

    Parameters

    name
    Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found attribute, or 0 if not found.

    function xml_attribute::next_attribute

    Synopsis

    xml_attribute<Ch>* next_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets next attribute, optionally matching attribute name.

    Parameters

    name
    Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found attribute, or 0 if not found.

    class + template + rapidxml::xml_base

    + + Defined in rapidxml.hpp
    + Base class for + xml_attribute xml_node

    Description

    Base class for xml_node and xml_attribute implementing common functions: name(), name_size(), value(), value_size() and parent().

    Parameters

    Ch
    Character type to use

    + constructor + xml_base::xml_base

    Synopsis

    xml_base(); +

    function xml_base::name

    Synopsis

    Ch* name() const; +

    Description

    Gets name of the node. Interpretation of name depends on type of node. Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.

    + Use name_size() function to determine length of the name.

    Returns

    Name of node, or empty string if node has no name.

    function xml_base::name_size

    Synopsis

    std::size_t name_size() const; +

    Description

    Gets size of node name, not including terminator character. This function works correctly irrespective of whether name is or is not zero terminated.

    Returns

    Size of node name, in characters.

    function xml_base::value

    Synopsis

    Ch* value() const; +

    Description

    Gets value of node. Interpretation of value depends on type of node. Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.

    + Use value_size() function to determine length of the value.

    Returns

    Value of node, or empty string if node has no value.

    function xml_base::value_size

    Synopsis

    std::size_t value_size() const; +

    Description

    Gets size of node value, not including terminator character. This function works correctly irrespective of whether value is or is not zero terminated.

    Returns

    Size of node value, in characters.

    function xml_base::name

    Synopsis

    void name(const Ch *name, std::size_t size); +

    Description

    Sets name of node to a non zero-terminated string. See Ownership Of Strings .

    + Note that node does not own its name or value, it only stores a pointer to it. It will not delete or otherwise free the pointer on destruction. It is reponsibility of the user to properly manage lifetime of the string. The easiest way to achieve it is to use memory_pool of the document to allocate the string - on destruction of the document the string will be automatically freed.

    + Size of name must be specified separately, because name does not have to be zero terminated. Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).

    Parameters

    name
    Name of node to set. Does not have to be zero terminated.
    size
    Size of name, in characters. This does not include zero terminator, if one is present.

    function xml_base::name

    Synopsis

    void name(const Ch *name); +

    Description

    Sets name of node to a zero-terminated string. See also Ownership Of Strings and xml_node::name(const Ch *, std::size_t).

    Parameters

    name
    Name of node to set. Must be zero terminated.

    function xml_base::value

    Synopsis

    void value(const Ch *value, std::size_t size); +

    Description

    Sets value of node to a non zero-terminated string. See Ownership Of Strings .

    + Note that node does not own its name or value, it only stores a pointer to it. It will not delete or otherwise free the pointer on destruction. It is reponsibility of the user to properly manage lifetime of the string. The easiest way to achieve it is to use memory_pool of the document to allocate the string - on destruction of the document the string will be automatically freed.

    + Size of value must be specified separately, because it does not have to be zero terminated. Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).

    + If an element has a child node of type node_data, it will take precedence over element value when printing. If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.

    Parameters

    value
    value of node to set. Does not have to be zero terminated.
    size
    Size of value, in characters. This does not include zero terminator, if one is present.

    function xml_base::value

    Synopsis

    void value(const Ch *value); +

    Description

    Sets value of node to a zero-terminated string. See also Ownership Of Strings and xml_node::value(const Ch *, std::size_t).

    Parameters

    value
    Vame of node to set. Must be zero terminated.

    function xml_base::parent

    Synopsis

    xml_node<Ch>* parent() const; +

    Description

    Gets node parent.

    Returns

    Pointer to parent node, or 0 if there is no parent.

    class + template + rapidxml::xml_document

    + + Defined in rapidxml.hpp
    + Inherits from + xml_node memory_pool

    Description

    This class represents root of the DOM hierarchy. It is also an xml_node and a memory_pool through public inheritance. Use parse() function to build a DOM tree from a zero-terminated XML text string. parse() function allocates memory for nodes and attributes by using functions of xml_document, which are inherited from memory_pool. To access root node of the document, use the document itself, as if it was an xml_node.

    Parameters

    Ch
    Character type to use.

    + constructor + xml_document::xml_document

    Synopsis

    xml_document(); +

    Description

    Constructs empty XML document.

    function xml_document::parse

    Synopsis

    void parse(Ch *text); +

    Description

    Parses zero-terminated XML string according to given flags. Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. The string must persist for the lifetime of the document. In case of error, rapidxml::parse_error exception will be thrown.

    + If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. Make sure that data is zero-terminated.

    + Document can be parsed into multiple times. Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.

    Parameters

    text
    XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.

    function xml_document::clear

    Synopsis

    void clear(); +

    Description

    Clears the document by deleting all nodes and clearing the memory pool. All nodes owned by document pool are destroyed.

    class + template + rapidxml::xml_node

    + + Defined in rapidxml.hpp
    + Inherits from + xml_base
    + Base class for + xml_document

    Description

    Class representing a node of XML document. Each node may have associated name and value strings, which are available through name() and value() functions. Interpretation of name and value depends on type of the node. Type of node can be determined by using type() function.

    + Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. Thus, this text must persist in the memory for the lifetime of node.

    Parameters

    Ch
    Character type to use.

    + constructor + xml_node::xml_node

    Synopsis

    xml_node(node_type type); +

    Description

    Constructs an empty node with the specified type. Consider using memory_pool of appropriate document to allocate nodes manually.

    Parameters

    type
    Type of node to construct.

    function xml_node::type

    Synopsis

    node_type type() const; +

    Description

    Gets type of node.

    Returns

    Type of node.

    function xml_node::document

    Synopsis

    xml_document<Ch>* document() const; +

    Description

    Gets document of which node is a child.

    Returns

    Pointer to document that contains this node, or 0 if there is no parent document.

    function xml_node::first_node

    Synopsis

    xml_node<Ch>* first_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets first child node, optionally matching node name.

    Parameters

    name
    Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found child, or 0 if not found.

    function xml_node::last_node

    Synopsis

    xml_node<Ch>* last_node(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets last child node, optionally matching node name. Behaviour is undefined if node has no children. Use first_node() to test if node has children.

    Parameters

    name
    Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found child, or 0 if not found.

    function xml_node::previous_sibling

    Synopsis

    xml_node<Ch>* previous_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets previous sibling node, optionally matching node name. Behaviour is undefined if node has no parent. Use parent() to test if node has a parent.

    Parameters

    name
    Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found sibling, or 0 if not found.

    function xml_node::next_sibling

    Synopsis

    xml_node<Ch>* next_sibling(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets next sibling node, optionally matching node name. Behaviour is undefined if node has no parent. Use parent() to test if node has a parent.

    Parameters

    name
    Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found sibling, or 0 if not found.

    function xml_node::first_attribute

    Synopsis

    xml_attribute<Ch>* first_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets first attribute of node, optionally matching attribute name.

    Parameters

    name
    Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found attribute, or 0 if not found.

    function xml_node::last_attribute

    Synopsis

    xml_attribute<Ch>* last_attribute(const Ch *name=0, std::size_t name_size=0, bool case_sensitive=true) const; +

    Description

    Gets last attribute of node, optionally matching attribute name.

    Parameters

    name
    Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
    name_size
    Size of name, in characters, or 0 to have size calculated automatically from string
    case_sensitive
    Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters

    Returns

    Pointer to found attribute, or 0 if not found.

    function xml_node::type

    Synopsis

    void type(node_type type); +

    Description

    Sets type of node.

    Parameters

    type
    Type of node to set.

    function xml_node::prepend_node

    Synopsis

    void prepend_node(xml_node< Ch > *child); +

    Description

    Prepends a new child node. The prepended child becomes the first child, and all existing children are moved one position back.

    Parameters

    child
    Node to prepend.

    function xml_node::append_node

    Synopsis

    void append_node(xml_node< Ch > *child); +

    Description

    Appends a new child node. The appended child becomes the last child.

    Parameters

    child
    Node to append.

    function xml_node::insert_node

    Synopsis

    void insert_node(xml_node< Ch > *where, xml_node< Ch > *child); +

    Description

    Inserts a new child node at specified place inside the node. All children after and including the specified node are moved one position back.

    Parameters

    where
    Place where to insert the child, or 0 to insert at the back.
    child
    Node to insert.

    function xml_node::remove_first_node

    Synopsis

    void remove_first_node(); +

    Description

    Removes first child node. If node has no children, behaviour is undefined. Use first_node() to test if node has children.

    function xml_node::remove_last_node

    Synopsis

    void remove_last_node(); +

    Description

    Removes last child of the node. If node has no children, behaviour is undefined. Use first_node() to test if node has children.

    function xml_node::remove_node

    Synopsis

    void remove_node(xml_node< Ch > *where); +

    Description

    Removes specified child from the node.

    function xml_node::remove_all_nodes

    Synopsis

    void remove_all_nodes(); +

    Description

    Removes all child nodes (but not attributes).

    function xml_node::prepend_attribute

    Synopsis

    void prepend_attribute(xml_attribute< Ch > *attribute); +

    Description

    Prepends a new attribute to the node.

    Parameters

    attribute
    Attribute to prepend.

    function xml_node::append_attribute

    Synopsis

    void append_attribute(xml_attribute< Ch > *attribute); +

    Description

    Appends a new attribute to the node.

    Parameters

    attribute
    Attribute to append.

    function xml_node::insert_attribute

    Synopsis

    void insert_attribute(xml_attribute< Ch > *where, xml_attribute< Ch > *attribute); +

    Description

    Inserts a new attribute at specified place inside the node. All attributes after and including the specified attribute are moved one position back.

    Parameters

    where
    Place where to insert the attribute, or 0 to insert at the back.
    attribute
    Attribute to insert.

    function xml_node::remove_first_attribute

    Synopsis

    void remove_first_attribute(); +

    Description

    Removes first attribute of the node. If node has no attributes, behaviour is undefined. Use first_attribute() to test if node has attributes.

    function xml_node::remove_last_attribute

    Synopsis

    void remove_last_attribute(); +

    Description

    Removes last attribute of the node. If node has no attributes, behaviour is undefined. Use first_attribute() to test if node has attributes.

    function xml_node::remove_attribute

    Synopsis

    void remove_attribute(xml_attribute< Ch > *where); +

    Description

    Removes specified attribute from node.

    Parameters

    where
    Pointer to attribute to be removed.

    function xml_node::remove_all_attributes

    Synopsis

    void remove_all_attributes(); +

    Description

    Removes all attributes of node.

    enum node_type

    Description

    Enumeration listing all node types produced by the parser. Use xml_node::type() function to query node type.

    Values

    node_document
    A document node. Name and value are empty.
    node_element
    An element node. Name contains element name. Value contains text of first data node.
    node_data
    A data node. Name is empty. Value contains data text.
    node_cdata
    A CDATA node. Name is empty. Value contains data text.
    node_comment
    A comment node. Name is empty. Value contains comment text.
    node_declaration
    A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
    node_doctype
    A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
    node_pi
    A PI node. Name contains target. Value contains instructions.

    function parse_error_handler

    Synopsis

    void rapidxml::parse_error_handler(const char *what, void *where); +

    Description

    When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function is called to notify user about the error. It must be defined by the user.

    + This function cannot return. If it does, the results are undefined.

    + A very simple definition might look like that: + void rapidxml::parse_error_handler(const char *what, void *where) + { + std::cout << "Parse error: " << what << "\n"; + std::abort(); + } +

    Parameters

    what
    Human readable description of the error.
    where
    Pointer to character data where error was detected.

    function print

    Synopsis

    OutIt rapidxml::print(OutIt out, const xml_node< Ch > &node, int flags=0); +

    Description

    Prints XML to given output iterator.

    Parameters

    out
    Output iterator to print to.
    node
    Node to be printed. Pass xml_document to print entire document.
    flags
    Flags controlling how XML is printed.

    Returns

    Output iterator pointing to position immediately after last character of printed text.

    function print

    Synopsis

    std::basic_ostream<Ch>& rapidxml::print(std::basic_ostream< Ch > &out, const xml_node< Ch > &node, int flags=0); +

    Description

    Prints XML to given output stream.

    Parameters

    out
    Output stream to print to.
    node
    Node to be printed. Pass xml_document to print entire document.
    flags
    Flags controlling how XML is printed.

    Returns

    Output stream.

    function operator<<

    Synopsis

    std::basic_ostream<Ch>& rapidxml::operator<<(std::basic_ostream< Ch > &out, const xml_node< Ch > &node); +

    Description

    Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.

    Parameters

    out
    Output stream to print to.
    node
    Node to be printed.

    Returns

    Output stream.

    + constant + parse_no_data_nodes

    Synopsis

    const int parse_no_data_nodes + = 0x1; +

    Description

    Parse flag instructing the parser to not create data nodes. Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_no_element_values

    Synopsis

    const int parse_no_element_values + = 0x2; +

    Description

    Parse flag instructing the parser to not use text of first data node as a value of parent element. Can be combined with other flags by use of | operator. Note that child data nodes of element node take precendence over its value when printing. That is, if element has one or more child data nodes and a value, the value will be ignored. Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.

    + See xml_document::parse() function.

    + constant + parse_no_string_terminators

    Synopsis

    const int parse_no_string_terminators + = 0x4; +

    Description

    Parse flag instructing the parser to not place zero terminators after strings in the source text. By default zero terminators are placed, modifying source text. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_no_entity_translation

    Synopsis

    const int parse_no_entity_translation + = 0x8; +

    Description

    Parse flag instructing the parser to not translate entities in the source text. By default entities are translated, modifying source text. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_no_utf8

    Synopsis

    const int parse_no_utf8 + = 0x10; +

    Description

    Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. By default, UTF-8 handling is enabled. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_declaration_node

    Synopsis

    const int parse_declaration_node + = 0x20; +

    Description

    Parse flag instructing the parser to create XML declaration node. By default, declaration node is not created. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_comment_nodes

    Synopsis

    const int parse_comment_nodes + = 0x40; +

    Description

    Parse flag instructing the parser to create comments nodes. By default, comment nodes are not created. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_doctype_node

    Synopsis

    const int parse_doctype_node + = 0x80; +

    Description

    Parse flag instructing the parser to create DOCTYPE node. By default, doctype node is not created. Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_pi_nodes

    Synopsis

    const int parse_pi_nodes + = 0x100; +

    Description

    Parse flag instructing the parser to create PI nodes. By default, PI nodes are not created. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_validate_closing_tags

    Synopsis

    const int parse_validate_closing_tags + = 0x200; +

    Description

    Parse flag instructing the parser to validate closing tag names. If not set, name inside closing tag is irrelevant to the parser. By default, closing tags are not validated. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_trim_whitespace

    Synopsis

    const int parse_trim_whitespace + = 0x400; +

    Description

    Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. By default, whitespace is not trimmed. This flag does not cause the parser to modify source text. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_normalize_whitespace

    Synopsis

    const int parse_normalize_whitespace + = 0x800; +

    Description

    Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. By default, whitespace is not normalized. If this flag is specified, source text will be modified. Can be combined with other flags by use of | operator.

    + See xml_document::parse() function.

    + constant + parse_default

    Synopsis

    const int parse_default + = 0; +

    Description

    Parse flags which represent default behaviour of the parser. This is always equal to 0, so that all other flags can be simply ored together. Normally there is no need to inconveniently disable flags by anding with their negated (~) values. This also means that meaning of each flag is a negation of the default setting. For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is enabled by default, and using the flag will disable it.

    + See xml_document::parse() function.

    + constant + parse_non_destructive

    Synopsis

    const int parse_non_destructive + = parse_no_string_terminators | parse_no_entity_translation; +

    Description

    A combination of parse flags that forbids any modifications of the source text. This also results in faster parsing. However, note that the following will occur:
    • names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends
    • entities will not be translated
    • whitespace will not be normalized
    +See xml_document::parse() function.

    + constant + parse_fastest

    Synopsis

    const int parse_fastest + = parse_non_destructive | parse_no_data_nodes; +

    Description

    A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.

    + See xml_document::parse() function.

    + constant + parse_full

    Synopsis

    const int parse_full + = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; +

    Description

    A combination of parse flags resulting in largest amount of data being extracted. This usually results in slowest parsing.

    + See xml_document::parse() function.

    + constant + print_no_indenting

    Synopsis

    const int print_no_indenting + = 0x1; +

    Description

    Printer flag instructing the printer to suppress indenting of XML. See print() function.

    \ No newline at end of file diff --git a/libs/network/example/rapidxml/rapidxml.hpp b/libs/network/example/rapidxml/rapidxml.hpp new file mode 100644 index 000000000..ae91e081d --- /dev/null +++ b/libs/network/example/rapidxml/rapidxml.hpp @@ -0,0 +1,2596 @@ +#ifndef RAPIDXML_HPP_INCLUDED +#define RAPIDXML_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation + +// If standard library is disabled, user must provide implementations of required functions and typedefs +#if !defined(RAPIDXML_NO_STDLIB) + #include // For std::size_t + #include // For assert + #include // For placement new +#endif + +// On MSVC, disable "conditional expression is constant" warning (level 4). +// This warning is almost impossible to avoid with certain types of templated code +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable:4127) // Conditional expression is constant +#endif + +/////////////////////////////////////////////////////////////////////////// +// RAPIDXML_PARSE_ERROR + +#if defined(RAPIDXML_NO_EXCEPTIONS) + +#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); } + +namespace rapidxml +{ + //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, + //! this function is called to notify user about the error. + //! It must be defined by the user. + //!

    + //! This function cannot return. If it does, the results are undefined. + //!

    + //! A very simple definition might look like that: + //!

    +    //! void %rapidxml::%parse_error_handler(const char *what, void *where)
    +    //! {
    +    //!     std::cout << "Parse error: " << what << "\n";
    +    //!     std::abort();
    +    //! }
    +    //! 
    + //! \param what Human readable description of the error. + //! \param where Pointer to character data where error was detected. + void parse_error_handler(const char *what, void *where); +} + +#else + +#include // For std::exception + +#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where) + +namespace rapidxml +{ + + //! Parse error exception. + //! This exception is thrown by the parser when an error occurs. + //! Use what() function to get human-readable error message. + //! Use where() function to get a pointer to position within source text where error was detected. + //!

    + //! If throwing exceptions by the parser is undesirable, + //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. + //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. + //! This function must be defined by the user. + //!

    + //! This class derives from std::exception class. + class parse_error: public std::exception + { + + public: + + //! Constructs parse error + parse_error(const char *what, void *where) + : m_what(what) + , m_where(where) + { + } + + //! Gets human readable description of error. + //! \return Pointer to null terminated description of the error. + virtual const char *what() const throw() + { + return m_what; + } + + //! Gets pointer to character data where error happened. + //! Ch should be the same as char type of xml_document that produced the error. + //! \return Pointer to location within the parsed string where error occured. + template + Ch *where() const + { + return reinterpret_cast(m_where); + } + + private: + + const char *m_what; + void *m_where; + + }; +} + +#endif + +/////////////////////////////////////////////////////////////////////////// +// Pool sizes + +#ifndef RAPIDXML_STATIC_POOL_SIZE + // Size of static memory block of memory_pool. + // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. + // No dynamic memory allocations are performed by memory_pool until static memory is exhausted. + #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024) +#endif + +#ifndef RAPIDXML_DYNAMIC_POOL_SIZE + // Size of dynamic memory block of memory_pool. + // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. + // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool. + #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) +#endif + +#ifndef RAPIDXML_ALIGNMENT + // Memory allocation alignment. + // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer. + // All memory allocations for nodes, attributes and strings will be aligned to this value. + // This must be a power of 2 and at least 1, otherwise memory_pool will not work. + #define RAPIDXML_ALIGNMENT sizeof(void *) +#endif + +namespace rapidxml +{ + // Forward declarations + template class xml_node; + template class xml_attribute; + template class xml_document; + + //! Enumeration listing all node types produced by the parser. + //! Use xml_node::type() function to query node type. + enum node_type + { + node_document, //!< A document node. Name and value are empty. + node_element, //!< An element node. Name contains element name. Value contains text of first data node. + node_data, //!< A data node. Name is empty. Value contains data text. + node_cdata, //!< A CDATA node. Name is empty. Value contains data text. + node_comment, //!< A comment node. Name is empty. Value contains comment text. + node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes. + node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text. + node_pi //!< A PI node. Name contains target. Value contains instructions. + }; + + /////////////////////////////////////////////////////////////////////// + // Parsing flags + + //! Parse flag instructing the parser to not create data nodes. + //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_no_data_nodes = 0x1; + + //! Parse flag instructing the parser to not use text of first data node as a value of parent element. + //! Can be combined with other flags by use of | operator. + //! Note that child data nodes of element node take precendence over its value when printing. + //! That is, if element has one or more child data nodes and a value, the value will be ignored. + //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements. + //!

    + //! See xml_document::parse() function. + const int parse_no_element_values = 0x2; + + //! Parse flag instructing the parser to not place zero terminators after strings in the source text. + //! By default zero terminators are placed, modifying source text. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_no_string_terminators = 0x4; + + //! Parse flag instructing the parser to not translate entities in the source text. + //! By default entities are translated, modifying source text. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_no_entity_translation = 0x8; + + //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. + //! By default, UTF-8 handling is enabled. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_no_utf8 = 0x10; + + //! Parse flag instructing the parser to create XML declaration node. + //! By default, declaration node is not created. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_declaration_node = 0x20; + + //! Parse flag instructing the parser to create comments nodes. + //! By default, comment nodes are not created. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_comment_nodes = 0x40; + + //! Parse flag instructing the parser to create DOCTYPE node. + //! By default, doctype node is not created. + //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_doctype_node = 0x80; + + //! Parse flag instructing the parser to create PI nodes. + //! By default, PI nodes are not created. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_pi_nodes = 0x100; + + //! Parse flag instructing the parser to validate closing tag names. + //! If not set, name inside closing tag is irrelevant to the parser. + //! By default, closing tags are not validated. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_validate_closing_tags = 0x200; + + //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. + //! By default, whitespace is not trimmed. + //! This flag does not cause the parser to modify source text. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_trim_whitespace = 0x400; + + //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. + //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. + //! By default, whitespace is not normalized. + //! If this flag is specified, source text will be modified. + //! Can be combined with other flags by use of | operator. + //!

    + //! See xml_document::parse() function. + const int parse_normalize_whitespace = 0x800; + + // Compound flags + + //! Parse flags which represent default behaviour of the parser. + //! This is always equal to 0, so that all other flags can be simply ored together. + //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values. + //! This also means that meaning of each flag is a negation of the default setting. + //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is enabled by default, + //! and using the flag will disable it. + //!

    + //! See xml_document::parse() function. + const int parse_default = 0; + + //! A combination of parse flags that forbids any modifications of the source text. + //! This also results in faster parsing. However, note that the following will occur: + //!
      + //!
    • names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends
    • + //!
    • entities will not be translated
    • + //!
    • whitespace will not be normalized
    • + //!
    + //! See xml_document::parse() function. + const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation; + + //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data. + //!

    + //! See xml_document::parse() function. + const int parse_fastest = parse_non_destructive | parse_no_data_nodes; + + //! A combination of parse flags resulting in largest amount of data being extracted. + //! This usually results in slowest parsing. + //!

    + //! See xml_document::parse() function. + const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; + + /////////////////////////////////////////////////////////////////////// + // Internals + + //! \cond internal + namespace internal + { + + // Struct that contains lookup tables for the parser + // It must be a template to allow correct linking (because it has static data members, which are defined in a header file). + template + struct lookup_tables + { + static const unsigned char lookup_whitespace[256]; // Whitespace table + static const unsigned char lookup_node_name[256]; // Node name table + static const unsigned char lookup_text[256]; // Text table + static const unsigned char lookup_text_pure_no_ws[256]; // Text table + static const unsigned char lookup_text_pure_with_ws[256]; // Text table + static const unsigned char lookup_attribute_name[256]; // Attribute name table + static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote + static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote + static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes + static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes + static const unsigned char lookup_digits[256]; // Digits + static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters + }; + + // Find length of the string + template + inline std::size_t measure(const Ch *p) + { + const Ch *tmp = p; + while (*tmp) + ++tmp; + return tmp - p; + } + + // Compare strings for equality + template + inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive) + { + if (size1 != size2) + return false; + if (case_sensitive) + { + for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) + if (*p1 != *p2) + return false; + } + else + { + for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) + if (lookup_tables<0>::lookup_upcase[static_cast(*p1)] != lookup_tables<0>::lookup_upcase[static_cast(*p2)]) + return false; + } + return true; + } + } + //! \endcond + + /////////////////////////////////////////////////////////////////////// + // Memory pool + + //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. + //! In most cases, you will not need to use this class directly. + //! However, if you need to create nodes manually or modify names/values of nodes, + //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. + //! Not only is this faster than allocating them by using new operator, + //! but also their lifetime will be tied to the lifetime of document, + //! possibly simplyfing memory management. + //!

    + //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. + //! You can also call allocate_string() function to allocate strings. + //! Such strings can then be used as names or values of nodes without worrying about their lifetime. + //! Note that there is no free() function -- all allocations are freed at once when clear() function is called, + //! or when the pool is destroyed. + //!

    + //! It is also possible to create a standalone memory_pool, and use it + //! to allocate nodes, whose lifetime will not be tied to any document. + //!

    + //! Pool maintains RAPIDXML_STATIC_POOL_SIZE bytes of statically allocated memory. + //! Until static memory is exhausted, no dynamic memory allocations are done. + //! When static memory is exhausted, pool allocates additional blocks of memory of size RAPIDXML_DYNAMIC_POOL_SIZE each, + //! by using global new[] and delete[] operators. + //! This behaviour can be changed by setting custom allocation routines. + //! Use set_allocator() function to set them. + //!

    + //! Allocations for nodes, attributes and strings are aligned at RAPIDXML_ALIGNMENT bytes. + //! This value defaults to the size of pointer on target architecture. + //!

    + //! To obtain absolutely top performance from the parser, + //! it is important that all nodes are allocated from a single, contiguous block of memory. + //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. + //! If required, you can tweak RAPIDXML_STATIC_POOL_SIZE, RAPIDXML_DYNAMIC_POOL_SIZE and RAPIDXML_ALIGNMENT + //! to obtain best wasted memory to performance compromise. + //! To do it, define their values before rapidxml.hpp file is included. + //! \param Ch Character type of created nodes. + template + class memory_pool + { + + public: + + //! \cond internal + typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory + typedef void (free_func)(void *); // Type of user-defined function used to free memory + //! \endcond + + //! Constructs empty pool with default allocator functions. + memory_pool() + : m_alloc_func(0) + , m_free_func(0) + { + init(); + } + + //! Destroys pool and frees all the memory. + //! This causes memory occupied by nodes allocated by the pool to be freed. + //! Nodes allocated from the pool are no longer valid. + ~memory_pool() + { + clear(); + } + + //! Allocates a new node from the pool, and optionally assigns name and value to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param type Type of node to create. + //! \param name Name to assign to the node, or 0 to assign no name. + //! \param value Value to assign to the node, or 0 to assign no value. + //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. + //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. + //! \return Pointer to allocated node. This pointer will never be NULL. + xml_node *allocate_node(node_type type, + const Ch *name = 0, const Ch *value = 0, + std::size_t name_size = 0, std::size_t value_size = 0) + { + void *memory = allocate_aligned(sizeof(xml_node)); + xml_node *node = new(memory) xml_node(type); + if (name) + { + if (name_size > 0) + node->name(name, name_size); + else + node->name(name); + } + if (value) + { + if (value_size > 0) + node->value(value, value_size); + else + node->value(value); + } + return node; + } + + //! Allocates a new attribute from the pool, and optionally assigns name and value to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param name Name to assign to the attribute, or 0 to assign no name. + //! \param value Value to assign to the attribute, or 0 to assign no value. + //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. + //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. + //! \return Pointer to allocated attribute. This pointer will never be NULL. + xml_attribute *allocate_attribute(const Ch *name = 0, const Ch *value = 0, + std::size_t name_size = 0, std::size_t value_size = 0) + { + void *memory = allocate_aligned(sizeof(xml_attribute)); + xml_attribute *attribute = new(memory) xml_attribute; + if (name) + { + if (name_size > 0) + attribute->name(name, name_size); + else + attribute->name(name); + } + if (value) + { + if (value_size > 0) + attribute->value(value, value_size); + else + attribute->value(value); + } + return attribute; + } + + //! Allocates a char array of given size from the pool, and optionally copies a given string to it. + //! If the allocation request cannot be accomodated, this function will throw std::bad_alloc. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param source String to initialize the allocated memory with, or 0 to not initialize it. + //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated. + //! \return Pointer to allocated char array. This pointer will never be NULL. + Ch *allocate_string(const Ch *source = 0, std::size_t size = 0) + { + assert(source || size); // Either source or size (or both) must be specified + if (size == 0) + size = internal::measure(source) + 1; + Ch *result = static_cast(allocate_aligned(size * sizeof(Ch))); + if (source) + for (std::size_t i = 0; i < size; ++i) + result[i] = source[i]; + return result; + } + + //! Clones an xml_node and its hierarchy of child nodes and attributes. + //! Nodes and attributes are allocated from this memory pool. + //! Names and values are not cloned, they are shared between the clone and the source. + //! Result node can be optionally specified as a second parameter, + //! in which case its contents will be replaced with cloned source node. + //! This is useful when you want to clone entire document. + //! \param source Node to clone. + //! \param result Node to put results in, or 0 to automatically allocate result node + //! \return Pointer to cloned node. This pointer will never be NULL. + xml_node *clone_node(const xml_node *source, xml_node *result = 0) + { + // Prepare result node + if (result) + { + result->remove_all_attributes(); + result->remove_all_nodes(); + result->type(source->type()); + } + else + result = allocate_node(source->type()); + + // Clone name and value + result->name(source->name(), source->name_size()); + result->value(source->value(), source->value_size()); + + // Clone child nodes and attributes + for (xml_node *child = source->first_node(); child; child = child->next_sibling()) + result->append_node(clone_node(child)); + for (xml_attribute *attr = source->first_attribute(); attr; attr = attr->next_attribute()) + result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size())); + + return result; + } + + //! Clears the pool. + //! This causes memory occupied by nodes allocated by the pool to be freed. + //! Any nodes or strings allocated from the pool will no longer be valid. + void clear() + { + while (m_begin != m_static_memory) + { + char *previous_begin = reinterpret_cast
    (align(m_begin))->previous_begin; + if (m_free_func) + m_free_func(m_begin); + else + delete[] m_begin; + m_begin = previous_begin; + } + init(); + } + + //! Sets or resets the user-defined memory allocation functions for the pool. + //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. + //! Allocation function must not return invalid pointer on failure. It should either throw, + //! stop the program, or use longjmp() function to pass control to other place of program. + //! If it returns invalid pointer, results are undefined. + //!

    + //! User defined allocation functions must have the following forms: + //!
    + //!
    void *allocate(std::size_t size); + //!
    void free(void *pointer); + //!

    + //! \param af Allocation function, or 0 to restore default function + //! \param ff Free function, or 0 to restore default function + void set_allocator(alloc_func *af, free_func *ff) + { + assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet + m_alloc_func = af; + m_free_func = ff; + } + + private: + + struct header + { + char *previous_begin; + }; + + void init() + { + m_begin = m_static_memory; + m_ptr = align(m_begin); + m_end = m_static_memory + sizeof(m_static_memory); + } + + char *align(char *ptr) + { + std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1)); + return ptr + alignment; + } + + char *allocate_raw(std::size_t size) + { + // Allocate + void *memory; + if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[] + { + memory = m_alloc_func(size); + assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp + } + else + { + memory = new char[size]; +#ifdef RAPIDXML_NO_EXCEPTIONS + if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc + RAPIDXML_PARSE_ERROR("out of memory", 0); +#endif + } + return static_cast(memory); + } + + void *allocate_aligned(std::size_t size) + { + // Calculate aligned pointer + char *result = align(m_ptr); + + // If not enough memory left in current pool, allocate a new pool + if (result + size > m_end) + { + // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE) + std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE; + if (pool_size < size) + pool_size = size; + + // Allocate + std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation + char *raw_memory = allocate_raw(alloc_size); + + // Setup new pool in allocated memory + char *pool = align(raw_memory); + header *new_header = reinterpret_cast
    (pool); + new_header->previous_begin = m_begin; + m_begin = raw_memory; + m_ptr = pool + sizeof(header); + m_end = raw_memory + alloc_size; + + // Calculate aligned pointer again using new pool + result = align(m_ptr); + } + + // Update pool and return aligned pointer + m_ptr = result + size; + return result; + } + + char *m_begin; // Start of raw memory making up current pool + char *m_ptr; // First free byte in current pool + char *m_end; // One past last available byte in current pool + char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory + alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used + free_func *m_free_func; // Free function, or 0 if default is to be used + }; + + /////////////////////////////////////////////////////////////////////////// + // XML base + + //! Base class for xml_node and xml_attribute implementing common functions: + //! name(), name_size(), value(), value_size() and parent(). + //! \param Ch Character type to use + template + class xml_base + { + + public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + // Construct a base with empty name, value and parent + xml_base() + : m_name(0) + , m_value(0) + , m_parent(0) + { + } + + /////////////////////////////////////////////////////////////////////////// + // Node data access + + //! Gets name of the node. + //! Interpretation of name depends on type of node. + //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. + //!

    + //! Use name_size() function to determine length of the name. + //! \return Name of node, or empty string if node has no name. + Ch *name() const + { + return m_name ? m_name : nullstr(); + } + + //! Gets size of node name, not including terminator character. + //! This function works correctly irrespective of whether name is or is not zero terminated. + //! \return Size of node name, in characters. + std::size_t name_size() const + { + return m_name ? m_name_size : 0; + } + + //! Gets value of node. + //! Interpretation of value depends on type of node. + //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. + //!

    + //! Use value_size() function to determine length of the value. + //! \return Value of node, or empty string if node has no value. + Ch *value() const + { + return m_value ? m_value : nullstr(); + } + + //! Gets size of node value, not including terminator character. + //! This function works correctly irrespective of whether value is or is not zero terminated. + //! \return Size of node value, in characters. + std::size_t value_size() const + { + return m_value ? m_value_size : 0; + } + + /////////////////////////////////////////////////////////////////////////// + // Node modification + + //! Sets name of node to a non zero-terminated string. + //! See \ref ownership_of_strings. + //!

    + //! Note that node does not own its name or value, it only stores a pointer to it. + //! It will not delete or otherwise free the pointer on destruction. + //! It is reponsibility of the user to properly manage lifetime of the string. + //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - + //! on destruction of the document the string will be automatically freed. + //!

    + //! Size of name must be specified separately, because name does not have to be zero terminated. + //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated). + //! \param name Name of node to set. Does not have to be zero terminated. + //! \param size Size of name, in characters. This does not include zero terminator, if one is present. + void name(const Ch *name, std::size_t size) + { + m_name = const_cast(name); + m_name_size = size; + } + + //! Sets name of node to a zero-terminated string. + //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t). + //! \param name Name of node to set. Must be zero terminated. + void name(const Ch *name) + { + this->name(name, internal::measure(name)); + } + + //! Sets value of node to a non zero-terminated string. + //! See \ref ownership_of_strings. + //!

    + //! Note that node does not own its name or value, it only stores a pointer to it. + //! It will not delete or otherwise free the pointer on destruction. + //! It is reponsibility of the user to properly manage lifetime of the string. + //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - + //! on destruction of the document the string will be automatically freed. + //!

    + //! Size of value must be specified separately, because it does not have to be zero terminated. + //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated). + //!

    + //! If an element has a child node of type node_data, it will take precedence over element value when printing. + //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser. + //! \param value value of node to set. Does not have to be zero terminated. + //! \param size Size of value, in characters. This does not include zero terminator, if one is present. + void value(const Ch *value, std::size_t size) + { + m_value = const_cast(value); + m_value_size = size; + } + + //! Sets value of node to a zero-terminated string. + //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t). + //! \param value Vame of node to set. Must be zero terminated. + void value(const Ch *value) + { + this->value(value, internal::measure(value)); + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets node parent. + //! \return Pointer to parent node, or 0 if there is no parent. + xml_node *parent() const + { + return m_parent; + } + + protected: + + // Return empty string + static Ch *nullstr() + { + static Ch zero = Ch('\0'); + return &zero; + } + + Ch *m_name; // Name of node, or 0 if no name + Ch *m_value; // Value of node, or 0 if no value + std::size_t m_name_size; // Length of node name, or undefined of no name + std::size_t m_value_size; // Length of node value, or undefined if no value + xml_node *m_parent; // Pointer to parent node, or 0 if none + + }; + + //! Class representing attribute node of XML document. + //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). + //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. + //! Thus, this text must persist in memory for the lifetime of attribute. + //! \param Ch Character type to use. + template + class xml_attribute: public xml_base + { + + friend class xml_node; + + public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + //! Constructs an empty attribute with the specified type. + //! Consider using memory_pool of appropriate xml_document if allocating attributes manually. + xml_attribute() + { + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets document of which attribute is a child. + //! \return Pointer to document that contains this attribute, or 0 if there is no parent document. + xml_document *document() const + { + if (xml_node *node = this->parent()) + { + while (node->parent()) + node = node->parent(); + return node->type() == node_document ? static_cast *>(node) : 0; + } + else + return 0; + } + + //! Gets previous attribute, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return this->m_parent ? m_prev_attribute : 0; + } + + //! Gets next attribute, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return this->m_parent ? m_next_attribute : 0; + } + + private: + + xml_attribute *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero + xml_attribute *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero + + }; + + /////////////////////////////////////////////////////////////////////////// + // XML node + + //! Class representing a node of XML document. + //! Each node may have associated name and value strings, which are available through name() and value() functions. + //! Interpretation of name and value depends on type of the node. + //! Type of node can be determined by using type() function. + //!

    + //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. + //! Thus, this text must persist in the memory for the lifetime of node. + //! \param Ch Character type to use. + template + class xml_node: public xml_base + { + + public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + //! Constructs an empty node with the specified type. + //! Consider using memory_pool of appropriate document to allocate nodes manually. + //! \param type Type of node to construct. + xml_node(node_type type) + : m_type(type) + , m_first_node(0) + , m_first_attribute(0) + { + } + + /////////////////////////////////////////////////////////////////////////// + // Node data access + + //! Gets type of node. + //! \return Type of node. + node_type type() const + { + return m_type; + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets document of which node is a child. + //! \return Pointer to document that contains this node, or 0 if there is no parent document. + xml_document *document() const + { + xml_node *node = const_cast *>(this); + while (node->parent()) + node = node->parent(); + return node->type() == node_document ? static_cast *>(node) : 0; + } + + //! Gets first child node, optionally matching node name. + //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found child, or 0 if not found. + xml_node *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node *child = m_first_node; child; child = child->next_sibling()) + if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) + return child; + return 0; + } + else + return m_first_node; + } + + //! Gets last child node, optionally matching node name. + //! Behaviour is undefined if node has no children. + //! Use first_node() to test if node has children. + //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found child, or 0 if not found. + xml_node *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + assert(m_first_node); // Cannot query for last child if node has no children + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node *child = m_last_node; child; child = child->previous_sibling()) + if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) + return child; + return 0; + } + else + return m_last_node; + } + + //! Gets previous sibling node, optionally matching node name. + //! Behaviour is undefined if node has no parent. + //! Use parent() to test if node has a parent. + //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found sibling, or 0 if not found. + xml_node *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + assert(this->m_parent); // Cannot query for siblings if node has no parent + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling) + if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) + return sibling; + return 0; + } + else + return m_prev_sibling; + } + + //! Gets next sibling node, optionally matching node name. + //! Behaviour is undefined if node has no parent. + //! Use parent() to test if node has a parent. + //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found sibling, or 0 if not found. + xml_node *next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + assert(this->m_parent); // Cannot query for siblings if node has no parent + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling) + if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) + return sibling; + return 0; + } + else + return m_next_sibling; + } + + //! Gets first attribute of node, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return m_first_attribute; + } + + //! Gets last attribute of node, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return m_first_attribute ? m_last_attribute : 0; + } + + /////////////////////////////////////////////////////////////////////////// + // Node modification + + //! Sets type of node. + //! \param type Type of node to set. + void type(node_type type) + { + m_type = type; + } + + /////////////////////////////////////////////////////////////////////////// + // Node manipulation + + //! Prepends a new child node. + //! The prepended child becomes the first child, and all existing children are moved one position back. + //! \param child Node to prepend. + void prepend_node(xml_node *child) + { + assert(child && !child->parent() && child->type() != node_document); + if (first_node()) + { + child->m_next_sibling = m_first_node; + m_first_node->m_prev_sibling = child; + } + else + { + child->m_next_sibling = 0; + m_last_node = child; + } + m_first_node = child; + child->m_parent = this; + child->m_prev_sibling = 0; + } + + //! Appends a new child node. + //! The appended child becomes the last child. + //! \param child Node to append. + void append_node(xml_node *child) + { + assert(child && !child->parent() && child->type() != node_document); + if (first_node()) + { + child->m_prev_sibling = m_last_node; + m_last_node->m_next_sibling = child; + } + else + { + child->m_prev_sibling = 0; + m_first_node = child; + } + m_last_node = child; + child->m_parent = this; + child->m_next_sibling = 0; + } + + //! Inserts a new child node at specified place inside the node. + //! All children after and including the specified node are moved one position back. + //! \param where Place where to insert the child, or 0 to insert at the back. + //! \param child Node to insert. + void insert_node(xml_node *where, xml_node *child) + { + assert(!where || where->parent() == this); + assert(child && !child->parent() && child->type() != node_document); + if (where == m_first_node) + prepend_node(child); + else if (where == 0) + append_node(child); + else + { + child->m_prev_sibling = where->m_prev_sibling; + child->m_next_sibling = where; + where->m_prev_sibling->m_next_sibling = child; + where->m_prev_sibling = child; + child->m_parent = this; + } + } + + //! Removes first child node. + //! If node has no children, behaviour is undefined. + //! Use first_node() to test if node has children. + void remove_first_node() + { + assert(first_node()); + xml_node *child = m_first_node; + m_first_node = child->m_next_sibling; + if (child->m_next_sibling) + child->m_next_sibling->m_prev_sibling = 0; + else + m_last_node = 0; + child->m_parent = 0; + } + + //! Removes last child of the node. + //! If node has no children, behaviour is undefined. + //! Use first_node() to test if node has children. + void remove_last_node() + { + assert(first_node()); + xml_node *child = m_last_node; + if (child->m_prev_sibling) + { + m_last_node = child->m_prev_sibling; + child->m_prev_sibling->m_next_sibling = 0; + } + else + m_first_node = 0; + child->m_parent = 0; + } + + //! Removes specified child from the node + // \param where Pointer to child to be removed. + void remove_node(xml_node *where) + { + assert(where && where->parent() == this); + assert(first_node()); + if (where == m_first_node) + remove_first_node(); + else if (where == m_last_node) + remove_last_node(); + else + { + where->m_prev_sibling->m_next_sibling = where->m_next_sibling; + where->m_next_sibling->m_prev_sibling = where->m_prev_sibling; + where->m_parent = 0; + } + } + + //! Removes all child nodes (but not attributes). + void remove_all_nodes() + { + for (xml_node *node = first_node(); node; node = node->m_next_sibling) + node->m_parent = 0; + m_first_node = 0; + } + + //! Prepends a new attribute to the node. + //! \param attribute Attribute to prepend. + void prepend_attribute(xml_attribute *attribute) + { + assert(attribute && !attribute->parent()); + if (first_attribute()) + { + attribute->m_next_attribute = m_first_attribute; + m_first_attribute->m_prev_attribute = attribute; + } + else + { + attribute->m_next_attribute = 0; + m_last_attribute = attribute; + } + m_first_attribute = attribute; + attribute->m_parent = this; + attribute->m_prev_attribute = 0; + } + + //! Appends a new attribute to the node. + //! \param attribute Attribute to append. + void append_attribute(xml_attribute *attribute) + { + assert(attribute && !attribute->parent()); + if (first_attribute()) + { + attribute->m_prev_attribute = m_last_attribute; + m_last_attribute->m_next_attribute = attribute; + } + else + { + attribute->m_prev_attribute = 0; + m_first_attribute = attribute; + } + m_last_attribute = attribute; + attribute->m_parent = this; + attribute->m_next_attribute = 0; + } + + //! Inserts a new attribute at specified place inside the node. + //! All attributes after and including the specified attribute are moved one position back. + //! \param where Place where to insert the attribute, or 0 to insert at the back. + //! \param attribute Attribute to insert. + void insert_attribute(xml_attribute *where, xml_attribute *attribute) + { + assert(!where || where->parent() == this); + assert(attribute && !attribute->parent()); + if (where == m_first_attribute) + prepend_attribute(attribute); + else if (where == 0) + append_attribute(attribute); + else + { + attribute->m_prev_attribute = where->m_prev_attribute; + attribute->m_next_attribute = where; + where->m_prev_attribute->m_next_attribute = attribute; + where->m_prev_attribute = attribute; + attribute->m_parent = this; + } + } + + //! Removes first attribute of the node. + //! If node has no attributes, behaviour is undefined. + //! Use first_attribute() to test if node has attributes. + void remove_first_attribute() + { + assert(first_attribute()); + xml_attribute *attribute = m_first_attribute; + if (attribute->m_next_attribute) + { + attribute->m_next_attribute->m_prev_attribute = 0; + } + else + m_last_attribute = 0; + attribute->m_parent = 0; + m_first_attribute = attribute->m_next_attribute; + } + + //! Removes last attribute of the node. + //! If node has no attributes, behaviour is undefined. + //! Use first_attribute() to test if node has attributes. + void remove_last_attribute() + { + assert(first_attribute()); + xml_attribute *attribute = m_last_attribute; + if (attribute->m_prev_attribute) + { + attribute->m_prev_attribute->m_next_attribute = 0; + m_last_attribute = attribute->m_prev_attribute; + } + else + m_first_attribute = 0; + attribute->m_parent = 0; + } + + //! Removes specified attribute from node. + //! \param where Pointer to attribute to be removed. + void remove_attribute(xml_attribute *where) + { + assert(first_attribute() && where->parent() == this); + if (where == m_first_attribute) + remove_first_attribute(); + else if (where == m_last_attribute) + remove_last_attribute(); + else + { + where->m_prev_attribute->m_next_attribute = where->m_next_attribute; + where->m_next_attribute->m_prev_attribute = where->m_prev_attribute; + where->m_parent = 0; + } + } + + //! Removes all attributes of node. + void remove_all_attributes() + { + for (xml_attribute *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute) + attribute->m_parent = 0; + m_first_attribute = 0; + } + + private: + + /////////////////////////////////////////////////////////////////////////// + // Restrictions + + // No copying + xml_node(const xml_node &); + void operator =(const xml_node &); + + /////////////////////////////////////////////////////////////////////////// + // Data members + + // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0. + // This is required for maximum performance, as it allows the parser to omit initialization of + // unneded/redundant values. + // + // The rules are as follows: + // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively + // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage + // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage + + node_type m_type; // Type of node; always valid + xml_node *m_first_node; // Pointer to first child node, or 0 if none; always valid + xml_node *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero + xml_attribute *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid + xml_attribute *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero + xml_node *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero + xml_node *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero + + }; + + /////////////////////////////////////////////////////////////////////////// + // XML document + + //! This class represents root of the DOM hierarchy. + //! It is also an xml_node and a memory_pool through public inheritance. + //! Use parse() function to build a DOM tree from a zero-terminated XML text string. + //! parse() function allocates memory for nodes and attributes by using functions of xml_document, + //! which are inherited from memory_pool. + //! To access root node of the document, use the document itself, as if it was an xml_node. + //! \param Ch Character type to use. + template + class xml_document: public xml_node, public memory_pool + { + + public: + + //! Constructs empty XML document + xml_document() + : xml_node(node_document) + { + } + + //! Parses zero-terminated XML string according to given flags. + //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. + //! The string must persist for the lifetime of the document. + //! In case of error, rapidxml::parse_error exception will be thrown. + //!

    + //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. + //! Make sure that data is zero-terminated. + //!

    + //! Document can be parsed into multiple times. + //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool. + //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser. + template + void parse(Ch *text) + { + assert(text); + + // Remove current contents + this->remove_all_nodes(); + this->remove_all_attributes(); + + // Parse BOM, if any + parse_bom(text); + + // Parse children + while (1) + { + // Skip whitespace before node + skip(text); + if (*text == 0) + break; + + // Parse and append new child + if (*text == Ch('<')) + { + ++text; // Skip '<' + if (xml_node *node = parse_node(text)) + this->append_node(node); + } + else + RAPIDXML_PARSE_ERROR("expected <", text); + } + + } + + //! Clears the document by deleting all nodes and clearing the memory pool. + //! All nodes owned by document pool are destroyed. + void clear() + { + this->remove_all_nodes(); + this->remove_all_attributes(); + memory_pool::clear(); + } + + private: + + /////////////////////////////////////////////////////////////////////// + // Internal character utility functions + + // Detect whitespace character + struct whitespace_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_whitespace[static_cast(ch)]; + } + }; + + // Detect node name character + struct node_name_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_node_name[static_cast(ch)]; + } + }; + + // Detect attribute name character + struct attribute_name_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_attribute_name[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) + struct text_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_text[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) that does not require processing + struct text_pure_no_ws_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast(ch)]; + } + }; + + // Detect text character (PCDATA) that does not require processing + struct text_pure_with_ws_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast(ch)]; + } + }; + + // Detect attribute value character + template + struct attribute_value_pred + { + static unsigned char test(Ch ch) + { + if (Quote == Ch('\'')) + return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast(ch)]; + if (Quote == Ch('\"')) + return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast(ch)]; + return 0; // Should never be executed, to avoid warnings on Comeau + } + }; + + // Detect attribute value character + template + struct attribute_value_pure_pred + { + static unsigned char test(Ch ch) + { + if (Quote == Ch('\'')) + return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast(ch)]; + if (Quote == Ch('\"')) + return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast(ch)]; + return 0; // Should never be executed, to avoid warnings on Comeau + } + }; + + // Insert coded character, using UTF8 or 8-bit ASCII + template + static void insert_coded_character(Ch *&text, unsigned long code) + { + if (Flags & parse_no_utf8) + { + // Insert 8-bit ASCII character + // Todo: possibly verify that code is less than 256 and use replacement char otherwise? + text[0] = static_cast(code); + text += 1; + } + else + { + // Insert UTF8 sequence + if (code < 0x80) // 1 byte sequence + { + text[0] = static_cast(code); + text += 1; + } + else if (code < 0x800) // 2 byte sequence + { + text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast(code | 0xC0); + text += 2; + } + else if (code < 0x10000) // 3 byte sequence + { + text[2] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast(code | 0xE0); + text += 3; + } + else if (code < 0x110000) // 4 byte sequence + { + text[3] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[2] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[1] = static_cast((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast(code | 0xF0); + text += 4; + } + else // Invalid, only codes up to 0x10FFFF are allowed in Unicode + { + RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); + } + } + } + + // Skip characters until predicate evaluates to true + template + static void skip(Ch *&text) + { + Ch *tmp = text; + while (StopPred::test(*tmp)) + ++tmp; + text = tmp; + } + + // Skip characters until predicate evaluates to true while doing the following: + // - replacing XML character entity references with proper characters (' & " < > &#...;) + // - condensing whitespace sequences to single space character + template + static Ch *skip_and_expand_character_refs(Ch *&text) + { + // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip + if (Flags & parse_no_entity_translation && + !(Flags & parse_normalize_whitespace) && + !(Flags & parse_trim_whitespace)) + { + skip(text); + return text; + } + + // Use simple skip until first modification is detected + skip(text); + + // Use translation skip + Ch *src = text; + Ch *dest = src; + while (StopPred::test(*src)) + { + // If entity translation is enabled + if (!(Flags & parse_no_entity_translation)) + { + // Test if replacement is needed + if (src[0] == Ch('&')) + { + switch (src[1]) + { + + // & ' + case Ch('a'): + if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';')) + { + *dest = Ch('&'); + ++dest; + src += 5; + continue; + } + if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';')) + { + *dest = Ch('\''); + ++dest; + src += 6; + continue; + } + break; + + // " + case Ch('q'): + if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';')) + { + *dest = Ch('"'); + ++dest; + src += 6; + continue; + } + break; + + // > + case Ch('g'): + if (src[2] == Ch('t') && src[3] == Ch(';')) + { + *dest = Ch('>'); + ++dest; + src += 4; + continue; + } + break; + + // < + case Ch('l'): + if (src[2] == Ch('t') && src[3] == Ch(';')) + { + *dest = Ch('<'); + ++dest; + src += 4; + continue; + } + break; + + // &#...; - assumes ASCII + case Ch('#'): + if (src[2] == Ch('x')) + { + unsigned long code = 0; + src += 3; // Skip &#x + while (1) + { + unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; + if (digit == 0xFF) + break; + code = code * 16 + digit; + ++src; + } + insert_coded_character(dest, code); // Put character in output + } + else + { + unsigned long code = 0; + src += 2; // Skip &# + while (1) + { + unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast(*src)]; + if (digit == 0xFF) + break; + code = code * 10 + digit; + ++src; + } + insert_coded_character(dest, code); // Put character in output + } + if (*src == Ch(';')) + ++src; + else + RAPIDXML_PARSE_ERROR("expected ;", src); + continue; + + // Something else + default: + // Ignore, just copy '&' verbatim + break; + + } + } + } + + // If whitespace condensing is enabled + if (Flags & parse_normalize_whitespace) + { + // Test if condensing is needed + if (whitespace_pred::test(*src)) + { + *dest = Ch(' '); ++dest; // Put single space in dest + ++src; // Skip first whitespace char + // Skip remaining whitespace chars + while (whitespace_pred::test(*src)) + ++src; + continue; + } + } + + // No replacement, only copy character + *dest++ = *src++; + + } + + // Return new end + text = src; + return dest; + + } + + /////////////////////////////////////////////////////////////////////// + // Internal parsing functions + + // Parse BOM, if any + template + void parse_bom(Ch *&text) + { + // UTF-8? + if (static_cast(text[0]) == 0xEF && + static_cast(text[1]) == 0xBB && + static_cast(text[2]) == 0xBF) + { + text += 3; // Skup utf-8 bom + } + } + + // Parse XML declaration ( + xml_node *parse_xml_declaration(Ch *&text) + { + // If parsing of declaration is disabled + if (!(Flags & parse_declaration_node)) + { + // Skip until end of declaration + while (text[0] != Ch('?') || text[1] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 2; // Skip '?>' + return 0; + } + + // Create declaration + xml_node *declaration = this->allocate_node(node_declaration); + + // Skip whitespace before attributes or ?> + skip(text); + + // Parse declaration attributes + parse_node_attributes(text, declaration); + + // Skip ?> + if (text[0] != Ch('?') || text[1] != Ch('>')) + RAPIDXML_PARSE_ERROR("expected ?>", text); + text += 2; + + return declaration; + } + + // Parse XML comment (' + return 0; // Do not produce comment node + } + + // Remember value start + Ch *value = text; + + // Skip until end of comment + while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Create comment node + xml_node *comment = this->allocate_node(node_comment); + comment->value(value, text - value); + + // Place zero terminator after comment value + if (!(Flags & parse_no_string_terminators)) + *text = Ch('\0'); + + text += 3; // Skip '-->' + return comment; + } + + // Parse DOCTYPE + template + xml_node *parse_doctype(Ch *&text) + { + // Remember value start + Ch *value = text; + + // Skip to > + while (*text != Ch('>')) + { + // Determine character type + switch (*text) + { + + // If '[' encountered, scan for matching ending ']' using naive algorithm with depth + // This works for all W3C test files except for 2 most wicked + case Ch('['): + { + ++text; // Skip '[' + int depth = 1; + while (depth > 0) + { + switch (*text) + { + case Ch('['): ++depth; break; + case Ch(']'): --depth; break; + case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text); + } + ++text; + } + break; + } + + // Error on end of text + case Ch('\0'): + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + + // Other character, skip it + default: + ++text; + + } + } + + // If DOCTYPE nodes enabled + if (Flags & parse_doctype_node) + { + // Create a new doctype node + xml_node *doctype = this->allocate_node(node_doctype); + doctype->value(value, text - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) + *text = Ch('\0'); + + text += 1; // skip '>' + return doctype; + } + else + { + text += 1; // skip '>' + return 0; + } + + } + + // Parse PI + template + xml_node *parse_pi(Ch *&text) + { + // If creation of PI nodes is enabled + if (Flags & parse_pi_nodes) + { + // Create pi node + xml_node *pi = this->allocate_node(node_pi); + + // Extract PI target name + Ch *name = text; + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected PI target", text); + pi->name(name, text - name); + + // Skip whitespace between pi target and pi + skip(text); + + // Remember start of pi + Ch *value = text; + + // Skip to '?>' + while (text[0] != Ch('?') || text[1] != Ch('>')) + { + if (*text == Ch('\0')) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Set pi value (verbatim, no entity expansion or whitespace normalization) + pi->value(value, text - value); + + // Place zero terminator after name and value + if (!(Flags & parse_no_string_terminators)) + { + pi->name()[pi->name_size()] = Ch('\0'); + pi->value()[pi->value_size()] = Ch('\0'); + } + + text += 2; // Skip '?>' + return pi; + } + else + { + // Skip to '?>' + while (text[0] != Ch('?') || text[1] != Ch('>')) + { + if (*text == Ch('\0')) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 2; // Skip '?>' + return 0; + } + } + + // Parse and append data + // Return character that ends data. + // This is necessary because this character might have been overwritten by a terminating 0 + template + Ch parse_and_append_data(xml_node *node, Ch *&text, Ch *contents_start) + { + // Backup to contents start if whitespace trimming is disabled + if (!(Flags & parse_trim_whitespace)) + text = contents_start; + + // Skip until end of data + Ch *value = text, *end; + if (Flags & parse_normalize_whitespace) + end = skip_and_expand_character_refs(text); + else + end = skip_and_expand_character_refs(text); + + // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after > + if (Flags & parse_trim_whitespace) + { + if (Flags & parse_normalize_whitespace) + { + // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end + if (*(end - 1) == Ch(' ')) + --end; + } + else + { + // Backup until non-whitespace character is found + while (whitespace_pred::test(*(end - 1))) + --end; + } + } + + // If characters are still left between end and value (this test is only necessary if normalization is enabled) + // Create new data node + if (!(Flags & parse_no_data_nodes)) + { + xml_node *data = this->allocate_node(node_data); + data->value(value, end - value); + node->append_node(data); + } + + // Add data to parent node if no data exists yet + if (!(Flags & parse_no_element_values)) + if (*node->value() == Ch('\0')) + node->value(value, end - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) + { + Ch ch = *text; + *end = Ch('\0'); + return ch; // Return character that ends data; this is required because zero terminator overwritten it + } + + // Return character that ends data + return *text; + } + + // Parse CDATA + template + xml_node *parse_cdata(Ch *&text) + { + // If CDATA is disabled + if (Flags & parse_no_data_nodes) + { + // Skip until end of cdata + while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 3; // Skip ]]> + return 0; // Do not produce CDATA node + } + + // Skip until end of cdata + Ch *value = text; + while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Create new cdata node + xml_node *cdata = this->allocate_node(node_cdata); + cdata->value(value, text - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) + *text = Ch('\0'); + + text += 3; // Skip ]]> + return cdata; + } + + // Parse element node + template + xml_node *parse_element(Ch *&text) + { + // Create element node + xml_node *element = this->allocate_node(node_element); + + // Extract element name + Ch *name = text; + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected element name", text); + element->name(name, text - name); + + // Skip whitespace between element name and attributes or > + skip(text); + + // Parse attributes, if any + parse_node_attributes(text, element); + + // Determine ending type + if (*text == Ch('>')) + { + ++text; + parse_node_contents(text, element); + } + else if (*text == Ch('/')) + { + ++text; + if (*text != Ch('>')) + RAPIDXML_PARSE_ERROR("expected >", text); + ++text; + } + else + RAPIDXML_PARSE_ERROR("expected >", text); + + // Place zero terminator after name + if (!(Flags & parse_no_string_terminators)) + element->name()[element->name_size()] = Ch('\0'); + + // Return parsed element + return element; + } + + // Determine node type, and parse it + template + xml_node *parse_node(Ch *&text) + { + // Parse proper node type + switch (text[0]) + { + + // <... + default: + // Parse and append element node + return parse_element(text); + + // (text); + } + else + { + // Parse PI + return parse_pi(text); + } + + // (text); + } + break; + + // (text); + } + break; + + // (text); + } + + } // switch + + // Attempt to skip other, unrecognized node types starting with ')) + { + if (*text == 0) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + ++text; // Skip '>' + return 0; // No node recognized + + } + } + + // Parse contents of the node - children, data etc. + template + void parse_node_contents(Ch *&text, xml_node *node) + { + // For all children and text + while (1) + { + // Skip whitespace between > and node contents + Ch *contents_start = text; // Store start of node contents before whitespace is skipped + skip(text); + Ch next_char = *text; + + // After data nodes, instead of continuing the loop, control jumps here. + // This is because zero termination inside parse_and_append_data() function + // would wreak havoc with the above code. + // Also, skipping whitespace after data nodes is unnecessary. + after_data_node: + + // Determine what comes next: node closing, child node, data node, or 0? + switch (next_char) + { + + // Node closing or child node + case Ch('<'): + if (text[1] == Ch('/')) + { + // Node closing + text += 2; // Skip '(text); + if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true)) + RAPIDXML_PARSE_ERROR("invalid closing tag name", text); + } + else + { + // No validation, just skip name + skip(text); + } + // Skip remaining whitespace after node name + skip(text); + if (*text != Ch('>')) + RAPIDXML_PARSE_ERROR("expected >", text); + ++text; // Skip '>' + return; // Node closed, finished parsing contents + } + else + { + // Child node + ++text; // Skip '<' + if (xml_node *child = parse_node(text)) + node->append_node(child); + } + break; + + // End of data - error + case Ch('\0'): + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + + // Data node + default: + next_char = parse_and_append_data(node, text, contents_start); + goto after_data_node; // Bypass regular processing after data nodes + + } + } + } + + // Parse XML attributes of the node + template + void parse_node_attributes(Ch *&text, xml_node *node) + { + // For all attributes + while (attribute_name_pred::test(*text)) + { + // Extract attribute name + Ch *name = text; + ++text; // Skip first character of attribute name + skip(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected attribute name", name); + + // Create new attribute + xml_attribute *attribute = this->allocate_attribute(); + attribute->name(name, text - name); + node->append_attribute(attribute); + + // Skip whitespace after attribute name + skip(text); + + // Skip = + if (*text != Ch('=')) + RAPIDXML_PARSE_ERROR("expected =", text); + ++text; + + // Add terminating zero after name + if (!(Flags & parse_no_string_terminators)) + attribute->name()[attribute->name_size()] = 0; + + // Skip whitespace after = + skip(text); + + // Skip quote and remember if it was ' or " + Ch quote = *text; + if (quote != Ch('\'') && quote != Ch('"')) + RAPIDXML_PARSE_ERROR("expected ' or \"", text); + ++text; + + // Extract attribute value and expand char refs in it + Ch *value = text, *end; + const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes + if (quote == Ch('\'')) + end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text); + else + end = skip_and_expand_character_refs, attribute_value_pure_pred, AttFlags>(text); + + // Set attribute value + attribute->value(value, end - value); + + // Make sure that end quote is present + if (*text != quote) + RAPIDXML_PARSE_ERROR("expected ' or \"", text); + ++text; // Skip quote + + // Add terminating zero after value + if (!(Flags & parse_no_string_terminators)) + attribute->value()[attribute->value_size()] = 0; + + // Skip whitespace after attribute value + skip(text); + } + } + + }; + + //! \cond internal + namespace internal + { + + // Whitespace (space \n \r \t) + template + const unsigned char lookup_tables::lookup_whitespace[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F + }; + + // Node name (anything but space \n \r \t / > ? \0) + template + const unsigned char lookup_tables::lookup_node_name[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Text (i.e. PCDATA) (anything but < \0) + template + const unsigned char lookup_tables::lookup_text[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled + // (anything but < \0 &) + template + const unsigned char lookup_tables::lookup_text_pure_no_ws[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled + // (anything but < \0 & space \n \r \t) + template + const unsigned char lookup_tables::lookup_text_pure_with_ws[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute name (anything but space \n \r \t / < > = ? ! \0) + template + const unsigned char lookup_tables::lookup_attribute_name[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with single quote (anything but ' \0) + template + const unsigned char lookup_tables::lookup_attribute_data_1[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with single quote that does not require processing (anything but ' \0 &) + template + const unsigned char lookup_tables::lookup_attribute_data_1_pure[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with double quote (anything but " \0) + template + const unsigned char lookup_tables::lookup_attribute_data_2[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with double quote that does not require processing (anything but " \0 &) + template + const unsigned char lookup_tables::lookup_attribute_data_2_pure[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Digits (dec and hex, 255 denotes end of numeric character reference) + template + const unsigned char lookup_tables::lookup_digits[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 0 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 1 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 2 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255, // 3 + 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 4 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 5 + 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 6 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 7 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 8 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 9 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // A + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // B + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // C + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // D + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // E + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 // F + }; + + // Upper case conversion + template + const unsigned char lookup_tables::lookup_upcase[256] = + { + // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2 + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3 + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5 + 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 6 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127, // 7 + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 8 + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, // 9 + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // A + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // B + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // C + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // D + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // E + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // F + }; + } + //! \endcond + +} + +// Undefine internal macros +#undef RAPIDXML_PARSE_ERROR + +// On MSVC, restore warnings state +#ifdef _MSC_VER + #pragma warning(pop) +#endif + +#endif diff --git a/libs/network/example/rapidxml/rapidxml_iterators.hpp b/libs/network/example/rapidxml/rapidxml_iterators.hpp new file mode 100644 index 000000000..52ebc298a --- /dev/null +++ b/libs/network/example/rapidxml/rapidxml_iterators.hpp @@ -0,0 +1,174 @@ +#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED +#define RAPIDXML_ITERATORS_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_iterators.hpp This file contains rapidxml iterators + +#include "rapidxml.hpp" + +namespace rapidxml +{ + + //! Iterator of child nodes of xml_node + template + class node_iterator + { + + public: + + typedef typename xml_node value_type; + typedef typename xml_node &reference; + typedef typename xml_node *pointer; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + node_iterator() + : m_node(0) + { + } + + node_iterator(xml_node *node) + : m_node(node->first_node()) + { + } + + reference operator *() const + { + assert(m_node); + return *m_node; + } + + pointer operator->() const + { + assert(m_node); + return m_node; + } + + node_iterator& operator++() + { + assert(m_node); + m_node = m_node->next_sibling(); + return *this; + } + + node_iterator operator++(int) + { + node_iterator tmp = *this; + ++this; + return tmp; + } + + node_iterator& operator--() + { + assert(m_node && m_node->previous_sibling()); + m_node = m_node->previous_sibling(); + return *this; + } + + node_iterator operator--(int) + { + node_iterator tmp = *this; + ++this; + return tmp; + } + + bool operator ==(const node_iterator &rhs) + { + return m_node == rhs.m_node; + } + + bool operator !=(const node_iterator &rhs) + { + return m_node != rhs.m_node; + } + + private: + + xml_node *m_node; + + }; + + //! Iterator of child attributes of xml_node + template + class attribute_iterator + { + + public: + + typedef typename xml_attribute value_type; + typedef typename xml_attribute &reference; + typedef typename xml_attribute *pointer; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + attribute_iterator() + : m_attribute(0) + { + } + + attribute_iterator(xml_node *node) + : m_attribute(node->first_attribute()) + { + } + + reference operator *() const + { + assert(m_attribute); + return *m_attribute; + } + + pointer operator->() const + { + assert(m_attribute); + return m_attribute; + } + + attribute_iterator& operator++() + { + assert(m_attribute); + m_attribute = m_attribute->next_attribute(); + return *this; + } + + attribute_iterator operator++(int) + { + attribute_iterator tmp = *this; + ++this; + return tmp; + } + + attribute_iterator& operator--() + { + assert(m_attribute && m_attribute->previous_attribute()); + m_attribute = m_attribute->previous_attribute(); + return *this; + } + + attribute_iterator operator--(int) + { + attribute_iterator tmp = *this; + ++this; + return tmp; + } + + bool operator ==(const attribute_iterator &rhs) + { + return m_attribute == rhs.m_attribute; + } + + bool operator !=(const attribute_iterator &rhs) + { + return m_attribute != rhs.m_attribute; + } + + private: + + xml_attribute *m_attribute; + + }; + +} + +#endif diff --git a/libs/network/example/rapidxml/rapidxml_print.hpp b/libs/network/example/rapidxml/rapidxml_print.hpp new file mode 100644 index 000000000..0ae2b14fa --- /dev/null +++ b/libs/network/example/rapidxml/rapidxml_print.hpp @@ -0,0 +1,421 @@ +#ifndef RAPIDXML_PRINT_HPP_INCLUDED +#define RAPIDXML_PRINT_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_print.hpp This file contains rapidxml printer implementation + +#include "rapidxml.hpp" + +// Only include streams if not disabled +#ifndef RAPIDXML_NO_STREAMS + #include + #include +#endif + +namespace rapidxml +{ + + /////////////////////////////////////////////////////////////////////// + // Printing flags + + const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function. + + /////////////////////////////////////////////////////////////////////// + // Internal + + //! \cond internal + namespace internal + { + + /////////////////////////////////////////////////////////////////////////// + // Internal character operations + + // Copy characters from given range to given output iterator + template + inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out) + { + while (begin != end) + *out++ = *begin++; + return out; + } + + // Copy characters from given range to given output iterator and expand + // characters into references (< > ' " &) + template + inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out) + { + while (begin != end) + { + if (*begin == noexpand) + { + *out++ = *begin; // No expansion, copy character + } + else + { + switch (*begin) + { + case Ch('<'): + *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('>'): + *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('\''): + *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';'); + break; + case Ch('"'): + *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('&'): + *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); + break; + default: + *out++ = *begin; // No expansion, copy character + } + } + ++begin; // Step to next character + } + return out; + } + + // Fill given output iterator with repetitions of the same character + template + inline OutIt fill_chars(OutIt out, int n, Ch ch) + { + for (int i = 0; i < n; ++i) + *out++ = ch; + return out; + } + + // Find character + template + inline bool find_char(const Ch *begin, const Ch *end) + { + while (begin != end) + if (*begin++ == ch) + return true; + return false; + } + + /////////////////////////////////////////////////////////////////////////// + // Internal printing operations + + // Print node + template + inline OutIt print_node(OutIt out, const xml_node *node, int flags, int indent) + { + // Print proper node type + switch (node->type()) + { + + // Document + case node_document: + out = print_children(out, node, flags, indent); + break; + + // Element + case node_element: + out = print_element_node(out, node, flags, indent); + break; + + // Data + case node_data: + out = print_data_node(out, node, flags, indent); + break; + + // CDATA + case node_cdata: + out = print_cdata_node(out, node, flags, indent); + break; + + // Declaration + case node_declaration: + out = print_declaration_node(out, node, flags, indent); + break; + + // Comment + case node_comment: + out = print_comment_node(out, node, flags, indent); + break; + + // Doctype + case node_doctype: + out = print_doctype_node(out, node, flags, indent); + break; + + // Pi + case node_pi: + out = print_pi_node(out, node, flags, indent); + break; + + // Unknown + default: + assert(0); + break; + } + + // If indenting not disabled, add line break after node + if (!(flags & print_no_indenting)) + *out = Ch('\n'), ++out; + + // Return modified iterator + return out; + } + + // Print children of the node + template + inline OutIt print_children(OutIt out, const xml_node *node, int flags, int indent) + { + for (xml_node *child = node->first_node(); child; child = child->next_sibling()) + out = print_node(out, child, flags, indent); + return out; + } + + // Print attributes of the node + template + inline OutIt print_attributes(OutIt out, const xml_node *node, int flags) + { + for (xml_attribute *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute()) + { + if (attribute->name() && attribute->value()) + { + // Print attribute name + *out = Ch(' '), ++out; + out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out); + *out = Ch('='), ++out; + // Print attribute value using appropriate quote type + if (find_char(attribute->value(), attribute->value() + attribute->value_size())) + { + *out = Ch('\''), ++out; + out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out); + *out = Ch('\''), ++out; + } + else + { + *out = Ch('"'), ++out; + out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out); + *out = Ch('"'), ++out; + } + } + } + return out; + } + + // Print data node + template + inline OutIt print_data_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_data); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out); + return out; + } + + // Print data node + template + inline OutIt print_cdata_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_cdata); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'); ++out; + *out = Ch('!'); ++out; + *out = Ch('['); ++out; + *out = Ch('C'); ++out; + *out = Ch('D'); ++out; + *out = Ch('A'); ++out; + *out = Ch('T'); ++out; + *out = Ch('A'); ++out; + *out = Ch('['); ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch(']'); ++out; + *out = Ch(']'); ++out; + *out = Ch('>'); ++out; + return out; + } + + // Print element node + template + inline OutIt print_element_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_element); + + // Print element name and attributes, if any + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + out = print_attributes(out, node, flags); + + // If node is childless + if (node->value_size() == 0 && !node->first_node()) + { + // Print childless node tag ending + *out = Ch('/'), ++out; + *out = Ch('>'), ++out; + } + else + { + // Print normal node tag ending + *out = Ch('>'), ++out; + + // Test if node contains a single data node only (and no other nodes) + xml_node *child = node->first_node(); + if (!child) + { + // If node has no children, only print its value without indenting + out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out); + } + else if (child->next_sibling() == 0 && child->type() == node_data) + { + // If node has a sole data child, only print its value without indenting + out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out); + } + else + { + // Print all children with full indenting + if (!(flags & print_no_indenting)) + *out = Ch('\n'), ++out; + out = print_children(out, node, flags, indent + 1); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + } + + // Print node end + *out = Ch('<'), ++out; + *out = Ch('/'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + *out = Ch('>'), ++out; + } + return out; + } + + // Print declaration node + template + inline OutIt print_declaration_node(OutIt out, const xml_node *node, int flags, int indent) + { + // Print declaration start + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('?'), ++out; + *out = Ch('x'), ++out; + *out = Ch('m'), ++out; + *out = Ch('l'), ++out; + + // Print attributes + out = print_attributes(out, node, flags); + + // Print declaration end + *out = Ch('?'), ++out; + *out = Ch('>'), ++out; + + return out; + } + + // Print comment node + template + inline OutIt print_comment_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_comment); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('!'), ++out; + *out = Ch('-'), ++out; + *out = Ch('-'), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('-'), ++out; + *out = Ch('-'), ++out; + *out = Ch('>'), ++out; + return out; + } + + // Print doctype node + template + inline OutIt print_doctype_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_doctype); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('!'), ++out; + *out = Ch('D'), ++out; + *out = Ch('O'), ++out; + *out = Ch('C'), ++out; + *out = Ch('T'), ++out; + *out = Ch('Y'), ++out; + *out = Ch('P'), ++out; + *out = Ch('E'), ++out; + *out = Ch(' '), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('>'), ++out; + return out; + } + + // Print pi node + template + inline OutIt print_pi_node(OutIt out, const xml_node *node, int flags, int indent) + { + assert(node->type() == node_pi); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('?'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + *out = Ch(' '), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('?'), ++out; + *out = Ch('>'), ++out; + return out; + } + + } + //! \endcond + + /////////////////////////////////////////////////////////////////////////// + // Printing + + //! Prints XML to given output iterator. + //! \param out Output iterator to print to. + //! \param node Node to be printed. Pass xml_document to print entire document. + //! \param flags Flags controlling how XML is printed. + //! \return Output iterator pointing to position immediately after last character of printed text. + template + inline OutIt print(OutIt out, const xml_node &node, int flags = 0) + { + return internal::print_node(out, &node, flags, 0); + } + +#ifndef RAPIDXML_NO_STREAMS + + //! Prints XML to given output stream. + //! \param out Output stream to print to. + //! \param node Node to be printed. Pass xml_document to print entire document. + //! \param flags Flags controlling how XML is printed. + //! \return Output stream. + template + inline std::basic_ostream &print(std::basic_ostream &out, const xml_node &node, int flags = 0) + { + print(std::ostream_iterator(out), node, flags); + return out; + } + + //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process. + //! \param out Output stream to print to. + //! \param node Node to be printed. + //! \return Output stream. + template + inline std::basic_ostream &operator <<(std::basic_ostream &out, const xml_node &node) + { + return print(out, node); + } + +#endif + +} + +#endif diff --git a/libs/network/example/rapidxml/rapidxml_utils.hpp b/libs/network/example/rapidxml/rapidxml_utils.hpp new file mode 100644 index 000000000..37c29535f --- /dev/null +++ b/libs/network/example/rapidxml/rapidxml_utils.hpp @@ -0,0 +1,122 @@ +#ifndef RAPIDXML_UTILS_HPP_INCLUDED +#define RAPIDXML_UTILS_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful +//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective. + +#include "rapidxml.hpp" +#include +#include +#include +#include + +namespace rapidxml +{ + + //! Represents data loaded from a file + template + class file + { + + public: + + //! Loads file into the memory. Data will be automatically destroyed by the destructor. + //! \param filename Filename to load. + file(const char *filename) + { + using namespace std; + + // Open stream + basic_ifstream stream(filename, ios::binary); + if (!stream) + throw runtime_error(string("cannot open file ") + filename); + stream.unsetf(ios::skipws); + + // Determine stream size + stream.seekg(0, ios::end); + size_t size = stream.tellg(); + stream.seekg(0); + + // Load data and add terminating 0 + m_data.resize(size + 1); + stream.read(&m_data.front(), static_cast(size)); + m_data[size] = 0; + } + + //! Loads file into the memory. Data will be automatically destroyed by the destructor + //! \param stream Stream to load from + file(std::basic_istream &stream) + { + using namespace std; + + // Load data and add terminating 0 + stream.unsetf(ios::skipws); + m_data.assign(istreambuf_iterator(stream), istreambuf_iterator()); + if (stream.fail() || stream.bad()) + throw runtime_error("error reading stream"); + m_data.push_back(0); + } + + //! Gets file data. + //! \return Pointer to data of file. + Ch *data() + { + return &m_data.front(); + } + + //! Gets file data. + //! \return Pointer to data of file. + const Ch *data() const + { + return &m_data.front(); + } + + //! Gets file data size. + //! \return Size of file data, in characters. + std::size_t size() const + { + return m_data.size(); + } + + private: + + std::vector m_data; // File data + + }; + + //! Counts children of node. Time complexity is O(n). + //! \return Number of children of node + template + inline std::size_t count_children(xml_node *node) + { + xml_node *child = node->first_node(); + std::size_t count = 0; + while (child) + { + ++count; + child = child->next_sibling(); + } + return count; + } + + //! Counts attributes of node. Time complexity is O(n). + //! \return Number of attributes of node + template + inline std::size_t count_attributes(xml_node *node) + { + xml_attribute *attr = node->first_attribute(); + std::size_t count = 0; + while (attr) + { + ++count; + attr = attr->next_attribute(); + } + return count; + } + +} + +#endif From 56048ec0f0bd573785d54c6eaa4a43f8dd757bca Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 11 Dec 2011 11:36:06 +0100 Subject: [PATCH 216/768] Added an RSS feed example. --- libs/network/example/CMakeLists.txt | 10 +++ libs/network/example/rss/main.cpp | 36 +++++++++ libs/network/example/rss/rss.cpp | 75 +++++++++++++++++++ libs/network/example/rss/rss.hpp | 112 ++++++++++++++++++++++++++++ 4 files changed, 233 insertions(+) create mode 100644 libs/network/example/rss/main.cpp create mode 100644 libs/network/example/rss/rss.cpp create mode 100644 libs/network/example/rss/rss.hpp diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 30ce40ae9..0911d85f8 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -11,6 +11,7 @@ endif (OPENSSL_FOUND) add_executable(http_client http_client.cpp) add_executable(simple_wget simple_wget.cpp) add_executable(atom_reader atom/atom.cpp atom/main.cpp) +add_executable(rss_reader rss/rss.cpp rss/main.cpp) add_executable(hello_world_server http/hello_world_server.cpp) if (UNIX) add_executable(fileserver http/fileserver.cpp) @@ -19,6 +20,7 @@ add_executable(uri uri.cpp) add_dependencies(http_client cppnetlib-uri cppnetlib-client-connections) add_dependencies(simple_wget cppnetlib-uri cppnetlib-client-connections) add_dependencies(atom_reader cppnetlib-uri cppnetlib-client-connections) +add_dependencies(rss_reader cppnetlib-uri cppnetlib-client-connections) add_dependencies(uri cppnetlib-uri) set(BOOST_CLIENT_LIBS ${Boost_PROGRAM_OPTIONS_LIBRARY} @@ -51,6 +53,12 @@ target_link_libraries(atom_reader cppnetlib-uri cppnetlib-client-connections) +target_link_libraries(rss_reader + ${BOOST_CLIENT_LIBS} + ${CMAKE_THREAD_LIBS_INIT} + cppnetlib-uri + cppnetlib-client-connections) + target_link_libraries(hello_world_server ${BOOST_SERVER_LIBS} ${CMAKE_THREAD_LIBS_INIT}) @@ -59,6 +67,7 @@ if (OPENSSL_FOUND) target_link_libraries(http_client ${OPENSSL_LIBRARIES}) target_link_libraries(simple_wget ${OPENSSL_LIBRARIES}) target_link_libraries(atom_reader ${OPENSSL_LIBRARIES}) + target_link_libraries(rss_reader ${OPENSSL_LIBRARIES}) target_link_libraries(hello_world_server ${OPENSSL_LIBRARIES}) endif (OPENSSL_FOUND) @@ -74,6 +83,7 @@ target_link_libraries(uri cppnetlib-uri) set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(atom_reader PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(rss_reader PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) if (UNIX) set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) diff --git a/libs/network/example/rss/main.cpp b/libs/network/example/rss/main.cpp new file mode 100644 index 000000000..6fd8691d8 --- /dev/null +++ b/libs/network/example/rss/main.cpp @@ -0,0 +1,36 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include "rss.hpp" +#include +#include + +int main(int argc, char * argv[]) { + using namespace boost::network; + + if (argc != 2) { + std::cout << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + + try { + http::client client; + http::client::request request(argv[1]); + request << header("Connection", "close"); + http::client::response response = client.get(request); + rss::channel channel(response); + + std::cout << "Channel: " << channel.title() << " (" << channel.description() << ")" << std::endl; + BOOST_FOREACH(const rss::item &item, channel) { + std::cout << item.title() << " (" << item.author() << ")" << std::endl; + } + } + catch (std::exception &e) { + std::cerr << e.what() << std::endl; + } + + return 0; +} diff --git a/libs/network/example/rss/rss.cpp b/libs/network/example/rss/rss.cpp new file mode 100644 index 000000000..f4864c1ef --- /dev/null +++ b/libs/network/example/rss/rss.cpp @@ -0,0 +1,75 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include "rss.hpp" +#include "../rapidxml/rapidxml.hpp" +#include +#include + + +namespace boost { +namespace network { +namespace rss { +channel::channel(const http::client::response &response) { + std::string response_body = body(response); + rapidxml::xml_document<> doc; + doc.parse<0>(const_cast(response_body.c_str())); + + rapidxml::xml_node<> *rss = doc.first_node("rss"); + if (!rss) { + throw std::runtime_error("Invalid RSS feed."); + } + + rapidxml::xml_node<> *channel = rss->first_node("channel"); + if (!channel) { + throw std::runtime_error("Invalid RSS channel."); + } + + rapidxml::xml_node<> *title = channel->first_node("title"); + if (title) { + title_ = title->first_node()->value(); + } + + rapidxml::xml_node<> *description = channel->first_node("description"); + if (description) { + description_ = description->first_node()->value(); + } + + rapidxml::xml_node<> *link = channel->first_node("link"); + if (link) { + link_ = link->first_node()->value(); + } + + rapidxml::xml_node<> *author = channel->first_node("author"); + if (author) { + author_ = author->first_node()->value(); + } + + rapidxml::xml_node<> *item = channel->first_node("item"); + while (item) { + items_.push_back(rss::item()); + + rapidxml::xml_node<> *title = item->first_node("title"); + if (title) { + items_.back().set_title(title->first_node()->value()); + } + + rapidxml::xml_node<> *author = item->first_node("author"); + if (author) { + items_.back().set_author(author->first_node()->value()); + } + + rapidxml::xml_node<> *description = item->first_node("description"); + if (description) { + items_.back().set_description(description->first_node()->value()); + } + + item = item->next_sibling(); + } +} +} // namespace rss +} // namespace network +} // namespace boost diff --git a/libs/network/example/rss/rss.hpp b/libs/network/example/rss/rss.hpp new file mode 100644 index 000000000..12acd4ad0 --- /dev/null +++ b/libs/network/example/rss/rss.hpp @@ -0,0 +1,112 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef ___RSS_INC__ +# define ___RSS_INC__ + + +# include +# include +# include + + +namespace boost { +namespace network { +namespace rss { +class item { + +public: + + void set_title(const std::string &title) { + title_ = title; + } + + std::string title() const { + return title_; + } + + void set_author(const std::string &author) { + author_ = author; + } + + std::string author() const { + return author_; + } + + void set_description(const std::string &description) { + description_ = description; + } + + std::string description() const { + return description_; + } + +private: + + std::string title_; + std::string author_; + std::string description_; + +}; + +class channel { + +public: + typedef item value_type; + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + + channel(const http::client::response &response); + + std::string title() const { + return title_; + } + + std::string description() const { + return description_; + } + + std::string link() const { + return link_; + } + + std::string author() const { + return author_; + } + + unsigned int item_count() const { + return items_.size(); + } + + iterator begin() { + return items_.begin(); + } + + iterator end() { + return items_.end(); + } + + const_iterator begin() const { + return items_.begin(); + } + + const_iterator end() const { + return items_.end(); + } + +private: + + std::string title_; + std::string description_; + std::string link_; + std::string author_; + std::vector items_; + +}; +} // namespace rss +} // namespace network +} // namespace boost + +#endif // ___RSS_INC__ From e1183101903eede2808611ae14a2824385240398 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 11 Dec 2011 12:14:09 +0100 Subject: [PATCH 217/768] Cleaned up URI again. --- boost/network/uri/detail/uri_parts.hpp | 19 ++++++++------ boost/network/uri/uri.hpp | 4 +-- libs/network/src/uri/parse.cpp | 34 ++++++++++++++------------ 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/boost/network/uri/detail/uri_parts.hpp b/boost/network/uri/detail/uri_parts.hpp index 985a9ede3..b577b7a3e 100644 --- a/boost/network/uri/detail/uri_parts.hpp +++ b/boost/network/uri/detail/uri_parts.hpp @@ -7,15 +7,15 @@ # define BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ -# include - - namespace boost { namespace network { namespace uri { namespace detail { +template < + class String + > struct hierarchical_part { - std::string user_info, host, port, path; + String user_info, host, port, path; void clear() { user_info.clear(); @@ -25,11 +25,14 @@ struct hierarchical_part { } }; +template < + class String + > struct uri_parts { - std::string scheme; - hierarchical_part hier_part; - std::string query; - std::string fragment; + String scheme; + hierarchical_part hier_part; + String query; + String fragment; void clear() { scheme.clear(); diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index a89bf6afa..82d1ba098 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -22,7 +22,7 @@ namespace uri { namespace detail { bool parse(std::string::const_iterator first, std::string::const_iterator last, - uri_parts &parts); + uri_parts &parts); } // namespace detail @@ -150,7 +150,7 @@ class uri void parse(); string_type uri_; - detail::uri_parts uri_parts_; + detail::uri_parts uri_parts_; bool is_valid_; }; diff --git a/libs/network/src/uri/parse.cpp b/libs/network/src/uri/parse.cpp index bbad450a3..49558f2cd 100644 --- a/libs/network/src/uri/parse.cpp +++ b/libs/network/src/uri/parse.cpp @@ -9,22 +9,24 @@ #include #include -BOOST_FUSION_ADAPT_STRUCT +BOOST_FUSION_ADAPT_TPL_STRUCT ( - boost::network::uri::detail::hierarchical_part, - (std::string, user_info) - (std::string, host) - (std::string, port) - (std::string, path) + (String), + (boost::network::uri::detail::hierarchical_part)(String), + (String, user_info) + (String, host) + (String, port) + (String, path) ); -BOOST_FUSION_ADAPT_STRUCT +BOOST_FUSION_ADAPT_TPL_STRUCT ( - boost::network::uri::detail::uri_parts, - (std::string, scheme) - (boost::network::uri::detail::hierarchical_part, hier_part) - (std::string, query) - (std::string, fragment) + (String), + (boost::network::uri::detail::uri_parts)(String), + (String, scheme) + (boost::network::uri::detail::hierarchical_part, hier_part) + (String, query) + (String, fragment) ); namespace boost { @@ -38,7 +40,7 @@ template < > struct uri_grammar : qi::grammar< typename String::const_iterator - , detail::uri_parts()> { + , detail::uri_parts()> { typedef String string_type; typedef typename String::const_iterator const_iterator; @@ -216,17 +218,17 @@ struct uri_grammar : qi::grammar< qi::rule scheme, user_info, query, fragment; - qi::rule + qi::rule()> hier_part; // actual uri parser - qi::rule start; + qi::rule()> start; }; bool parse(std::string::const_iterator first, std::string::const_iterator last, - uri_parts &parts) { + uri_parts &parts) { namespace qi = boost::spirit::qi; static detail::uri_grammar grammar; bool is_valid = qi::parse(first, last, grammar, parts); From 59791153658bda274af5544482d8772ce766e561 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 11 Dec 2011 14:15:33 +0100 Subject: [PATCH 218/768] Added a simple example that uses the Twitter Search API. --- boost/network/uri/decode.hpp | 7 ++++ boost/network/uri/encode.hpp | 7 ++++ libs/network/doc/uri.rst | 30 +++++++---------- libs/network/example/CMakeLists.txt | 10 ++++++ libs/network/example/atom/main.cpp | 1 + libs/network/example/rss/main.cpp | 1 + libs/network/example/twitter/search.cpp | 45 +++++++++++++++++++++++++ 7 files changed, 83 insertions(+), 18 deletions(-) create mode 100644 libs/network/example/twitter/search.cpp diff --git a/boost/network/uri/decode.hpp b/boost/network/uri/decode.hpp index 7f1441f26..2f950dfad 100644 --- a/boost/network/uri/decode.hpp +++ b/boost/network/uri/decode.hpp @@ -93,6 +93,13 @@ OutputIterator decode(const SinglePassRange &range, const OutputIterator &out) { return decode(boost::begin(range), boost::end(range), out); } + +inline +std::string decoded(const std::string &input) { + std::string decoded; + decode(input, std::back_inserter(decoded)); + return decoded; +} } // namespace uri } // namespace network } // namespace boost diff --git a/boost/network/uri/encode.hpp b/boost/network/uri/encode.hpp index 4c1d2fcee..a68f62658 100644 --- a/boost/network/uri/encode.hpp +++ b/boost/network/uri/encode.hpp @@ -161,6 +161,13 @@ OutputIterator encode(const SinglePassRange &range, const OutputIterator &out) { return encode(boost::begin(range), boost::end(range), out); } + +inline +std::string encoded(const std::string &input) { + std::string encoded; + encode(input, std::back_inserter(encoded)); + return encoded; +} } // namespace uri } // namespace network } // namespace boost diff --git a/libs/network/doc/uri.rst b/libs/network/doc/uri.rst index 257416003..63aa2ace2 100644 --- a/libs/network/doc/uri.rst +++ b/libs/network/doc/uri.rst @@ -1,9 +1,9 @@ -The URI template -================ +The URI class +============= In addition to protocol implementations, the :mod:`cpp-netlib` -provides a powerful URI template. The URI template implements a -parser based on `RFC 3986`_. +provides a powerful URI class. The class implements a parser based +on `RFC 3986`_ and `RFC 2732`_. Generic URI Syntax Overview ``````````````````````````` @@ -60,31 +60,24 @@ elements. Another example, using HTTP is given below: The difference here between the path in a hierarchical URI and that in the example above for the non-hierarchical URI. -``basic_uri`` -````````````` +The ``uri`` class +````````````````` -The ``basic_uri`` definition is consistent with that of -``basic_message``:: - - template - class basic_uri; - -As it stands, the template only supplies a URI parser and no builder. +As of version 0.9.3, ``uri`` supplies a URI parser and builder. To use the parser, it's as simple as supplying a string to the constructor:: - boost::network::uri::uri instance("http://cpp-netlib.github.com/"); + using namespace boost::network; + uri::uri instance("http://cpp-netlib.github.com/"); assert(boost::is_valid(instance)); - std::cout << "scheme: " << boost::network::uri::scheme(instance) << std::endl - << "host: " << boost::network::uri::host(instance) << std::endl; + std::cout << "scheme: " << uri::scheme(instance) << std::endl + << "host: " << uri::host(instance) << std::endl; The command-line output of this program will be:: scheme: http host: cpp-netlib.github.com -A future version of ``basic_uri`` will provide a full builder API. - ``URI Concept`` ``````````````` @@ -127,3 +120,4 @@ A future version of ``basic_uri`` will provide a full builder API. .. _`RFC 3986`: http://tools.ietf.org/html/rfc3986 .. _`RFC 2368`: http://tools.ietf.org/html/rfc2368 .. _`RFC 3513`: http://tools.ietf.org/html/rfc3513 +.. _`RFC 2732`: http://tools.ietf.org/html/rfc2732 diff --git a/libs/network/example/CMakeLists.txt b/libs/network/example/CMakeLists.txt index 0911d85f8..cec93b61d 100644 --- a/libs/network/example/CMakeLists.txt +++ b/libs/network/example/CMakeLists.txt @@ -12,6 +12,7 @@ add_executable(http_client http_client.cpp) add_executable(simple_wget simple_wget.cpp) add_executable(atom_reader atom/atom.cpp atom/main.cpp) add_executable(rss_reader rss/rss.cpp rss/main.cpp) +add_executable(twitter_search twitter/search.cpp) add_executable(hello_world_server http/hello_world_server.cpp) if (UNIX) add_executable(fileserver http/fileserver.cpp) @@ -21,6 +22,7 @@ add_dependencies(http_client cppnetlib-uri cppnetlib-client-connections) add_dependencies(simple_wget cppnetlib-uri cppnetlib-client-connections) add_dependencies(atom_reader cppnetlib-uri cppnetlib-client-connections) add_dependencies(rss_reader cppnetlib-uri cppnetlib-client-connections) +add_dependencies(twitter_search cppnetlib-uri cppnetlib-client-connections) add_dependencies(uri cppnetlib-uri) set(BOOST_CLIENT_LIBS ${Boost_PROGRAM_OPTIONS_LIBRARY} @@ -59,6 +61,12 @@ target_link_libraries(rss_reader cppnetlib-uri cppnetlib-client-connections) +target_link_libraries(twitter_search + ${BOOST_CLIENT_LIBS} + ${CMAKE_THREAD_LIBS_INIT} + cppnetlib-uri + cppnetlib-client-connections) + target_link_libraries(hello_world_server ${BOOST_SERVER_LIBS} ${CMAKE_THREAD_LIBS_INIT}) @@ -68,6 +76,7 @@ if (OPENSSL_FOUND) target_link_libraries(simple_wget ${OPENSSL_LIBRARIES}) target_link_libraries(atom_reader ${OPENSSL_LIBRARIES}) target_link_libraries(rss_reader ${OPENSSL_LIBRARIES}) + target_link_libraries(twitter_search ${OPENSSL_LIBRARIES}) target_link_libraries(hello_world_server ${OPENSSL_LIBRARIES}) endif (OPENSSL_FOUND) @@ -84,6 +93,7 @@ set_target_properties(http_client PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETL set_target_properties(simple_wget PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(atom_reader PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(rss_reader PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) +set_target_properties(twitter_search PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) set_target_properties(hello_world_server PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) if (UNIX) set_target_properties(fileserver PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/example) diff --git a/libs/network/example/atom/main.cpp b/libs/network/example/atom/main.cpp index f4636e979..b419db720 100644 --- a/libs/network/example/atom/main.cpp +++ b/libs/network/example/atom/main.cpp @@ -6,6 +6,7 @@ #include "atom.hpp" #include +#include #include int main(int argc, char * argv[]) { diff --git a/libs/network/example/rss/main.cpp b/libs/network/example/rss/main.cpp index 6fd8691d8..141f7c335 100644 --- a/libs/network/example/rss/main.cpp +++ b/libs/network/example/rss/main.cpp @@ -6,6 +6,7 @@ #include "rss.hpp" #include +#include #include int main(int argc, char * argv[]) { diff --git a/libs/network/example/twitter/search.cpp b/libs/network/example/twitter/search.cpp new file mode 100644 index 000000000..bf80f724c --- /dev/null +++ b/libs/network/example/twitter/search.cpp @@ -0,0 +1,45 @@ +// Copyright (c) Glyn Matthews 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include +#include +#include +#include +#include +#include + +// This example uses the Twitter Search API. +// +// https://dev.twitter.com/docs/using-search + +int main(int argc, char * argv[]) { + using namespace boost::network; + + if (argc != 2) { + std::cout << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + + try { + http::client client; + + uri::uri search_uri("http://search.twitter.com/search.json"); + + std::cout << "Searching Twitter for query: " << argv[1] << std::endl; + uri::uri search_1; + search_1 << search_uri << uri::query("q", uri::encoded(argv[1])); + http::client::request request(search_1.string()); + http::client::response response = client.get(request); + + std::cout << body(response) << std::endl; + } + catch (std::exception &e) { + std::cerr << e.what() << std::endl; + } + + return 0; +} + From 7af0122c5f6495db76bafcf4106c7db5190147fc Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sun, 11 Dec 2011 14:48:23 +0100 Subject: [PATCH 219/768] Minimum version of CMake is 2.8, as advertised in the documentation. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 052e5c2f4..4667f235f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8) project(CPP-NETLIB) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTI_THREADED ON) From b86fa8c79e91bc35b2d7c330723d5efd8dcc0a03 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Tue, 13 Dec 2011 09:43:44 +0100 Subject: [PATCH 220/768] Fixed bug where the parser didn't ignore optional URI parts. --- boost/network/uri/detail/uri_parts.hpp | 28 ++++++++++++++------------ boost/network/uri/uri.hpp | 24 ++++++++++++++++------ libs/network/src/uri/parse.cpp | 12 +++++------ libs/network/test/uri/url_test.cpp | 5 ++++- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/boost/network/uri/detail/uri_parts.hpp b/boost/network/uri/detail/uri_parts.hpp index b577b7a3e..f23efa45d 100644 --- a/boost/network/uri/detail/uri_parts.hpp +++ b/boost/network/uri/detail/uri_parts.hpp @@ -7,6 +7,9 @@ # define BOOST_NETWORK_URL_DETAIL_URL_PARTS_HPP_ +# include + + namespace boost { namespace network { namespace uri { @@ -15,14 +18,10 @@ template < class String > struct hierarchical_part { - String user_info, host, port, path; - - void clear() { - user_info.clear(); - host.clear(); - port.clear(); - path.clear(); - } + boost::optional user_info; + boost::optional host; + boost::optional port; + boost::optional path; }; template < @@ -31,14 +30,17 @@ template < struct uri_parts { String scheme; hierarchical_part hier_part; - String query; - String fragment; + boost::optional query; + boost::optional fragment; void clear() { scheme.clear(); - hier_part.clear(); - query.clear(); - fragment.clear(); + hier_part.user_info = boost::optional(); + hier_part.host = boost::optional(); + hier_part.port = boost::optional(); + hier_part.path = boost::optional(); + query = boost::optional(); + fragment = boost::optional(); } }; } // namespace detail diff --git a/boost/network/uri/uri.hpp b/boost/network/uri/uri.hpp index 82d1ba098..fcebbbebf 100644 --- a/boost/network/uri/uri.hpp +++ b/boost/network/uri/uri.hpp @@ -101,27 +101,39 @@ class uri } string_type user_info() const { - return uri_parts_.hier_part.user_info; + return uri_parts_.hier_part.user_info? + uri_parts_.hier_part.user_info.get() : + string_type(); } string_type host() const { - return uri_parts_.hier_part.host; + return uri_parts_.hier_part.host? + uri_parts_.hier_part.host.get() : + string_type(); } string_type port() const { - return uri_parts_.hier_part.port; + return uri_parts_.hier_part.port? + uri_parts_.hier_part.port.get() : + string_type(); } string_type path() const { - return uri_parts_.hier_part.path; + return uri_parts_.hier_part.path? + uri_parts_.hier_part.path.get() : + string_type(); } string_type query() const { - return uri_parts_.query; + return uri_parts_.query ? + uri_parts_.query.get() : + string_type(); } string_type fragment() const { - return uri_parts_.fragment; + return uri_parts_.fragment? + uri_parts_.fragment.get() : + string_type(); } string_type string() const { diff --git a/libs/network/src/uri/parse.cpp b/libs/network/src/uri/parse.cpp index 49558f2cd..d33f864b5 100644 --- a/libs/network/src/uri/parse.cpp +++ b/libs/network/src/uri/parse.cpp @@ -13,10 +13,10 @@ BOOST_FUSION_ADAPT_TPL_STRUCT ( (String), (boost::network::uri::detail::hierarchical_part)(String), - (String, user_info) - (String, host) - (String, port) - (String, path) + (boost::optional, user_info) + (boost::optional, host) + (boost::optional, port) + (boost::optional, path) ); BOOST_FUSION_ADAPT_TPL_STRUCT @@ -25,8 +25,8 @@ BOOST_FUSION_ADAPT_TPL_STRUCT (boost::network::uri::detail::uri_parts)(String), (String, scheme) (boost::network::uri::detail::hierarchical_part, hier_part) - (String, query) - (String, fragment) + (boost::optional, query) + (boost::optional, fragment) ); namespace boost { diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index fdca7014f..05748870d 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -44,8 +44,12 @@ BOOST_AUTO_TEST_CASE(basic_uri_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); BOOST_CHECK_EQUAL(uri::scheme(instance), "http"); + BOOST_CHECK_EQUAL(uri::user_info(instance), ""); BOOST_CHECK_EQUAL(uri::host(instance), "www.example.com"); + BOOST_CHECK_EQUAL(uri::port(instance), ""); BOOST_CHECK_EQUAL(uri::path(instance), "/"); + BOOST_CHECK_EQUAL(uri::query(instance), ""); + BOOST_CHECK_EQUAL(uri::fragment(instance), ""); } BOOST_AUTO_TEST_CASE(full_uri_test) { @@ -164,7 +168,6 @@ BOOST_AUTO_TEST_CASE(username_test) { BOOST_AUTO_TEST_CASE(authority_test) { uri::uri instance("http://user:password@www.example.com/path?query#fragment"); BOOST_REQUIRE(uri::valid(instance)); - std::cout << uri::authority(instance) << std::endl; BOOST_CHECK_EQUAL(uri::authority(instance), "user:password@www.example.com:80"); } From 8cb6c999ae7c0f92ef18a16bf74a5655eb6081e2 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Tue, 13 Dec 2011 19:50:05 +0100 Subject: [PATCH 221/768] Added uri constructor to http::request. --- boost/network/protocol/http/impl/request.hpp | 8 ++++++++ libs/network/example/twitter/search.cpp | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/boost/network/protocol/http/impl/request.hpp b/boost/network/protocol/http/impl/request.hpp index b777e8b4d..5ba92d6c1 100644 --- a/boost/network/protocol/http/impl/request.hpp +++ b/boost/network/protocol/http/impl/request.hpp @@ -63,10 +63,18 @@ namespace http { : uri_(uri_) { } + explicit basic_request(boost::network::uri::uri const & uri_) + : uri_(uri_) + { } + void uri(string_type const & new_uri) { uri_ = new_uri; } + void uri(boost::network::uri::uri const & new_uri) { + uri_ = new_uri; + } + basic_request() : base_type() { } diff --git a/libs/network/example/twitter/search.cpp b/libs/network/example/twitter/search.cpp index bf80f724c..010fc7ee7 100644 --- a/libs/network/example/twitter/search.cpp +++ b/libs/network/example/twitter/search.cpp @@ -31,7 +31,7 @@ int main(int argc, char * argv[]) { std::cout << "Searching Twitter for query: " << argv[1] << std::endl; uri::uri search_1; search_1 << search_uri << uri::query("q", uri::encoded(argv[1])); - http::client::request request(search_1.string()); + http::client::request request(search_1); http::client::response response = client.get(request); std::cout << body(response) << std::endl; From b040182a561556683ba1c4c0adf2341c496c1c5b Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Tue, 13 Dec 2011 22:10:59 +0100 Subject: [PATCH 222/768] Cleaning. --- libs/network/test/http/CMakeLists.txt | 51 --------------------------- libs/network/test/uri/url_test.cpp | 24 ------------- 2 files changed, 75 deletions(-) diff --git a/libs/network/test/http/CMakeLists.txt b/libs/network/test/http/CMakeLists.txt index b06a2a12a..88ac4ed45 100644 --- a/libs/network/test/http/CMakeLists.txt +++ b/libs/network/test/http/CMakeLists.txt @@ -5,7 +5,6 @@ # http://www.boost.org/LICENSE_1_0.txt) include_directories(${CPP-NETLIB_SOURCE_DIR}) -find_package( PythonInterp ) if (OPENSSL_FOUND) include_directories( ${OPENSSL_INCLUDE_DIR} ) @@ -60,54 +59,4 @@ if (Boost_FOUND) ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}) endforeach (test) - # if ( PYTHONINTERP_FOUND ) - # set ( SERVER_TESTS - # server_hello_world - # server_async - # server_async_less_copy - # ) - # set ( PORT 8000 ) - # foreach ( test ${SERVER_TESTS} ) - # if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) - # set_source_files_properties(${test}.cpp - # PROPERTIES COMPILE_FLAGS "-Wall") - # endif() - # add_executable(cpp-netlib-http-${test} ${test}.cpp) - # add_dependencies(cpp-netlib-http-${test} cppnetlib-server-parsers) - # target_link_libraries(cpp-netlib-http-${test} ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} cppnetlib-server-parsers) - # set_target_properties(cpp-netlib-http-${test} - # PROPERTIES RUNTIME_OUTPUT_DIRECTORY - # ${CPP-NETLIB_BINARY_DIR}/tests) - # add_test(cpp-netlib-${test} - # ${PYTHON_EXECUTABLE} - # ${CPP-NETLIB_SOURCE_DIR}/libs/network/test/httplib_acceptance.py - # ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test} - # ${PORT} - # ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-${test}.passed) - # math (EXPR PORT "${PORT} + 1") - # endforeach (test) - # #else() - # # message(STATUS "Python not found, won't run server tests." - # endif( PYTHONINTERP_FOUND ) - - #set ( INLINED_TESTS - # client_include_inlined - # server_include_inlined - # ) - #foreach ( test ${INLINED_TESTS} ) - # if (${CMAKE_CXX_COMPILER_ID} MATCHES GNU) - # set_source_files_properties(${test}.cpp - # PROPERTIES COMPILE_FLAGS "-Wall") - # endif() - # add_executable(cpp-netlib-http-inlined-${test} ${test}.cpp) - # target_link_libraries(cpp-netlib-http-inlined-${test} ${BOOST_LIBS} ${CMAKE_THREAD_LIBS_INIT}) - # if (OPENSSL_FOUND) - # target_link_libraries(cpp-netlib-http-inlined-${test} ${OPENSSL_LIBRARIES}) - # endif() - # set_target_properties(cpp-netlib-http-inlined-${test} - # PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CPP-NETLIB_BINARY_DIR}/tests) - # add_test(cpp-netlib-http-inlined-${test} - # ${CPP-NETLIB_BINARY_DIR}/tests/cpp-netlib-http-inlined-${test}) - #endforeach (test) - endif() diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index 05748870d..dae9589c4 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -16,30 +16,6 @@ using namespace boost::network; -//BOOST_AUTO_TEST_CASE(basic_uri_range_test) { -// uri::uri instance("http://www.example.com/"); -// BOOST_REQUIRE(uri::valid(instance)); -// BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); -// BOOST_CHECK(boost::empty(instance.user_info_range())); -// BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); -// BOOST_CHECK(boost::empty(instance.port_range())); -// BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/"))); -// BOOST_CHECK(boost::empty(instance.query_range())); -// BOOST_CHECK(boost::empty(instance.fragment_range())); -//} -// -//BOOST_AUTO_TEST_CASE(full_uri_range_test) { -// uri::uri instance("http://user:password@www.example.com/path?query#fragment"); -// BOOST_REQUIRE(uri::valid(instance)); -// BOOST_CHECK(boost::equal(instance.scheme_range(), boost::as_literal("http"))); -// BOOST_CHECK(boost::equal(instance.user_info_range(), boost::as_literal("user:password"))); -// BOOST_CHECK(boost::equal(instance.host_range(), boost::as_literal("www.example.com"))); -// BOOST_CHECK(boost::equal(instance.port_range(), boost::as_literal("80"))); -// BOOST_CHECK(boost::equal(instance.path_range(), boost::as_literal("/path"))); -// BOOST_CHECK(boost::equal(instance.query_range(), boost::as_literal("query"))); -// BOOST_CHECK(boost::equal(instance.fragment_range(), boost::as_literal("fragment"))); -//} - BOOST_AUTO_TEST_CASE(basic_uri_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); From dfc95a64bd754f2170bc761e649de1afce7427e7 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Wed, 14 Dec 2011 19:57:31 +0100 Subject: [PATCH 223/768] Updated Jamfile scripts. --- libs/network/build/Jamfile.v2 | 6 +++--- libs/network/example/Jamfile.v2 | 15 ++++++++++----- libs/network/test/Jamfile.v2 | 9 +++++---- libs/network/test/http/Jamfile.v2 | 17 ++++++++--------- libs/network/test/uri/Jamfile.v2 | 17 +++++++++++++++++ 5 files changed, 43 insertions(+), 21 deletions(-) create mode 100644 libs/network/test/uri/Jamfile.v2 diff --git a/libs/network/build/Jamfile.v2 b/libs/network/build/Jamfile.v2 index f0fd0af91..2d1a33b89 100644 --- a/libs/network/build/Jamfile.v2 +++ b/libs/network/build/Jamfile.v2 @@ -18,13 +18,13 @@ project cpp-netlib : cpp-pch client : boost/network/include/http/client.hpp ; cpp-pch server : boost/network/include/http/server.hpp ; -lib cppnetlib-uri : libs/network/src/parse_uri_impl.cpp ; +lib cppnetlib-uri : libs/network/src/uri/parse.cpp ; lib cppnetlib-server-parsers : libs/network/src/server_request_parsers_impl.cpp ; +lib cppnetlib-client-connections : libs/network/src/client.cpp ; install headers : client server : ../../../boost/network/include/http ; -install libraries : cppnetlib-uri cppnetlib-server-parsers ; +install libraries : cppnetlib-uri cppnetlib-server-parsers cppnetlib-client-connections ; alias all : headers ; - diff --git a/libs/network/example/Jamfile.v2 b/libs/network/example/Jamfile.v2 index df6ebde7c..5bca45589 100644 --- a/libs/network/example/Jamfile.v2 +++ b/libs/network/example/Jamfile.v2 @@ -21,13 +21,19 @@ project network_test : debug:BOOST_NETWORK_DEBUG ; -exe http_client : http_client.cpp /cpp-netlib//cppnetlib-uri ; +exe uri : uri.cpp /cpp-netlib//cppnetlib-uri ; -# exe dispatch_table : dispatch_table.cpp ; +exe http_client : http_client.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; -exe uri : uri.cpp /cpp-netlib//cppnetlib-uri ; +exe http_client1 : http_client1.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; + +exe simple_wget : simple_wget.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; -exe simple_wget : simple_wget.cpp /cpp-netlib//cppnetlib-uri ; +exe atom_reader : atom/main.cpp atom/atom.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; + +exe rss_reader : rss/main.cpp rss/rss.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; + +exe twitter_search : twitter/search.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; exe hello_world_server : http/hello_world_server.cpp /cpp-netlib//cppnetlib-server-parsers ; @@ -36,4 +42,3 @@ exe hello_world_client : http/hello_world_client.cpp /cpp-netlib//cppnetlib-uri exe one_liner : http/one_liner.cpp /cpp-netlib//cppnetlib-uri ; exe fileserver : http/fileserver.cpp /cpp-netlib//cppnetlib-server-parsers ; - diff --git a/libs/network/test/Jamfile.v2 b/libs/network/test/Jamfile.v2 index c04d04fbe..3375ac148 100644 --- a/libs/network/test/Jamfile.v2 +++ b/libs/network/test/Jamfile.v2 @@ -23,14 +23,16 @@ project network_test : /boost//regex /boost//thread /boost//filesystem - BOOST_NETWORK_ENABLE_HTTPS debug:BOOST_NETWORK_DEBUG + gcc:BOOST_NETWORK_ENABLE_HTTPS gcc:-lpthread gcc:-lssl gcc:-lcrypto + darwin:BOOST_NETWORK_ENABLE_HTTPS darwin:-lpthread darwin:-lssl darwin:-lcrypto + clang:BOOST_NETWORK_ENABLE_HTTPS clang:-lpthread clang:-lssl clang:-lcrypto @@ -41,14 +43,13 @@ project network_test : msvc:BOOST_ASIO_NO_WIN32_LEAN_AND_MEAN msvc:WIN32_LEAN_AND_MEAN msvc:_SCL_SECURE_NO_WARNINGS + msvc:_WIN32_WINNT=0x0501 256 static ; build-project http ; +build-project uri ; run message_test.cpp ; run message_transform_test.cpp ; -run url_test.cpp /cpp-netlib//cppnetlib-uri ; -run client_server_include_failure.cpp ; - diff --git a/libs/network/test/http/Jamfile.v2 b/libs/network/test/http/Jamfile.v2 index c5f317858..9f587c50b 100644 --- a/libs/network/test/http/Jamfile.v2 +++ b/libs/network/test/http/Jamfile.v2 @@ -15,21 +15,20 @@ project network_test/http : debug:BOOST_NETWORK_DEBUG ; -run client_constructor_test.cpp /cpp-netlib//cppnetlib-uri ; -run client_get_test.cpp /cpp-netlib//cppnetlib-uri ; -run client_get_different_port_test.cpp /cpp-netlib//cppnetlib-uri ; -run client_get_timeout_test.cpp /cpp-netlib//cppnetlib-uri ; -run client_include_inlined.cpp : BOOST_NETWORK_NO_LIB ; -run client_localhost_normal_test.cpp /cpp-netlib//cppnetlib-uri ; -run client_localhost_ssl_test.cpp /cpp-netlib//cppnetlib-uri ; +run client_constructor_test.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; +run client_get_test.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; +run client_get_different_port_test.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; +run client_get_timeout_test.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; +#run client_include_inlined.cpp : BOOST_NETWORK_NO_LIB ; +run client_localhost_normal_test.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; +run client_localhost_ssl_test.cpp /cpp-netlib//cppnetlib-uri /cpp-netlib//cppnetlib-client-connections ; run message_async_ready_test.cpp ; run message_test.cpp /cpp-netlib//cppnetlib-uri ; run request_incremental_parser_test.cpp ; run request_linearize_test.cpp /cpp-netlib//cppnetlib-uri ; run response_incremental_parser_test.cpp /cpp-netlib//cppnetlib-server-parsers ; run server_constructor_test.cpp /cpp-netlib//cppnetlib-server-parsers ; -run server_include_inlined.cpp : BOOST_NETWORK_NO_LIB ; -run url_test.cpp /cpp-netlib//cppnetlib-uri ; +#run server_include_inlined.cpp : BOOST_NETWORK_NO_LIB ; exe http_async_server : server_async.cpp /cpp-netlib//cppnetlib-server-parsers ; exe hello_world : server_hello_world.cpp /cpp-netlib//cppnetlib-server-parsers ; diff --git a/libs/network/test/uri/Jamfile.v2 b/libs/network/test/uri/Jamfile.v2 new file mode 100644 index 000000000..aacbd1ac6 --- /dev/null +++ b/libs/network/test/uri/Jamfile.v2 @@ -0,0 +1,17 @@ + +# Copyright Glyn Matthews 2011. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import testing ; + +project network_test/uri : + requirements + ../../../../ + ../ + ; + +run url_test.cpp /cpp-netlib//cppnetlib-uri ; +run url_builder_test.cpp /cpp-netlib//cppnetlib-uri ; +run url_encoding_test.cpp /cpp-netlib//cppnetlib-uri ; From e113adc150112de3d61a07829961019dfc005533 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Wed, 14 Dec 2011 21:41:47 +0100 Subject: [PATCH 224/768] Updating the documentation. --- README.rst | 69 ++++++-------- libs/network/doc/CMakeLists.txt | 9 -- libs/network/doc/atom_reader.rst | 15 +++ libs/network/doc/conf.py | 4 +- libs/network/doc/examples.rst | 4 +- libs/network/doc/examples_http.rst | 4 + libs/network/doc/http.rst | 39 +------- libs/network/doc/http_client.rst | 31 ++----- libs/network/doc/http_client_tags.rst | 43 --------- libs/network/doc/rss_reader.rst | 15 +++ libs/network/doc/simple_wget.rst | 123 +++++++++++++++++++++++++ libs/network/doc/static/background.jpg | Bin 787242 -> 0 bytes libs/network/doc/uri.rst | 11 +-- libs/network/doc/whats_new.rst | 23 ++++- libs/network/example/simple_wget.cpp | 2 +- 15 files changed, 228 insertions(+), 164 deletions(-) delete mode 100644 libs/network/doc/CMakeLists.txt create mode 100644 libs/network/doc/atom_reader.rst delete mode 100644 libs/network/doc/http_client_tags.rst create mode 100644 libs/network/doc/rss_reader.rst create mode 100644 libs/network/doc/simple_wget.rst delete mode 100644 libs/network/doc/static/background.jpg diff --git a/README.rst b/README.rst index 02792cb30..d07b4cb3d 100644 --- a/README.rst +++ b/README.rst @@ -15,8 +15,8 @@ cpp-netlib offers the following implementations: generate message objects from strings. * Adapters and Wrappers -- A collection of Adapters and wrappers aimed towards making the message type STL friendly. - * Network protocol client and server implementations -- A collection - of network protocol implementations that include embeddable client + * Network protocol client and server implementations -- A collection + of network protocol implementations that include embeddable client and server types. This library is released under the Boost Software License (please see @@ -47,30 +47,15 @@ The recommended installation procedure would be to follow the steps below:: $ sudo mkdir -p /usr/local/include/cpp-netlib $ sudo cp -r cpp-netlib/boost /usr/local/include/cpp-netlib -Now don't forget to add ``/usr/local/include/cpp-netlib`` in your project's -compiler include directories to start using cpp-netlib in your projects. - -Running Tests -------------- - -If you want to run the tests that come with cpp-netlib, there are a few things -you will need. These are: - - * A compiler (GCC 4.x or Clang 2.8) - * A build tool (CMake [#]_ recommended, Boost.Build also an option) - * OpenSSL headers (optional with CMake, mandatory for Boost.Build) - * Python 2.6 - -.. note:: This assumes that you have the cpp-netlib distribution package - unpacked somwhere in your home directory. This specifically assumes that you - have cpp-netlib at the toplevel of your home directory. -.. [#] http://www.cmake.org/ +Don't forget to add ``/usr/local/include/cpp-netlib`` in your project's +compiler include directories to start using cpp-netlib. Building with CMake ~~~~~~~~~~~~~~~~~~~ -To build and run the tests with CMake, you will need to have CMake version 2.8 -or higher installed appropriately in your system. +To build the libraries and run the tests with CMake, you will need to +have CMake version 2.8 or higher installed appropriately in your +system. :: @@ -81,16 +66,11 @@ Inside the cpp-netlib directory, you can issue the following statements to configure and generate the Makefiles, and build the tests:: $ cd ~/cpp-netlib # we're assuming it's where cpp-netlib is - $ cmake -DCMAKE_BUILD_TYPE=Debug \ - > -CMAKE_C_COMPILER=clang \ - > -CMAKE_CXX_COMPILER=clang++ \ + $ cmake -DCMAKE_BUILD_TYPE=Debug \ + > -DCMAKE_C_COMPILER=clang \ + > -DCMAKE_CXX_COMPILER=clang++ \ > . -.. note:: This uses the source directory as the build directory as well. At the - time of this writing, cpp-netlib is meant to be tested in the same directory - where the source files are, because of the way the tests depend on Python - being installed and having access to Python scripts during the build. - Once CMake is done with generating the Makefiles and configuring the project, you can now build the tests and run them:: @@ -102,7 +82,7 @@ If for some reason some of the tests fail, you can send the files in ``Testing/Temporary/`` as attachments to the cpp-netlib `developers mailing list`_. -.. _`developers mailing list`: https://lists.sourceforge.net/lists/listinfo/cpp-netlib-devel +.. _`developers mailing list`: cpp-netlib@googlegroups.com Building with Boost.Build ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -113,7 +93,7 @@ to copy the ``bjam`` executable to a directory that is already in your ``PATH`` so that you don't have to go hunting for it all the time. A good place to put it is in ``/usr/local/bin``. -.. [#] http://www.boost.org/doc/libs/1_44_0/more/getting_started/index.html +.. [#] http://www.boost.org/doc/libs/release/more/getting_started/ Building and running the tests can be as simple as doing the following:: @@ -130,7 +110,22 @@ please do the following:: And then attach the ``build-test.log`` file to the email you will send to the cpp-netlib `developers mailing list`_. -.. _`developers mailing list`: https://lists.sourceforge.net/lists/listinfo/cpp-netlib-devel +.. _`developers mailing list`: cpp-netlib@googlegroups.com + +Running Tests +------------- + +If you want to run the tests that come with cpp-netlib, there are a few things +you will need. These are: + + * A compiler (GCC 4.x, Clang 2.8, MSVC 2008) + * A build tool (CMake [#]_ recommended, Boost.Build also an option) + * OpenSSL headers (optional) + +.. note:: This assumes that you have the cpp-netlib distribution package + unpacked somwhere in your home directory. This specifically assumes that you + have cpp-netlib at the toplevel of your home directory. +.. [#] http://www.cmake.org/ Hacking on cpp-netlib --------------------- @@ -174,14 +169,10 @@ In case you have any questions or would like to make feature requests, you can contact the development team through the `developers mailing list`_ or by filing issues at http://github.com/cpp-netlib/cpp-netlib/issues. -.. _`developers mailing list`: - https://lists.sourceforge.net/lists/listinfo/cpp-netlib-devel +.. _`developers mailing list`: cpp-netlib@googlegroups.com You can reach the maintainers of the project through:: Dean Michael Berris (dberris@google.com) - Glyn Matthews - - Mike Dickey - + Glyn Matthews (glyn.matthews@gmail.com) diff --git a/libs/network/doc/CMakeLists.txt b/libs/network/doc/CMakeLists.txt deleted file mode 100644 index 0f6579a80..000000000 --- a/libs/network/doc/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) Glyn Matthews 2010. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - - - -# find "sphinxtogithub" -# generate conf.py using release, sphinxtogithub, todo, style, theme \ No newline at end of file diff --git a/libs/network/doc/atom_reader.rst b/libs/network/doc/atom_reader.rst new file mode 100644 index 000000000..67edc3bc6 --- /dev/null +++ b/libs/network/doc/atom_reader.rst @@ -0,0 +1,15 @@ +.. _atom_reader: + +************* + Atom reader +************* + +The Code +======== + + +Building and Running The Code +============================= + +Diving into the Code +==================== diff --git a/libs/network/doc/conf.py b/libs/network/doc/conf.py index 9af3b219e..4ddb10aa9 100644 --- a/libs/network/doc/conf.py +++ b/libs/network/doc/conf.py @@ -61,7 +61,7 @@ # The short X.Y version. version = '0.9' # The full version, including alpha/beta/rc tags. -release = '0.9' +release = '0.9.3' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -74,7 +74,7 @@ #today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. -unused_docs = [ 'http_client_tags.rst' ] +unused_docs = [ '' ] # List of directories, relative to source directory, that shouldn't be searched # for source files. diff --git a/libs/network/doc/examples.rst b/libs/network/doc/examples.rst index f1cfbd7b8..bbc06282b 100644 --- a/libs/network/doc/examples.rst +++ b/libs/network/doc/examples.rst @@ -5,10 +5,10 @@ The :mod:`cpp-netlib` is a practical library that is designed to aid the development of applications for that need to communicate using common networking protocols. The following set of examples describe a series of realistic examples that use the :mod:`cpp-netlib` for these -kinds of application. +kinds of application. All examples are built using CMake. .. toctree:: :maxdepth: 2 examples_http.rst -.. examples_xmpp.rst + diff --git a/libs/network/doc/examples_http.rst b/libs/network/doc/examples_http.rst index ace423ab1..53aae22f9 100644 --- a/libs/network/doc/examples_http.rst +++ b/libs/network/doc/examples_http.rst @@ -11,3 +11,7 @@ embedded into larger applications. http_client.rst hello_world_server.rst hello_world_client.rst + simple_wget.rst + atom_reader.rst + rss_reader.rst + twitter_search.rst diff --git a/libs/network/doc/http.rst b/libs/network/doc/http.rst index a3f808815..65424bb3f 100644 --- a/libs/network/doc/http.rst +++ b/libs/network/doc/http.rst @@ -99,7 +99,7 @@ returns, in the default case, a multimap of strings to strings: response_headers headers_ = headers(response); for (iterator it = headers_.begin(); it != headers_.end(); ++it) { std::cout << it->first << ": " << it->second << std::endl; - } + } std::cout << std::endl; @@ -145,9 +145,9 @@ implementation while the user-visible implementation is the namespace boost { namespace network { namespace http { template - class server : + class server : public basic_server {}; - + }}} To use the forwarding server type you just supply the request handler @@ -178,36 +178,3 @@ Here, all we're doing is returning the original request body with an HTTP OK response (200). We are also printing the IP address from where the request came from. Notice that we are using a wrapper to access the source of the request. - -HTTP URI -```````` - -:mod:`cpp-netlib` provides a specialization and ``typedef`` for an -HTTP URI: - -.. code-block:: c++ - - namespace http { - template class basic_uri; - typedef basic_uri uri; - } - -``basic_uri`` provides a parser which breaks down a URI string passed -to it's constructor into different parts. - -.. code-block:: c++ - - using namespace boost::network::uri; - http::uri uri_("http://www.boost.org/"); - assert(valid(uri_)); - assert(scheme(uri_) == "http"); - assert(host(uri_) == "www.boost.org") - assert(port(uri_) == 80) - assert(path(uri_) == "/"); - -The syntax of the HTTP URI are defined in RFC 1738 section 3.3 [#]_ -and the default URI provided with cpp-netlib conforms to this. In -such a way, specializations that conform to any URI scheme can be -provided. - -.. [#] http://tools.ietf.org/html/rfc1738 diff --git a/libs/network/doc/http_client.rst b/libs/network/doc/http_client.rst index 3041239d9..6e254c66a 100644 --- a/libs/network/doc/http_client.rst +++ b/libs/network/doc/http_client.rst @@ -7,10 +7,10 @@ The first code example is the simplest thing you can do with the :mod:`cpp-netlib`. The application is a simple HTTP client, which can be found in the subdirectory ``libs/network/example/http_client.cpp``. -All we are doing is creating and sending an HTTP request to a server -and printing the response body. +All this example doing is creating and sending an HTTP request to a server +and printing the response body. -The Code +The code ======== Without further ado, the code to do this is as follows: @@ -19,37 +19,26 @@ Without further ado, the code to do this is as follows: #include #include - + int main(int argc, char *argv[]) { using namespace boost::network; - + if (argc != 2) { std::cout << "Usage: " << argv[0] << " [url]" << std::endl; return 1; } - + http::client client; http::client::request request(argv[1]); request << header("Connection", "close"); http::client::response response = client.get(request); std::cout << body(response) << std::endl; - + return 0; } -Building and Running The Code -============================= - -To be build this example, you can follow the steps below without having to build -the whole :mod:`cpp-netlib` distribution:: - - $ cd ~/cpp-netlib - $ g++ -o http_client1 libs/network/example/http_client1.cpp \ - > -I. \ - > -I$BOOST_ROOT \ - > -L$BOOST_ROOT/stage/lib \ - > -lboost_system \ - > -pthread +Running the example +=================== You can then run this to get the Boost_ website:: @@ -57,7 +46,7 @@ You can then run this to get the Boost_ website:: .. _Boost: http://www.boost.org/ -Diving into the Code +Diving into the code ==================== Since this is the first example, each line will be presented and diff --git a/libs/network/doc/http_client_tags.rst b/libs/network/doc/http_client_tags.rst deleted file mode 100644 index 86a56cff7..000000000 --- a/libs/network/doc/http_client_tags.rst +++ /dev/null @@ -1,43 +0,0 @@ - -+---------------------------------+---------------------------------------------+ -| Tag | Description | -+=================================+=============================================+ -| http_default_8bit_tcp_resolve | This is the default HTTP implementation tag | -| | that resolves addresses with a TCP resolver | -| | and provides a synchronous/blocking HTTP | -| | client interface. | -+---------------------------------+---------------------------------------------+ -| http_default_8bit_udp_resolve | This is similar to the above tag except that| -| | it specifies the HTTP client to use a UDP | -| | resolver. It also provides a synchronous/ | -| | blocking HTTP client interface. | -+---------------------------------+---------------------------------------------+ -| http_keepalive_8bit_tcp_resolve | This tag specifies that the HTTP client by | -| | default will keep connections to the server | -| | alive. It only makes sense if the | -| | ``version_major`` and ``version_minor`` are | -| | both ``1``, to indicate HTTP 1.1. This tag | -| | causes the HTTP client to resolve using a | -| | TCP resolver and provides a synchronous/ | -| | blocking HTTP client interface. | -+---------------------------------+---------------------------------------------+ -| http_keepalive_8bit_udp_resolve | This is similar to the above tag except that| -| | it specifies the HTTP client to use a UDP | -| | resolver. It also provides a synchronous/ | -| | blocking HTTP client interface. | -+---------------------------------+---------------------------------------------+ -| http_async_8bit_tcp_resolve | This tag provides an active HTTP client | -| | object implementation that uses a TCP | -| | resolver. Response objects returned will | -| | encapsulate a number of Boost.Thread_ | -| | shared futures to hold values. Users don't | -| | have to see this as they are implementation | -| | details. | -+---------------------------------+---------------------------------------------+ -| http_async_8bit_udp_resolve | This is similar to the above tag except that| -| | specifies the HTTP client to use a UDP | -| | resolver. | -+---------------------------------+---------------------------------------------+ - -.. _Boost.Thread: http://www.boost.org/libs/thread - diff --git a/libs/network/doc/rss_reader.rst b/libs/network/doc/rss_reader.rst new file mode 100644 index 000000000..334c50f2a --- /dev/null +++ b/libs/network/doc/rss_reader.rst @@ -0,0 +1,15 @@ +.. _rss_reader: + +************ + RSS reader +************ + +The Code +======== + + +Building and Running The Code +============================= + +Diving into the Code +==================== diff --git a/libs/network/doc/simple_wget.rst b/libs/network/doc/simple_wget.rst new file mode 100644 index 000000000..beb125fa5 --- /dev/null +++ b/libs/network/doc/simple_wget.rst @@ -0,0 +1,123 @@ +.. _simple_wget: + +*************** + Simple `wget` +*************** + +The first code example is the simplest thing you can do with the +:mod:`cpp-netlib`. The application is a simple HTTP client, which can +be found in the subdirectory ``libs/network/example/http_client.cpp``. +All we are doing is creating and sending an HTTP request to a server +and printing the response body. + +The code +======== + +Without further ado, the code to do this is as follows: + +.. code-block:: c++ + + #include + #include + + int main(int argc, char *argv[]) { + using namespace boost::network; + + if (argc != 2) { + std::cout << "Usage: " << argv[0] << " [url]" << std::endl; + return 1; + } + + http::client client; + http::client::request request(argv[1]); + request << header("Connection", "close"); + http::client::response response = client.get(request); + std::cout << body(response) << std::endl; + + return 0; + } + +Building and Running The Code +============================= + +To be build this example, you can follow the steps below without having to build +the whole :mod:`cpp-netlib` distribution:: + + $ cd ~/cpp-netlib + $ g++ -o http_client1 libs/network/example/http_client1.cpp \ + > -I. \ + > -I$BOOST_ROOT \ + > -L$BOOST_ROOT/stage/lib \ + > -lboost_system \ + > -pthread + +You can then run this to get the Boost_ website:: + + $ ./http_client1 http://www.boost.org/ + +.. _Boost: http://www.boost.org/ + +Diving into the Code +==================== + +Since this is the first example, each line will be presented and +explained in detail. + +.. code-block:: c++ + + #include + +All the code needed for the HTTP client resides in this header. + +.. code-block:: c++ + + http::client client; + +First we create a ``client`` object. The ``client`` abstracts all the +connection and protocol logic. The default HTTP client is version +1.1, as specified in `RFC 2616`_. + +.. code-block:: c++ + + http::client::request request(argv[1]); + +Next, we create a ``request`` object, with a URI string passed as a +constructor argument. + +.. code-block:: c++ + + request << header("Connection", "close"); + +:mod:`cpp-netlib` makes use of stream syntax and *directives* to allow +developers to build complex message structures with greater +flexibility and clarity. Here, we add the HTTP header "Connection: +close" to the request in order to signal that the connection will be +closed after the request has completed. + +.. code-block:: c++ + + http::client::response response = client.get(request); + +Once we've built the request, we then make an HTTP GET request +throught the ``http::client`` from which an ``http::response`` is +returned. ``http::client`` supports all common HTTP methods: GET, +POST, HEAD, DELETE. + +.. code-block:: c++ + + std::cout << body(response) << std::endl; + +Finally, though we don't do any error checking, the response body is +printed to the console using the ``body`` directive. + +That's all there is to the HTTP client. In fact, it's possible to +compress this to a single line: + +.. code-block:: c++ + + std::cout << body(http::client().get(http::request("http://www.boost.org/"))); + +Next we'll develop a simple client/server application using +``http::server`` and ``http::client``. + +.. _`RFC 2616`: http://www.w3.org/Protocols/rfc2616/rfc2616.html diff --git a/libs/network/doc/static/background.jpg b/libs/network/doc/static/background.jpg deleted file mode 100644 index fc7edde076049b492166895a5d8b4428e3ae9486..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 787242 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 x=w3@Ej!B?vRAbXA_Q z1P-~WN(+%~5RWJU@zO*PVem#ERt9ls)?F~40@)~VUpjPZ!D2x)lIiT@jKmQ%0OS_j z;{f4ko8~(PmV5xfQr$5y%?D6P?@2-=aY@<<@ux|u{7q??6mE%mupMe_3 zXBj${gzx{1@|zKE^KOjDKf@7-?tOh@V6joDc`B>K4yNy&m=Cp{i|nU>$FN7v&!vY6OwQ`_ zADWGA^%?a@DR~d>-R%a2?^-vmkMY)m&2o)= zDNv});_r~yAk-Qh^SCNAouUSSh;6q>P9L}Sn7A{)NX7|nejx+JFP?fe z8Es!0(a2LO)iPEl+co}1M*=0tX(cqP7qA z%G;nsf-fy?bbZ`6n?p=N>a*8r)Bf8u4ae6TSYyLC;caaL^hDVX1wyObOP}5=H2$$3 z?cBSmDQ5WcHS|T^s>_P&wYB`b8*{P|6U%t9^s9@|>I69c4U(?Kwwb@|I52ysw|T5J z!mhvj!drVtV{3}Mg+;gKBofC&)(jO}*x!!Hl_;DVuNSdFF@6Y7nAYQFE00lPhvIa# zB+?>=;zA$=+rw)^sz8t_l2{I3t^pK_ikO0w?1Rj7i^*tQvr?9xK1eoS80f}JMhuw_ zm8Z)j^_sRQWHner_5hS(sL*0MAmH!!l&;7;;x~fKVbk3=E^HOSnMSmYtzYCU4P^_EGky#bv(AkfQ0jKySkXzV5+da2rsv zA3%=HT-2p3e0MJ#8Ez@kQ?pP15A|J@1SVDIFO44lFi__MxvayfRu@eJ45%f*D>C&E zq~s&Q%ae=n0jM{mm0mSroFj2xSwp| zv1N++`8)CZA<`#um8~Sl4ux?*Y_68EI=SIAUVlx*iQ@mM-nQwj3}OE(kLYZ5{1`%% zP=TZF2R%y&7WkMEgRaW$@Kv^a`MyPBgqNZF>bt(km*OJ|4mahNT5MyaJ0-?KVuj7W z%k0I1drSIUf}7|NWxhOPW_WdF*I7(lQsM`oN}C_Jd(-b2H4TqO8cfbMq|XeC4CRQ% zqqn!3HR4cFzsIE{@MGiUp8u-<7-r4<1i{0}2-G&nN7;5HUse)QMIo1}T(P!_609Ds zG+~~HcU zvpTiMblz3LKqr*R`FSTehL_|@;i6{dyl`cEA(JYQYqUH#olt!f4pw#aTac$W2Dy;3 zu3WDALn*@c0_{Ka##|Vm?fR9eCh^7uQ*S1F_mQV=X+t(E?~6Fxqx%$Z@?|Z*mcc&| zRM1%)GrfUs8^504G-hfCSQx?l{#K$uYs^olMw3}rEb+bjQkTRn^8m*gIT@W1 zK#RacuAzgZ^A}xRkC?BKXF8YOk`l$tImW!J9h0(jqcK@8qOYV;s*(YvEnX%0Er!;| zczYFj!>((E8V`g||K-WsHJzWwpc3|6ChObzI3qgdB6WVd|L{6$K46tL8o%_ZMcMgn zK1NGI=Idw_u|XTV{%SjWQYpbMwlsXyw<*BN00aAx2GolB=QK_-G1Eo z!aM^$RiKv6ya@E<%-cJ)Asv|spUJ0@cS%6c05KcAU4Xrs{YocRe$lNkl$XKvpJ@|kR8IBsUUuD@G*z`QLCSg!oD&z&{tO;Ph} zOO0$988X~+?b@L2Yi;3e1b63acA)gJIGrtC%vQ1pY;U5YYB6P8&w;&C{X& z{+)8sa#gasU#e*ug|ZTVf8b?Fpkn3aQ^7aun}ydlm9i?*Ao&RKgs0d~@F3#}5nmA| z<@z_nBNXIJjr@NnMLKc>|HwwwsE!)^v}vXfd3ku?@xwooGp`o<3G}ks+2FeiOy(Pf zjR-11e{a)nUgAyO;QcX4ImZ&_d&qA+MLh(3>z1Xbn>>bkJsh{P)sW*KdD15cjsdUJ zP9;a{wRv=M343O|@Aa@qeU+JG<~t`5%jw;5U`N+W?1(P z;mh_1+&|uh1<>X12B#WS6<=<@)@McHclPyLCiK-TEVwecWUEfyEUj%QPitq`L2!ex zw)DgaFepcI&Xd|oI9+CRdAVj}XPwcCQ(*e`i$=7Mz_-vkkoE#tQ4+w`ZGf8*5E6h` z*Ae-g*)QdH;3Ao6;ADIc;!m))o@S&umInd?g-jR-#DHWg55gCJ7_`b*!(ZmpSv`zv zae605gA=y_aySG-#;oBzL7++m$+@#kkP>hDLf+!T3V?Psh_KF+kidMpMPr-uBXdKS zs!Mp$;7~{F%Ymq?8xKGTpAQ{}BD|nrzNX0wVT%QGw~j3kLIK*xrzMas`l<9CnmJ3C z9sGlx5rXhJ_@@cHzJV=W@Y;~^?WUh;58xusoX!b*<5E7Lg5*W@AHvG?VgWnN5V+Xe zR1`=bxT~~uVY5*WS%ik(Fo~@OctynT%XBvxIg6F|DhonH+eW*HHMZwov-MH2mo^o^L_E@JaM z*p=ef^0U=)C6L5%HHA>M7;0m^R=ZAKE^ewx_bSGf`_J6^8veWWi^wE)`P92?piLIp z<*rKYD3^cBDrOireRT(MdQ{p_0=TywKgLc?phlSyqHj6LSR0Jn#|XVYTF$Z5b9}@_ z*F0?_h&;APcsqdQm^a%GF1~0>FVl7CaWr)U6h_f`AuaaA*jn!AzjZr}X$EYK=-Gi&nt*x3a!|Qu7MmBy zMR>~fO&~^W)-IL_mDHh{>FEv_zU0;CVx&B8U|D$i!wbK~>%uW*=XD{7m$@7j$S~(N zkbbkwwKzT>xBA;z*OC#nIRuhHl~CF5l+6PN_1ymXO;PI~rr?$DRjz!tb9ZuKr*6=@ zfd4vX4huj53evK7oL)Hcn^~|~Gjn(X7Fe*tU`oz$*~BHe4D~X>j7=_JI>Qy)e_c;a zdNx!~3B}Jnjbp&dJ#7OtwECO>vf~6_<#ICg0S_N{k5yO2x7BJWVEu~U5dmMnr4z9J zYz?JRzMFO@o?*B1W)>E5b0zO#7GswFnpK(w}y&K7*Lwlu<;{}un| zHFGv&y82Kg_>O8;&hMCF2W|^XG1l>LfCH40SYI~BR3H1m*!@CU>>7$1Hg?4Sy49_z zaI+Y2I`Z694M7olVXmGiE#;Z((-m(`ekCP}2T>-N&-(}F| z1LYSL7kmbw8{|T~odH=tQ>Hol|0*d2P8tLSDEs{&RGAV2c9F3(-}eRF34WmOqP4fj z1dlbTxYybQ<>de9E+bxnr}bL|2UQ~2ae$l&VTTleW#gd~9xKoR{vXfD88B|Z7yv)W;2vrUVckXrP=^z zgm#fE;+1vW(mwF8XY5CT8zj%itErY(DaiF{L4dZ9y{Ql10s+hHVTk0`$Ue5KrHL5{ z(dCtoXFbG9i@I+lnch&R_OsxIw)@Sv+V3WzL7z5g4e5cB^$~@v>cp)EF^mPdZx2X? zxb;;gBx~CXMFFlv3B|OR0W!d#* zE@l(9Bx3_?@j@yM@pF_v<7x|w5C=dcG$0F7{FkRT>OT9vQA7dvArbam&#iO0W{BQa zdCHY90b1xp6Pmdvm>RDCHzdq;`pG>;+aLJeIFW884X03k!GG4K`YZWaE7SN3N@W%{>YtMiI3NXC4N=#$G+Pc|h zT>ZpVv_tk9K8)eL1akNsxy7#^ncFz_e~qhUXPkYshTbqpsd>>%zTkN?I#lj|5a)SP zH~WLO)8}p?(tby{MU-_8rNNs}37d9{I)PsLLv zAFyrb7PH|9{k5?IF&Lk=qmi8R%iyjQ5EI{L|Mud?VR4gwu>$u;wH z6^I0lN;`Bc?DTu< z+5B=!&_gRurg!4c0sdj|6t=hbo70!;uPKom+a2#dBJ`+iNM8l@*MZYs(NJdujfC%i zC0aarFg&X@mm0C_+I?I$JDhWE;-|=+Qw(7yd15d6R$B$%xG?4l6|{M}IS6a^oalV5}zbEihqK$?o8&12d@ zfK{VIrj|hFw6(EPB79rC3IlO^63ZVeY(a4N@!~Q;i8i2IplmEBXBVh!KkWxueovmx zHKY95rt^B{7eHyL;RDKMBg^?Mie~lDfBIXX|59xw(9T+_y2t8ZGmZv(%oE*#${IQc zadcPFhx>P_QDZC%wf+)h7?6^hKi2A9dT`{0hCSII`GKf5Aox@}fm@i(UN|yhsue3U zJaNsi%VmT<=u_V8x4gW^d}kIq8o=|ZoBmvBWF7+Ri6Xr1_se;Bi7{Tl{MqHr0w*W; z!*oA~dx_N@=_AfBUYD}&ig*$|F1Y$HSC@pH?my%Bx!S4m0s3F_=o>dlnpzS2UoW{9 zF@2I~g2RB2r11^EJzq$;FTjakp(L9FUnlcnm!-aT)xu=57 z{I~a;>B_cJ_cCN0v2EODp1r=4OS-uhpWo|kOO9>QhjKR`zB6OMbt|Qnb8Kh+vZj94 zDuj9lYE)5iU}j*ME@m}67nR?tO7p*2{v_1NJO4$+am<5@-(NZK`(2g^n{#}@n7TCe zz?Qb5ZEL(+@0(Z21uI*o;(j|9I#6-RO9&dnw4Rrj_rpV@7{>XxV7OswTIElzpq*9> zmaztI`F9dW`b=&Zy7_ovII|>F>cNKZNB{a1ur_;&`wWT8oiMX6JJsu7yi#a4XLPf6 zWXz&XSBrh+*_!gTaHzQQP0NFMt5@N{pO z^W@_MU>9q}*{JHsh^^Y}fFkWj)F-H14x2JISe#7a_ARBl@$3Q1r8ec%P>+8}-7=5H zdHC{ncp0@{lbWYBh3*yT^?Ai8X;Gc7fnn-F=@BXU-xvTmGwHa_!z*8Ue`1pVzYQl@F?qc5LWk|C7xQ@S&McMFIy#{sB zV?3uSv~6CGnq=Pk5^1B@H2uW!Z17OH+Jt@xer!qk&XS)Sghnu+VxbYgQ?|bzzRsMF zr_%^JMW8ZF^8@Qjgfa<8aFt*pEM24?4G#VSGn0pS+s++Nf+xVKv;(OG(R&m$!y+IshI-EqR9vOnc}1y>AH?wY=>;6;Yva_RWmll&|A zJL)j}fqS6?Q4@mt%MNdwU0RvipxGNnFH8taB>>fwrcVASsjcSVmJgvRN#`)_d@>MA zg~JtBDy_?y#7m>8Hb?LN%#|c0J3?f-nxzFYF*SBRw$h?Y%xL-$dBGSF`h`3l2BcKF zIg01h&bU}iuTxyDcr8*RULWTyX+BcZ|EaQY+FO8Au^#>)6P1bRR3`D#^Bdy!n6Boq zDDtS&R>Oc=kpA*maz_QB!d60Jx$tj@gC?N@5(~^|1#f@^%Kt07Eis&>w>k{;xPILl z1Nr{@O>J)iZ6G@Uhm#zA)pB@-gqRS?ZM%qAr!#!lVK#phw_d}*FWz`qlo0irSLAAr{PX%D31Je0< zHO=12k8)qO*B`#Fdt9C0K2^GXG~#=3gMy1;=C1|T%zmYm#Mbp>WBwE{pCMxx@5Rri zIO~A7Z{E1Wgm~pUGSTKIO3uqqUTlFc!5@=E{Hl9g#pe}51%7E8#hp%G22DS=?-6Ys>*cueMfLa1%+5`?c!I z6t?utzdljCOa|VqRkd1lP%+71FU2mHS1aqtRCBL!SHqBTY2U&|B3O68Ab+m0g`2u! zd4$bIo!n~P-kK+dGT;$#qotW+;{KM_CuAP^@GsfNVr-m6ZTtMm+YJTfU;Bq(VZHq)1V zM)2P$d0z5iu7zf@FU#c2gFA@X%ZECw+*SYdcW*aCnL5zNlD(`w zH>J8@?F8hKDNw-PO0}kt=*TJ(gBi3R;w7nFt)*{liZ&gp&~W8sgKo068~;u9zfxe$ zZy%l%VF9i7sw-X{K0F|Q5NN_=z@u&v=X2rP7mCOD=BKo{2DE>B+}1Tbrt4i8aM~v+ zPIjAUVSaorg0dxB*Hkb(ZOmsYQt%#@YqrLat)iS#@sqsT{O-XzSaznG|u zzdsSXTokeUcBEp|0ClBl__wjz8-|i^`pzw-oJt5UOt|VVman#I03X)zgz+3&%v@u)~wqS!->JW}f2ZCst_gEFVdP9-fm?U}?Hp2?2<# zX(p!>$+?Z$pfoO+rEFAfSat*YJe08Y@qp}u5dn5Gx zk4LbC+zUDwu*4prrs>fz44KE_5Dmi#^MJO;9Phh~!SFna@{sj1s4`Hn6xXd%P1s-d z4(Q(WW8>C1t09VJxsKge2yRgV3mR|@$d za^)LD3H)jY<;sUVB*IBRE9Wdc7*=8BD=&N)1ERAxRH7jafeP}QQky!h>LU2siH_`d*cF@d3hhFMfg}B*eIjckZ&d(VzwMylHkGe zyx^Tml^uLvp+@znSratR{ix&!U=t5v;*7PrhJnqD9FxiT$THa)X_xmd_`6rL;_9Vh zvmod6vp$?ydSSLZf^k{|Ne%92Jg~<4KgeC2F?2$^T380jXQAL@CLQC#0jmL2H^T$*OdeeZoG=< z9RwY)d!@3|OS&UUpZm6#B*7LF5K-oorFXF z9UhF?LF<{d44^ICP!6I*#7rfdOcxCfxG|JynqTZ;mK4I&?bn4Q{yJpq5qYxCFXDM) zdTSMe)D`ZG6?+Y$jx|QY9Eg#}Rqlc|&Jnm6c>ICcT2GS%012m(uY#WhwUVz@&GxcF zD3HLjjwnGJm-59UK(DzH!rucvzB*Ops@X@9Y+dmY9>Bm8QrKz^9mf_#&8*XdeZ#f+ z%?+Fl`Ogs~7X0@^&bTNsUJkNHOGP3aBgP)U)D4p_2TP9R<@|K=Uva2YlwVZ_dbPKu zuw^w-Sf z3Lr-v2`g{QTlFL3jF+_wcA#g`7m6elkADYXW#)wPko!WSyObyX@mavJ5a$tEg0J_{ zJ;TO;oeoK<2AV>xwy*E9m!56umMb4CxEp4SwGWNMx;=-8*txkw=Ut$THGBT|2oG=@;^B3GS5M zZjQ{KaS1I9tI?vS0qg7gXI)a_s{wdgm3!WX*L0}Og{sKeL5ZP{70k7sToy$Fzijhr zRaA{VWwI>0@B_b!@%sKU{mcc)6Ua_UG}2XVPwdUTDsq(&e><)07+pGo;@{$2UJu<( z-OwLYhxt!t{L@1K!`s1#);S+O>1wqwx4_gdgr5kP)D-U9IYa}l7>-c?dw+4xf25As zCc9BhZgxIUzuGhfhw$$>vG61Ek&(aubPpNtu{P>h#HS*=SNIQ}!FMORD}=+6Zi3oq z58}6b2@cwe@^3bI;wBsriVx%9Ky;0~)-^1;{oR!ly%3qyPWacA_~XDHa+jy$2yNVveC}OKYK_T)tVt>0iP@NOf zt2m81xE!437s_y%QrWyEF|<2o&qo7mbyk@czLx>Cfm(jB6wPPZ^phCw4Cs${Y)Mu~ zHV+x;hLlE;^pVV2pC$cWrxrtQmaP4WrY*Xz^^9X=)bwFwr8lxsv4C^F$%2_Gnq{t) zv}vwjxrh(t>y2&^lE0^1Ow^Z=z?wYWdUFEfEsBtklq0R#pH>LH4ME7*0zej*gg>YGM z&FW+kfG27Kn#he;In-%&0p=kTfFAa-khS5Jw`3?S)I1J2QKu7feN;ZjqrepM~gT=6NN7ymgFC;>W#L@$Wq1C1LWY6m% zt8(M1-*IgN6H4FobV7Ugn^P6Q-#BA_nAR&4qufb4_&$#)=!CHYx?Q7i&cAJI&pDU) zZ#4Xwokb!aVNaL|u3b2~WBIJ~MCWHhN9Mg|Km3yJaWPH^_t|GH%6df_0Ry8>E@|7e z`iP5yvB>o)07%xWV-2?s2!gG_y?YBda1Ic7#6Ej`F^(8CoTif(K5AJfj>FikXT$Z@ zoT9BBh-0)IZ!CM>E;?@1w>qfsUlvDr@7)maM$(Nf1ThA>r?)0Xu``5#vCi^AZ~GQH ze)c1LQ1qD#Bn^tQWhT*{dTy@}Vl}L!UtDj$(Y=4D{Iqy}-5(Myo!_JI2Kho{vD@v_ z&w3wp$^IO9ve>ToUD$uZkwvB>wIx@zoi?xBB*OETTtnRABUv&Dasy0-vDr(vej0=H zm*^SmMHy>;CKHavzd9isRlMJXKdC1FqIS7Dxr2QeooOcj9ZXJ+T9Rupe?OK$oF1JR zo`O9_8<;D;1lQ&_U^cUF^ z&y<{!C(-`)mMB@!dMH%1k&xkt-=xH zl(z#H>ahg&hm&ar;XC0Zv_KCI{EWC<=Q6!-j;h?xCCytC1#1T0_}0S1hDKO=inQ>GpK?8*r*bLq8M$jPQoF_kTnsm69&#rrvhIEW zycfiG>}wWP8Lp=FC%wwbzxeht*yda<1YlY=){?s38iubhq70R0u$tiWx!G{Iq&(m)vFA5L*WxTC8E~hfef$$2@wWbay_$0Uqd&rJ+7{||z!tMe6yFkYWR*RvA&ghlHsQ;m59PY<@ z026)y=bQY$a2kvWrD7p;=tpv-O ze2b1Ff-oyn3pgLZWDT4G&kJ~R0mGQb%#4cV0jCp?i5Gywi6#-G%RPsclD)Y}f0>=g zG{yA>DT2tOlGQIpLfO9}Mtn}9N_BydqmF;o95||C7Q(TT*mEcRi>E#onlH)WPyjcF zH(x7e_@AcCs1y1(Zxfz}hE#`STV&W0B8(qjrqwz}j5(H+Gg+N-=Tv#qs$>mQyoi!q z`X;5;_AV4be6%!3&$iL{Cdu+IbP5c^Rkg=uC;};VR$l#mBQn5mr<<+rNkplsl}nG(G!Q!Q{2l<*3kIsf7v<85g!CLQ+i zfd>65gyJvzz_6M?AHtZN;Fnil2qdm!*d3}5xfEo8AFY0cI7 zBD@pPA}(dVI%WwR<6GIC)I=3*Cp5ma64+$`PvCtgYKx64hmk4CW@l@OGUfOA;6NY0>*CixbRm=`yb;tUr z{tT6My@u%=gs2`tJ zG+#(_)At{BJj^5H`NURHg7QHGg3+gl;-3=Lpr7n^$NuPtuYk*ZZPYV%(19IqeU3Rv zF35;mKy5ew>%vz$?CP}7GcoDR#U;kr%?hJ4wO`qFLBef&P4n2=htQtF6L&>&EpD>A zbkBZxCK~~8+asH@T4uw0DSO}Sq`IwHMg{miXE9yBZijN&>HRp<7pYRHdTl4iNT=of z=4|T#BQn**WiLe=>rcpWj%JuU8n@x;Y;~f3B2{U{YosW9O^XF>{k|o*X&$m(y{s0O zA@_V*(xg!&b)dn!z@w@6uPW!I^2bnpc=7LQ)jG>F;q{(dUz2;5r|nCx>9Ix6jq~LF zbF0@M!e_h3%!p*VpTh8$Z#)H9yjhH)b;JhQj6isI79JK+GkTTu&V!%Ir~*mY79k7s zO9fYY?lZQU>|u}`%<<`QCFm3HjlK;wvZo2 z#1EI|T=EU1WAbcYeh{ZU~?BNo0u&D%YRh+)D z>ecWuk<>Y3)l?|M3!hq^dU&A9mVn3cfH7FPvMmAMpC1`wnn`3E1eQQAw!@DIiEV)J zqRnz4s=!?a0IgXMATrCOXDkAYoB_GuVLJ~2w?N=<7$`C+5lsR+TOn~cNc<;2IE;yb z=m;vid=En5K9r1qJ5Ud6<#%H;y)1Y{cZUD+!V>sSv5XVl1Tl8P7)o_{Z9CoLiumwy zr8)812n2zm>d|fs6NZ0cAz>ogh5y`xY|E%}eOF!@mYgRm4;poC0W@{{KPP#fudY#5 z%hLNvh-Ai!>zz~S{*(FM&dRpZu;cj?AIq6vPiUdHP&K{ds@m57)ad=iVvEF1pLW~1 zhMIinep%tPf_Y=7(`Xs%o5SWBH&B~}VjT`O^=>jbEgz44DA1WqcJFPBP}N2Z;Rt1V z?K3?I;id*=<=r)Z6r*VcA3Xt#%kZTnm|VUc9TS6 z#M#!VL?NyP>9nI9r7tlt!GhtqPNTo7?Aeq1U8tx*t+wBej1S*T)gV5l8ADF~RqmwD zVxd0L+)q>P80mmc!zUf5z7fCi<`W*?3VKAc=|K{eFe=8~BIR%RE70!l0GEBWK8ceEAUKli92ujF3cJnHytlw{#w zQDkm_OxDfq*4PX}CdKb#c?8w@u6}iprz3BSx$I4FsA5<$2rsU-zY7=j`oQbPOh3k? z@$PRXQrk=gwZU#!?9=&(A>vu4(6FO|lC8-KAv!s$y}<=82;19oP85k0PewO=``1@i zyI1ckAJ{#3B4lCI9_x@ZeqzwcUk&L)FO{W(zc$vNdR3|TsW9K7rqzLqeFP5S_!u?y zzTkvU-gU#X?=y2Bl>PB4DmHK z{Fr@VZ1XK-0#_9lb>GrIso^k?5jwnF07?Ly0EPn;Az@YwX`AnT$*mE$Z>x0PraTb$Q^l>BPyclj)UwGRrn{;M2`@eE67#Sjx z36RV9K^mxe;&}kA3t;YWqgWnx$p5EphW%e*VDOMxf7nuxs|Orbb_me%!O8FGZ=frn z}6$Of#!f2y>$5LcRns4ucJHyvZed?|oUjCjSg?}hr z*&}N5zniMs93%VeURpjJKoF5dir;fpkWy!5~pQ0M+)IY^NJghEQg*wl^Q)d^O6+ zkOL@SFMo@195wETsz`P~C`$yg$OyxOh$sie&gh9C84p{P&WAvPadk?jS`4Fb<7N>@ zg(H-zpxW(bY>uDL^jZ~A7YS)JtW!21#y}2kcgwaHwGgyhN&evodCy1<<{OC9m{v?9 zsb%V4^OcU1R6M36#@0WKroM9nWeuWD(SoLy!P0~Xrv* zIP^WR+3SE6Ax0yVu@*72IiFgvnHsOpP+b2~I_O6z!S}ZchkBghxfD^M%sfFK58Wj*#eW3`E7Q%p5#idgSe1q8mbx27C{IW6aRZAf>K=d z$F`98M_Am7YIxOSYst;mH-&h%OjsCeRrjoZXB*hr z!yboiD@r%{W1u9Hzx<6M0^TJ;g&PS~{EfQb35tZ|^|>J0_JXVI!0eLCT;sdDUHADS!Z6_TBUbTtePrPo%g31s$mBR$-9iY2ZKFRmxkPAi+L3EFenBp( zGFBYJdhnkdl?rAUd=+)+ZYKxHz6d>Y zQtp~cIJ^}hQc(V-a8IxkQMl&O%qviOrG2@JFS*o1O39oa5Z*$`_oiH?#XzED$HSfM z6N(8$pV{9m2}R>SDS3nuf#dVgT_?9y@GU%#8c_)TFzqkr4%jvN3*p%W_(KE6r7cNa z5#-(>Vf%VB&S=q$!7@9- zO>YDJdy|`$9?H)dT@PVP&x|g#5UvS~p1D8K#OU#2mZ3H7@ViiwquSoMSEVfkf73tNso$efjM_x%PUR&Z~Nz(WBqnR%m008}l7Yx;qnY=o`_?rNu?YaoaRY81e?m)LLO`Tvhu za8fVz!1&K6uu0G~WG5lzx`!@m@Gk%<#&i?t(#>tF04&H4Sc%xNyCFb74Z8Aa;C2YA z3f$U%L0rv>4Kx9;QZh5U+(A(OUv-&>_xGmcLTs!RzKCd3g zKj*2F!|MBEl)ZWKk!TIJcakzuV~e(BWf?;Soc_-G5MkGgGO3pl|MGG5>Ez+iGRgvrlM|qf zMY~1Mn@bm!5;pt5G>7+Ee4opN0$Cd`-D+~)i=*O9`Ql?pd@Wa*FCrLT5Wn9nQm~UO znxsnFx;T;wc1{A1?{xwBlKj^ewN4aykX_;53j;{bm&N2&2kKFLHdzv>Z(1*Z{3OV%#L?8#A0S_LBud#Yh*uO}OCjFpaJ>Fg$t_CB$Le zgy)x1c~l)9>`gpUp20}|Si;#BpnM)14(MdW<3fqC6jl>!ms{e^X|2yMs_`TAp_81} znyvaq+#b?Gfmo5H>Awy*%&F3xYv_m-tIQpdZnP>Z_q5E2ypkD90s*|a;?j@84V{l; z(Hy^4eop{i^wGA}RmX*5hEOPPRm5v`>HxBL*vwQ_a^DJAzK$8r7WRrv=oDd2$Q?(x zknOE#FJ{bS4E_c~QEx}8sMXbzBB@6nbGNf}bK8ZLB}kD_j$$c6=L*gh^7~53bNFuz zO6AStgV`uq(_!6r@RD>5!$Oc3r*rtdLxUNL<-;8$mA`XyJ~PX2;hN!O0-&93=8g_E zwcsE^#*wBiuENaLbJj)?4EO_A>(Karo@}e+50&46IrFy~fUo4&$z4Fk%VcZ)!zAgD z8RJFL76K3Tzq&8ZCK2V=cflQrHGdfW5G5=7d4sq$hMZL5qNa3-K+m1tS8Lw2# z8xbub6%6e3C1WdX%aJc+u+R+V>!X$o`W$rRBDZxp!73BN1UBg)h4Qp2SBaPve5)iF z(pNFL=a&kBYzhla(E5wzEzcs`mwi87X5nRpD!p*pA1vMfA4%sP&vgI)|INl6<~-*) zZqDj*STe^sj~qvmRF0W0$tcGh=9u&5lq5!T>L5zRRYDGaniU=9FR$>1~m}c+-Du2&C z2uc_kK9;s zwxJhMdYRHv4x(WyHfw3rqde@BEfm zwdBz=Goq=lQ2AdDh{*oY3ds03_`^LY+j|&RbCn!yxAbauV~0xez$2PcQqd%#F9&2O zU}tBg#~#YHp*c9Zbrecy7F6%l%s1R&H;?vOc8>oQ96_u^xU(=@c<$jDr09CMOf>Pk z!|ZunPPC1J@;_D_+fcP@pPc8S0GL6-Zmvz1)x4|KCV!Do+~hd~R?BvhwQf-J6jWO7 z!7!7b;1TSCGcukfM=lg~Ch{_uzT4vrV{DbnXp+Amrf^#-&Ff;@ z2$;$E1Kf(VIn+Y`=i9^FHs(Uq3%4P?u}iLH0Sh zV0G(|&ca$3%mmz5Z`<(Yirb3COmo5H^>}XAKTo^)5G^3HqB-KB&JH{Fm#pibM-0XtRR6Cy#kw(9T?MYmo4YaR-9DRjEL#6$&#>Gk$Wctm*t~{|4;{h7 z-rggA!@6I>D?(V)9_$eTxrLab9u6tFW!%FiI6z4P{5hw1Cmam34hHvcW`RJ&U zNI80k{fVy6zcd48ICXP{tRm>#A6~-hD# zvK|Jtc>wLUZ~~`Pxd^yQTz}HJ#@9sh6$Ll5boZ~}QbD1eHmK{no!hBbT?gh39e67_ zGpQfEcX+e8A;FkWX!^Hsfm}KDizgUc;M>%fZi+54ntD~5*OBW|c7ET?cSJX7I@{*i zy$OjHLQ=)Mdu9K$xcNJSDdX)<>TPu|13;@_}mOr zd-T;?%+Wu1N3dNrU*(NtX~*|uH?mgjx^qE5P0Zq$fsK&3)N3Ww`330I0irAFyjg7g zY=9V^Q@s$pF-k6Y6IT7}nrq<0q9oCwj-p1ABQHhH$)F&tz-Oeo#7AY&v$Fa#6#-66 zHC8%7$SNRlgM6m-H*s97mx)1MSU)~xXNb#>k z&$+ygyo<~AbRV%PNg1Gwljp1K8iip=234hYCa@3b;e|XcAl#usOd{Uu7Zh8KHt6V- zo4j-V(~Po*_vRi~wGkFe$xn@RyurS)X*s zhv5}GPvcN#ypHp4!GH>8zP`9&4X|W{zZUOHW1&Wf_h~opgiST5Ek|olZ+9Y!zt2%6r`yI~(p+&f@qc6HXJJ4EZxDuvd0Y+4E?e0jvSW11VVRTe1~G zy-n2TK+fTw|JT=AyZaToqgmrX9o36 z&woz;X18*TI!$Ub`1$kOkyPs$`2c#5+1av{{2aL&8%*l|`$NND_UH-~AHQR^m)} z;~<(y7=eYNVlm1uul71*IfKEnxKmbEL8eO$BdC(U@0dsjWE*?<;+d64e_{?b?}+8R z-&WM(d5X8~5Fv6GiE-`fUHseT8PkU~;75w(pWVZA^K3)QRpqJWSLAKe-VEMd zv4Yx4U7S4oeihyJB~?dkOC#w%fn#ZGiO>{V=HK~GiIDD%@%8`sB za*#Toi=0s}qWDRgZojc_iwW~tzMj(iO3rs?KDh$bJ1eTRw=p6<0Ue8WNT@R;zL;=} z(&w{6|8V1cQmtAFFENAQP}$^v+7qzI152cg%>Ls^cmpedzOT z)h_fLpb9&B^olPPKWQ<}XyW(;y(l_KYA3&qLMt^b9+3|8kul;| z>%jY#4XA^R8)*J!bgSn0{S8wnb@0f5!-p-YzvLc`;4n-lYZac%# zKrs6OtZxJU`oHBEys`{2MwGU&&?bYK#ne|!DMQj@NMuk79LC(1Roc{>P$Muxir(o& zlIe!V2_U!cU6GS!RQk$1&t646L3SqvCu)O$RZ9-~so6&-Ecpb?D4DV~U;v2;*F{h2 z5CCI)kdfz*db=A*^ogJsUG4rtn0e27NmcFQg3{Wo0l@v|3maGf1~05Sk)*BKJC|6% zHdvghx%&8?UWb;~LqrdREfl2^j9JV>1fu8I)Z7=vU$jfC&OUW_DcCz6E){4zxArov z?V1VfRkw=Re#=aXJu7fVc1I8qI50=qGieAcatX6&F`SfYFMW$?fT&<;X0ePoB@rlx zP7Ho=w_t1UT%OGwf)x1~niG>FkYVl`so7#Dkz;UaOqZ%YV1Xc?j^24cq zxPf16i{%H2;J>9-3{vbaY|M#(^cit>n&U^}L%F$LxNlNQ_4`;!@n1LR|z8(2UJ9#{|{nBM9fOi z!=|=H{|7nFe@5IcTGXX>N>NxvqnIJL;#(U5SSZ(Gzg5?WD*I2V4urI4k`!oefLc-E z^cnK#{5W@1Uo|%3W0GVo3nvxG&K5a_4oL;4qH+~tTj4PNnNli-7>kajd7np%x}RLM z_K}ArWFTr!`lH!Hm-idDfMbtEjJ2OwkrPlnTXqOY+&n(Qk+sUwAW8ELFgLMa!{8%V zhe^BQZuO1LUnH%9{vBnZt(GhP9jH2Rz5)f*vWi7;g|HzP+@W_;Xr>;0$Pxe24-f7M z@Tlh*#(zt_WtNp=80v0L9ZRWX)Ei;$&pEmsOp#KTzLuGgMBN@nCjnX^U{%j3w?bLd zlYF@`to9`m+<>7Rue{Z5HFmmHSJJFH;QR=;^UGNlC&u?A7N* z67FCmf!nW$*iTB~O#kC5~BP~<(SZ*97%|0-kC%0Vp{LkO_Xzfy_g-TzI_qbk9F&Z(;s3UNYy9O zCO-MSyHu{Nf>u5m;j>u%LM@1%$Nn6oJV^ykfKdZ~BVwFL*}y-Eww*N_1BxbpSsWfb z9$={%wKTol`rc?t*ffo2(WE%L9ESjN79{=ZSlC1t)M-U-{1;^T7t`Z7q z(JUspNVo#7r;uO(zXG_+(|>tva78T%6u{%ckZkDNDhNpHy$3cr(1iulz;1|A2ZTop z4rd!bp(1(!LKCPjAtF65(`;g1QiWy<_o98PH56Qj?23-Pv;JZ*+zewWH5?Uf|@L%yQd}lNYU2vrE z@4J`i)mbGc)lq5n4GawAbo9Ey1+n%G8*`rfgjF7vt6O8=Qs<(1v4>_a+!f2a{3Vg} zPt|Y_>U6}x((Hv)KX=>1?bc7NDR%t`@bBfQ zJ%{kB?<6L^@Rz_;x!gt+to@oUq}6F1X&K*SNbVcdz`UKUCUuc3_??hRN}E2C*ni^+ zvOzRd8(GjCtFkq>2dq3p|0s73qo4=6^c=Seb%jMP^JsCa*R_Qi{LjQ988sH*A|f11 z$V?TRBXtT>VH$}slT@ZltL!;2MS7y489x`cQ3v(&{4Xd~hcI&Z=lzK>dozCHOUaKf zk7}?2n|bP7z9;_S)h#Y_@3>H@*xaceSZwti`jzbBau56DP~ea;xQ}a)D~CTnL2lq> zcYr>5@CdC24+vns$D+k+t+LG0{fcxSRiGh!Dcz?J+1kuoc7vdjz72LZU{je3a4>4+ zyU#gYz%MgXG0ZrA``(Uxy{E3BRzTu8zEZ8ATDN!I&FVC#{r()P+dz!uQP8QFH4$&6dAvb8-9k^5?ICQuk~6Y|9|(0(MO%~+qgd(G;qf$G#;^4Q~! z!NBJAGjBw}m49Rtq$WgVBca!N32_bD32(b9{C$?vSTTghSf&gZ%fUCIIL1pBH30I$6 zbRo7W$08EtwTVe$QI6*HQP+n>b2mnQ_TrFNggV+6=!6`*1dJjj!<~_BN;6rlf=@_~ zKQcwuPG&xN(k8oow|MP(ZUNnAWg^7oJPeE>i~M#*>uKL9?3DBM^k*bqLnEIcc6KH7 zGp+Jk1FWt3a~kv|2!nvqI!M#0ntiV1RRQyP;D|E-zk(_ixR{upXTUY@!S5d~U-G?{ zck}7O%NzwD(bWQ5S0Ta^5R4o6Tq(3jgq&lL{XvO+w+f;qBt#5+pC(Z$M1-M`{(?Nc z;IM?LvJIyE1?{T#C2ciCmvk<7?vT2i1i?xHoLvV!#{qIoQfI6AREq?I^^wITJ+rIa znWvL4{5#A+U?)QdXk1XjQl$?^S$Y2QvICMvO{Lx1<{J*tA%SkIx2>`cKmV^NaL7vR zw6hqGW4D1XWN|O0Or)=kTg%!dciz;%Z=A@c>SL<68l@$x6O%lM?*&*~mqSs5u(r8+ z+90PD&-D02aJTYvEmR9B&iDZG+Yz00{P@Kw>TXMcs0+80r8ufeKgeF#kRs+ZUl(!w zJFOeb#^yw_&X&b8efoz?Ia9mZD5EF@x+)gymB+W=>8#67R9@$DH)T5+!16l%6Z4Mf z@pBauK2v>du0@8=*11utH|DAc76QGN8Th&aie^-cc00(VB7$rE1Z^IeXtshgrXXMZ za&@X7R4slTVKJ_`IO;^Pebha>xlsHA5E^_G7w$jlF935+oi~CvI(9Z;i&gs%w5vf3 zzEGxS=JN|x9S*@}QVTT<33I_yJ(KAir|%R*@lXI8AJp@>Zpdj zajl{$t_DRe*>6PRIk@Z&_0CWFiNUp=c}|7p&v+xKtg{X9nFpsmFEu^j5+DMy@bhxx z+&xsKnl>SnL$9&S&J;%SU+DiZwcZpRVM%LhV1n6h991``hfUX`VuUFXZh`=+>hy*Aj0OV_Zz9@r8pz?D~Oc0<1tB2eF z-2nv#>nhSFc_TozZ9h}x2w&Lv60Y)9FC_XkXRJV9baRYrAt2-i-$=Byv@1b5$+ELFL6tewFYjq>z#mSu4AyH%(YQu zJvwS0ooul)+36pw3g=uCu}C^ak5g2zj0aK5RTuexO1^b*HO(A9T3?aB{1l^9Ic!eevhc_@a!fUuO)0z2zpq02{Tl-}L1nIi-JWKzNyDg}HwzI6z` z#ExumA;}aH&s-6u=9khCwZuWJV%(p5%dEukSQJKcHOd%>IBi{S7a%2vQY*PQ=}gE1 zth6M`$~oX!i^Q^paZ$~DzMP@8lI0i8IL+NZT6TBv2X}k5&8z8$gCgy?;l0ZG%46ku z_TkqooSspp-e0z3moPZ&bDJ%J|5n7(?_D&f6yHt^YLl9aMdT4H(uNH29P>S?`ctmr z{)iKgw3dnqMlMd}v-(4ZwgI9MQ!c^Rf{e2{1>!p|1nO2xZtcB#2T*Zkx6fp@8z*d2 zR+oTh*!J znB* z6UY|+|1pPh{@F(Av^jV`Rm_$mzVmn$&Wh$8|MiWzVO{i5^dF zr_1G(-N)!e*BSgSSn!N$%p)Spe9>8UL8pUTg+p@u{H0sFH*3SqUk(oL#H8E z$USU?Q^6XmL0UV{(>oYlQ=6sw8lHAg&qZ;J$oa=?JEksX(4ka>%@KX_; z=J)_eviitQLhVn_qie^gb$7)IYd>0z(T+81zDKly+>6C0o&(;p5uYAsSH4dlwq+c) z0@~NS;fIHmno1q5u~QhW@d`}OA~CiL_rUPFUT~8M>Q*fIQ{dMW56TbmlJNGrX9lNW zAYPN5??NZQG~4I%3!D@v@I(OU{CC)&W>m0&f(02w?03{L^$^Y!QA`UQhX~3`gtlN{ zr#G;IKDf@`PHwX3AJfV9`dCRb(;<;417N>vw0pipOANcsapq_qoezEcV2xqB+^?5; z{rffS9%{w&MC@5JZ0SQerfBqYlZb39Ewmut#fHNymSUh8 zwkAY2Qa@PNxjDE$`+Ii4UtEA31okc&HS3D;3qN)|u!i9W#q;1Zy>d^g1H#}_ZT_@S zWf+)x!C%9#9|XYgdk(>K*+(2g_LS_AOwFoqonL`ET^C`X<5U6xd>tR1g^MNVAA6f- zJn|nsD>pC@3TYzPd$&n$JTZu`dRZ0}OgmdtFt8R-6Nzx&cf4!YN^rm0YXg-xqKy`S z=-LpXtYsd@xlb0NpY1bC{E6coxppPe=v8wQMexU2?4;uG%y&aPLZgK?{G|HF(hdMd z*s!Wa{)nzKsdvsDo{4!`GjGcY;uCEKVW>NDE=R{rn3XGbp>l6bMatN%?x-)u3)NhW zG)3H8#%ydu+iRZn>csO~*Hr}tsp)`qFYRJ%TJ0I_$ihTIcDN{!g_|tR=^yqPl^3F0 zAr^O?%C3%h_C`K_%{anGKg3z0+hf#?mpeRq zI*L4Ei)ubx1?j-9=d-=R(fo^V?g8(Df>>DIU5)-75B>4eHl30#`!y&8e?N#e(gdhA zagZDo47R&?(S&J`$cCia68d-KAw>=WhCI5yLn?_?~uN#Uk0oX_o=vwg5 zdgTKtNhGj-1z4iL*DVzC#6}vp2thU&5uShhvp_NBp#lSIWWppGfsSQ*Ta=!y1EaQrpTus`0CY zRYr3n_0>Hjxvl+U@}Pzh;%M!lNb2RCg4`n8I;LlE?ogx){0 zh&oKuWU03Ft#K6*Ja-A4q)V0+P0zQqACb!%QCx>?Y%)E=(UE<>n{H{4WG4gHO=EYp zB=uMZZ%f=y`@nUc*NvrI-kAu>EYDTQ0c;;QUT@|E2a?huaA*DkZ9)0Uhne}bFF4C@ zG)u3SY5yraQng5;4odSK2<Ng|%^e=Zm zS6tv`nWxAxH4aqb7lQxF##IX>41`|w0Hl+~5hdT~M0Bv?P8B48b~9n5Z&;4;Z=i&K z`^J(}p|tt(w`hL+T;c+${fP2b@A&&MkR&u%kyXvM__5n8n^0izXVSFzmb6f@19rDR zqc?(tXi3obMkY^`Bq>b~w>@uqH%9p|%O1+fI^||mJ9)`N_PX`RI087uQOB|-+8;J; zG*%iua}rW9&mfY+>F_i<8<{LDt=M{qtIOBRp}B9iwB00>;As?^m8BcG-G1Q>>aoyy zP7faCoB7XG+4I8-N}@d{QgyDNERP&7(6`3ml~2^t7>FC%+mxqaXb+@=y+YR=?M-OmZyO_MjnVi< zBkrQ;KkK#S@!XeLjMuyam9Ed7lyBn)4eI}MZXL#(bClCsLT4Tb-Pmufsc8Dsob9&o z{4k9s0^Rr~%ulBot_b#W@ctPta>=n-WAmaQ4|j+n{_sqMZnS$-5AG(;P9tP#3s@#P z8>KaWJ8YTJWx*Ad z=Y4+oi^YE)6TW-{SkoeS0L2ov)cJYrq4ke?7yuB)M+m_}Q3ajWOO1sEdm1vO59p zv}bBU_9rk84*-Kh24M=B2La0#Xg+A%ntEXN|5wZ(wM3ny*DKZ-5bJ;~ql;Nc&tI8fkTvIYwCiOaq*?I`1gpL>6xuDC;nJEl z(|NZ32K#DHfScY?wQP|Dm9<|}5_Ug~jEedXs23Ec&zO^fZR|Bh4odc7i@7d7dXk^l z3OLp_Ux|Z3iks_ZWGGJ$T6%K} zYM;=3)T)jY3)R#DTi8HRoCjlTE)VXiWV5<~XSL0zsa|@13LCfVRCniD_@^_wgApZ0 zdEn$bHQ-}V+rkJZ8yd>17JmdCj#D2W-UhR>B@g)hc7s!Lzq`W^);VLENO>8Lzd9A( z5`b)r|E{UeFQdb++;NEM{S(jNb9gRSwz<5`Rvl3d6ROFi6E2(33qo_}0#dx+XjVo< zXJfhGF)>SeAJM$G_*GE{)sQF7pl`8SFkIlyb5Sw(f6O-Ne zgnvI#X$xh8pOm4>p&_9SO|TlWRVnDACvdGA^z9euWdSi@592Cb$tsO0w{TT0v6j_@ zf5+o|`4@EV7z}wwSqaM0rtu%+aRb8(^cUMEU##SvAQEH0bF4qSznVGxnmHyKkZS8v zaR^Fsv}Ekzd?gjtS~*2P0CVfXb*Y zdZ9-y2sw!U$q4o%@g;5Ie2<{-9(*_M=PFE$4{}(^0ns1lq1?jRxe!36Ffa_gq7t%> zaMqJS-+qu5ua=)rkO=tA$#V(P%ZdHAvE=qdZ?J%S-yO$)ryryEwM3nc3WyeQOD&h~ z^si7$luSn?`si#aCC7}%ED-~eMT7KHccn5&SRO=x`}Y6rc>r`0 zb_;|?{MkGnNdGMcoMFSwAPi`t1nzWtG21uyh~PXn*&)(p12r3w#4cgowZPm2OxYa+5*!98_tG8UMjR>_gVYP*;gTVGTUW z(`&y-deJT8OI5CAhh&FGHb8i;wV@n!sG}sM+Pg~4U3=YR$t$`9eg7^B&Xa7gIiLO1 zGlc#6`DpP&YQ?B-{j|b9`-X89%r#_+!zDxA*9L1}BrAN(_fv`^CYHr52TM-GCnm*m z79CARgPwl>Qu0^`Ey3cs)M33DYkE?2R`)_v)aK5VmqPy?lMUUj6mMnyk2#yy-l!#K zpf8x6W86R=Y!IpE%?ZA>i>GMo97CEVP5(EX>JzN_{m=7%(=8*`ysy`X=8)6A#PuC2 zQxT!KgTI=Y4Tx>Wv&QA1J9PWKPTI7*tvUjdE=jl-8 zyJPg?+gulU+2MsBv#Fbl^?on~WX${gteX(!F{C|x(du=VxJ>rlK^NQVq$r%jzK=Xpd2}EQ19+%D?d8k4nnmS z3TVj<)MckHR&oA&IH{;bny8oaCy4oPr7|8K(a3Hs#jFtod~FG2*+S?co90`8!f~X1 zDrS75K_-8>%P44xqoVb0A}LhOp;WN{4`^@t`N(1QAewmWre$WT^L|{8*+Nlb3=2F- z9Moo=_{Fr$JYDC=4q^9}BI2HcUWs8om`LB4<7k%tnzYwYHj7jNKi&p)2Wd0oo-Y}9 z0$4?qWm|jyz_52COOsT|?ZOU7%qzr>M-KZix0(Y7$2bk%f))P^fSReS@5ekaIa{_a zs+^_Le(G~@2M3fm7RPb0nM@*Ksi<~3Y^@P?d~BuXU=zT^ydvtc^ba5JyWE-ulHi6J7Ff1+;s{tP8G#Sui3e~n6OizP6{ zGy3L|g7Wz{Q?SQVC9XD7#)=5Tsf5@o$9`L5pYDYc_H_nLp-*$IL0+kuMqoWf%{o=orRiVZMXL7)bwbN>hk8+m#1Ht z(X+aW)yS>z>?nL^${wK2^dV}xyA8alB~H40h_*2>?exKBhrUO(KZ`j;IS@4CVZAXf zx70gmxS!N1LHST)nNDXObz0AilX9x^^|>OL@cWVIZNGz(w)?Lh72FzfHP))X_usN* zRxzj6d9>=z`cNO=)Q>RDdon61>%;vPMaf3Jb%M_e8}O=$8I#xhf(9S4$ncFZ$9qU0 zX(t$7W$o?v`82z*M#lhXomy7b2lEYB_3s}$g3Mto-M1oe!zEqSWGDS03SDv*kIQB*E+9pW=u=7?H~Dk^ z_Mbq3tkmI>9v^-ff7&Ux#IS__TeoG$i0s4kwsBbPZMjij{t!LDCtl=$xc9Ggw5#vUXi>}R!%Rf+7S4K;+j}!J3*375Gfm2Ll5$u9Y+2KRC$cZ(2gxWXPC9 z>bP@IcWL9YJCmXQG{fLX)vG|5pO(bKkqK|D#N1b^^q z24r&-I&HgH(;-m!`u)|B1!ZEp7JMH>okvE~vLhQ&d@qP#Z$yF4R?-S8O5e|K9z&SGQFI)lqus3YyXhp@T7a7v+y;mjS=06wR3zp3s8Q6LZ8xD&OD#mbEOE12-Icfc~$(rj)E%Q z>Gm^~eZsRBdS0eiq(A>)a2O=3CglXdoThCd*;(}Lg8!2j+N z3L7!eE@-;uR7i%)?0c9Egd5VjZ2`kQT!4BXFiQE>vf8(+1udDCO5s(#6Bs{-T$gDE zR|aC}i+(H2${f_bkH$>H1Q!9;9{bb!c97BHBFlL{n)&lvozsb%2~6C+fqq$*HSw$s zJXY&S&snaEQyz1*Z|OaCQ&rE7nfGtdiI4i{U7!6*vCyv9cp~@i+S_S#>BgX^K+*kE z$64$u9?XKxZV_aeM83=u`HudoMtg?tQC3zngFzwBk>etHF7Fe*oY&5>OwZI1-w$#` zj@I@$ognY@X~-hyqZ99tZkC*4;tPvRw@b(FWFkRZ1wLei))mPpbsn5;E9{m9?g*U) zXf9UiPd7O*>d2eEROl}+vDe?dYyLF1?<+bg<;|HXn35X0^nv=J733JPy(&+4e*B`i z8lFf~HUX>UW@ztRnAP6(aEU=k?N&^c9+su$V`47(K6}VyF62B<^je9L5qP-5PbT-*^02W$#b+>cK49XSz(ZjtM)3g!=ATh)z~!OE?(4 zz1?kiOj)?^U6F+WLF4$*Ht6d6DoOO+u%c;y38`8W)@j0oxs`q&Fjii18gJ(=In_1d zk7&N_M#8J~9adPMZ~`=5v#zZ{Lp@`%Z5=!XfLiP2_0JztEqT^w#mQ^FtKB;o`i5ZT z_ri#N%V7!&(4F{Qz>T^EQEUdt&Lp-z7sqe#lA8Y(1qq_&oNeI2(7q>!Geb#!sD+@v z0Yh)P;@@x~7+(fWLjI01=l`z>JfsCB%u};X!0{AGAq+BkHWvxKf_(d}bgTm%D4;33A^)*>O49)v71HckSVag6A$(geuB3QhtHH+@(Bi>~Z%T zy~tSfG6uVams0lA`SSRG5D~cXJmG(kZY<<+=X}md>lm4D<_Zxdq6ZGnAu~3mGFo3B zIS~0sy{YW1q3RW_}%Q2`@0EBM6B` zohchS8cz~#o#`)q+jB4GPiV#K7DT$9(51@Y(rQV-`ZDMhPDe2Yi z!aTC(sv(lkUiWfLzQ*L8JW6|G<2ZLEOvE`DD;2!xzO;`o(<|Q6q)t^}mIy2M`&W8q z+w;UfyemP^R2&O^Oa?uK1;o-wh_NCW06Umofjf_Zg_P3PwX4(nq^O!}dIdO?~q_5WQs`0#8cYyG>x(#zUc z;+9X;&3br^d2Z^pn*OmT4XRWqN-6X`Pg_NbPO)F+i{t^Fv3fF8I{3^}iyW&4-7=E`<$;*Rui7Y` z3|3R>(`=lqiWop>L|OKXQ9E2pnokgR{@6>)WAyl0T-yNJFE?dP#_CdrQ=#Gcul%dK zEGfMXywF+mC`Z}VJlAv{L+-2FQ*W|KN(Z4}?Q@G)bwX?3`0bOoPwT;NHc)mgSaaG? z@nBl2@>r#W-ZG6cU7F_}RF4gj(L~_K%%aFVM~~+&zLMM7+$*E8*-s}86!j^N1ZmrQ zuQ0b$BiPgu{PSQ;O%sa$P@D%RPN}EZIq0izcsw)_xw$b&WC>VX&H+G3Kl(9HU7Zu1 z%CK!GM!g}bz=pzAXMD<5g&))yZC6jWSs8qy?iv*j(FTOGu{+3=N1lOsIacxK;Goxl zb-t3pWmug9pHjOu;@dXI0~pQqEfKups4+}dA}SHgxCW zFd5`xU2N0{o%{WRl((%4ayUW@SAH=+UnW>F&(C&Md zY_OpQh61(}V>g=(S<82ehSwxApDsw?hZjUTmz<0Ouf#t)Z`E?$R`=OM;ery=TFT3! zblWovv1I`vVOFCaY~TU?3}9UflDQ9T;{l3a#7MGUVoZ{3*?{UO zPtZ@xZn7eH2ZGAq(lkibLqxOyXu}VL>n&O?0-q*??E!9vP%sasDRsa^%3yz;p69@u z1Dh`l1zxDw3{Kxk;Dd^nSA8|tEw&vzgv(c?-lzMp-Lx+f0GqdXFF9OVA<7!(AIlR> z<{Ml9+r?;OQJj>xb)U(uws0i)7FU^U56=~Xs%SJGADTnuVyJ*ucz44`LUnHagVg!ZuVaUf8RbE0s^2CgBqE)I$WlqeYBd`LCvF_x!rMBj`}^^?-sv(e~o@ zM3j<3^@Fu@jNnhSI{{HiB<+GyGe`3|5}(86aN|_T^YsIp*dopCB14%xIdVwEqBi_I z7!_Ze)c5P%R0RZ~=s+}+@imBzUt!DJ`GkX8lo;b4TB9FO9 z1m+>p&)QHmBZKWku;Foe010*1>;AJS@>8+n8#1vAn4BUE%Aj3c47&-tf=ngZXszJ( z6aU8095MIQZXWpACfIG=$B6iMP2ryu)=Oq^AV-d?Sq1M9C@avK6CvBu=)`$@m7OUG z%>X~!hYtv;rlp5Y>oSCEBlgafD%hgiF4YJq(;F{FK9Tw}XSpjn)QTmB_OGf#cmABd zSlXr7D%HMNliVDXkM()hzWJBKEm1PFZ`Xvg#;Bv4s$kaz26fZS^9TV}yvt%=5a`B7=oOmd)sA6L_WE_eZWptBl+r&Rno)}c=?r2yI&MXP=#GT8L|(fZz3$( zU2Mz(0ydfYqU-0c5nROg&YreaI@W4hQwF$Y0J~8GHae{B-nQ{3Twdp^3u%sP=ae=o z#cxK4INHQ)pKnx~4vU3;@kvush8I2VY=p0UY=8UeI}>@?{bVGsjJim4lx6K$mDFHn zwd78+7TVX0_am65|IzWnk;#j-F{QR49i~3Y#%4cvby`nNIL|}A@EOg3=dX!qKYX{% z#KePObjZv0FbksGa^LR1wwDV>c{(3&Kt!zx{b1WOmQp6TB_lTomi8wB;0uQoSS8Bl zs8wD*5jGf(qP(OZE(R#X5P)p`yXsFvDRYV8S&)D3@nU5^0~rW|7X&0@-lRc{2!kwK zHf@eqwL`-M*Xtp$*O3!w^B}PJd;P~C@~u;Jr^6+3nq`~)%?AX8uthvuR*4N__b)|?8%YHx=Og7lS<+dvmyEDTlu+j3i13G55Ak@ zPWz<#$LYM0_c$2C?VgkH5{10%`!;X=FKF>-mMRoM_L6N3N(pjvq5F$^pE<`4PQ2@#8 zpJ*VW^Y0#mJcJJ8&AN+C8eeOdkM>+rKu1}wPF^xNvL8ooj=j(X`TgUF%sD6cnvUv` zh>@P}gD0N2El~V!tVCX`7M*_SKWJ>Kt1kE{+ZW=UY&!8AJs40}tR>?3Kgdne=Pui( zd$Ts1_$MGCd)f;=a>=zs_BCY$^56mN05e2W4I0tRbDdfpQhW>VHdpzq(zt&A`{M~e zx%g|9acU2yJY^Ehky6UJb#0$DtN2rf2U^i$y*r@L|HAzZS<&eXT!;)n@xEdW?ymqD z#lcTt#q(juMJ>Gyirjcp%eCr`70>^sDx9dk)FbAijO$$XX`9vzSRI`v#;0KU4%|0S zUsIs_{qFZ6)hp|TWK<`9?kJ4Sis9q*KAj9fVtl?2<)`gJSiUcjAG z#@FT&UMSkxs;oPneq+KMIY*~!X36Wb!W9xJL-wa{G}-?FGS+Whqid-RJZaX8|K18yb z8NsjaBix)emYvEf^JZ(gs{{?V2Iu855rooo;eHj~BK}=O;xS~2)g}5b!6VutUNzR^ zJ=;4TxI_E_4({+D8#v)eb>|n8Bz-`8{eCoF`6?u5 zT=h&-JE}x0=-W)3^2xn>X8gymm47oC%&sUtG7)*>N)E6u{t06ORIOHb$lmOcnL^{ z75pX+bug(WIm&tq&mh;RvYx%AZ_hL9t>r^nmI{KG2$$9BW(Clj%FaPuD5~f?&STd@ zp-e~dQ_%{y4E*o6bPuI$!9|xymyaLPmFCCpq?oiQKJy$poUod1*>MhfNB9ySWf&$yo3hP<7PQT>p7MWvGXDJ%(lZ z?kkPIAp=@eDZ5*!o3YPfr3t={ALqDY%t}Z1FQAi(Ckr#npVk#QY2xL$OXEN43~&0~ zjV|J|c=aVYyxS?X$2@B+CLRB?A>bI#f0u?AO4CIXV+qc8?zFm(k}`+$SE5DtmAVZx zUFCOwVRWa~m>SQ7(qe{T=~`+}o<;cXK7u$-Z!yAY2@wrBEpw9&Ei}`TRHKbSl5B#N zhMT@g;A)=i6^XaQ4*!G1D>8pegbQ5KBzQV=D46xt-LH|@;d!~plts_+CVww`!vtfR zg%g)O$Jv>3DKV1ceo#*}Pt^%*V<(uPImN9;Bu_&TeajPxzhkd=38x{Wk^<^ zE<^o?ug26+(jY(xd`t6r*IY2&dH$>8qgI93n4K7#0Ou0%g0OuVwZU)lXM$%+nlMT| z&b;ivx#lmA&|8hV1sq{o(!w4tzq8)rc3NVQh3N~-!4@TclfBi^V*lz?=Q?A@sEo7z zw0On;I4EJm13n%xYz~~A7qlGOs|iEb){QUvT+a6^tPnLghWIpWvio&P{o4N{>D=R) ze*gbJhB@VY80NU;OolMWInVi=Ln_CjB!^N6b3V4H`kpq9oZsfq4MP_ZIX1 zLzRGT)_?ZEWbsDvq(s;yN*zNu8(B=~|Cg}zse0*}ps1zq$O-oGWNd^vL!+bG*F-5Y z6G$f7FH<2_5OEsSlVEF%Ar&IMTYfc)$K=HDQ@0g(iyS1>wf{IUgJQtH>lG(D;i zCsp{rtS{5n7WSs_e>3_W?Ca)l`eM1_I!&4;Ygz12EZ}KM4-{mXt5~A@DRn6Cl9U;K zhEXzqkD@B}XH(CEj8?LmOj0d=g?DGxSxkcZOVZmZyqgt3ga1%ZliTwr;w$74w*qzv zHT-i&%Slu4xO5_|3~R%fKC<&JY3j^-PYVZ;jo-H((Ap6bZj4vw0K$kV2CTJm_qXysIpXX#}QU4US{eFc3TuawADZ8|#z7T)^#zqBwe^kPEtB2TlmPZ|8W`#wFB(^YRW?P(I@)U&VZMi*BL|U>H!Qq~W-&O0=nOQTUh)1b=cSdTR5YyL1F4Y@$K>goVw84Rw zv*^?*^aui{(f6O*(fr9*9NvE{%eMV`sWB>%G;F6HlNotu`%h#aND<*~O9ON9LH`>i z0tv1<^(oDY9LqZr)g#d%zsU5efoYpV+uxyem~)ZTgbqf1yenksD*)o1x1%KmeZ0M5)Vt z@b$p;YPHJC*D0og1= za5gWxZ}Z>*t*!aDGPi+65WjSlj6LR!rm0s-grINb;N?eYnYeSCZ)})MI25E}ZZ-H4 z7sDcA_fG_%0Zq~npOxEWhQ0UD0$fN;JqveeQbn2>+o^7F3Twf+pY{a2_(jBtK!1jZ zn$EXiHS8D`iaDs&BYsT1NdK-$=}3l)$Ii5AoekJ2_pg)ck$E-o7d^zu)`hqp+C9X0TM{bo6FGMXl7zPXfBwW5ohDhFX9B-A;n(-EMU$$UZV~B>EPehgXr6GJvg&1Fse%*Ckji>01YN{qHICPr z@B~M+2IyN79Q9aE0qqP+-gnqz$qKdZclvR>0txU zIVT~%esd>%PU%Kx-^G~34{gPoolH3?zhnJTQ`>s?jkLi)Tj+h1Md2mxo3l`2WD<98 z;6d?x&ik7e&e)qj%MpClI1aktN*LGc1$^N*LS&po3D88!B`*Pd@mY`ar?b%`nL=3O~{8X?3zX9+jJ58(nftp=$~!mi%S76vNho^3ZVyxS0ciVLO$Ek?P1U zChogs?tFnC#q6=JBebf}(!UDBDg_E2#5)1||8)LYlX~2sdA3njnfk~%qw5NMa(0RI zSHW7#pU`S9uec+VJj3AN#f1O=~Z2S?jo?^dp@aOL5w^sez z@UW`nsNfymJg{rPT(P{EwpUNxHVQB?N9NTsoc!|A;#jyhd8T{~1^K)Nj8UCg(~PI} zSg0%s2(I9TTGOy68uhWQ#*&}5j+^iEnT>Uaf*UC0(R4_F%iX?)AI~%nZ#G>R&bTfd ztUfxW(SLNgBfHJO9K?vt7Q*5~xqA(L%vO=SvO4;p)~#wK!22@4KiVBG_2*XedFG)G z55n*JC3^{+?2Ru}jK5h4KCw}NZigo&c%>b{R9LJ@#Wz2e^Dt1l1hzF_Z?@<>NuFQ% z>)`A5dfZulVSTE^MxFB(W0PHBt-sZmYuaJ#f}bnV8}FXwT=881cLY<>_bKe`KMa&E zwRogAj=zL8p4v-#dGq9~)9?itP%bszaiY2Vq{xfFkLGOAYului1Ou>93kqVdMux*fzCd59H{{0m0B$yaGi z2OGcHeQ;WBE^~z0C&^)wlLDh5ckbW5%P=G91psspt~UgaFx`@%zXSVd#NI}R zY>7`jh;YhpYQK;fZ_&tRr98h3uFc^kQ=9`hCV@`+6z?2L;`4Miagf@0nO&E(uU#Le zcwR)W(d{sLlXU2RD9U0If4#Q64Y{vB!{Fwi*TWfk__N91Y`2}M*sw&h3IHNh0MgJP zGI5Sv4OQNTsP6R6-0oC+R;$c5s^98x_Oy&SdrTOm3AFMKnxuPetjEL_ZfY`T+w(9K z5Qv>p97@d6PY=L6E7gChHzrP@_-w>9Bzi6Pah=;B-25*6m*FhBTBNJkCk(b%OYy^% zX8HWxPEa&a8IWeWQoXhTK=TIB@N;KT>d^OE z{5*Ne|5P=^z)Nhn?-jdLMjp+!+19R$jFqQBc7Fo|o?E6*b{O-EwXZt_zfw-p+~sJn z`3Il-1LqzEwwysoL=V#N<(lR;x&(s9xFr5|RvcV+)x+rc)Et6;wDHU?tz#|m7z1S2 zjvk#i_V@}9ZLyKB6p3Ejxm^D$sO>vPGl8%o*`k># z=NWIJ3w%~e?5nIy5wWxxfp>jbPvi$8_sW-IB5ga=AjaP#M}KV{H_2rA@JlV&f9V4o zq^H)(TGRFpn3GG>1sXvv9Qh_~qx$ilLnvV$RY>22y?V?o@Y-hl_+O9euQ3581&j6- z6OH8l8{T2T%%lFNS;R(%?%v4H1vf?ZXcC_+P`PpokJV$lsZMBWowWeCGahN>$;Xp`9TC z6A72v_k~Pgpg|s{xcuFWw6ZAGzV|gk_srqhe>~qf%knPm&-4aGwChD~*q-D0|N3sc zBbqygX&|=_0@H+=P+5(Nz?2K-kIhSQ;b76J6#`C9<3;>8kxj6hK5k?Hbrn8g3>b28 zRp?R~fkg;>7QprKygUzJQUT8+*TU^uHIR7`;OYzFXJ>&m(#f{+91u;eFCYE`CGcFy zje*$DG75n|82xpHlv5e0V8qTO@!wx@(K)@H8T5es7YfRBbU@JRg!&$DK-hhf@cbW= z%*lR{Cz=p&w9wE%xLbXhk5c=Wp1lrjfusU5&Don$%cUH~mQ2nHd_|w$*uA+P-m+n9 z8-$oSE#oHFVyb1*boe(FdOll0?1|3gRi4@dLG_?OSqk#*(0Rba<(G9(unPQcR3S5M z483+ogjiT-nHS824wOVH^s{f>eGrXS?7Jb|(a`uHj!B_;@ zqQs@#)-S9aqoSU1DexcLg8@7_Pnl3 z)sqt+>si zts@tn^?-8>+|EJm)+PdmSH$IIe+FJYM@rLuTO*>y<#DQIHrzbvh!6hr0qI>f@dKyZ z@TK`(6TkUlm3sZI#ia!65dGmTS-Vfq9hrW}OaJ~BCf^1!66T>xS?0XM|N5yxdq6}+ zRJ11PHAY;6PByhkVgv@dg7C%57VqdZ&3y6qBB?}&kTPsWauG_@FNAB@WwT&N{X85! z2l_rrxsa_-U_sP1XRlGTIu1^P=j#?Q@;7w z4Qxq!vFVG?2etj`eR-jijUy6tp`kw(+vTw{s2H*w@eU}P=Q)U+JKDG6MBXU5@`HTF z&)I6{jg6^jT{iDL5aYm?wP-!{(rjYsG%Mm!{z}ow&1nX=Ou$o6fAfMySlR^zc4=bd zMt|)o-lu}Y+=%^y`d9skQXP8VlydqzsUJoZ;yE&mScv&Gs*HIcsFc>~0CW;3`7~Vis zL6VKz8j=aFr?XpPT0NI1O1>=TjQlI{s<9g1-w%m;6EQCIMu4~B`jUr?OGjYh=%c`lkk0CG zeWNS*YOKPj(b{7BtqYXM8+J1);y8K1-8u22S?l_g&n~9l*DJlGMEu{VUd#GkDx+v} zMlrH#xPCdrkFqMLh=CcIx`nA|Fh;0pNB&;U69}EQLJc4Umz;gFWz^b-|GC?9Y*mlD zr#G%@l)_8jak-W{l422jP8|~pTUHo?st(oLlSc;F;i?H5?qkzEh*x#(A6~>rt?f|` zniOfv<{_;*j^~j*KrV94F=Q%9{$#lI{8yK>OCiaw)9t5TrQk5ayQ=2}(&*A|_0WfFq>)^SwQPO-7xRFYI0{G-g`}RT5vq9{R zW@_i3zG#OV6aM0w)?F^w&+??fn2G2kmwTi#B~AP3W{Zdc-@1|Zsh;DmDapXPB}kT8~lu5(2mW|{PelX zqA~G=`J!nexU~LH`uS8OtPhW&^wbNhJ_@%I-B}urfK@lV@rz^UAHE&=3VD69m0NR0 zL49beg={yq=XhmZDf%q6@Uyd6tl6Er@8F!_2Ndgm!&NPdcj!qmt*N$KFlyv^C1`=U z!p(8Z%pZwe;mParKeOH`Xh)V;4LG*RjZYXe#nJ`7c-CAi)wrW7s2a5vq-@xGty!nu zya3Z;Ilx{Hz!kLJ)(k%vnC(Ch2<4yIOZt>hadY^=<OyU@{oCN(2%dNV3Jl+_@E zT#L&b5r<(;Ze|-N&(y=b%w>GAklP2xLGqVhpS)~=U|b;ylbRj@eLUUt(Kj*~yVO`J zL@dvU%V1qhJZAy0Kvr?*dNjj1lRm+$-4zEvhV@+mO?D_Mj}fS`{s$3dNw+Y&PLTpu zTD{`5H`2g`+ycGkthq)U2V(?vM;~I(iCN+O3 z4K!SoIIE0GADyyduh2z3C$zKLhg2^TqVJzZf;_H|>ci z{3$i8st-DC0IO&ai;EU-43wT~PKErn{Ng-@MNPt5qv@MvEM7!6eQgvc=g(S3VW~=5 z^&726nmWR_AQC{A5(S3<(Eo-h2WjMW7~6y%)kzu2TXk`^L|CPO)grvID&5P^opDKr zJx+%{an<9y2WOue;=0JE`IVLBynLqnTw^g&KS96ugMftaeG1*D?cm@D-<~V1mSBt>iI^Lz4~#1*ZxWrWEX9*j&D??OVz=6MzX~%(|UmC zdY=pBMo5_`2fHI3MU5n@V${ja55|$G|o3ZkZ-L3 zKJUc0di!rA z)ul&1lvM-~=CC$oH!k(T4R4gD$EZ+`{?f1W%@VfX-2F()aul(O{Z!Q=%;cFSGf?T^ zzvXrC-5G%PcQK$b+8N{a?K&OlP@UO6XF~5G* zI{QJah9hD~JB!)#JS}=OuHsccuX32-k8cKCAYdx0oc8xUk{DHfRQ8Z(ibIuy zlfXX&vDmFDyplL4(XlOzyrmpjzMFa+oO8;XGp2w54vYm>p-!^XOGSE-Bnmi;iB93h za1FOZPoHxk>`u0#vz}_@>g}E@HnE4S1g!mw0j9rFJMaA$jajy?1kUnvQ!xlPU0l&{S2bnDdWiIlV!3<-mrkvrZ_)|p3QcCgBL5K3@XsAe5vygGP)1YYNF z@7pa`260%m&G*reu)LZa*j5VSN`0(jYt#5^ST57c*&HPa-d!y+{Z=C4#^j)z&WBg# zsk~8$)eFWas`TvM(H4`3!UpIeW^?{xK1B0ckjRis7u$*h65!Eqm~=f2vgIWxmc<9oK5T zTWQDH*`vrz@@NCzXL4PW(6U$%A`-{8v;r=YtO&*XV{Q^2v$5~#*)gN&xv{Mkb>Se!=tmf?!!PdLhwj|BOLEIoHKvvZ=Bee2_?$PQyUDGHc zncmYBG`;d{wNPDxo|V0>ce{8EnT(s_9rmvBHRTi1zM&!a67-x8&anL;ABUNzDX;v%h@2E@tI}E) z5-Gh<)9`;yE6cx@@ryq@+wZbiF@j54Q>cuc#)SwiV;N60zpGwnE#K}xUKgT?;}2i5 z^YQbvOHP+mqd)8i{pe)1s*6NgUq&*P+El|H^1Xm0dI*9A@ zZxLq6@C?t3aXC%Q#4z3Z7Mvk?->{GkU&3dMaFJO~gX(jkt2Rv)IK>=bM0RH_LW-+H>UwpIax|qMMPTYP zgC@IE^aP>nL9!I1xFE-NsQ&H_(2c&8xc`Z5$o zG_W`o@a>sF=^bqIOT{nGAFtY!&?0k_^2MQZ;u;UrQc0>16AStm(Zpe5=jin@U(; zS6f;$8f(?&S2^rb;W^c}n$e)p?#Z3lMkL2g&CHcCR6lDsY0{8h_-GINQuU)Dj_DWj z+~ug8G!0Va`~F8OW9_Ib%y{u1H3#)2WhxdN^|U#}nRiKM`OB7xUoO4qmz*xBOqGA2 z#9H#Safx?w?&XHdYZr-k@B-$r;aY(X84m%*0St`1W0iv*Wj&J@RzpYDNd=@N7a^NA z4>q0qxn)ihszsDp&|7u}Oz&#psMOHNs{{f4&*gXK~F z^t#tSSvsWdlsv6kaz1akhN6zydQ@{}z3G#Sl=R14C-A;r$q%!@91%eL|6vC2Maw+? z)DaG112Mr%j6oD;h1tYow<2~;Ekw`TCMU}oJZMdXUhe2 zYpIZin8k~1BUR&-_|67(|MLR%UHQl~CaxMI?->P7td0NiLA{fbszBAnf9JpA;T#GQ zDOqBo5}3_$x@HzkQp-{YG({|b-M&dyw&xAwhR_9Cg?RYDg!YbP1=MVmRC&xjQP)2I zB#hU1gBV{+^}^*C`q}G@!q(;CPoxwnh@Z7Cvw_e3*=ext-ObsVkaMSd*exL7S7UzK zRGK4gV}^WCox}Z2fcDtvhaz+YM~jHRVJphOACQQ@qXWv@)Bn~W#y-aQR3<>*mGD0K z?oUiOq9;n_^y`6l^dhEyI5n6xynrHdte_^OF*4~KmcaW4diu`$dts94ok~T1Dh>KR zc@eM~z!OrRwf{YABw3HPA|O|e7l^b@KxLh3gw4~BrU5CM8~OOgtGXO%+708mm$V^f zlob!EywbrTCP-9FIb}tnWU^P*Ejvt$pDB{4=;+~~wn7|uJYC{(2m6~TGP&xjdwSMznuT{#d?;nHmcz6NjzI9+R;29hr^$uGswV1}F#d`QH~q^`&bsqncU@~RFy0!H z>Jgk+rtKSfJ5G!8y<_II+UBzS?cBB|<8JFMnl*?U#L z+^*<*w3m=RM=Tr-aZi`d?U`Ip@PfB0D~{Ak;K2JMtL3Hm@ab(41ox{_rhtNSiPDd` zbylXvD1XebpLA8@(45Mbra1Wf2OP<7M<}b4^oQr!kBVq0dv!x+hrO?)y38?_ zj8F*r@RCGDa9*ZgA>Q~z0{u;%-|XW6*?_yNZKU}dc2qz)csWnp z-wpP`AH(Wl=z`+o*cr2VOY=XQ6FMB$BLSR@y7|%nonkZE9L7I>?81=AObVN6sNKyS z^U-i+{yc_1i$(4-1MUU+7<~kN%X+CV;!*f~xT{^(pu|7P__*i$wn2_~^~65J31*q( zx3mUL%!}MAf6FVQtyH{G<>0VX&1sGP&;(fm{@QNEKpdVG744BO6w+Y#`GLi3frD<8_8pjDA!`b_STk zAn1I77`;Ra6%bZA6*9P401ky6E78H#7efU@I=H^0kN_yC7DA$yOP+HaZwUI3K~T1i zkrP2x>mx%y_A>I7z(S}fh%-E1pbv;Q)@1V3>ZK$)(nRW&Ql(SDt-QEAToQPDO6wVp z8zBIX#R2R@1h60AZb7R7_geV7L>2?kd+q=H0dNp_OFu3?cMz~&E=6Y6p69tm#)U~q zUNx6%{Mru%_8vbj`d~T~S1Ut|-Z14eBlM|GeeOjCeJa9V5ve`fhUDBb*y!Mm$#P-( zT0|LdT((%$b9Bc#RmNeC<(V4^I#6IF@)BA~^wg-V2o^Qx^i#*`U(qZX?5bG4EV7gp z(EmPbI=Y-|VVPu?1?Gr1YtbN+k0ea_b~X9(urNDZd77V6siqI{g{{D zZ!F$(rZtPCu_aUY%ugj5^B!jY{F*283e5^nfPYPTHz4<_?SmCqlc=%|H^g)cDg_d( zZNqs_j|u3vVaT<7TM!<@8~g7_cI&2yn(EEutYF^o3(0cbTi7m{y zHxBsH1j?A`h{=)xuB7Z!z0B|cz2~G!nx)gl^>bpS*sbXjG-?bj{vs}jCwpH=PM^xl z>$;6uLuQ$pWU~5!k;PbImK-woBHcq3jo77_4r$@;xxgYU|2?Ji;PUVudUMl`=e_Fd z`rY{}lGdUM>Q6^Rx;GY6QdZ;v5eY)Z%Josaf7MHm^`Q+I;DXB2XPj5~n0?NFs2|So zZ`-%mm8i;LV-Rbn-H0?#nQ!Z1s=62y#Pf9=5vO6|b099JsNgcYM%uDHhg4@Ytmp+d z4UeXpkc|iRDgB7hFw2Xxr3#rcc#X=c=`t1z`1T}L&xKd_`47FUbBeU2yJRkkKnH^{ z67mzwG2Pg5Jz16@gl!b*X7_8_Uza!1FYmws+zgYQDdGt9wB8c7|l{u#e{P;YGg^SuYx-`$hAjr@tL zU)A#^tv@KQG>NIRKNU-dgZabcRmLyGLIC5eWu!t+>j>f|YTB($0YESMtwfDNDTM6b zUS`_1YH~-iNOsJr$8T{sn#+xi@qrtkc7uuS`?enyLnEGs-x!JyHoW%+YokmV-*?vE z5xO1WrS5KE7cmLHIrGX~Jg_0LI*Y$Z9A?-pNO2LGD4DVGkC^NKiDvzL!?sxN-$?J7 zK`ocFHPc)E-XRS49#8i)Xi*~EI?VL&8z1NCz;AQE;A71TMBF<-4n5+TU!Q|sF`bZa z)3OnKD#Eg#yfZ^AlsT_#F5u_e5g@l{SX-uzstRS?mIQN%z1m^d@Jw}e4bpE%D!(+d z8r!6)^?3Hu&H z*mmyiHv9|f{w>{m9O!;IkPx>U6ca=E@ci=wd;GgGNDOsr?};A4|FgcEO3IMp$>oJz zYL#um(YkRQvtqlRpcuZN^6nnCM-)pH|Enz`qU2TfFIYL1%1uiEs=$N-{{?pOT zlPGeZwB;rBRR+BrBEMNM*>Kgtc%hh?tq0Fgvf3OfmNdRH`Bnb!7n)qXVvQc#!=f_+ zcKZ4Lp|m4cYxm2fDZY&NQ+EgUswWM)Yf4N8r;yugL{KeIA=_}5k3OxpI#w`G9Z^Lk zD2+mQ?vi7wyryXv##92nwKmkhHTpIBhOH>#Z7%_ptGUD#VURF!wZ<27>Uky`d(WZk z${&K`SJubj4OM6EK>hGWdG)o<#dRFnl4#TBWCEjJz?HI2S-n#2czEJeznBLX>(&Le z*5&lr@}ZryR)IuRydURMZbA|!mSfz# z&M`T>`qwItuYllzc0Gdu#>h)dfy;y|fgf=1aM<2hU zi|=}E7g>{JvcS-Z-8#|SmTSa9kOpic$H7|8X5R&$#DtR$>cR;b5aVxvBaD7v1u#@c z)GTR5c5sswo0^&tMgLkL7Nu&;Edn9Ua!=P4L}0GJzb$0IEouMOieMFp^?=Si-Y7E- zP^Rg?bR=`n;>2dn5y!m_2byVV|Abgcep>r+Rg0&o=mQ(-*D-)stAfHh?HJr)Q*&6@ zC_nbNzhL>Luh&^F4ud6NOg2pjy0X?LnPZn8M!Fyddszn+gZq~sxa0uxRgrrrN5J+b zmLlD+QjnZyRD@nI8NzS7I{EZwhx6bJ{(#dSDJ3yxtwjyBXbjzT!qrlq>^Kn{A!l#y;DdN|ks7Hto?C7>4jU}VH;<|5N>acu8{8mmue~hOC?v9EW|x8v*M#XWWL_el@M+lk`=7qHpp4LdFWSy(%vzQ zVVE!=Ce+!DwS``v*N2WJ&tQgx89h!s-ymR9^FRw9pw)I)~Zv@Kj$ zOC;EijmTtWwJk^PyEl&`aSu-oKydo|FOJ@N0EQuX>%(gX#aKR=zz0;w{;8E)Yf^Eb zDczd&UjGV;f3nM{#jVwCG%K$gBTeKo0Er5v{E(%}B?w6Q%Cw;fc|Ax2wQ$>FhprW6 z3)cg~o*iQ$c-TMaKRv?+3f>R-hQD#S0y&o9taqgo2VjvMx!6X@ltM1_-EA3=jDKsz zXD*s=lE5>nQXasiaEg16;xgb*0FNU0_br!vJs-)K2h8U(XApc&&Jyk&BD`irMDgIgO**aImcyIUDW4UkaDP%yF@%*jw z3?MakF)?#Oo~QSv7sMK1x;?xgCh{!F2uCRp4l;3p?BJB)%lNjaH|U!T6G4#WyuQld z%rtoh@IIk2nvj<(fSha1kP3n9V!=bv7;ti#{$p@QVpG9MpkS120#KhWM~mhXaPJg96sRM~ za%q~6v@Cu!Cl;@DYO%3#6y3N_aQ4rhE%x-#J<9#jWd6*GKkxnviP;aLerv0T>2lRa z)Uh6(3(e6h<=kU{prF41N$*1b*s>mKpq3d_TZM+3ipr+n$p5Yb#T&8PcDTFgWy|m2 zc$&JO^3MoJ^J>VIu+u5f#n$0alhd)AQJB4hr3QD zo0-4hQ}|Jqs*?!vwT?LEc!MES=5eU-%Nr8~mn&FU&+B~WvSX_Dcl1b{GcYWCeYCSv@)Fj}Mxq z(tRPht-%W^%5p1;v4EP`0O6!c4=^+6^8_(rM*JE+!hVqbc(6Zra1ZCNKGf3s0a!;S zCp%vch9FwFuYvV*P-Sh!G9Y zJjI4y)2CHURAhoc${bitgRUmo$LXHPCh}Rz!mm^rgMB{fK8f^3h$CB#iBZ=v<gQq-?FO~f7?0a0s)cn^@@EZA`E; z1_(XduCy%x2>Kb{EwC7v&}l7DlPyq#;C?K?`dA|j)HsF^Zv)&yuepZdwDv(8o}?T# zqchfI@YMM$sWw>qiFU|cxm()BfrqAXJAHG?yI^jqc4|9h>N z=x_i0j?U1+<|BRXlNRsm7j-Bt;WomNEf(_YD#u1Qf+`&yvEO13h9W1P`bM7n@b;W~ zV@*49(_`P;u2^EioI`@^-CsS|7uhB4J!*n!QMubk1&S&BF&+EGbbL|HYY@B3G5$u^0kxR4@wi8jEBZ0?>RtvF6M4(R ztc4yae)@84NJzFq+{fEKh};lSKV+6x|J?|C6R>UMCxW;Xn2@{97Dldx}BMMa}bMft_hlIT9jlus|khRbF38@Gd3aiUtMBlO;q|Eff( z=CqhB;keQJ<_Pk$pgi2(sYX%vrevyXi8<$mCZ3$0KK*!oS6QK1+|tMXKRqjdTo?QX zyXBC0RzPigA0_^fHv$7~xhBr}{$j+1S>h+$j^~?&#%e!w#{1{(p;f7NZxdUv;%$nw za?(Nd*m{(pD@Eexw*jeGQI){3g(N}0v7rdp;>jL_YvE{ZE^3$R!@cI_XC>&*V_7L4 zzw`2H{o9mZN)`kRG|1?2q$9~T|BlR(;T_bNR2 z*e<;|I`|ueV_fD*tTFADV32IApEE-((tNw-m%0#PFQ@Cw>PIT9^3<08H3rbBmh@4v z!SVfoTSgh+$?v9VooD!7B;k2Y;R>vySI5wvcA9Wk?UoZ7>qZC zh+9CuWbRlE^2^+@fkmyzL%3t^2RXKV5E;YwNFn~lyhSbczwwLBmT3#vpUb`LW?g31 zbk!|LTMpXzsVd}LP{&}(7VO5SS4*+K>h(B{{wei%tOSrAvG1DHP8UPmlSlm?=@B?x z+6ok-Bl4RuA1o9e3PyPFF{|^YDTmX)mOT-ARHs?HMTmQ4@#TATQ%{s6=hcx6qim2T zExE63SDW-iHTu^!YqPEOW$&NzGRRP4jKu64zt;xt7SHapkD*EX44)C~ANYf&)iE}I zp`({?UKl01{vo(u&>gBT&ADC6tz32H8tpOdf>U$i;Ltt0@^lnd7<=Pb< z7_ddBX-cB~9Ofje8~j>rB-ljsZ%gLLrWsI|RJmgO0d^~(?YL$xdPtg(M|61k+NcPM z^T@TOiz}#^m3)f<&;j|ofz~9#ElRJDD9d36{MY0rR)LW+C&JK%1|fO}BVe#2cAiY92-fX++ULgy)rFbvMI-uz$c;^B z?T7`J=3#Q=CLPd%72)TN^T$Mt4UGGabzKQJ6}dcaZqYY@u3Xj7$6)t+%#@EP4CS+> zzkA$_f08%+(t=|6Dm%#(*Y}Ee2rN_nDO_U?kI%~V$a^yoyLUE>tqO+wU7(L)njS25 zQ>OTr3N#Rl1Y5M<+hQ2W*z&C6EM>7&9ca;J^1*UZ(tsCO7=06s^1wtq#2Dd>qqTv8 z7t8w)(^WZxM3G;^33WEuk{N|Q=P+H#{oiiV>Te%KgC`HgU|9Z|$$6nw;V$Uh#vAD& z(u1OfijV&h{B9$8!Ve@{^jJN9ZmW=zf>^Aj$MP)W8b1Cv8{v5`le%aOgH|;O@|_bk z9l5(ZV}w3(-PYq9UJF-wMeB+YFr%x8&(m^VzAI(okmn@df`J#>C`#?&eDl&j>f2(& zhcbs)rKjEO&c+QXBhWMYx~@w;qJnIb%dj<~XZhb$_( zC%$xmf@plmi^x^4QALk2OFD-IXT55=Y&-|6Sp4Upxh?IV8&xGd#w*i|xS1=;8sOou zX~&jNJ{{$+&lMN^#F6k>0ooe#_Y_FNLXVdc*yK*p#n(B6@@-oefiQ@f$^{l_7 zVLc*~Hi#(_e-)?hn{qq}l~<3!$4-mIa4n#_X7C_GoMth-b_0GoVxaqtUJ}oC7zTX3 zzKdzweKuOFz2#oBDK1DXQ7R&O$gs9I;}e^0Rbc?15#lXUuKM+z{PzLQP6_`cD4!z* zoV^)+uJhXJM0g+lh0>j8aS=Y^c*|HIJc=@YDjwC+ffe&2lo`L<`8Pl z#~&mhn9astmU z(ZQT7(5LIjawBG4-*E?f3mlp95xvp1<0kFn;U>VzfFIBC%j$mb-yITLZuw#fU^^UN|m9Zddtx|i{`ky2+WKLxRL zvL+ir$zRKu8#i2qM0CClQ(})VG)RMTx+z0m zTHY4oh+UcYHY&&)r!l$%uv#CTW`^BK9|3T|wG7wJkpA8C#y{NFB2M!}cP42B13saG zu|U+dymEZ>!GP#%V~L6!6laf^+4&n{IMDs8>plz>unFLyz`rC61rMsahVBm+u!-R-<8V|ajyP*wc}FPN0W5q8p#*^Ii6XH2tY4)cAtTH zKS(?*E6#C|*)x6YsL@yBV-{iI?5LakdDD8}8!kY?DF;AA4I=@mP3q+t{m63a*>7o@l^RmK2-#$W5K^{Ilp4yt?uT|qGP11aEOp5dtc_uwp1lD9;A!};m3 zDe!^Zy)z&=q?s9F=p0RUKkc7N`zVlh7Rqxw%&1OFM%I6ov~JZbFFDn=W zoE7}ISMAhMnL-*}3-KL&4k|x|d@E!AI8uuT;PLCU9q2UiK`h!azsB(Rq@%B(*f!Zp z<`**KJ1LS%wWg9L7l+XxcvfBTrle0Ycg@74utN!y6E%h{jC4DEL(KIqkUHvYD3tc1(^>2)7<52drb^|veTB{F8+%DtU5GqneYevTt$f(a64g_MwtCfy-{v8p`ZLM^c1>>!ggjZ?S=fnk)!wv*c!lze~iIHWxi~%7mGryUS*z=1U zv!h`Jwr1MAYz#VEL<43`Q%k*s>+O5Gw_E%suI4G^&P_k+)1!4Va(l6Wb;R#aLisc# z#9vcd%e8Q&s^uDg+QZXNr(3skM^bXVTpm48^a#dnYDz*!H7xe3<5ma>ic1d(-(y_E ztaYDu%^WibpdY+WbW8h^ID&a>*s4+yp5ioZ{^ffb;h{aw59oX?z zla+VvHZN91)*jDfkpsI6AK{-FJ4POC*ag|3KCI4a|G4|+HvxEK3B{6&)zHN9cp1ET z%BLF$5)-E7d9T#(JSHY~s^6Kt6@M)q zRI?xDX8DS(Nus~R7edXdYok4WiuX2khI8jUP3}metY3|S-^+*br1TlIFW&cak_Q8g#gZ#J{!E#ot`q>r}uUsOirj79760J z1ThnPR8UQ7BzEjQs_quCZ&isFrS{%iQG3%;l%hJQk)TFVv{bdBsL|G_Qv9Cp{rtyq zPUMi2eBPh;>vdh}_%qd#Lb6-Vo)~Q)F>l8}NAD-o*uHub0)VcyjW~EAu(Du=m28f` zqhzyK$64r(_%6rZo2Dsb-XW%8j9)VAt;b>*J8{>%ez-D0y%4d9m78+Q9)XF$H1AB= zFtq6DA;E!UA}~eJ^(4HfL4L^^zu4j>IWwUM&w9eWKJ0rEzeRu^?|bk`DCyBxH9qV>G;tWe#Pn8?8Jv)-p@!_$p? z!&iLSBVg>JCMQ*-ribjk7(Puq#JG0w1Gkp~JTfl^2|w5J(SyNrjaQ>`@YNHq-k#<{ zWL!H%W!82_7)*@Q4M@q07&_MQ>5=T=ypXZThVSV5zsZEYfT>@C3Up~Iur^CV%pYs_ z#1Thd;a>}{gY7&P5?)Zr+RGej&Ik#i5r!57yZ>jhimxOgdE=iXFcICD=}HS_Sg^#j-9Sm@LQ@Uk3cO*Df&rAM+Si8dV7 z#^f09Q>D9aPM!G>(u4#bsS?^R3^USt(V3Tp6Pd*R0yb3*mslr{aZVu+*Dyc3^)R&e zXcOC_gKJQFIbw9vBC+7Hbdx7D5MBXlgjG&aMS+9O<(Shslv6x`sJ)gc7gK26%b@X+ zW4=T@et)Bi439A2=hh?GP#zEdU^kG6b8|^tkMO~1tH9RMuZW4Z`bB3H=R@Ed=;K;D zLsh(9@RZ0&?Yru>NxEL)t6BB;>SNbqlq|6EZIsF!<>IaV|A9CFzDE{nPb{Z@jWGSo zSls3IgX|F2H9+)mdyvK+x8@d zE7F*4{i1i!_VSw2Rnh*r3{-m`tzA&&y`yG5kJ>~uBAA_H-C$In(gK_UPTNfed)@@c zP2ISs-8*69(Ro=k6r**b-S3rMf^^GfzbX0{kNZAcHZ@PXkzz#ASHn{$C3Z z?3EdB$bfcnZ=$(lSa3`;MJ#itUfIWBTpVWO>;Sh1Xy#LadUSrjGfuh-BwGpAY7~AG z%>lF_)xiAQ0ELjz1cYs&<&I`{WvB!6xVvWm80_NR{*xooMgyAYVeu3*U4YWy`m|!c4I-sZ~aDPj+oa zHg-ePY9t9gP{nTYCQycEbUsfByclL<&|VAQ=%VY?AbNsl>*#N6GKvB9&?-t@No;N( zv`N8$vA&CUWZrgbJ{OWwqwuZ(tQB3^LYeMpeRrG%9d%~Q?{PI}L|Q08-cw_Y^J`hZ zQ#c~?Q+vd;ulW;=V+DAMmbvC^xjUo|O7{ZJeff&Eq?T!OmV@wpvAMQhz^flVLl7z4 zF=S91s5;0^a=Q@Elx54tL#e``Z}EKa%IF$^d&;LWM%9vC4pB(aFY-D%moqhs#~T3F zB7peP-T1fH*^&7wJJauKnPM%Y0E>?ej?fcZK)|DiyD zGD6LcNx(-!A%1Ss=YHhHoZd`J!m%9@Y%M|gg!_`xv~t+$??%`Y5wdZ+gKVzCqb z$7Oh+FDsu4v|=)*)+segR{KUx_ZOS@a*7B^ms=|7v;7ajy1 zR%Nh$WUaV_IFq5pPrF{yjjBVrwAOqJ9Bi;QOG{44cx)Kx+rf3IloTb%+_O;Bu}j9B z%kWZ+Ci=9ZOz0FWthfLczfVXTRZJQZ-Lqo47M6E14Q3HuW)HJ=cS+%oTrMx$^zlt< zXu!#`DUXt$Mc&-fapYPqCH_d|L{VsCEv>?=2DnpFT*_a*%4c75>pLVvi(LL~zYy5~ z=n|&xHTQeTYN%v8b!F9UgJHK9i3p%>G0&BD=cqpAyNS*SAnZ=f{Wz^p?D3v2k@^}7 z2nWLVeN#|xC*m?2UP}Cy-*LxjMkQDmD_qZ848E+;Y4(71yfg%Gt4nElYnYVJ&450J zD2319hCM(5XH50{@T^5(R)3UrE$AXb)~RZr8)pZs=&(y4cg{r(@-a-!%uJL^1CtaKLSLm2@4}zopA0p==R+ z;Z=gHX}p$XLrkru1vtum%5=Jy){zm0(8GyulD@)cL{8_w0$vsA^O3olDicTlU~qV zD0bvqyJH|(ebsJO;no*g^qZY^yhvhi?~?1{hR`$!)h++$ZdE(yWF3o~I+22Prr}^p z5dGwK5D9D6e-Oa>#4S4#r^B)Xk-z4TJW^TG4*83roTm17IK-sD>AS28VN@KI zDfG?Hkp<*V1Fk~+Buh1E(6?#|k6G%2(Zatb_#w*AmUC4Y^Z<9ggW4?*`=sEvxjhV9 zE3FENT_Rt`>2IWUBSRp0db0SX3NK~r9_cNEwDoot?@5{wrYXc$KY)aJ_acSQF}Bt< zB6L`7$Gp`kag)B^#xW@1XiAjo_|`P#s=R0F&xRj_pVi2Yp|s9+1Q9I#xvdiK-Y0AC zvDJ@g(`xh&=7M;OD(#0(y)!UnPe}TwSvkb}wZA>1hgHr?V&6BacG}FtWS2g{=8v9P zn)GKXa;0~Ax;=yBnm)|s&2BkqP2?M1o*Y8Mf%dOJO_2$besP!VfU`Vffz(#BJlx!U zzkI&D`w2*y`QI&DeHgF;xe^JE!P{n}p*oBGTUCN8^gbry+hZpi=DeDm%F+UjIz=B4 zSGkVr3n(57e8+rMH$jEF&K4DNQYtp`z-`udbJFs=W9qbGOCC)o_y>^uz}JxSTxEqUcpOK zK5|$#OV6t~3qJsUFsE*9PL-Af^(J9$584Q%f6#uSW7Je!m=;wC)}zrQ%$w&Lp1Qc;JW-16l4*AZ-_)3SFJ* zjf!85FmNs?e(20Tr^LFTlZC4aJv@B$$bR%wyts$0f2mufb!o+Y;x*|i0^uZ+@#F#g z+`wcmSTgIjc+XnuJEVk9^?^$xsQeIFthm@hq)q6D3G|B`aVsgr{c9vLL$i^$RX%sw zZDq$_xft+Szf0b=ENBZDe&Cg%Ug{Q98vH2WO=_=wejk*|%KmvsbnDt(r8PE|?(uF! zAYE7pbcg)b5^gm_lYRe##_NV{hg|Vx&xKreC8WTeEyuEWK;aPZ?OPh3N>A@wjo z4*3|lk*Ug;~y3}LUC?~`4y zB$gh{=M(((RXB9R=D#~Ct%Gk#v{Ob@XpZY`2=QP!#wqwrFFr8MohqCHrCns^nW{vH z+Tz}^fM7J+No9|Qk%fq z`C_ym0vE|q+c@r&ebg*wF#N#g9ln6~!R>~IFEJ)mNq$xD7J1uz_PO`uP09=Fhe)AQeqZ%a$Yc&<3 zhu;;B5)78C#xv#G;KyQdM_aQ;wNm8evWA=ro$YkyY_rFYI#n_)LeG2!c?44I8G0u< zUOU(G!RiLX)-uS8GXzCsR&IDE6qr98d2nB*rQRh_8v;6Stfs7zJ{kF6xO^?_A8naD zMrJYs&75~^e630k_p9 zWKJv}xy9gOf>n6V^ba!0YOQK9zY|>2cj?ZJ>rr{T1~idggFNK`wAnXjX@qG*z=imo zn5PRF>al9A!ZG8wwuWWd*mRAM9wgA|+@fcNnm96jqq_%2-muj52j!|~ZfE(=vd~%# zB<}#W=O{rTe%V_AIaC1t1!vJN)0F@9%Eg2YLKDy0HT*HbM z`1jKQg9VNOC~{cQeD?tXrh_OGU|0cU2W~h>#PeyIa~}|Z{e(`d1N#vvjS_lSU=2fi zw^H}76-vv8Q;;SV4K!XH~<3sRz z6UTjBO|0-S5pXK1iBZ<9B&)=va;n|?*m|I;w{_y8QD*U&gMlLeNvL2My>e#bX^_TT z?74LE?iQqM@#-xkYR$@4&%rT$Es{3Yt^{6h81d=vv`~BN+dos*W+FB3qwZ#XRV$jA z*4eLTu-0STOsbuD>I(;x59-|W%aV5NfkCziD$yx|4cDHd&g7U9C2fGWih~QaM6Oqy z8=o0|)xI;{G>6YH4jeYP)vH0urW$KmY%Zf&wHTqJy-Fjbx_fe%Dxj$W;lOD584;~C z)Bz&Crm}o@jqLVH;+Vc`Vcx8CiO<{iZ*n6#KW6fju5!wL`mqR<8M22)%#K8-ZMhx2 z(n$|UK(~zEa6{k7-!8v#)4+U!TYfUZHsncE7~O9np4`50p142LG9}N#tV`@y0@J4E zJiLi5z_-<9a z)lbH4pbUc#+6c=l$2JZlM~)?pP2$Rp^mO#}xB(`T4)HH@LLP=}0*Mb6-{-htc>qM+ zjs({S<0gq_X1V;VE#>UWfKOHm#eU5QpuLQ(-M0OlEhE75=+2q%V&PSs33x8Y@M_0tDXj3!b3Nv*5AeAFe?BMBr_|mFas2x2pa<8&b1p~*3 zylm<;KSGL?pVLbeMVBofYWeVz=^1=?WMrIbB%f}w%MeU$#IE1los>;I&5ehBGNE=2 z1)BVfX#b%rnc=|oj6-Ka<+d9s5Vz^eORUSh(0W|}?n(cArE%LJ_G>JaIVw2{*qX4! zV3j!Fak$^K#$xQ)Ngt`zp}3rBkBd?(w%9&;Y7_a3LE_?zHBlW(rQWow$Hg5rKBNuf zcDjvB!dJ--c92Aqs;oFj3=mo)HBn1(e=gKmt(J<){|EX4Fm2w_xdOXReEo2I!0p>6 z3i7$}nx{Y`!+bY8BC3v$C2lMbf}X;Tl|YarmGV$XVyud2PiE;pB%+Czq@#qNdi}-L zt=cXSH?Va9EHo%Pke~x%svGeaB_xD=!i$h}@ZVVcRyH(RlV3=lMOXJ1ofIWePMM9_ zsivqbtx44BQG;7RBBx#UCnGg+)Iav``l3ucibCcqxsBZH(!GU>J@Nhy4={_HUqjGV z#)ud_H{Kvy)9H=p#a2xN=*tNvqe8j`#~KrtzHFN!eb>K`AePRnkJ8$wD{~e$F9e@H z{qz#DYG}E2Bf@0jNO&^!Jr)0+*JylT*!2ima=YwGChfi-4R3j{hua(hysZn-&l2D5 zA(jU3Ius0t(>8d7O*knF>d5?U1QN z>yYfIBg0Rq4?nkI;CEu7TmKFR+$yf}*)6qe574(70!3nansxoda{pP}Kco4vZ5?=> z&JRo*7IJ)4>9Nc?bcaFy5I{GTNQ@3hX8^m69;u=kiF{+kx&;(<)~NT6r`8}iaWz5y z2?eQY*J_XwasnyLfv9ftj_>dou8-@6u|LrE{z9tWTS^F_ZX z=jJGDf6jj$MrPx}+RLl|jQ7oL9Mm53Qr6;B18~HGQ*SjgX(({l3;TwcwQiU4@&k#_ zPJ`I1$GS1Are7?+uPP_}>SdI(ds`h7{d4cvbH5B?*W~HiM|*<*HY{CMRO!tjcs$C6 zsK)>_1<5SOAp}dNj`T}M^|&_5ny(?lvP%N_rP9Ayg~Q=#?lZTSbvEVI{}u32-$ht8 zHtd0%PSyu@LEpTTWhZ@`||eKRU7m?3fWOb3?n9p`m*AMZ>|CFPHi=LBbHl+gZw-DhT7IK1EUvqxgC%_eTGj|#d4j~S%^zYP0Bx6 zpEYTmr9JdsQa;g`Z73LH&g7hB9^1kG2l}+ZuvF(Yws`mPEzW@8J%h8D(U!_XXrkIJ z^{>nHCsVJ0T-A-LPv5nYbChA3wRsh0tgLn;!_P2lfeqkHV^JN8-%>+Ts)#Zw%?Yyn zLv4ATOQsJ+jGdQc*~+0~++J)f;*5}{Y2tKoBd%JoTCl;1h z@m(&rEy$&MT;WOIbJwiK#(;0}KZhnKV)AuOz0dwy6)WbvEDc}iU504&d@ITRK`N}N zZE`@oh9Rmn=bJrcVWdCTq(I6a#{w;*oHsMPQf*Xz+?Uf=sx!1VWxf0DdDDU=DL?aS zgt|{@DV&{gYyLS`-I&5upYL`iFbUWcjf&uC0Id{oAXr4OI;q|{tl}l^_ku13M0W1j zQ>dV|u%p_Mq{4pkeb#Vh5TSPz^lN)hrcDYp?u|&l^BZXkQ3%lU2I5ngO3!zJrAioT zDkOC$o;nwG`npU??Xp!&td`R`dRR=4T(vc|k*6zT9D{MAz`n**5gf!s11zZ}iDUSu zxuILp4AhxuVZK!ehI(S{%3m8FSN=7}L19q5e-DJ%2A)L%U2cB_b^5PhPJEIp%R+Az zR9hOHDBK6^-m9DlZ$Hpc5r|tLSta60MGG6PYX~2JVge)o+O~}nboTQ$Q9o7^qw@mk z_IAR6-h#Vlk;mN;+?gf7>XKw`#%P8B?<_F3QKalvX~j6K=BmAK zuQeccA-ZNmV_p2<-gyLZ{vo&imdMUV6`l8i=uB>oBKOdW18Oe#2=m`fo>X=l!{1u( zt@)UbLzoTW#SQJ!bXx(!sBTQs4Xm6Xz4&LjXhzDW<;HwvwUZ?M0z&hrFH-8p9YdfP zmQ|R>Su}q4Q@>^@*dW!vtDP_|@(HwqvKV5ytKdq{mVO!n6-PQ|#r6H+0CIvc9d0mY z2J3Rm1E^X8acrmd$z8H`tzDaNF0~%NQ88bV+-ktxgIM^})M?|Hlu_&yH=+{xsz7Wp z3#?M06}qu)=9`Xp;wt@>E_wrn+XKle_5=+~%?iuVIF37t42B%k$8hmV`*n|@x98wq z4~p?5)QKK3+rr2dm9=5trl#VZ^hzyE73i@mF~gAw7}pIgrlj{`2lQ5E@1&>9C`Ky!zg^4E$c1JV=3=OIDff#^V z8GtbcCBs=GW`)9z0@*YgN~OOH(!vMyttk5NOh$+q2keCaD#Y6#|41ilplj_1q3i=d z*(F=2*1iP(qD#syMC9xhJ<_FHkRF8utxdBK$t@D))B+1tYGGEPN%Va)EXuT{?)O6a;7DeT4@a4Qz#P_7C97*fl{ivF75 z<8c*Ywp_>E)SbvA`;Q(Q>FG^3`Z-;{>zRvx9anYw%eVxIqj3)r3HQpLuja)3z`Ma~ z?`|5R07$699issJ;kI#ptPB~m8R6s6n1_2KQ)Y==`$X(isP{ZK0* z+02Dz4c)~zDw^KDIzkrnxYO8M`JwHdnDn|<(_Nv(7C{hBc&SArMPAT6NP&3vI8->w z+3=afJ*3Y;xrMCqvv`P&Q@{qpX{vi~m`tuQ!Rtbd=B!Djg;YDf{))fh&rHu_ZcfHM zLyqkURNKwsL`ymw0mUJoitm$-P(Dg_q50y7FG|AB9Wpz8Sm~ZlT1kwjK?E?7wPZwf zl1t%tfw=>2^@!D5YfF4lQ1?eURTPk%j96XYnlHgE=APALJzu`KGb+w{E$Bzqo8pIa zI3Wh%Mpw0N(aC~DS?a&Rl}ct)y%0-bU?>nP4P-vPxN9sxA!*ZvKi_De8duLfQ&eff z+_aG68?NR|k`{gnQ2ivVi3fCOD*W#+TrqqPp15tt8a)C;-5BA_^lkG4=C3mt&3q#_ zsxCTrOpyQsada1#{DFz?=xe+@r>blEg}qPWj>h=?AKw|AncOy%<}d+k%*9WN%zO zQgaG{b##Lcw+-TJucx0qY-XE(Gssz%dOV_2smHN5IXic^`b}42yQ}e(@Go<)MD`v+ z6JT2Bg}`%Z$W~V)p(TPI{-2&6Vx4`=7tNQmrcSM0dyYwqh{oC+^UOt)L@jp9lQS8X z<$qD14)?Sg@j@bl>#X;tV5c)}dlIG3h-AND?&Wae)Pht&V!!AE?Xt+uQ9-Bl-=gyc zNkp>-kVsk3o==;)8oWFrL&ZoL=@FtfUDSWgImX4h5E+R%suWVF=ND}RBGMpf5PT2N zYa`gwV^yc1?9`id*%~%9zoLy6M9ZvlB(l+n7#p9Wm3R(7O679j!pH*9BMEX#6?CZ1 z)<+2%v`_CZYQMOE)Owt298nL{`or1{>D*(DF-wPQ5x(tNX62|-!VyL-&JDSgmp64d zp%kr8G6v6CndMV9_cFOeQ^;-c|u zsb3zYs$1jt4xcc8xF!L$a-k|1H9gU`FD?2(aCts7!M%#lNYAo$GC8Jix6mE<-5v1i zTdl`CSuk_phm%cYq5JpNN@~b>R-L?)lEc7Kg4WfDAl&%84Wq*HE&63nrXAJ!PMdZ% z7mrlafX%<=mdZPdFPjP$`nW2{7=Rar|GmvWKDU-268BQvg;zJPG>l^;Pe4;r-~Y*e zHw@7}%#@HMYnXk-is>w+zNp2`!=36gVy%NdrhOQ~!WfS%WsOE-w zoB>Aw2VN`Mv6my30B(_MxR=DR!T{cMnmMIgh%QkA4qs-od-7~6EP-kf=Q z3Ew|t0qmQrhYe$D!`)q%xQNrGqW-q)?)hCxnp|T#aAkOSkX=rRhgmL)RpajQ6r`>y zQ{nsLpq_)Qs@lbOtghLPdvUYd1|#FdH|kWhbkmtCz)Bpwp|B?&$nfdZD>scLdkQ$Z ze!s#li!LmZkYURkL7%1)b);@4N|F|->vUjeQt@*0+h&igoB^#@osa)X3*1ZQUi61k z7uSGTJ=Z0hP+mH**NWY+!cmyL?S0hl?;q9Hs4R_X% z5!6i>Dd?fLxn(q*qF*jXKMZ z=0eW(HdD6O;?Y8YioXJ>kE^o95=VQkZu_$EdLFQkioMs zk8x%`D)0K&{hGTN?M86Wh}_KdM4|ICy^4t;FCeuYzMlBNLsoz+-y2~_+_~54Sk)m4 zhUZ2l@4rqmF^;7X zFGtS}_LTDEVlQ2EIXg42nI&{{E)f@g!7lP2lZh!jw>+hvm`#7x$Ze-EhXM&^{q`?c z)EQY|F6RdJt>7y2_QFZsyy%FlHoA}~WqF_?e+Nq#3 zsT_(CHqf>P-=BPv-rS1Xk!uA@7qA#M_l!~h+jL+)>!Yi3a$(PCmNMD&ofdP3JaeKC zB}&}_Np0P2Zto1yhr-RZU5p*w1=cC*t9upEw)!I?7&$u8j&kb5)Ck^{K(Lp zDPudQSjAWUu#_qkVW=n=MzP{>@JYD>T_;C&Toiq0f52;nr6Y zooDP_?GM8~1rt27n*L>>0~lbju>5%KDTl?zmV2lt@fcg;VlF25eD4Jy^eFZxuH}`V zoJC8Y*!0W@$lU7p-p;(p7xQt+u0=@)Gim=BMlI$pQ^7shbAruCS(-7pm(JUF620>R zm|24Pt%t7CatQT+8~m+M#Tatq#kC3ZRK2f7G?cZN5(PDU*1>+Lbhey{uzZu|De;dj zPW*m!|9{sOeoom@@Cs*$bCyESkLe3F#)l*smaKawQRS zF2vpuo!X(zCh0%>v!zOi(HtIGp;M*lQ6c|%WBZ3@nv92Qw*6f9@UecWDRhK_0%BSBd zk79l($TO;L^(-O*$;8ENR?E$NMaNE_d8a9+yl2AHwc7Yw4xim>m}poCH|_zeFM3DI9a70Xl=S?A3c=st`F*Ol+O?E1Kp!GY5i$vLtYj(jo6_U zh!%h->q7X`(yxg&{JAee09%(<@&~6z_(rMs7J1tsRd_&?grjQ5mc?UzT$fj~)-8rQ zG_%*r&nm(kWqHmIDQJcYi<(s9T#7V~k!^B@d1KDnt^TSC|Gyl)vBsyr&wX&?@)Gf) z>WuLB%M+ExNe|nIF=gcGqdFof>mF0&JvfiyT8?H~DGk8?vo?rP`8U}0^(Ex}7Z;t` zs2!BF066AZQTD_K@?6egt$nhz*x_zYmf8P68T1mo1Tw~dXKDcohNm-WM&5N0-_zEM zAzPq@U;5^`>Ld(o%|&WX7tKJUp@eSRT_A+@$Sl$Et}Bx?%|lT$))_)OccEw|kS8DY z00#suFo={zH=8+#5o7QDS9{VvGR}QxvZbS25xN?^2z=iuW$-xghRkdmllAnkKUXfl z5GcTxvW~V>j?tHAiocCs%ic(>(MbDoVug|comz=&0l?hyeER-7K=h0KTQpB9oyZ|0 zfYsc(fU?pIgUS*%y1<;NbZ??*eISEcG9X~a@PPrRB}P>ov!%sFCn!GMik0IAmKg*A z(7d2&RvDVm3GjC)=uRd0br&eE1tfj2jVp?B2BFm;U$#%CLBw<`Dbe{Dz-g;@Sn01f zLFOtCXx5KtH z-8d}6m|WRFMQdw+ZM?GKs~gg$KbfGYA=3F-35?p4)B-xD-}7V^e8WW1WL4-xaA%iAOIdgvki;Xr|EPU z+R5H%IGG{PyRGjaO4kICX#qH%aW(TFOYX_Op?6Ocp3M@%DXo6qrld=9^YsJR8cHs3sB+KeU zGeTUXZsVq7@HPzAxWd7YX0Z$y(H4mxmCdzT4=N5Oq`+Wx+Kq-VTI!gxZI%haM^q>u zpkTR_8nk(^?p<`I;ynV+O1-5Swm+7|QqSs`UjJ+o)Z^6|=Q7KcApZ+Kf{reGxQK*t zh91?A>V5hpV7+kWgQHNb`osSRvgjN_S1}I0_Jc7t9J`#_e81c_SfTLuPQ8&%P+tF< zEd-!=lcHp_39PDSclN6e2TjaExZVa$bT=?U!D@LEQqUks9n zk4w|7;wjz`bx0GJv}>@xQW&-Ia9AbavZS1jW?booof8jijhkIYzbk~eE4v>JC+hNq zaYjdRW12l`m1fJY&h&ib83%kCWy53F*p-a}K4*B{=K6i$pJQol=E(QWz}I3WsYM>_ zA*IXjBWimH-I1c`DBym~JRYGIo0QeemH-{a+0QNXsB|)s?Ekey{~1lu+9|tCyKG*u zwiPzsZgKvUw%uSo5ByW)_nXKQa~GxTUlXx9BO%)%dY1# zEO`d%^P{3k^*%neWHU#x7G&ZFPIqHO4@RmOnNwC%G5Aw06$w~wwigbnGEm4*eP_qD z_QN(or9cgU&ZNWR@YHVcReW+F{>SzYyHWjZF$#M1j%b}hDn#=qT1#s}jg1FU)@NyT zb+-44futWvQMtsJ>Y_Nu^&L~NKIsDym9OfI)4ND{^@z@`lDoP zDawz-*BncW{mEnOVZS~%9JC5{m8PiKa$#HuAcF9t!ehwjw6Qpik+AWp4TPevAmwo( z@!`@TFlQNk=#J@qUNO?p`0jE>pXvTxP2o9p`NDv&tF*7NM^$|(ydqKt8SMwe5(6ox zeUaaav_*W&&MT_` zZnqRszuQwhxVSRb4Wm|_F7jujEQUYaa*LG|`)2m#B`WJzb8fqwc{VzQfP)C-k`MYD zJ=yePNh-=rB5^HZJoG7tZ~$!|qR8uH%5maDW%*;%lPAvkY@Ill`Kq{H=s{)jJ)Nvb z%LO&3#L;Nni}XtfYyyh88MgLw%u>7PhdGTrs8&Ib<}@qFp-XzM(=Bxc6jY2CXo1_| zEp{4_IK~n7-I`yIGZeHGb!<>)m|<;mMv{>5!)SIb)$&2L$F?~E8o{7k5aL^X&K0Tb zh6kd@Awh@3w!z%`ASN2aRgPa@V_Wr~MWL9{(qQeHmwfE**B@{VA>s5R#2sIi%2vBX zOLdi<*Rn{_R+(_<`(g!)C8sNI4Rx>?=ELsiFH)^sN!T|n{$A6gU*$+IomNGIfZoRR zO`TR8=!tDk7GdGUZq%uEICR+`Nzjbh8X?*Ypc44Uxo?eHkzRGOulzk5D%I?Hal2DuP3K`6IKbL)!eEh-V*}UK3~1+{b5XT zn2S%~X8p;znsp;=4vHz@{n>l*3#*5R6qWYw)!u&{JzD3s><6_X)5Va#q&jZWnmkH! z;pCvrqf_Q?$KxhLC*(IBZPZy3{LemMcv(ZFpSl&gD;q_*1nFNQc{%eHIUwpuSayc} zmfkzP@L?D6V&12P3dUNo+1M6?F8M0AH;pni*^n8a9i)!@z!?u+zN##}|E*+^)-av1 z23(2278n@XSuRr?1!Cleqj&UyhZ z5t{qg-PBZ1uFrKxVBknoa3=p!lWO(@C8YNo5NKrYM6LdfjFVW}=snay`r1W(vg9qD zZqnl-*Zb`W?l7LM5m`)O4pR5Bc&f*S!0%x@;gk^ZVno1lleEZ(3H^1_SG((;o}V+B z)4gM2Dtdhy!GYa+5i~6&O~ZPwNF^X(ax{_ zwg5chcV5u#Gijf_t3e;T3`>VY3HF8x80l0YSvK#Jj;r38hmU=V-tK_|2fZtXzQyD` zqnWy4d@ft1ZqZ1)=ISj<0bn^&cK9}Bq1I5b-vYJcyjE?iB$X)e$21mFC^h0mI!X1g zDOeUYA;KQ!x*7@PMH+6GdS}jwE#GlXqGJ!E)w0AixL&>$z{}&du{1khFi?ezx|{{S zi%pOkYg_L;F-B-48XYva1v#ZCauhipoXPn38C0~XnN(&HOV6X;)K%Jumt3Y}1s3^P znzQ(46af+d=rxEVLUaFK4KK-A?xrClwk;`oNW!}vHXUgMEM~!93#Jfr*%7CN!+IT})Jc0L2i8nb zL7V`3#W-RNcnpy!|1m0}VKz0GALTUirHE?;B$`0)(tb{fUb;(f z88r*!g2Xa!b#Pz3A{KrOO(jZtEi;iPDDZP!v$%w0cGW+h7I`vPI(Mv9U#;Rrs6W@< zRVJdrr6eQKGV$b6J^``l-l;a~$=oubcygJldAP^MN7FvGfxs%=J7qTzBfL7u{`5c4 z`JMjKp?Dx;j6J`-uB+OU!M{T1rh^OvJS;{1j2JCoyP!A%mR`V4HU)T4zQrp`8k)p( zhJSk~$)1wz4_st@>j;0)LlsAQcwHjb5GQWa3BPZV^LTEvZL^{0QHGJSi$nG$9S~o-j&>RIR#a zQwU-nROH>?|3%tMbp1n@5j2U!v(v9l-1^(SLEX}biUn+fa=W8|VorDI>K!x~TkIDy z?ST2gdF@AXH$x@Mrp}r}yVot3{ayFPVGJmcY2fTpGwZ>&{y5g+U%lcq$~G>3O%Mbj z0tJ2)1lZC5Refv$P2d#Pg!aoy3=yTgS-LG zw~O9PjPle?Yn%(a4@7vAhMrdMg}Qlw2L;T>=Ee7N1r&l z(^U^)1nNp{SB+%$H)Y&LZ|!wwF39bl_2#2B*|{X9VJT-qy`c?^z1BuZ z7ry5Yq_ibs+PL75k#H`90dbGb>vQ|QY|&%7_|0X(2)(L^Z|NUL7zdV84a=B=ggf|z zhZzek;l|>WFIFDszAm*%hSsIBaCV0IJlO#D1nZ(pfMA6J7Jb2>rz4v;RE;yHf}zFL za}x9(@IZR`{2Vo;0LvB3gm}wvU-mPa)!=HX2Z}YDIMA==#HDQLc#^2Bim#3L`lz#; z%DMQHM?Nzt750vW*7Wzlsx`@2JUw3e)$A~lTPjO`DWO4c1W@* z+?Em@P2fZ{ZR|sYJ1+;6dDy`VD+~Ktmh4%yYE6@UBuvlh>th!T%7*CFr}ziD$g@Vs z^t4pI_aaOQH|53$i$!ZCFo6kcG4nJzBUi21IBCBx|MmV^Zz5$V`BK?jBKx55cG3At zY>e~QQSNGPj2Q7`#!SIZ!T#y2=zL>ZF2tQBQ`V_3D^stm=hT*^U}NPvY}DDe`0bta z`<;|kcFWl=VS@<9Zk}n<)!8-|zt(SCBL=Mb@-kwXr9XYEOs%8a$lZQ)N%8B51r-on+09au0s&CQSNvF2$nuBL=21^_i@wiax zS!O4Vn^xb?s1_X`FQL~q=z2au#@!2Z730X?Oozh~F%>Z}6SO_*_|>EBKg^sefU!Kx z{wcS<%RYK)zt)Bz{45viOt&a6JUH7$!*?C3X0B1f@JLTMmB}=SZy0_M+=-20T@9q;|>&edXot~C8J80>QO8lqBWKGE(@`e z>+av{$x--tBZfj=NHtGgQ%w*M1L=_e%(?XOGH28tTM>^YG%^YmK3GS(B%&4nOdGq0 z9#519S{R=mm@~2YXqyp`K&$K_OJ;(=Le4DQ2KPa7>0SrKekt|^M~gZ#0e3}eAXEEx zquLTgVb84YL?{z$7Ui5DeLL@EigoE-a1&W7UL&hpuFoZ185widRBx7TEMy}J0q$55cOH2ept$->!iIr^sK)@C{JSA&Xc&j zUs2|htY;r{sjpr=&dS=Q$AfwK*7i|TuY;KT8aEo*O5D;7%N(YBa%v2K7@u+IIdn-3 zDt%JPIkYYPOQRR$~*cdGwEbn;uU5@8I_(nG;b545K_*X(L;bCel__A!}}EonH-ib0HCK8 zbZy$3iM^%mbXJ%viuIlB6v9{F_kh|zSvnOc*XvF2 zbEBIZ*ZMM4uHUJ6>l(Ugs|g69%3KI;SE~GUEBrntJ+s`fo3CxCx|TIn;1V-k@dP+5 zF3V#o^-9CA}jl@vr)8fV@k@t7lC1`frxW#bs zgEBG?9=Cvx!edF3Hva^;josOIm{Zx0&xXeEL;MendjMn2P7(6OW8b#a zR8~Inhh(H6Fpy;VJ&XoBuv1G1#Lm%L&Gp%Nu)mt6Trng3zrNPt>ACo%vkEd9fAdz) zg|rL5H5WvGIBs947;84JGBnisodtbL^M4$jcQ}>*|Hlsp$KKoF7{{iJlWfO6WN%WL zg(L?NGLF5^IS!JHLuMhQA`SZ-dnO{u9w954-{1ZD{mCC(7x%gD_v`(7J|B;`_WfY1 z)d_VmtB$FUk|0ATqu@OE*@CSkk-8xfjY5f6zfu{_<2}6!9lc~K{VPg`f6NR#6mf8U z0O!b3cJMEEzz2NG%~qZ-iBWb4f?o8IsojmKD>Yp;->4% zzm#qoDvDYkx9>!T_DEREaPtX$1gVEqrV2LH-|)&8Oc~WYukR`NngbSJSVhR37Ipfr`fOo1KNR5VUmn_ThI^hh5 zBd!2hINCgCGfIxuCCM#^6#qQ$*(3|(dW_8TxJfVD>_B5G=p}DO!*6y}zH8_b&}lCs zv2F3kscwt_;gr7kR3nJ%@@QW}{L0fxrx0x-Fjd0)xyqjeD*yb$NsE6nRNC10vQa$6 z`5$>*5gVcBxol%ZyRP#TL4{%kGD~tnQE$GNm-#yV7Q-o-kluqPP;C6AENy&%U*3Me zy5HWp@wg2(aAMElp8ZB)O$@qc=2OQGyAG~ikD|U|sFf~b8Jz$Mp7>+~Ph18Uf6~75 z`h;`2KMkICcdnxK=sczNw?ryKfUv?@c{Gq!RrfF$>*Z@Q2C^8cFG}UJHN}H|eA2Si zHOm$K{FMo_jjgnZG0k(9p`OL5LL^ToPf(^J_zF!_JfE|_S`lx`?5H7-X^wCW|3 z08gg&=gD2-2b|Hs7cF%FxC0jVmVEyM*yCqvJZn|HxyT;8BO_tIIKQ4x&owzw{E^jLIp%l zNGygB9l=wv%>MzEJ=if6N5HfZjNB2*p=1RB+Z4twR0*rG+?W&=1f2q~`JtzgIwZ0( zOHuJIc*Hgodc*?O#^*f6ow2N|vF@{iK0q3b;^+K-2mxgzp``$TXOD=i5errnyGRB+vKv8H8or82_5(pSkRlXBlXL=dNAMp} z4rU56rMfx}EP^Owbpdh9E`B_g^=_;#GX7+g=B`>jp{wE5gm#WnnaVS$Ii)SS8t;7UK%?c>bhGn(7syg)zNNFcM$5z$eK(SqiS4x zf6eH=&HY=SLs3hd&#dR3{N{z)Z2HQlEy;xM+IdGRb%$2!ITePL+c=8Q1DZ*^oLQ-5 zHQ?OPpnDsA1b%Nl)|V@srJiQa#Y3bzxdFH_>NTi>9#Ca9f2VD{jD#}3ly-X3RSECI zX}i$70h9>!h;e?d{%zqyqEHuGUuO(Ug$n$X#W$z}0^kzO;c801-)-cKxCZOrEi9J| z5x^{8-!JcOrgnQ1|J8WQbmftR?=fZZTe)WAhkT(SBoMzl+h{ytn)&d#j8y1?8UR2{ zYgxrdFn`Jvc~4X^{cn-&I4X*(X?M+7h_<6+|5&jy_d{{ym+mdYhjN`gk!zy8FefBTNPW7E~XUV0`}NszO1|LdWXu6c<_9>wHe72A!l zg=fpPP<&v-->9Cd_HSZWJ@?Corvyt@bJBk&q-wiz#Hs>zUlysthT9NRuj!Z{YmJ=A z9uhV*K$sz8dV}NG@8V!&yr_HhwQ>u%0c54pOD3wQE_?22+6b_kyx-d0Hp>$sK-AV? z;}}S&gVf3mb2xV_IjPA8n0&&yaRE?B zX`m6+ZaE$2b5$8#Ykj4>PCMrn6pqMWYGh3OC2HH{M z6JQB7=o)24RwK-rq}$28e)ST`l%<@>kATxr_nM2ierMuOjZbxx zA@1^As;=zrT!(V;31LkUAfNy$RM4Qtmpn}Zodz5))HF$tdfVay>T1m z`CY#OO|k@ttfHt{#nTI5`tK_XblvM!<*aq_+V7>I1(2UgOkMa%j#GX&(ks@Fp(C92 zvg{Hj03(xnK#?R?f;XXBxRANoAXu5ZFmqMZ#xAzsBDxBwJi0z=lo1;foKO9geoK9b zzWPV}NDJwo<1?E#1aa~-rc*LUF%NeASIJ)OO?cMk%5(piE{sWAoP)@Nd8hWXZqGkN zgZiFZ&RFXA6ab;x9c?&}xPQ9O@=Jf3oo$jW=f;USLfqOZ&J>JlrV`HCR=;9tGiK2=sZU7!>5> z7OmC;Hp}9cT38ZRwEf38s-k{J-bi=F3G+V?BMe4X&dz zywl@|IS{gB0jSt$ix}2?&c0;%mDQ)pn0CRe7YbHc951hq(`*@>aj*OQO3FCm5E0#7ejZ7R_^;_)oiJG8J z^<-*k_)#FEMVBTk7u(Ca_j8XcbBG_>6qjOYi@~m$vyUmKI!Te{Rqu?y&cVNCHScQm zXgwtP<<%m{gHM)Aa{jy+O(QoO1b-=&iC{6aY3Sa69?o$5SU7Uu9FZ8*sgoD33dxRv z{UP#01<(%LX%7CD24XLSI~D+=LUZR5Jv)mg{&bwTHqf%+bZx2@S(DVqCw8)D>n2_h zoJi#s%Mc9=g41x(*w~ik;*w19$jqcpg_~Lb9UK&yGwq!e`NXKO2ZyhcmK!HfZIgdY z`h+9tZE4He)Dy|e*nF(@cVc7Tr&L;$>Hz&ORPE919spx;T5oYjNlqW%Xo zb$|0nCh{R4RE!CHdE$V#47y3zyCK-vw+6Gkd@ETkGAe>fXt`Lb*I{$%nPKlUklS8q z?6uI3%&`5Mx^9kcKziurf#Qs9355=CBAoJfgVmmTveN{URwEoW%)Tm)!Z9$P1-HnB zDV#YSK4$=Ue`1PHY6xxoLh=LT_!JZ`mU=QX8e12yXwya=rQoLC(RGiuv;QR8a72g~8nbeDQZLC8c=Yt0UUE zWBl>01Do@#${*)lmSNBDeJlKSOVc>mY0{YG<-h32`!87ah_DY)6rvw;CZ^{(TCwPd za0`RHGe_uKs9f1V#$ELpRQ z8U;SSZ0^RLlv9C=`eRC59A(H1Xu6iT5QqfAXLidd7iWm1?MmmqZqT(2?3S&^v^s^bmV&nJbZC!!x6akKQK_8c4B2{tK`*G=SoF=PLkFKhR2P`P ziZv>6Y5<`tA5@+hJ}zF+C`M+yH%urWzRlOSY}24ZV?*mXP~8pyM}^ZgcjiFC89-9p zqBhN9=LgFZd+L<*8iEfm-_oBYF1c4ePEyYq7Vf=XF-y;_$dOXp#&&xoWZJaSGpg)F zJw7g_!-gk0g+S_K054|}-sRQ|qxN6A^VUj4pFA|+YOyNcF%=*TGMpGz007lhVyCuB zFfgkfbCodoH(jZSvZ2{SK1QR*@F*jlA|}2^%9T`#Bwk*~>@|sXKNO8496G9!%=Poz z2H}Lh%vkniOUA{@#;#R@xj=D{+B%bx3w*9ExEKW@Y?Fi*)pjB@6<$0M`ccE&boz_ zx681vLn~078t4{%Wk=tZY!I>)YJpveSV)^^?5qvZ+&txg4t_rWX6C#$nVHsF$Cx0B zar!SEmUKD+cV&*lOq(4O^?+$(DwfhniUyF!ptG83Z_im-S&4vDRf#4LPSA^!Q3b#| zqsm8gY*^aTHPgo+^NSKGdD3VAvY8Yo6WwLF3@{~b3mt#ie-0S*ReWk zrUD0kTzs9PsJ$?F*JkJiG1d#ejm&O&c2doC1eNBN0@Z=x-zm|3+o(2Y#=h^ty3*?) zcavQ+?i4W(9d%yAY*f%nvi^7lkL09Jhih?brTo`E7YD1VMxZ1k^OpYmc4c~?Y00aTY4Sjp%iX~jCCF1a5y>GqFjg9;b@5Y_ zfG|)Lu@gJ{v7u$mW}y1;`D+`k9tjP`r;JLUkgJ#`1IYnU$ip>#evfK3F~D3>+S;eR z1nbASMu^a(mWyA^=TCKUDiNmd0bn$$XI}6L8o0qpn%2$NZ-vc1X+J6Z*{Q}^AkT&T zuC^SJrt8kefcuoG==5yTpam#nl-rEnH+~B~_P@+wqFocPM9(KkpoEN1lsguzG!oMK z19f0^B6FThwZW5Uq<`0-JvRO)!s$vauOy?!sKm7vO>_Z88n#dx5UA8Ur!B+bY=pk@ ze#4;I7pFjk*u!Go!h}8|^jwL=SOKGOORK5SAsI_zQi~kt+!0@Gz|v z*uqXFnBjVdN743^NhIpdwNaoiVCG|7lmbgRZ`9NCcXmK^Uia*H*-+m9D|PLNnA1%j zrdud*n|?Xe5)bUST)$&cML7$>K=99?l}|8PBFW4sTf>$iuJCSBLUQ#Fg2}p_eK(kJ zYNgosZDJlHVIuis`0)aNj;)9TH40z}*cwPcR?Whowg#W9>6Jy=7weu?xtolD-~Y3r zks%EGD)ul#;&)MHI#zzE&?=cIU&Ts=zgz}nvD=ELUH!>KprUYy9KMKn_CMLz& zz<=kysg3PGWH9?A=@3EY(ex6Uxy)f+_@|kbTt_RIAgMY;$)UM4QK!hwvqSN%r3SH% z$mZo}hmM+KN=iJxeNRxMd~fMO+p@Y*d_oL^@_N2rGGTnIDiEVn#|?G%5PLs&cuk@v zFPH4fHh}?hUdY)nb`9WOM4T=cHot+{`ktAF2&t1<-3hF&+66@y-B+_~s0$uPT%{}z z;tQYwffBW=xYnk+r>|t4nZC_J*cpPPR8PIWJ(qqrxUBw*l9l3w2TLN@z^!HaT^{ZV zK{oUaSzow650iYTQv_F2=W#zAX@4MkrdOJ%Jyt@Yj;jp?95$= z*0cxkd0Wj5Tf6@}%1h}krgYCfmJFz#CrWUOa&H2kI;ucl*&AOP-^=pn+_-Na*X=v0p`$cS#0VVO?6LpE2vN^xGTnLM*EyLTPTl!^+Jp zkddd%KZk2Xd5Y#ZwJQ@(YFs_#;1li zGN4LFLcMjV>}B2*VEJjA2BrH37wb0RYX^u$gLGwSBX5YPCb#y_%Mar>&=S^pmI(AQ zSxo517Wa^i>|mS6oOYF9lq_FfYIAilaB0xl>f@yhx5N|U*J^cZ zuS8|KeRSQ6gVY_o8?&kyjV(~xpK458ed4(6#ZNtVqhXgXbJ@#xT(WIcwxRjy;O(im z{zD>|0nw&Hc1O${+kZ8!m$Q?=CErn#&grBRK!ed?JezvpXT#sGS(M&!yZ8l{3Ue8i zYj(t553ReD?Y_`;mi#jte>S>6S~HFjnBL>+h#b5o6}!L}D;+2h8__eyKL3URd~Jp| zYmu)dlxQemw-0N5nQo>1nd=|Fw@#<^Z|GWSIWe7PJ3q%gQI)Ly6=?F|A_RxNRasU@ zOxIoyccuj=^_AltBrzHJ^cuJq^EGU6-`YP^=3T37opRx$TB3%#R}2w&Jqz6 z;%}}$-~U4)9(*WlZ!2N&K7&nFBR)WKU5#^%Sf;}HgL3acarrd(l1uuI?)$rDaa0eo zS*k{l>O8$$uUyc2<-vohmC6~TV=f|wgWilb*S{5o^I0rd7;iW?=DDG8(g8E)$)-~b zt?Vu4QobX6x0A=P6Mg1M|1o7vXpBM90CzDF`YBtw`zC6aq zYAG=ZfTlaUYkxk@b|U<&kev=~S=XbHTP{{5-7!V`ou+1o$Lc3+6kbBzF6}KMoE&x( zFe05996v`Fa}Svk{I?eZRb{vBo>O)|Bn>K{$bUC3uif|H7qx8RRgkNy+LS(tozZsB z@MLP+>bY`1s|)Y#DE}TriQ4YD78ojH($eaowRcqQ-`p&oz)k|i7vDGaA{U45hml*> zL6YO|2#pLjvc6v(3^xaZszw*z*aC$0`mq%PyC42 z9`tOw3L5*c-D)(L1(aDH+8aEbX3j5RWVEBZ_Ill1GF+NcIa7>9QZ}+wKKZ!gTcFG!IM%DsqZ9mjWC-ftLFkwKj&`aX&B4=m|DF+B4N#ut#MkvPYFH=}vV*q)hchRtKY{)6Y7$1Y zw&lN)uuhR|0edgR;s@wZbLnJ4Ja>n=cX&L=Sm=c46T#(WyK&*8=aZ>xw1Ccb!nza< z+)XgLmcFVL$a6w*I-%&%$-H0*Wp|wTp3i(E?sdjq;k{}8E70;Vb{fyEc>F}2EC4Ue zIP8N)=OhQ&SPC?d+$z_T&7<+j@*k1raUh6EOp0niYB8{om z)OOHzNshfs@x^EWaLuNk*s)H*E7Thsfy1?Z2myw~npdbKW^nL&WE3ETp+VWwSpEWC zglpP1WXK1Q2f)jZZljjoQQxPzCms?Wlj48gI+qo@2yArd_Y_Waur8C!fbONoUCW1p ziPC*OKOPJCF-OM#AN z;RsM@4+u7BMbQqddVrwI7LnJA;sQvLZ6lr3h~NS$zD3NO>Iec9ISL9VQe8F!$TrZ{ z5%D?zRO9)MiM_O=1dm#&K<@$sXkgenBI?E$fPiuuMtFC`4>C!+gaGSa8iItL?ILM3 zMis~~7wW*pSc<7wz0gGrz1DwQp&^o`>4xS_29l{EL$llIUt%bD9Md4^!#<~sbdAxH z=9UYWH_5tcJ>JWDTEHP=-QYkdm^+@=ZPC4zQpxP4<-=dIs%oq^w@NM}NNm>B6|#1GX!g z9a&#*(Y`CM^cbv~cn$c*PwF+Z9f3imsq+`7(C0~|-jTp|8G477=WLv{cklcfp~RGH zRh;N*Z7{Dy0SDG*S!^@*NlMi}tc$;>j~@63t@^@3$rHPRqeiYx3Ss**B6`>Km&j=T zBIeC8*0Ph}EnW&`Z+=dCeOQ`si)5UzahwVu?^rx~mixWZ#Lr&E`rQcVTK2&|6*RWi zHN&j@5E%hOqY<@&2C8>zwvoNBiaJ;<4k36kouOtM!6N}t%2!zz)h*v8-n&Dq?+Bpd zwAT4Y(b?B?{yIPow$3*cak+8^(N!hG&$&LZXgkS3tV{OFx#8J?4?45LFLOAH6VO)< znsF*Xr^c6AwDgV!!?c$zbxU@mJb?_U6P{z>;T^Fs1b^ytkRJ=>y|hcp?S0B{92w|C zDJ|iTAF1~(H}7puY(RgjqoZpKEqeaN)ct-bd5t2%v!tJ(|2b|rQ9GbjP^#e>e^G3< zdOWtbcu`P*BQ`P%7zd=S;)UX3r|&m1Dh?rT%%MHPI5v><#{%|_69v~{*W%#J`qz=c zx>EPqe!jLvsu(O&L-wwrQYq&8QKzGV^uN13buw*?%(3^x)igbih(g`S%;MGR;&|5c z_TrowK@;9AmA$OybSOdT^KQ3|59eF4lcpco3I#DHJ3Y@EZW920Ewdk=X3nf6ey;=4 zT8;Wjc8^xxviGFKfCA%ma(>9ZWX{VQCikMy?A~ITnx+R`}X;t zPH>S_HH!~L8rd2N`m_!ARD0;?$mTOblTHGhDjFe|Ax>9hwJo$7O@#eXWgH17%0KuXws3l;;qP48E75*5qMKE1#;2EIE`UJ>BTS@L2mv+hMy#|QZ zh7w-A0eZSv-fT9`jui9}B$aUsQsKih@%MWhp<7c6QXI81rpXE3l$M z8*SSpVTrP7UALY!=8+{arYpH#wqL|>CTrgd`242i#~)sDb)46f3CNke9eDlPvb1tK zFOkkZ=fTLJU&K>%#AW}>AP+KgW)A+GkZEH0|eUex~vqrn?9lDO&i zNa@1Ya{W;G4k4q9=_gsAFnq79#haYIDL3jo@eV#L6;bL7O6O$Dtv@dHg|!BY+N*Ao>;&@RI<=#sw6FU!!DO`&SSAm@5V0xIGnPj8_^?t`AhV-^ z#&QF@Z*KnfDlyxn$pE~|mJ#zNPSKIa-RX%Z1s$(2B{ikEd3+#r33@?M^#BAds_p(m z5}Q?Be1j9Qe%H(55FMjkQUUf1^IRS_>FYZsT-?9jBFrY3&^RKf819|>Tnlr) zf#4AYeJ?!)hM-(p|3)^r|B^ej+WN!HWI_U(Dae$0k@NYEtAPH;VQlyhdvzM>EneE6!W zwJ_Ctc4faSGTZdbWx`7a!GkPwUANALkuR}4K1Y=pD8jEffe z^ZK29mLNq7bujO~vZ^~-IO#Iv7KRNHsQr;}G_qg)xxy)T@SeN%xhk-2v1!2lg)>`% z(Aa>O3dGk$cdndQC5r*v*%8d$^f%Ogv_mkvHtAlY4NvMJa_9{b05E&G>Ywe&3VKCJ zN;LdXB|E!n!6*4ypO+^~JpI>0x=ry&#vCt;gpl zE;?;VC)l7U%U_PvgJePzLNZP~qX)(Z(ZSHXE3|PiLOSIFFVg{}rl^^PD>IA!Mvs18g%k4m*PEJ63l}kcfH64vH>j{Mj$-7D z2xQ;A%ev=sdV|;?>`QrFPkmr%V{RC`z|m_mFvEN`IbKrlgrA8~R@2lFqa+uqpm#&V6Qm*|$jkho7!ZZ2b_bZre7cW-UXOTbnzxH|V zJpg-J^kV)^YWWNz!NUyGv2b?$Dgu`V?$$Yd+Fhx z7w!`QbPrt*j1|jG|B&P|K0Ya5xHrN1R=VM_y;mS95G-f;1iD~f;~aNa=nK*JnCb&4 z!-Q8*O^vj5OQC+OLQOesQd6Qg6brs<#8SmqpYOq8Z06;5`*8$HTrm$Kkb3GcR$bgn z2H>9hMFYDfRhHu~S48mVgLX@Tx<^`yCIyn{14I6@?OoEzdCenvPK>CHaxWTd7FJ2y zP}?zypL7EfE;CqPC$@EsQMhv;z_)pL`AIabVy|#{O|=qOzXbEjMF5^PCOlV@-I3;n zkG@aPJ`#vtq3FakDDKo#Yoyq8%nG{!3bhtKdqB}LF@;fRbqlvq>j2;xv;f=EB4)(J z$8+3}YG*kWn?!_;xw0%CuY`&y$k^ zfZKZ{oaF*O(rBqK&ErNJYx)b1Bmu;2IHNGL?m}?Z-0~QjaMKl}@@R?XnNq6zvVamz zP~@Y&vSpVZ=Nx4PNs!=|smfD+kx`=Bk>F;nG)ue993VwQ<(c#U+OJyoF?d^Ac7==J z+r@?{zAXGICcwClQX@HNX-WBfRpL-)T;3awsSq8P{o%^4popK{y5xM0NR#dpqtSj* zdOB{D$|3jc!B3;prKx9348n3VoOce{YZAkwut zza4V%J4yz{6F%F5ZlBWuo5>mJ&eJYnM$guO%1{qoyJuhf+C+uCfozL?`{qZ_S*R@o zM-QP3JsDFnoQ@ZDdxekB)(E8vA?CF|=#tXeg_)XBr$irA-ATDS>2!Je=U9 zm&4#c2cf>B&J#sb#oV;r&-Fon$wUhBUB0uG@I#<50$zcH{Q&3#7M%hsjY}CvI@o`9 z2p}4+)Owrpy^Z<;KRYGUAO-2iCh;uhXfrm`q{IJc;NI4xEtLyq7)0*V!~*)2-?|#m zL_P@QJf;(u0=MC7!)NKZc-NU8yb~b&ga|gwS>bAps-jt-=Br-9Ulz&xDPaj`6>G>{6)NDz_r(Pa(@wt}Psa&B?4+;Q=mqZB|0ZVUK=`5#d| ziJF2KkD#NE@)4j1X{~d0VS9lvo6sTXUIk^#T?~duB`C$t3?Q!UD4u`+V99Ai>!Bsh zRA(p#gm`ovI5_D$m-rAgooqj+FbGYd$xK^rg)lFAGqekVXT-MeGFRo=CvwNY@?oWE zmF&8D$j^ow|Y!_cGD11VJUOPA-0`9s)@LHaCc^j0&UU&d{PPr-dev|(Xg z8+*)@kmZui5n}pPu=2CuZ3Am%kH)L~)tVSm72-qg2biyLN+Hnpp$~#0_$2#*cYP2w zTt(p6qN-XF5khkW#~*8(Ec~bLzA4xiEd85>Gl}uU?Gw;XXpnl+mG$Dh0Q7`9ctj$} z#K(zHgEvnV3AI9#x6Z3M_-O?Aj)`<`;K3`FW(%XLbw)~_g-5DHUi_cXzojWf zi__q&>mlX70p)%P3c?3~Yt6(dRJkzhKWGT!m7XT;^}cf{5B-efoyIM4**Do|c%rpL zOhR!ChrW1#$vgQO$@2n34Yp?8COdRN`3>G`l8mLG4nLh9J_}+AZ0q<2VD89z5e@R` zzIIMKn!+MR21Q8+(P)bYFt+e^wr@4Rr3^BQZ;`~#7t`sQ6k1*H6+ipCZFXH8o+J{% z$TD2+!PT`~m{kR=)foeV@slinhI)ucN6l+{LPYPJ&q%2us>rsR@Ro}dO5%9&AV z5)FVrzlsWgGZ;g+kd*8e>Z2Ws%9E%3)M)3X&xdf8UhK+LKCXAG;O;~89-aiKr(Jn# z!}-dSrboj8kfGW6Or^vTbkJmNJX_yiw-Akte|-XMA{(iVYnDfo{<13{9E>NiMZ{k$ zZRl|(2z%YbOy%c~t3p~T_4OW#sU4Mdu2KsZN7C~WS{Bva&Z3($skLH80KiE%MO>gX z(>h{-SvqYIjHE2IqD!-MwPMPY)N!Fk&yWs@K6G;0Ip8o3I1o$Z@Jh3Y8sU;_%j)CP zI;Gcli&%SKp(OAI+ID)-1GZS|SdIkh6XLFo0)bka&M&>&WKDLwW%;v_H%X?tE>ZR%qQaZvvU3W{<9p^oZG@-Tq|GeXMrNvV2ctV7I_}1 z=sGla3zbp)PYJ3h2(bTfJ2I_ToA=WKbzJD=P1(eLoZl;q<}zVVYZM8xw0TVA^Kse1 zaq{W*3AG3^X>bIMe@MhOTE*m=j$W76XwH7`W(l6i_^P7ePCjBzWPPGBK|NJHi*)aVTn3Jt-+sAjlk;!B&8k-!eE4H^t z@YH8eP~C~C05=%iK+&y#=}+n%$eVx%;xl$MW7;#>y!zn@^}q!Vw<@Xnl|(m>)RPtA zC&Z&u#_^VMk?(C?k#69PlFPT|0|MNOzb(bIfFv_m0##1c^Aq~sdW5Equjw}%&J^|m zeHvEBF4Bf~t?0D;EF8)Rb5nbDh5K#(w$aw_Kk(}4=<6_ZVA+D7Nc@o+vNaLz1;;%I zH6ndO%v=-cAL3}|0`E*sx^G3ui7QS9JT3eR-o`} z@EI8gy%dx#qvNtv(`*Dq8ApV1rCK#nDtD}Fty^?>(1~AsU$H=b=h@q``Kep3_N1W- z5*(;EHcE4gl~aKa)`N{OE7ym{NppI}DX;`@+u)|pGEN?lEH4|YDOtj@Im#d%aFq$#oEKyZzV7+7`n`xuhqZ@oY^$(8X7ONA8-0C#iJo6 zI;9-^yQN;rMS@|a>APYZmJ;6)%hwXk%T2AC->414LNnhT;G$%?-;TbTVTC8Cj?DY7 zt;-5|d><`S`6U28VT05bjo zBY&k6?WV61#wS9fq0ud`Oju{w)PjeDEFcXVHr7&uQqvUaEML|Y?IT58mKBXq@JCe9 zUoKy!`=Z||{7Eq_`mMwNoHG%$eUdfK%rjRQZ0Y71{e)(nS@C4404GjcTberiURAP{ z%Y-g7@A~M&GO;_Fy1-QO>1Lt->V1%CHZ*gvHlqOV)5ACdmFvLL)%7SIsWFPt}L=>mR zxOC*1in@>Nd15QfV+(lypkjWhLbitPa~k$G`&T;^n}8w$DPCsZu(GsyL8%>mVL9s2 zI`b0xa&4y=dFi@#YGZaqW*b~-5p8|=GF7g*hLye>C{JS}W(=Lu8=I)v%A|U~TE~CO zY_530&LxY8-TW!AJU|9tirDAkMdvrnu03nH(OebwmTx7Tr-*GZ}Do*3eG6j zu2QRMb8nQd9V1=cZ5;;CO>b55YEuno_1^Z3DXUsOU0wQoUwTNzmv>#i4J|vXGlH=x z*I=Km{@y=B6-aUZ%7=YGVF$aSn@vp8UILP~H(!gX+#ReMIH1${xU?}8tTi;c*ln1l z$_M^3_0rsleG*lH?bkSgyly^m#sk zOf@q=AH>J$6q((6e`QIcgeigQit#s)7w}pR3WGWZiDwR6Ic)D${2!<^I!9_2J(n`` zwmZ3L-|}0Xi=(tf@2!=mr$!TfBOARsy0$}}kI5aA=bDmt-2&TLA)^kX)njA)$r9Rlc=CYy{;pmd@4fpocDw9}l__OnTUxp0$$VAz@7t1Z=l-1hbd*M(S=X z5uvP!(H1k?yWev=T)lkSg48i1b)uu|?Y_vPCG8?9K9TPVc7Kd5N9~$$>n4)GKXpP6 zelKv=(&Ed-!>Ni~51%_>RQI%^lix~+hUnvhf1Uze3l47#o`7lBJlpqaNoD+JrMwT+ zSHw&hp4z-ZS&TncJxTtg)UCISnVq~0`AuEgjVx|iX8xQrUF#T5Cp*pDjCY{;k`byZ zxiO?cm-jVaB1oSNSW_0r-HMH{j9UT|ax4R@9`#qta&_{;=dxXmgZUxtku1|a+oGmVQ=wxL^$hw zqE#O3)wo9A&5umwa`uE{GJrEaoD3H+f$fi|kq)ZwrZPE-Q9-j*D^*f+_Y){OHlq%D zteNPWC`5K%R3DWyft#}R3g0^jO?IadC~3hvaYoS}t{CdoV9o|!wDQj(F8V%e*I%UW4 z;>m(Kpz!hpQzG-+0p2cS*=V!W6#Lw#>)!V|B^T8aF6V$Oq(<<`8W3k2F4G)770oWO z&^i4&!5#k9!|qyXI!78E>$2x31$rvUPn1w&Q$vJgog!#s2o#5Fx1uo9O@p{?BNh0D zC@IeW5m~Jm)!K<}kwS-Ho}HZyb9*Ni zTQ+~dsV2!gfD*)_cSmaVh=tLQ+bvH&>pb!<{>rm#Yuvs<)Vh~Tr;f1a>j+j9R|GIP zp@Oe4M;Qa_O8g6hlvy#!HnhoRe`dBA`P?@}!AOcLIs5UD=ngON-l6P#1T3HM`X;e5 zH@;$re?Dy~zxCUwolxMDlq^Jds3j$xLZK7(iL#-b(?f?Ia-W^mnL^OcM*dZ4Mz_@I zD6aev5W$piDjF0>Ve@`NDkNO(lkTzQ3I91ZJQ&s@`_Ib$uu-cpMIoXAR>xSaB+dJAaIJ7JE&IcqSIgEnFsCr?g?Q}k zb{pQkfLZJoP#|Qdk;Knd&{ozP^PF}R$4+>W&^uq$wBGcXPFE&VcKqXHsa}C8jLd8K z@LkdSyz~>>JuX|FXa(M#m=(?KO>x?%+bHmA`YpgmCsa}-X5g43xTak)o*=^d23=gF zwLb0B%5UT(CKMTIW9Xx@VlCbuHPLr^H}<{_n~J0F^1Ux>h8Pqf0G34VF^MvIQ~W|x zs027}%NYmSqkhj&ovz{yZKV$^!a>n?+ohV{vAp}oN4sh2*oq!F6rB-dS;q)5l;B*d zS(i>*GV^Cv&(rd8OKS7KI}*VJC7X?rZ?KikMfDrND!FOx>`EA{>>cMP|-fgr8nWHBzG1 zz>{e{=9@y!YVsqMet2%)AUdiGLrSsS4pmsl1nLk0xL5B~(uG@oaUp6=K>iDVj88~{ptN26#?*RTW|#?TIt zdk~2d!U0l^n(bBZ*Yv4Ko)g8Y<+l9HET5DfR@ZiEMk7St@sg=7?Le(d8z@T~N)uR- zb2=w9NQ&w-t!@@kAdQOtmBl2wb1f?zG5WlP8NkQU(fA1VFvS6~1>PNXD$wpzwDghz)P9;fDIhXXw{4LzPb>vr?R~?-*A1jrPlxBe( z4~Gv`1Jo@z04UvvGs#@sS`uyt*Jg^mKwevQgUpes`Y8=joDYz?!8&s z&X-TBV>!>&zbd)b-%8TOoPL$KI~rc=+;Ir3nm{Ac&n!Up0g!VlYxlV)rZjYGVU{cB z8`s&18u!!a%-6I~8f&JsZ1?E^XCoStmm!KV-BbjfK8A%!V$t;#%JuY}g z_%pnM_8$=2@5hK)sE4)^st=|BQvAEdSu0_w=1B2|%sWEl{4UN6_K+;yIGJ?1Vm7rX zEyAb-T`oZe-FIYA3UB7VEpp71rQKS)!d9t-aCCo9=(<`d-Tff9YR*<}=0SJ#TlVQ@ z?w!UKMx})FpBA~PmexYz$~2ZW=l8X5X07Cd;odpF95c=+ZcaET6PVT>Up;P&Wmz$J zPKB9}E?oH^=#FX94x(0HjM|?$+P~rO@bZxuTMFCDBQiXGt2nMwKb3;Qs)jeXkj26m z?xZj6EmnCGzg=kW(&ZCrs?W9DxUe*yPUu&=$~H#?0)y5g2UUX|ojtMBE2lxEbE!D(FC_#A+t&)1=dd)xxLl5=db2 zNcyvMd9qSvH zn~h$TQHZWA{85C{w-0Jt@$_eTP7GM$x^4)+*<_Z>tWLmIMFeJ*o6m5s6-c>Bh_oJ4 z%l?ii>1-27bK!;0%3O=3QZ9DdJ3Ourw>7!-TpI6+c&y9600NP!B068RjkZWmy3I4_ z+|CzD=B=I!6-x5eb`3)5B%uq&75($Z#Uq{Rj2^a)o`MW*<2OwUq~^}+ohYrg`Gi_( zCGNA08m(Hjh#*O8;(dZs+{wq=ts-P!lE*WOD*yUOD9g60?(!0V5P?4Qp)6)yTq z9>cWp_C^IV88mwvTR&Lzl_a0lO?-nB9I0kGf8b6QWo3wJ!xY;2*MhR%NnF`nsqwhs z@ujB)8Wrp^nTE;n9<+W(U7@6~uAC93Hsr~~SBsm?9L%t#P94_jVaF}nE8>OSXQ|dE zA628Ttfah{J5vD`!a|cTxTTeT2T}+$#|BzJERMd?Zq%gbec*x@*abH{8jgWozO~da zEVs==PIa;@QW3WLHk{Sgeez0iV-y)U#eX(I<6Wj*^x8eUy}U8%nMT^6J8B!FunJ$! zSq_F3L)n#!mCLJjzBc51JZR#^1T7~wc(x#O`mX?7c(}rt4ADXQ9`Q%eY1HVGhHyO4 z;DXj>RpPs3kx53yv#L!+f+;P0@YUHpqr1=?)sfeRH3e_3C+ws(8MMue2;Zx!r#AoX z^UT3qT_DlTQ8rFJ6ntvm8!DUM-u7qNRnv2FZvwdXslQ*wHS^IATKu}SPoQWEYXtit znepv`dQCwM@B7d?*5SF}$w>M!fl9rXKWHL6(;VfQ_kYF=s%-Gn=bbW5?9jTr(+Ln$%uIwsccOv|=p~&3zbN+o z4mrc!tv&6OJ;HX?_^5F*s{*CHRLY(iA=%{E zL>U>$_jiAOf57p0;Jokm{d!&3^}PJFe93_NFvG)DLNG^}q$26y5&Jk>xoV`;s3CaU zc&+8Z_Ar}aN?I-zVN7x8eJqB^-`efMRCmju;Ts1zBa;cA((4~KN$3{_DDVL~bHugc)%NJgb&%W4`zh>s_lD6zf%a?$n zS9t{6oy(IZ#PGe=GBbP)5iQn>RyvG+y+oIC#bL)W5X<^ZIL_wZ!O(O5{swoUlqbWJ z%R*BPW^4W^BO(9LqUoq6C#}Eg@)OVH-ElG=ym91FF*~S@sFK|yVV_?g8NFskhz5&f zTiARZkIXoeKyaF-icgl-cnc%dp1@Qsrd-Fm9?3rXjU=+E7MmcVY-j$&T;+bACfSkIa-wO zqS*sAbw`0r10T*_=veJ9{gKw!JDqD6js4CS)=u=UiSJ@k0_npb=L%7&c0 zz$Z@KpF?{s68Wc(LC(iuIpo8m%a@bzuIZmKy2Aaf>hCu%zI7&{4qt?SAAS~f7eZkf3>m`YIRtQ*uuo92gV?m3Rq+<&)*$fZUmzHW zcZ<|gwNQ}Q22u-<=}4{%3sr{B5rhNeKcPuzTMM)r_4NOHM5jPO0FDhHPapS!0R90m zKauK$kIBZZDY${&9Y7+Av_LU7F#ypcq0L{#V71>`&RS*>+2lG$=N7WS#=e;H0Oe-Q z9FYoUJf>!X_B)bA0;B{jN^)8Nq2SEa4C>y#(g)LmkpBbmXz_oRbR9ol|D_+@@s(Lg zWks-(>9{^~q_Ohd!_-c(Mj0Z4OOW?+N_Qgb?z zh#X#~T5uX2BJ-`fuoBDa`p}pIyl|m9SFCihq^%$M{GDujZsPA;&pez@Vu$*#17lZQY>~Dz0CE$n1Lu_X&1;kD=&>$4#^93@Kh_yH@WgXrwx&1*x_|rT zKa9Tv7*G+n0K!tVA2OuR(9xv&jfe0(^?38)q)fkJY7h7+5Y9?UY);UOs=!w7z@1W( z-_?63IuVtHhc2e_mn|tC4yZAfPoRzBsC~PVQ|rrr8FydbwfI_or+-NP;l~J;ji+tq zZr3cJp__GxYt=F8OeTOK;hVMuqeXBEQx~D4`PvNG5`LqSbgNoZ>MRN3rYPNJZDJBM zZh@}H3!02`w(8wh5s-_>!MO6%S*cmAkO~40th{h6TqA`s@3th~*sWFc?FFxve{!>E z9Oz6pU#*OcMwO*mK_pSVTy(b+hUikOUYl14xA(QEJnDN~DWa#dM#*n3=m>o0li9NT z{&`iEFnBAMSoDN_8(`!Ui6tv$MW0DusPn~f(_QSN!aKv3#VRVhLC$K!DLPRy;4vYEeQ!7za z%DO$IUh|&~H39LK;YD9251#61c{05#vh`&vQcNwpGJ|2&Kyb6VQg~BS|K}Mk#gLDA zzJEYw{$xqa!UOzO;CSw6{BpkgQkUkgDNUL_U>cWDR4(B@6lY_1iz-%c7w6?3F6zs_ zkF%$=Lb5Af<0bP8DSj1&ME=xz&dfIs?^WK`nwfJ?P{*)xI2DYKOOOGF1EfIi9<4un zT+{eus3&Aopjpou9eD8#rU>QL+D8`Op#V?EQ3vyXm=L#)i9-1(Uw*J4KS36UrXE)c zo0|cHBcy86#Gb3b^Y@5w>fpg#ZoPOh8{GL3|L3|}*O~19$pN&NxZGp1s4*yTpzI~6 zXdXVXFdZ3T(juOJOHifRUT#MtXSOTMHs3x*cQtmBZ%8Y_3xWq;D}I8RG8~|*9uwoD@Z9swn|U6&A7 zVLD_`1h1xth^Z_0lT6ug7R7H%3*uG;YgTigrl>?a1b192mv=Nv$@`5-I{E+Us7w^b zOzFG{IBmPcpiR&)hMs>5{^ICs&c2;1E;fpwuh~LtB<>PKvas&}WZ~{o*+lhoIp0X| zcZ`CN`|#Vsa1(d@)H_#dZ3N5IMs}a99`$C8T9MiEP;9LQu`@%9pBm7VN-FiX$dr*5 zLFvCQt0m-ORbr#Jq<#~XFFZwF_SF~0C0|Z(UD2~@WWiXd==NZd=4<+*sw~b1?g`au zM-w$7t9$yTvx5)8d5@(-j{o*GFH(Am`s$TC6%^$XBOJpRjbQg~MK+1r`S@-ZwgJbi z?v9P!Gui4B`TYt}yW^b)`43B)EXjx#o!^PYAWh@3+z*@-6{SdZl=aWd{OX~#nMWVi z=L@J05xYs{gBW+5Q7Z?;(?4v-eW)>rk`jtDGt<^MvBWbU3x&W_&ci}hCNg>KIrY&~ zzYLhB%V~t$SPWAN2$yHCQff`Id*X3#m3Q!0>}^q{7PAquf&a0i=;(wTIyy(4$m62q zJ~r}~AH(^I!t-h*@b!FkhK{N#?cQarJe3s;#OuaEbUQ z_1^a16k&`9zcB2DdiX4E_kW=2dV83A%JX6WBY5l@_JU{dZ9VH7snKh<&7TbcdfCSa zM_wL}@`8k+LVsQKT*X_(c)qt!`VaigHzF!r5vBVD@q3GMA#g#T^erh26x9efu4z5| zne?@e#>9x-Q!-pvcd5%HS38GqMSvSPrS(V=`d|bAJ^18xtys=sO=kB4G3Myi#^tY~rJFrhSDC)l`mmQrJ0=&l4@x?!Jb9(gQX#dg2 zf^pt+<5?$Cjt((cLN`)OW44s#gJi&X>&|?hQot!lpy$YR%RL6&@&m|Z&c7CX!N9m4 z#U^dY_oV!2fneOzVkqIe5_5Q{EjUzO9uEaF29}ZP7q-sNsjG*$3v$G+Tbyv8&<-6G z@PA~&`|F_T=u@k}ufHqI^y&6>6N06=^pepjaep=o?7qK|Z(baz z%ucyYm%jh^w1*RPc0w#^Fa9K9GuiB~d1*eD3z*^r zc-uFf=Q3T1!%}ag3b}EHei2px~=h(J? z@E9z~e`~zMEpMIk2Kv-;}_S^#+5TmUEm2`IJ&LxZ9VfA%MGahtT?iZ z!1_cfm_k3LgNrl>6x|A}$uj(g3{L@2xH9Qit^2&k^<+WIKBX{861(rl|cV7B0#V%0$6j z&56W;_xDXFimjL*K?Qa5d*7DAd?)lQxC)5uf9b)t%zk^1rf8pb?oes*t6(p_Ily2y z>?eK@Z#q*grp`c5ubP{#p&e|dNUsAG;}jR<%9JTWzuQRNd13itG(1eUtSvoi!QMDn z(OM)QRPB!>k9)xBnT-}jbchx80Jf+p ze9$YsMz|T(QfRnHRGMBm>F|_2icM&k>f!3XM2VbNhOaXB-;ZBKzTU%t!6}cbB{xLj7$W5HfDj?3Aavqd-~-s|O<^>~>5)~xSe2BH%Xnt-Oj!%wx>ZD(IjzWHDL?rDSa`&!S82U*BmWEe%mTqmQz0M!)a-2D@5p_vUG3}n7dR^0 zV=?eM2(&y!bl^sDr<93I#c$Ra?}VtDsr@54cyqiKwVSCc0|#$_7hJ=$IBz^_OB4)-)_jWgaS(B_Nr{T-|6vn5s~i=+4QEv( zs$5v4tO3y!-IT-Dd(|f|MQ>OoroLMXQcHim^iP6^O@?N^$o$K18>zI6CmjMWfceA3 z#gfo^$f*5CO23aGJ=b$GNc|%GqtzA#g=-c*gJ~i+&Y-AsoGiUkvR>B>1)sy=(-vH! zVoYg!Rkx1lDmAQuhTiHV!~C<#o*FnfM{t;9k_tDS7SFyN9Tsx+XgqIokp8EQmIZk* zV05z(>Jz7<`JO%+$%wZG0Zc||kOll{uW;jkg+OlL3kyZCS`r0$RODr3F-jcN3vQ@7 zDJPFmaRXd&|M9eebv>Cs0IQlY@5+s72h&mr0-U+DuxdJ*i*X@9YkIm_WlY5$2SN+h zfigbjU1FFlX(~m#=YSlN$~Z_}UW-areTxivSq=OYEjYh8cd%fc5F>sPq&6ueILTK#?PW7#`LD+wQ3gUO<()7aKf6&qO$qs}Lp6{i>!joGjss?=}RHYhmKoOM2vcsFjt4 zrdq7NF(m2=i#3*{dM8_jP+epBwb(0i!8|PNKwe~>&s@Hju;O!csasNtvIvF`%ulw9 z{49~Hk=j7RTFb5Wk^blfybDpI$-&(@PVJatTzHrbv3U?-Hs$Q)oNK^A6>9V5ScK*X zdvaMr@HHso&{X0Ej!}fM4;xFeLIG1IJN#BK`b!Cfuh}&9hFcF~9OoEcbcD>59D%*) zV|D_G-xPG>?(KloC~%9qR(;&n=r_}>E%X=Zh@;>qFzHUz$qKF8XB~@9d)x^upHOKK5cy3nr>>GL?#FJga259L z0%Rd(KeMCK=&qeb_W~nE$E|jBjcN-ISl=dLL6kFuvoMJg^?tPv+1S1%35Q^2#Z`#w z2q$Cd2Q;k;BSve6@YW?m98(w#4K{2#**2St$%%DB z2MUDY!o@j2y)LbL3m~F?#_KP5$Wd(8ksq-a@Q^jqTm|;bR3+)Q$00ON6D-@mF1g}(SR3;`riXYxh2e70y)g8k+=GsA^tYi(oSg9g)OZ?YJ0WI z3^zQg$gJ&^f$z+Nj$cC-_^YP;w>&Q9!)dK*O#KRx_CdCD?PT!uLqB)i51$pfse}*S0p| zme3_1xN>qSpFi>pyDEwT+D#7>CK{Dk2SIs+C`lWj31hnPPOr%H6wSYdm9&`=liZ9( zE^cs!`4^^=@>~V@U<#i*-~i$&HnE`U!bb)RR-l}tlBq0HqUl_KT9H#|5T%`t(=Uz6 zX3OzWb4z#vIeAfbW6LvfQQaGPk%>o7dOXKhOS0HdolojNP??hk%V#Eb^ywZ_1gif& zV$o#BbWR1beZFN%zV z=(2mB52ArxsAHUMt%m64LklzWDs@U@o%?S_IYE0L(?6tZ-ysCqBbU~V#5@;;G$oY# z&rfSbPi`hP-l<5%7NS-d|6y-GbESRAeK)vJ^98LsIZ1|s@XLUP8+r<@P#B+V?Hs&| zUm;C_ZROmK+?e?9xFTK1usoe~mkES^I80Og91JQh2wP>EZjMWc z(+}8Ct147^y=!$Uslv(Js#VuT)}c|AUpW}mx@)NY;k(#7XX}{pyix^d2-JLt$$E?F zCXI8c4x8WJWzQ9GuZT2lU2B7di8^~BP|2_n9eqWO z5haZUk96yODPwG#To6C5Y6QNv*UfTL1&8c-r9negu zJ-Dyl+s4wQ|1E8AExm?x_|n&bW1#M^_$~d3q-M5`hn!AAO`}18-KM1GL@=`s;2N+*Zn}ss)1uaSMFbHAV4Cjg%Woo3^@>eK?;cecCfinxX&KyuOEmoeOu55BAnW5C&q)PL4DF)&z`fOmo^SziwGiNkjJz}tu zA=N?d3_Mk2?r6v3meH}Pd=PbD@RUvR_;^&Kj4C^JRy-Ehx^`g;*F|5`dBYqgtI3jY z!Y29CM?zg)BWrv(#}nZo?m$lT=3N`qXy zRjQ`3Njx)g1vS*JdwjXoQ0MkQnIbi2oDuRpNn6R~#gk7lUdoqgG^L$fxcBmGPX{ST z8jID}bI@)bSAxU;0g^@nApRxi*-0gVTlg z0FR$+b+EVHoqBElt0V!Z^hLXm3h0-W#WZp*R!u@TYEUDk5^2*5Oz-nC*NZ0=?H|w+ zwXT}>IUCusJHZD6g_jXe!R|VKG=kmV1!ixec&?KJv0l1yCKDFmP9Pv*(P91T0JNRi zM_E11=n`2eyGBXrul=_@YzvhWl|YeJh8(!uNpLqQXBwkb-G~&%48j}KR#=WV1)tgu zV%F3wJ+gh$f(ov(Ki)1_4GBB;5OpzxAvIGU=^gI8l6%*%YvV4~F3Z+V&Nv0pDh4ZW z78mOTOkN(D=m0Pgz{!_SB~%Fq6^-RnMP2~KsvsCpA*3K)P7MT=I057~GmrZMQr|ZO0aY-P`Z};+b ztYY*--m`p|0q)CSc}&iOaYnMzRV@5nD_PsR7xC+ZKzX!KK(A`N%u~8W#xCD(m(7cb z)> zN$ew0Lr}J0Xob;Bv{N0}HKnSZ-_Vy*%TCVx?i9k%)y5^}JKqG4*5W@v!s|3XcNZwD z;AF)!P>^7Cau16&o$(g&!uHa@h&lBnl2a&5(h@giYc*hBxfCJE%j3wD3}d*Mdg~A@ zDCNN=P)U?D*KydeO?LUyzo{#sz#NwqFGeQr%7J}j?5Jg~-Em>*f)i*v{Jv1YjZ=Cwv#z=DYuVDtF7_hwZzQ9j58x zxj%Y^53>^5^Kh7jSF^$dP8S=CE>-G0pi!uk9pT)P{`Z|=Z=^ixEAxWcU!7CIA4bB) zx=;Fs{>fhe;4P&MLSq3r^0Fp52-PT8Xyz5jA7@fQWv;`dY0OI1ueT;HXg+0yX>Eu2 z&7{$+S-CW^O31dsgib1Hwp2Xsll9Z$#}#9ZsGSRO{+e~7ak*0DYyZqQ^<&?0j|Maq z{H$_yE>t*DBmpy*p0$?k?}8&!go3cDGbeX1wZIA)Eq1D~$dPg!t;uW7t*kI{ZBNMe z&03*~^_FQLS2sfNDJNabJMa=v@x?OF7ak~U@_>zKRBX?oE%Z;*5sISeH>-^F$@rnI zZth4ph8cD$Z%^08_N^RjL^)Ypk2E~*1GRAN#Br%!Tw&s{5T)+0f+8d5AHV@l?)?!}N?h>;|n3OYXL!t&P1 zIk=w`%Rq}|u8~s#1FW@9#+Q6|=WHYX(5bh2gJ{3*cHNuFDw+&u;dgXA+z>4L5j^X! z?6Y>uj4$5KT=M?Fj2pJe!MOWWRzKoTMr)d~35(IB`Z2fo#zC^g`gi)t~X7mq)FnIairWo@oK7^|Ud%^5I0oL97 zNgH=1MCN+DtIc&|emHwOroeL{Gf5gX9333>^(`^1UvT185OtixpHHh{+WhZ5FD6}X zv1<_s#LpAuykZWsWiH(*KqkO8u|2^9YPIO#k{>-ObQm9TXE~~T$i(91J;6tB0gvWP z(~2+bJK&lYB_;XZSyZMqY*wXROVYNn!p$f2f(9$$GVF&2@}{wF<1h`SPliaMr~ zUDXHW4#N)wl|X{{oO<}4x)~qofGk=g9$KDJZ=}c;dg9^3)MMLDqi^pL4=ND&Y;HV~ z@24_jC?UOQvl50dm01nepSE>r?4JKT-4br#HII{S=-bz6fwVkO?1O?XNYYG=71(U< zcLn`zVAyOz?eLbPo^7%}_gug^Pr2!U0Pc>1J0s0YeJ7pJC_Z<^V0!v1wfvT+oVEml zcE98zVxG_DU5OX_LfmL*J*3{;J1s7uf+f3hMq9ER$QPi#&GmgGvyX$iFou70i%o$K zmZx&jYsS<4lRP&v$)hnc5<@h=Z+yZUS{adpkzubHaUNUpPIgUxUfEW$tMz*+&y)TW=7#%u{gascx)*MsR& z6!w`LjceGNXHA}FWc)tAGm<`9t0gX z5*@Sop1Q>Vn9D}YH;((Uc_6#18@pBnuPw*akAx$CE@F85Q|CaS(=U2;<(BCGKsrns z%m2`~ZL)_`d=N}SRZt zT8B{R#@jYujEP=2nnF-68?t4fX-xeocD-#*TQY`1aJqiYf%X~9rH|>J9|H~Lpzys# zz7`Zo)9iSu{Diwh^5LjM(L{0iK$OeO3F%_0G|z9m?`@9j5xS^k^<72T)DXV74cC() zo1_g?0h%m!N%mL_Lle`eRTIFwmSNKNmUTQodCj<2tFWorIzLH7=hjiZvF!0cM2Bksk8VI_KzaY{|iS z@0e>(a?mg|CW@3jMfw>%1Uf`5jZi!sz@nyL<##&P=uMlBf$$k}Y&Sn{=2{7F&Rm5V z|6jq5BOMo%kT4BB_|QfGUr6(6eMiQv>kISVR%nEZR|W~!u=G>-ZUE2*d0>-0gf2E2 z;v!bTG*<4{7u;m8a=#^RdY-Hr1---snPi8TBL;$BBp3YZ`4_^$*Q)`hX08m$P- zva4(R7%2=jyd)6Isy-WwAq*%@{|9=6eX8!w5+vdg@WB&Ye6O$aB1=USQ@-@+?DS>w z+iS0KbTZi@#&nb~8N6?axa`mZez~3ATWDDDbp#3UT8(_jA^=)dr`l^x=fem|D&vHJ z^dHLeXF-)^)%8a3YuC7uqoB*9qM@esMoD{7mMpSPFfN*D-R?!k>l%ZVrZ+EuBJ_Zw z;@WkY4T7#)f`sasa>pqU@Uq#XFMHyk(xq(MF}8xZh_Y7nqMUl5Q~lusVG7TPX^zQX zv*;Gn$Xg3z@btZvDfpI`>|7g&@F6rwjt=^_%dWG%Xro`FI)?UI>DPF>dh_5jEGlWZ zVFFo_sr-n%FFOMKiklK&e2HOi9=y*E-`FV`x#zI=BFoeJ9e9iCL5)1-P3l|&@8?)P zG8=+Dwa(t+GWX_0GUI9)Nvs&aILKM_X7T+6ln@1$*J=fxmEO0Fa>7S#aUr1J+V;$C z$yK`J;R^k2$cM7X%gFLhIsjEJ5Q+18+Jm9SY4ssVbAUbl9W&%L^7OzO8zs%hj4uQp z?@8SsOP7^&9&2hBSn>CEK#)NFNJLQuKiQ6o*pvNH^VcK*50hAqd<)xDi%Op;m)3`y zK-CR37LH%)2vWls(u+^oIdG>reb*Py2QMF2joVM9vBcdCzbmI+Jryi-tpWS-sDH7f z)X)BLgW@~O>54kz*4hu+(7!VPFG5;Q{2i1XF{+s@l82Ma1@V#Et>n?}**JT?V<1o~ z{E|^I{irZ2i6tNhrYXhW|Cu~D4{tXVc%A?X6)3lEqk&G)Fo{*lnonmMB&b!+(X0rB z=T*40;l8r@Q@Esm_~%tBdJD0q;+bx4Y)USUB%ArOBf(SpMUJ_kAQB%&smeSo#4^VF zp>Qz(MZ~z%9C=b4rDNwxhyY@9q!lsh6d6HVoYXMz%!`5^UG<|^)OL`iWi1T{^m~aI zDsKoJ};!2?CyGA?0nGuTnVbN{=jhPqD*t z`p*=RjSo#8Z37b@+%d~FayKo!*usc6lI1yHm9;K~h1;O`eLs+9o!Q1;pnip0^YO95 ztRi&7V@!?Db16Hz=huSbI9cb_fpaL2oe0VxSJ8lp+vnnUfwfM947uM9KB-*P5J6_9 zj2!wOsN-=Z3v5Aq)PPAa-P>hYB6eXh2%EM5)o#?k^fx z5V%DyXXirDc<%0m01ld-=bZ*RaBp6`q z8Iw_hAOP5IOPm>>b_~ggPywlngTIqAR4o@xS4(T?52~U0!XI%dG}=9$giU8SmH8s6N$L{p@i0mp_Ao;qY;vDk?YN(v zwi{|Drzz=`*M!7TQD2PPXz`^GM!gt<(O*ZITvR7KgajWKF6z@i!2U=>>`qNw2W4bQ z>|h!uCpyd~)A};z8;bc-f{TN0d=yo6jTr>C8oCR!KGuJ~uBE@n+IYU_SX-kcu@iYc znhF#sGAJTfEA}67m9Q_}?>buvJE&7g^d;1Oh(koBdCla0$f1=2p|(-)s%PzSfg2U- z20d8^s9!4nK*ne%{`RN-&1I42l00lI(2TYY3inW(tno1=aN7Ss_{i4y(=_ftK8x!e z@1wQ3Jro>VPf<3J>C@Dfp~1{kGnTPc8S*uK1Y^-J}~mDgEWvYw(-z?0i1b}U10+!?)uk2$$8 zxs1yslUq85gxj6!l)@Qr{j&D=a7|yCa08FaaI$m)|7zswlU@^zz_i{30Eqn~{Nu)p zK}>y5`g9F+KwAtw@glaOdi_b@j&k|9s0N$~0of-hsK#^CtQ;T@KJ04uw z3GA^1O@MM$;v+qM$$+Z>9llxu$jxZXLb4V}Js0Kfnu_ox^r`-NDW}EA=tX(L>{(>& zlSLnL@mq)Lg#E|kU2P|7C&2yL_`377GNEv#F3psIJVObX;ke84sp1YgM>x4;mo6_R zVbyFSsT4p-vKtRR(_|!W zFR--Je^g%Uz;zagPJKuQMyw5jJ^eTr{c2=u9%^|(Szqx6v-Jj&|-o$UdoJe}3F4yl-j)FO( zW&}^ab8H|LM?<{jt_+qo)vCt;1-XU)qYAmd0}=AW=mTYv(rvrB7u29D4y86DX!N0b z?qxYd7}7}MsFI1xu~QI+59SC84P16qqXu(a-wD0?ya=H?qvx3#dE@m??Y_wgH*9-^ zlND|?zz#A;a-S6IJrmB0gCGaQmZzTGLYR-}|UT`lCC?{Jy!P4BUu? zr9)1B40=4`P*_V`GGevb9U@Zy;qGN|BZ5X{=wc2@nL7bi!dH!Ssq-;tjPyZz7sA&+^L?8!2`h8((y|gnHIoJqnVPPP$L9m6Ou~3$(4)R?mzn zrEVyMUxtU&raBuo_|E4Zy#w!Nj_|Uo%%c2MP6ewD74&$=zom)y#J*Pj>}CeY0_8u||9O>5?eLZ#F^SQo06O5!;yJtP^QzSAR`MU|1H2+ESr@1(-7ALM> zwi7lt#|DjdSnlY5XvPTftuQ7U&&<%g}7S^Brc(o&Sjyo5^bfZZT^OmMWptISg=5cl$<7uGwBShp`g#Kayn4IY3N;1|WVo%Q%y3d-?VcX#LJ1s^tYx9iGH&6 zpz|^KRdx*FNttaxpMQU5IzBmtqk?Ec9#E9a*j=Igs?m7hNdt#(@jj5!z<(R!nX$}y z8o-<9ui}|?! zxOmN&NY+Sab{~UXVdN-welkA}k(lEjbX0JqK%8+q%@3yP{CH?9( z$(}_$X*h@#eBaqvga$tSsyRw7X71BAceIhv(U>xMMQK(-PpQLmOea_fUk#5i#!gk0 zTyN656|X57t%>Nh5s{FqEM6lPudKwR&HOYDeFn<0rYwmO)Bux*joiDLk@KdlKq&Ne z5sZ#d6adVTwKh7e~5$s9eqza*b2a1>V9UBlC!{yN({yP;T%7GO7}Wf#b~X zVfZ1}|6wFVO!lFW3@pJYl~E5cSDrV>pYbU0${2sm9hGGg+&rlqkdXHz0H`cUk{k@q z$nI)5382&{xYkH9*HElX5gF-08!ui8Mo3YE${FZ+w+4M?)$z z5{Oo*>7DTvAT`BpCL9gut7{H<1GFDTNcWSNd7eVAJ?3VBSO}eHGo_e}j>jBK6=Ii9 zO4rI+2Hqe*?(W!wK8XciE-ci7y3=)X0q5mRRGuPhGt~UvOilK-@MBDW)%1&wdK>w` zA8*KNJW3r}szClKr#lE8s$uHh?8rVyz(N0U>Dquv3omSgA~M3-N-C8iT3M**?mzQG z_B}3{e(rwfL+*5A>HD*MFF`QD1N1~}l0Fg+2d7*xb-k#?B+Ljb0?iiQD0JDg2a(D` z?tk5Y7qrH1alcPjO^RB_39PhfhC7A;2|2UWwT0!7R8;Rp9K3xf2goabYB-WMR^lZQ zdrT8~Ud*T;d8j_4mA@C(`oblHcSBQqLfNdw$G^4#MNPXVG*-@Qo)1j~ca3`x^uvcF zLIFasf|KI5!8v>JeWFPd=efRoqthIZ>m)!F< zX|4X^mu;LtjO> zc@NUOi0q)kr7X&r|Hu#)Wc{03LVzuyPAj)yBbTmMxcFxh<(kCqPpz3e62CY{cMFEQ z33NY_`Q)^iJ6H3bF@;1QvX~pJC3Gwr$pqZ<^uGcoqLPayfX1c(EmfL6^=jr95($Wj z$Ob^1%7=`rBxy-(ZfnT`eDW9DkwIg4?Q!R$d2-H^ zwPXQp3M9@-cDcpF3}jZmkpU*C?h4S2hnuKZ)aH0MAH;N&gKEHBR9wimRz|x7y}G6& z=#QEV;>;3PYfm&_GZ>3f{ zlV~Jryal9F{`>n)Jq70|F617lZ>;JsW3mCW$uYu)Wb2I=-xKE4r4z zOBPg!QV**sQRj$Pd$9g0rVm+xZC!LW?QP?)ZVkCef}Lzc`-th#1MO-W1C8bBIORG@=u8-Z8FQkeChL577lTd`l#G&r zEdJ*i)>rSkc0*jtUp{4=-{)Sd$8BTJHM)1l)k>i=mEGkJmh$)S_o-xr>`N3A-(E{e zlOJdFzU@Vf4-xU$9Rq4>u771twG0*j05(KBc;c`pcEw5t-izhc)J~H$Zi#`pET>x^ zn8q6Hou>mcr3spKtm1)qX5En#heT%4PL}SUo0xXWf5h!mREE)@z|4qg@~6@R>5nIn^mY9t$C3^)vmTrT zy?*R~*(6Z>T(6%QUG=@fvZ#8ZySmC1$?{nzbke|z$6Ou%jd|vNWNTxFmuxc6M!u*C zJ29*po!lz$(SrT~TRtYfm0W%Vlv^7*9xqBKN_JXOoU$j6RQR$_@zur0FWlRG*kxYT1QC_Q_qEH>ET$10_R$_x8i%sL3K?*08x^AJ?%vEU;3`sn3NmlHEBf^!E ze7|-196t3$#pw&RE^OpoPhu43-xF8cRLB(-7fGfZEKaQOe<`1tl&A`G&>x%?s8|8u zvHT6aJgXtL!HOz3K;ILS>Zbl|Yg;G&bhOR>lvkC|2DrxIL+bVb_4sM*wji9g?wrrpQ%0is8b34q~l z=Ns)vh#)FCa+{dU^O)!&&r^D^=5J!?c&0*(_YWXq@&V-6( z&T(wf>IGK6*XzEWvPyX-Iv$ z$#gJtL-i$<}C0e~hv@nLn_Pfi&_T7^{ zeL8jt= zmN0jI*NkG{ZDDpSANu*1tK!C|QVTNe*-XD=YxDpyz z6=skVXOduY4vt#>wNYuXy=A^}BNy&kutM6stprfV+8^>c(dZrx1iSzF^U`F<+-mN9 zOw{=C1?^i^mcEVwS!JZ^r?NU0N!>g~ce(+w^bT8RR9G&K`dKtD@?^~|mhDiwUpDbq zw|K|?1vtMx6so*nLwg9Y0hvFMkQ~o3B{2Gc!aQycC0=Qj24~LU3{d5=j*dtN+ZK~R zlkk?E7xnv;7Bfb&(_M=SUsKMWQze7@ojZt&r2K4TZV4~DiSZGA1VlQbLhn`^O>E*j zPhK4Mf1u*YM*Ev}i)HV0An5*fFHYBMLE3?%aQg06z%n1VIGi+|=8U8$AUk!M2`Zlv z{!lgtISq(9Flu&9p{>+uU%nO|8Ram5$?AXi+I03G&>^W@lJ)`h%qxK;2EB?Hdhh;B z2OVCnMO;?W?T)xNWv@OY&3SIy_CJuIqYu$^guhXJ;kfPwCUdGj{sAQ<<@Z@Y(fVys zCkg}ShEA~!$Yi@}0`WGjWMAI>j!QFfR>xfS!*kr(dPsTtgc6*(r&;pj~)lzBbM(i`kotdUCc00 z0Z_2uwXDN4<@4;GvU36BQd2>vmbqHO-_0vcHVpDHq$gTS%(AzmA*I zbE76pqx)Ut{d~s~hs=iYYFMY~`&5-Ar=ALUWbU1dt-++s^Ja{sGS(U8$CPQ+C6r3g z$n)rYY`HH-aWb}f4EW>hT9h-w zCbq5DcfLdzzsHGMisslVt`x4Y^lN07SCr6r>&UpzMu%`)A9IfwHhCPDin%Pg_H%>N z@1A5eU&q*?NVkJoGC*@-DpOT%3(2g;`v&WS7INlh-utsO*BW_BqvgW=BvU60p{M{gFBGsKr1`B=dGEj8rj*Rf*)g*UdGxSm1TBfUK-W|V}PfoM6_>C zl$km>Bv1938a{LGJ%_5_{q?Z85nN~fHQ#}c;O!`DtI*OifpX)v^y^2myJ=FaGuyn9 zHb5{^nA9XV0ieniDnJK9h-S4jh)JzALG(2>ohDW`!v@Jj46E!(Jzf z0?+w633IC~%UkZ5@?S{aY=b9Yk*Y5ff5zinCiuv;?jn!bU*lS&b$vM1Uj|jHZGKOx zW?r+)LX8e-#-1LFQDtV{OndtH_$>RyPzJPdtli6W%Q`RSHD;RF58LY&=k9NQz|*2s zC7<3l=@Dm@_O#6PgGOQY|FLx5|5X0}A3q#9ws6Qe_MX`tdvok9Nrgj3$T364vB$wV z_KIVV?6Q(jcG){bj*$^%B*Oc9eQvk!AAlcR*Y$cmpO44m{#Y=1=V}lnbJy#!JX^5V zFz@uc=YELcSg-Q0VSb1y>Cj**ubdyGrac~X+CR63eal3ABUCeQB}5B(-s6ifp;p4Y zBv!je^a4(;zRcIP2=gD(IQyyJq;0d#ME$Chd1xV@LJavFgoG3iHSQXxNPm%v<3;uI zf&hyEFq8B)E73E1DO&!c{>ZTE z4m5W_mxX!V_YQy?%O@El4QnQ~oB;yWJ`t5d8u%fn*X;^B@Jk2F5NLu%faTkhkt>nM zu}nO#5O3nQPjnh%{DfS0iQQV5ALZ}y! zQFQo)E9wxdY4~FeWryHtwSd8|q(2FZ*BR@XS6skTgV-{MuL`sgoD< zo;c9iIlN~+W&lO6-uT&PHNxJKJwEPmh^_0AzSs4vhCjoLrp&ExTyHvNqyyXKK-<+- zaz+C5da&`u2eJITFh`Zkm93OSstND@)FpHj=owvg`=x%!)4j_3HFvcNBC6(wRL)W*fa?H3=FZi~xY*(4nOY*@-S%pYCYT{qgyZeesjWvjMEmRDsPb`{SywYSS5zb0{Hu z2Zn_Op1gbF%VoE%3iGww#Bvq9@z+y(YQrVzxmykp$d9o9KqKY3ww~HGW{Pnts_*CI z4f&;=Jz=QA>swsSRK-%af?0M>I48|=iJVe0PGFl2@Xd(Jy%@c8wJb?DEiB;npo6&a zVkV7~jv2**KhsU@7!%$47*$6Lq5(2uC1o+cA7Ph^Yjz(&mnI+P?F4+E^E`Mhmo z4?QbqQgqX05MGQuq5=d3bhaOq04tD833-eM^Ks7S0-G82cAASL^?^f4H%>FWW(WWT z1wApfBNd!SLrgzL(sT<^f4ZFHR*H}@0!>ocso&L5?`LMgBj6KIDz!MYKf~2VZZyV> z2-y1rKdME9F=Hp0sF&;r8pdm+g+LsDXB`;xlGLI7P*5p$l9hCTB;21EXwx+^Llmb- zLjMJoQ^^37j#y&)Tq3}k_#a3h@=p6{xg?&X5~OHGrewy&gMKSK=!alA&_OsT6-B_F zMr+LU$BrBlja*vEXeT%t9qX~*lBFuLy(h#QZH&d~J9+((Ie&;dm2F^>C=WJd*VwMv6wsXWUceE{Mv`Qt(X~_6 zR36WdPp_@Lsw#Az%q>qmAhYGmdgm+z+ziaW67JqkY=MmWxOJ4bveVaag z2lBeFds)UzEp<;twEw>3i0-!39@u+;Vs$b7bv#_J!Mw~4%UR@wRle#cmmiwvvfRz}l#w)wGaa2e&T$!hf_GwaRwvrQ4@jxp-i|+a z>`8F2=y<4+f;k)lQMlJbmTfMBLkwrSh&&@=m zi)QU%+IWqxk@R`IhJGgfZ32Wsb4Nd#F>uGs!mfI5CtiZr*;0EXg%oYiRuB3F$KQ1v z_*>!B8AF{EDDVfWYARcIAAU3>3v6j7`#c~~I$)Vr$~v zowTC={OpU%9Lj&2rHyV2>u@9qhbl{7~VpteZQ)~Kp`+3`kvK|bwve_m z#F~BxVZc*mk15`{7AAUh4;P7=;8@(XDJos;7S?V@OnnFv0j46arQ6x%p38R9@9+M) zu_kkRr)pOHv$IE9cu_w?%QN0xaL4CC1l6>gLb9a9>?-$8g?wUIq~`e6LOb0~-r>KA9hNXZB=B1l}HLd?Ozas1A55Mvm*j@~V{&%;EB zuVFrjn$AE@AL|_QkL&C`k4xjo$-P)?q0J*Jt6}6LW%!EDyKDYLEqZ)mrktZS6a#Tz zO{NARg1@)(grX=JqfkN@MLPTuYB${$Hsa%Z16^;etbKGj`L0n(d|#$Tq{5*-A<^bx z2JA480~hlvb;6>xfV{1cv;Rwi`>hXI_d97dB-qwQ-HbyH<{OJuwRqJ{bA zF!`3)T6D|HuU8Pf06jEh@3>`lf0Gydtua^ZzAK%uN%aLYd$q|x1u9v=Wu!R&g%e9{f=&!Mx_ls2DjuDQ&EjuS=-o{C%)U+bB^QCcUPk_FK`zN*|&t3|nA&${>d#Hntv^|7$n>l}CsDH82T~T4J?V z>cGNYD&5k}g)G;bL3(})JW9}GAV%{)lA@$ZdoVl+=w|CR-cDzxM)ba;i zQMXTqd7TfkzR>d0zm9XF3<1HbQC;G)SWl%$IGbWp0agCWh0lMWCdhvvdmCJKoUdJi zji7@%3+g07@nPyfbOM_9D1bBe8K-~Bu(v?E&SwtLdg>fQ0nR*0$3G>B=8L+ZYGw1& z9Fmk_PI-`E+F-tun+=QO_0%x?F&uix#7KEdNH=1MqjRL5XT&8&Q|q}B@SpD_Fuu3R z&ug#tPF2#?I4@AXd|EMU-zKcn$%0*FkZH7E_pU2ZVy9uH|5bP8TzFfFpgjL_b;Pad zzP~FNL^sh0-4Z9;(=>E6V>qtvyNN6PnT=zd6r+2HSJ+wYxUu?5V${sl&Q;Y8AkdQdNuqQ zk$pza;>Rs0xNtaUyCn4kZFZ8XP~}v2KSR~=Y-EIEjbLFe_P~P1gw{euYUZpmZi@T! zCT=>Jc#<3L^n@AYqvB@dnSpw0MgwP2J>Bfbabr_uMt09+lbX^=oy9S@uenr83M{>6 zmFgqbZ?aTqgdg|L4W#Ohcsl$7okO7Z?(|}L1*sale_7qKlRb5NReyn%E!h*Yw+hgh zRKJy9?yR=BdmK{7>8AS=yXHR4ii64IE^5-4@V5bURyll3YQlR;8wIR#KT8sGR){Xl z{RCD=r(4Jq*deB$^Cj#Szs`97oL{2~W*O$VqHr%fxXMQZstc^6Zug3iv2(XS0c=B9M!lL_hS2Yi`BrgTmsgd5i6`Vdd!tcvppe^zJT# zo{QvAd=_L(iF*6M=zHIxZ9|CPbcR6x0Rfb%=XelY9y`iSC?QneRMu`ZwbY7){`{e$ zXhFZ?Op@LAV}u@|?FM^+y%Nuf&2v4vKnc6v*!fpk6I$-FI47Ru%?sNI?>6c)9Gul&w2NhvS z#*{UbjoCm6T0~yy7SB6f>3fd3z7Y)ni_!@oByDRp8~u)S`f(n-Bd9@LHjY&{qqrz% zFFdW*@E*i2h?3gMKAq+cUpN$3<9jB1c_eDvcu}eNt*7M=A9>j#4xvg!C@El9?oz|CJD96!uelg_Nz#7Jh2?HIdd3&(4Qp5t%fNdTaGR4%uV%n^cq7K9h$oR4%& z8%HO8LkCcREZ}%Aq5)zWK%S!k5@xAxL?Hli-^?F&2DE8GZ^fMB)!j%r4M;$&q}YhZ zvt*J|>b6oBlS~ZkVY{)>%o~x=X-dcm-Z6ESqE`X$W~OMSL_Xv}5~^W(8tK=|d@Y5T z9tf760K6uoWAp-3%p9+Nbn+!CM#)Ury-v=I4Ln>?+>B7XZTr$WIPV7bTW82Iqxjpp z|DHQnvxmZD6=eUfWv4i8N*SNIubp^#8QYuQ%3iA1op3@onT>=VPYa=`mIuL~Nrw2j zt6ry$9bA48Uj>b`>6omSn3|h(EuK%#d+YOo``3%am3~$8=~w+zgKO>|S3B2JQ92_& z&2}U!b*4r$&I1_#-XSwLHZ5STbyUwiAnp*r*-U?wPAWz4UT)0#9ciLru)Y4&KD zUH+iDZwF(cl_A0Wr!M$hPM}SAm?pSZTgr*=W(Ti)BO9Egl6=qOfmu-`NQdupI&*@C zRuKqLMfsclWqsl9iUO>|dzOoh6gOvjge1@0dc&%byRDa(v%&f84P`zgo>Qsh3YTVl z8t<#O!uqa7Vsd#BrD-{O>@60>QF~P-glQbY?Rup{O`i5-JGYHv1}M{6huv7!DXnQp z@O=cm2j+e|lx9W?Pm14oSgd@1e2uhW#!R<3F0{o9!{&ArMSi|ry0z%r!~f)Kh7R3$ z3F_?`%b10LGh$P%J){zIktp?^Q1bJv9IHTQQbESIBj-*hPA+c!;j&AIzYCDr1HhY3B5?BLXiY zRcf7*GGiR*`e48n+~J%}tYSG;xZJ2BEa5lqswShOevLDhjP-VrX)Cd(wx^_ERfwm4 zszaSVjOHy?Hjn0;O6`|At>`XBU3M)&!C6ZpQp5-z;qT!5ZyFgzYC+pnLS6E9m?jQQ zO`0c+KEpG|R}ec9`xzDN2|K+g{j}Zj(H*YK23MffsW-eoKJkQDA)4p&gOt$u(5nNb}rMewgtA z-&ZyX2x<2BFp8OB!z^|m;FX!8*Je&1stls_Glp0Q1g_}%0Vc?SJH-BxLiRXp`Hesg z{m9mLTfIp-OwbMht!GifaG!7fBR~(hvzsr{YolXH=p)4D26-}?`OMSxy?xe%{y=l{ z++k|cvruf#4WOG$K5i9bG+Q)*hLTjqsJhKUSiogJ>_)W0-4OMZr-b+D}PPRXC9z0MU6jHp{;PAjN=R3GRpX;^Q33xOL@rUdr5QS0soHdHkZ;VEYenv{(Vqp>a#PpC z$V&TA$s80dMWj-HfqO+Q6QQF%gWGaYYN*Ffg18h0-%nlbgw8N9o=da$d@B0z-m*i$ ztn+@l^A5%Rv`>I3a{jL7XI-S%4jx8Wg9h;W+Ai?V#eaTVdh-CUV`~9m&W8@EVE=>! zYWYVhQ&ehBP{&2l7r=u@m77o%DD#naM|Z<%_?x@bpT`lZYW1=t7Fcg$^i91<*q{iX zRUjJ_P0E0W@Lda8uxTf-g=DF{pb^YzaOoT5 zE}m@?DqKe&I@frQ=Bgz2Rg8)z6kL^(ecFt^-$bYFL-+!Rlw6v{jU-z5tpYv7eK-C^ zo9XZV1C>P=wg7zIfWS%pJsTX|@PxwYAADDeZPJm0uD-~p$q=)}Bj2}QUN-Gy4-f6! zFj8mZ^z}6>-Z4xpkhXX(@ghwl-wpBJTNT_LuHQZIvtF4-ZGkhgxY3-E^%$Fqhw*D% z$3q~_saRp@>83w{BKF0ZzA9;^J7$agHBi4J%&jdSEzVC@?tb>(@-DMzqnAa6oP!nV zd9VbiNc8N^31eZB2FG_yz+=im{1xW z!ytL{=0?xIZDt`}<6*;N&mbiea@Dg1FVXQvPMNvbCF}7m6*ly#Lb;vj<38nsWZD&z z;?I|s`YmOA$rKctbg6nq;m`v^XNqaI7$;I`4Z$Wx`8Ts(ZjWB^eyxoMxn6nH>Pz#W z)l(<~28pir=~{F;F8&lUF8BT%B&Bv|;ei?430i)H1l=}4{V;YFw*Mx3nU?JbdjRG} z3@ykBC+coCjQ;hJ1TClaW|)|4+I`}+e$qY50px6Mtlm*4)dt>v;VO7_qgfI==+G#5 zh;datl}c*b;36WBfcMX_W&wQ*6rHgg!UW8gYJxS2%R!P*?&$dKl5dw_43) zo<8cxkYiElLsC_PGv4B=3T}$paPM#z&Ul`f29gb(L}GCEI%mI4OQ5#hf#*y5{wNwv z^r8*Y>9r>puv8w05UihZh5WdWunqs60CX#@_!=`w{1KPVouais6@3n5hr+pTVs zaE`?x6QLQydjKkXi;Y|<_vW*DVIBDf*L%;>zg02Pv=S#Vc>JXJNf1NS~ z8hUbArK<7LL=CVFG8d+pXAu$2?jtCNm%j1X8pzuwV%wyGr9&_O17(;^waX1~rPKI~ z27@ocol5YXUZ2H;lGl^~#jPDkLZ*u_6R575VE^X$y>vobS_dDcTG5+8wh>p=E3GBQ z+DUzezGJu_aF)7Nlfe|4e67f`cx1L(oau4NSX82MvgBhp^T^d}(QH+v$Je&ST?Zc1 z3{DelLSm}FuHCjAeM=I$s5oT${wP#*1~I2r$BFmIY%-kIn)J?%`f3kkWfVHlo$l(K z$(d>j6L1y4$8%Gp0p3#HbhE26G4^+kSBLkWc@zBzM<04m<+YpjmK^4b$}_!Ks3FVp zTv|ntX8qXi?4jRKNU``t$n2g8p)8S>@0V}Yg2I5(t)ce@6>)wT=P+X)EM$pWnURGv z@qZFPoEDdpK4%aNISY8onZ)wJ$5AhkeU*GFrJtjhgJfmNY!SADYBB3OzW@>3h&1ejTFbJI_2n0{J$H=KYvoB6_};rts514? z+#-8rXPSHbP#~o*n^(y`3qEmHg0;07d~itvnQ4`>edCo#1R;^?oA3s%G^CFiIE-A= zb~VgrYqpG~R!C{t-Ak97Hov&(Rh^c8e};SCa>!Ry9;wpp&WQi#0~lZloVlFSxp~4m zkGjw4qSU%3?3{S=1*GGiZ0zt(BEhE>jx|&`d)jb~OCW61jumzMyBV(4N@mPd$U;W` zKk+wC_u~m2wIK6;S_RjNzbE^gO2_4?T7`AYT=HG|1NeHBT1jdD6AS!G0VNC(e%=nR zd74O9cfkcjie1@h?MSDdjlr2=0Ygo-%~bJzbxDi8JCJ?-OyfU*FRAf)y?}(ddG0$- z0Mtz~xrK}5!lDLMF6UGdo298oL0m;WuZTNIYU0*jeb#TmCj5n~EGyi+jp`HKlE-Dt zs1Zy)>I4uyQJDqW!av3oup!M`6bOPBPPuu3@;@~8XO8=>-FY5}-2Rky0#r{Qe{9+T zVw;URBRm~SE#%5b;KJojrOnnvYXe-NTX1oY@t~o0d*FH5&1;j^8CLf3jQ|0*as;Ao zFZ?`^g=H75B~Arv0{zNUOBL#fb*O6OC{Cy}oUB`pWWET0UZA|gE)wUm_vJ2oLU8*J3ylmwis7Vz(mN^7{^I{fDy_&He<-%_>AVGAttLfaaGNo^Yg&0i9$k*AOI9zCj%RZue zDwHqBOMOhQW}pzAm4lZwkp#YB2BoadW8MYf<`ZXlO<696)ba=sTyxJ-lf7sn=|;%Y z>NwQ9^T_G2@j^yOlIHW0osjI@dC17nH^Ihs=#j4%Quqa`D^ezjq@DSKG%|z^tD!ol zeJ0jVhs(V@F&lHrAg*n$x#0=-plro?@aec9qbC8T+bF_iR(;~QC@S4iXiwegDVTFd z_R#P?8!NgaK+WG;Mu|#C1hD1(E{X9MQ!jsm#BW#R_cvKTL+F6`JC?Id_4|wbf?kMxdYaq3rEAwsnT+fbG|yK z#L4ALG50@wghZ=wzHOuQRX?C2C|erkar5Y&$Xri-i#vt#R_|(faxCs^BGcL7Rup%t z_s>c^6x_t$p+EbBlk%kcXij{|&aZrgZ5x~v%K0`!!&}WYGZ+_{I9G=Z^uZyxQ$a}4 zoUW(&2-Oe?t6NU>(nz{}bT5=!#a4USnYt+Qv?Ntg+FDdb!iNm5mcmAJ&W`%mGOBun zJgw0R;Q`%Im=LJWjPZ=p^BzQh`!v-P*m?10KEp2ct_Ht(VWR;9X+mzg2#!kK#1!>4 zk1H5{D8vQ>v4<2oVFw9Wefvh)0AAaeLA`1QTPJr(*4_}aAD%-!9hriFj#|oGkA^Aj-XV*eR zos~NMYOhF|R+E4xsQ@L)T%&EYJuqk4PbwuB3DXdO&5$H%q>+IGd-d%DAZ!M8io!m{ z9tz>z?9<(E4RP^Dp6%-Aus@i8q1kI3M)7V7?D8Ss_&^npXTzoZKBYrSG1N^2~J;Lx5~`oa5v|`mUvP$ zB|-MF!xQAS`Ma2H!_tT7WMrVKf`n3XZipRX=@Y`-2i zL9ixuQR8lL7>xfYOrqo+5Ge5W7a7PCHsK1O7Qt< zW$u9j9hT}>`PHoCN*3J`OY>l$xfglIWUmO(WEAL}F~fyy(N&PyiR=oZr86iq_Eq`A z;{L8W!^4`4K)tmes*!U#i9fVNNTo>rjcOoIUz4axvPTNSe`=C`RFDiLY{NJQI zlxRF97fJP)Ig8w%p`>*zx8Y}xi?fsxF?uPvKh<7%3tmvTF9vd?#esgQkEm(sOWj_P z5v#~)Ais8(E`7^wdgejC^XgkG*rghFk#y&8u$oDhIZj%;iTD>0cEnQFi zIL-7ViFJ~J4k{|7+>+9H1vEC^6Y^6$6O1$wLG$!170EF$9J{nNc3bKQwA~@f!l`vH z{MwvFlYEcSXRS1h&;sCM)!74s3nF1rdSS)A%*6|GIhK$8Q%)4d=s@8yg`dTF&)ftHNf-6|TVS^DGz6~>_x_>KSL zZD0GkY)UtR;Jd=j(2a@~7t!qKNX!ei0<20rqlC6COI9%s1Ec-;Mu=`^Z25|}vGb>e zyvgEf#<<3CZSrjP;}fhd5rG#xBR9WU=ZKWuL>v_Y#Hta$5;}Tob@q6{+1VBxSVy7{ za39veSWV=GrG>>OP3qor{5|@bA&!_qL$GBv3ZVHo=@8ryb6;;C2rE)2KZI?3e%|wf zjPPrW;^T*MGkZl*EYT47_v`2u5p#B!mss+eI0opvVq7d}Vev0<31II~8!c@kBu~C{ zNq#=`Ir@@y49xefoL*A*1#v~;)6+Nu5t2SL%>?+c8a(ZR%LO z*re0aeL2s{%NBK)tB~+}_digYgx%@bL0&F#YqWmL!HKO8r!|wKm>Yp|R;N;oGuR=nn8(_A5pg?>Si~aF1|d7u8HE z-=faON~F-e=xFVH<`)>zFJKKw>lSFY>GBfEOFkm|Hm<_g7!x8|6E?p zHAmRv&cG$5cbjL1>pY_L`F^JodOWiI()$(GgEnbHP_udTTcAK+BEFvh?anG;Hu1v` ziWdMdE^drYwf8rZ^1+sAkHMTcRbvg?yd{9fSy+nfYu7>f6$ph&0V1 z*|6H?1AiK;W?=e?plNL3Mlhy5S=+$0*!o^b1sJ2SJft0emS8}GVmgxwku#-1iB93QPro-H{ zN;e~Hcwc}^AgYDdvV3yO9!z_9SMV&Wg$9a+B?po+q;L+KPA3_Ne|9JsSxz`E75Tw8 zOh}LhSRm_ZCZ(}#DJ=(52Ns+#&QFZxyk1`_L=Q9%@E1u^O@%iq#ysgfHu?{@na5EV z+byd(EutOR(Q>NhAE78rgovrl{7!?7 zq-L#QuPYcXmicVow)|NbNvNmr1i1PPaQvmXkM<$z|M&`6^U@%$^?0&cMGG`7AvkWa zt{jYY$D;j$j#7g5@tfFX=Dn&`zA?*Y%{^rp&(8C|GfxvUpUa-6lb%3E32M04m`-C} zag&D@lUIeRess$4%liQ$?NhJJYQm_VOx02;!s+*bIZQ355GT*KhfOdEkdq(rltz9HD}Q&}q9 znx7C1nX2@AKA%5PS)?q2E#BM&Va|P@0NQjt9YkHuuDoW@)#3;PKnT;#G4$nybju6f z(tLw!@}war%fHG;(VFnS%#et)YDDLq6vfMGDZ z{tu$v19w>o$5<<-;l3fe+wu>Sw7D=l>=A=;`cC9I80@D`)m0(QrcIp1qfb4YseTAn zkgxiFQQ5`h$AQnTx)u=LLR!ytOKoYk+>h-ey}YpVz8aSSoR_`uf$GsrgYZfTW1I6C zx1Tji1;Mfw@dSIuY2=hOiYOAk@6J3C(O7YZK`RgYYH>3ib-JAzB{DqP_!iZB1&m+~ z=}!}x4jM>LGB6n0A)s|giwDKuwJh~9HI#FB%9kld+cTiAk0W!G&k(C&v1o0My8ze| zorsF8AezsG#T5d{h-4prA6-+8vr45q`0`JC3Gjf5iJp4 zr1>ygXCbaBRfqu;he_>3XERAF05A${|Kj2Av(Lk7eHfluD!&s4%7 z9y*jf&1Uy2bpi4^FE+AZTxNxKyoO%8Lc5$porNQJold8>h0ly=cZU7)x50XBY%dAJ z%Bydirxl^Mk{t&ri@HFR%PJaIyJhkTYuVK3cCjAZ@Qqbm!UG?5&fu0#cE8kCP5wAt z3q$tTleCi*nlAAoi$jfEA*^muWxQT}${4C}xj^>Oovo+CyOWdV!faVSzNXJ-Clj5i z%27q8TD!|~i2K5i2D(+fL1NNjwHX?n+ePAS{i%yLcXyJ0RF2zg!sq`DzBAvJy{GJy z#}imde15INwFjvHeM$luIMJMfGRb6$_thVN2YiO-6I%%UStS?8DKU*Z6}6NUEjWqf zQ#F8tkDo?^cGV}%xWfQa?r`d9l4gh{AK+y?#;g070?U0@^rhJyD#9`9WuZc_o+57!3v?fW& z2MK|IQZV93hW}yg>p`)9@Q!PjlSB*5SHe^f=s=Sh@BFyxH0|^MK#!gVU~H~l+i8VMFNrROqM-iAZSN4%>p^ghZ zFBdLC1(B0>j^nLvQ|Jtjxd2}a42J3}X#v`NYJcu0-KS(_x?_+x(kE)|3o~q9OIh`$ zzQf;(eRPindT7cmd*6UPjBE$!zBG&$CnI1n|AB5Rhq+fiof>%Q2O5Nr5_rqbRrj7D=IsojCjyaF+mak0eshkg{&MxhlB25|W z#+r0tF(OyKT}2V7@L(9@Hay?eiMk|n=5x{0xSVq6ggT`A&7S<7=_IE&yz{x^3;^=y zZqadP)~LoHf0Yj~*^-nJ8iH${4tu6_Hw`UXsIQK^$`%6IJ8$HkB9gcgzBiw^a!vVK z1@L!14O&}vBdkzRv$1(^4#crYC{BmQuusOxrr3r|1I&J{?Y@6Q71G#rZVPpSO0|(u zvv*(pMD>5e59SBWa_=()vRH&@fjVO)puI z`-^BBUCPr{0LIG>bPPFIA)Bt<{W5ui;GMS=k&#=}wT|m$9 z{7CgNpz)fbjv14zmuA4Sb{k8n*$zMOXJ<$GnJH}AUT<%4{b7NQgphY9Im|HjJ*3cU zG%%*&idn~;5%QS@xH*M~=5urVieA;E=Xzgs;P1~qTH-jhm5^1yL@%@|*=HZfEu&U3 zmWb@5YKN?GH}-}&IB&hID|cm{n8pH>oIKS%!%=2FkH=e7VH-YZx_86U>|#pt2{Q zq_Xz$>q}v%m(-^?(0?F}#}Bhsm&R-!C5PlmuM9Jkwrl(lO)s1EvC;L#gO2QF0#qZd z>?fPW9y^iT@G(yiG@XRs3&PDY=a-fp^nA{ZqUX8dQj&%a%Nc*8uF5Y@OE)@Yv>9=z z69Gz2d+RD+Z)5i6d<#_UlY*ihwdn>aXzu<9cgmt}nRukT{;39Z7_Zr|tOxqu!_g{4 z8ON`{%a$g%JDr>^Eh|f_~aDK5S13q|FrKf); zWPkb^3crdZ>V1-5(_fI1!m3Y^H8?dvFx#*UWSq#B9ukr2`dyY8L_c@l?79QqvOF8J zV_@1E&eA;TisS7;sn3^ft~_AT`;6iAb?=CxyYHaqU3l}fwAVy6!0dg4TBCudHmZ}P z{a1kFp^*CEC+6`Tc<)8{D-oE1XDEKODEA@)wizK(0Q$swXu0?wNNV4>o=EDKT6W-R zA7MAuy`E@~=X!z5p$X2YE@zOI8*!Vn3VIczz@s#-dIFxP>XxfshQ_8jAZPfBt4QO> zJpGvdU8yQw0^b>`C~0MwZ*3PiGyCX8H(mcW$)p*)?Vn4eLwF5sgAO4xZNgHwfA%4-^uPl6 zu2kob$2~$j7f#jp*`DVQb{A~5np{>s;l&E6~m^`MN7jq&Ia;g zLTfA&Yml_T66{@?yg{Y3dMzQ!*IW<`!%4^nwoXz1wn6mY%)^Q1jaYo0sh^Nk+TCg} zX@jqTP;8-MGnj>i5$B{GO++hr8CXx>Vej>^g?T}Nx4l&)R%fO0jgR%9Dl!Au;&hhA zyS$5(>Erz&`jF*b^#C>OVaR%VSRb%LomSnTR-?-K(4q$v#~OMDs?xPi|M;Xt3za zGJK+Wg&^neVClWubHZWr=tr9oPguZkj-}Vh`YEqVwjGuN*YE9)3qM}ZiaX?@+r1G; z*Wz!pdMa~|DB@#lW%jn;b0?*E=?=%4zk2O*g|EiA>TVD74$gdbZEU^MRNlZ9cnnnF zDqMw5g^|LAyxB?s7<>hJ@*5N%4fzhooHzx6ovl)rcJ*?)*&VA#FV^+@gacS%8tOg_ zq39d|H=-;Ao%&(=LzZJ!_jn%Ct%P0I!kI~HHQ1y0#rp2UE#Lmj?yF!7l>c1MhICye zUtr%4mWUHBE#+06nkgzyV@%R*mk8F@IX)vO9Qw*Uq9IlOnx*Qmx4O7abc7YXQ_?c4 z{tz``(vw#=D5VcyQ9M;kHQmjx?xH|6rI*mC-`t%I3AaYM#nW{Kbp@^Vsm1DUc_z=- zG`F>@=3V}NWW|dtD(ejVS(>_}iAqJBjRh>^11t7jfvuXt{&!73034Xz$>w1IzXMuOMgbNoca_xTz5dFnBBGne16R7>9wUYE8WMDPBRELkK zymf!C!<}m0#t(j43+h_*0umr*zm!i4vYFn4OHM+I2EBj&eIPK_IX-n2EMbtzOH@%H zv_9Rmvm@EcCtmDTm}ph-q+6-a)Wk@K0K?N_GwF9a-t-=M71Y-X>D--HUtS1ObOV3W zw;+UEhr3c+il6|(gp=Z5-yYt|J@=&k{CBpwgvFQWhqO#_c+YsnYiRBY14kf%E0!a- zgv%%;>*W`J%E2QC8U2zKQ}Mhx^*&8PsgW2 zQAuAFc^;REmzc^Ps^|~Rzk=^qZ=SLT)92i-=5GS=&Jed|H}v=Weqw!jKx*v^@im3c zT4?%q36Ds<blFt~(Rp?2;jAAK$v@ z>W0>(H(97!0jT#Q{WlL6Q%--2yf?!0U{02k-u|pHf0g>oYKqLANm<(0Dg@aYV9~g; z7pp~s*lN3FuuiCMm_1C*9o=@WWf?I)PeoLE=MK+`#dfEiZs4>lHO^(C*6yjE_Hm2% z`H~+Dsh-wJhZXQy?@6T%0m+)W7Ky3FP1;WtWDvvzmt&FAjf#*%f+II2DTxDt(~M0v zGLzxe()yp%vl7fg^JmP?+OP62n>Mq4Bg)Rd)9R_J53J34y@$T3HTY>5Ww{KJ`i37( z&NwwAk#rMIpv!#CPGM|qCO9Kf$2_xLro!(JCiM4d`Bb?^CClh9vc9v8d^YXhH6lRr z?R!zHnA>d9qT&$=(bsfcUmRB(jbzm}XZ34(>{eo#@14IsK=+C`krL+Xml!EEp`Bxe zn$Cx}Tj0G1q_oGCNk$>J2oVs$BsUfd2U3kQCDg9|p`CN$@%J>XKF$iRkPJ}KmhjsAv1#MDJ%P8QVclO!JXbDi&X4DAdZm##lFj6{mi(7>mLZLqOi>k}Y#H>PiY2_@C_5gh#1tk4aS6K&LKIXwWJiG>Ju>@L$o|+J%2XCE zVa_L?;dpWj{*``M>ZxrIhqH6?V~PVdr1QhLi9726`}SxsnL(T2qO`R~IGFRPaFdisTJX@K7V;dzKWJk{y|-mV2 zNP{@iR6{ty2sMu;r9r9JagIiU)xZ7^e7}D&Nqi$qWk7QGcZiuPUd@h(Op%oYTn{2a zsmtLzU}j3Bei;{L#AaN3)Woag-y-iUw}Qb}0PGP$9H~i|4Ts)}{)R^5nQ4JM8hASL z2Oz3Np~)1BjV8(LNCjxz7-P8zYFR+nvZ5KWKa|qZjTulE07eK26qp*%#`4(y5k0Wq z|DpKwQT+c(;JToh*{jQH<5{B~TbW^3$Ru+9L%QW=Z#c4e zG*5!>SFiamJr5_hH{84cx)0@xQ~m<-4A}iU{h@42;;a1|Ma=2GO;M!`x?!({3+N`O z+@@wxOpSh~($$_#S?ECM7SOXCeQ*B#L1~em&UZc2{%MH?`0{Iar;KM*9B2A@qw=Cz zf`wro4O%+Ms{HntNYkw(qiMGE_o2yz98@-+FgIEu!H01aq|4Y)xN5sHX-4hX$_P%Tz@0lt-Xg#4d z?w;r|B6v}JVIlG`U7Oc-nDgc25Tg^ho-!54FaLJ_q{a8roo;pw6|&FGB1(SP8<4X14z-lIU2Ndwn6H6Svb-G+u;%l| zNLDn%gcuw`!29YdaT!M0{et}((JMrF2C8jzn~*Fq5U7Kc6zhfT7Q z9n}Ac`mMUlc3t}$Meijuo6)>$L)L`HP`zPay7YVOaw_RTxOz2y42#kq>X6Iq%JRkh zYR-YAzNiLnQlG_=`uz#Ae3CY_tWE5}BUi%BOuVsyQ6T~^u84pM(`spl6jt;fC>~gz zWq@3z?di*K8EG}IHQiFT_4{v`UG4Q!g#^i!B9mt0mcQil%b*06x)XNwOFnDquEIrD zgqe~1`Bb@{T*7Mpsni0!dYS7)eZ3`;&HV4xd%NO~qkhyiwct>{3@bx{ zB!+FNgMO?CKGCyFOetq`oeFFxtLapmyXnpxwoWR{jn#kN&CI#6e+1}?w>7rXu+9W% zy;BC+hUHrZEQB=2Ji`&laQE%5v1}AzxiLvou@Ekpm8=w95m&9EeDIlUcH|^FP?#&= z#(AUAOkO@vd@GhM1RLISQ_HL!nhm1z>+}tqh?pX4nhbnU?|u~ls@xYr~Rfv&Tw9bv>EUl)i%6X34iX%;l}3TzJ~hv>QnJ- zQuZjqiY?Fd@z8Sq{aGe3AmzTtm}X9baZ(1*FQsi--<|E)e{7K@nYq-n)o0O0LJoC9?yg^G;Td>kMw z>Pn$U{#3iYPW{BlJ^?a!&{1%b>EAOUhj3;K$zke7=b5DKmYq3lQ|2B~*2oFiCo%@* zz$Z+1EITvvE7tXU6@ zD7-H>c5%1queyo)f1n2^=pVLJlRVT0eU)$Fp20m_oT~@M^bc7rYo6*?X|{b0>GvIr z(pT||zJc23r*GrJsYg|jy%5yp(>F2>%#3b*H#};J;|Nb@x(+I~tXqL$O0$bB+~&nH z4TowJnjHad3OdqA_ygavl=rk%2Cevf-VUcd^7T{5?=eGh zZsJHV=g^)|(-_IprjRlwLiL$#p2|n*5AK+=!%(Lh`XT-T8OIO1H?1C6#cXYw1bZRn zDwevinTZt-_(yvqHIztib__7Zcvg=Z6vz-_z;{)Pi_I%b`a z*$R8vF~Ty$Y^QnOML!pVT;P1AC8y=2>-tq;&-Pyu^dVbT>|+|lMS(z$P{V_`mA2^~ ze;@sNN8@gzEhVZV$p%HoPQhQL&q~aZlL^>n`*!Og!VRN7Ut)G0qTxZoGk-Jb2rY{( zA5>F?z3T4;%Jw}ySw23adWo4XAV<((qT^Mo{liikhFoFzd)n~yxswchPzeoiuufSM z#WTab@6l#GGx$G_&NH0N|Lwzx*n5Nqv15-4YSap`_ok|9l~7ed%_24tdlWUIwxXyi z)j{n&i>kKT*t0dN6#wV`Jukd-I1ag!`_A{eKA-dS@4Ug2s(DXp@3YpK`4s8GyWX)d z!jzgr(Q532KX1*Jaqjd`7yY(uUw|^zm!|unHm#lU&-4!4#yc)&l*Ai6m+^Q5Ute_W z&G&(2?zie39$@qp;x~#*4XVZifHEiNZ44EL$ES!BAuz-pn7*E7_<-YWD_ba^;>~}I z_k-Hx-d9Gvo?QB^_9L4TDX`G~371){lbuoyy20vWw=r-h} zNM$RkamjS@>~zuK{=nmLV$jy#jT^K|?wv@ya_osR=lMp_LY|;?C)t~}ZBnLcX$clz z`oQ=;a7d|-J51N2jihc28@7~qs8(iWM&UIv+9KVx_jG)Fqt0&`>-aHvu26tm&ZuAC zjph<-*wy?hi&Ix$yQX**FYUT~?=WAWQ@tR(PkhnQu)$8jrXO=d*-MIEEBpM|b1Quv5BKe0mNT9DRc71g^?6Z=#~XD+ zUl$FTKN4Q3o%V<58J7Gi8IhjCsR*rIgw?nkC%bu`6}ZP_n3agPDU1eZ@(@Wmle1(v zHzT9hq{*pAm3UEKxCc;IdI7{XfbJGdz~XiA25&LeM8`Cij%|2y%?jWA3!)?%bC{{V zo&OQj`4HQdcaUD1o8T(yh3z;#`NMZrZ%QVl`ZjApJ*u-FLv7qz97iZZOCts)l}})zT=o5PZ++;SzRG<~pbVHHH!@*#VCCLX|4(G`16-E^DZeMPZ0oQrTP3 zoR8h*r-<=AR2i&e7pA8YUB<@QyLjY?%#p)c1N2EVIjpRlzqEvE$g(L@MchVgU&hU+ z0uNe2CKGT!wP|)(gw00W!X_4#TgY@4^rmqYe2#6N(~d#Q25zzeS_d;Z()3_Pl`TSeANf*_jA?l{VkPDZ`Z-5uAHr9#it|@D z1X;u&=kzT^$2b4?LTtLY4R0a0UMU4`0(2koJ{&ws`s z8O7L`uqg1!0ZJB121W@41Qt>G3*ubMj(|Udq2%4jLOD?x0W`)bei8uLCsLfM&A>vg zfbCcnlK&Lgbu}l|@Ll6&! zm|;whqk=L&OZ;G>+CsaI2#t4QOZ9zZRN05V#+nOsTx@oTJrPhw2{VY0%wB!uDLPk+J7SZO!*szBZ&wcRi!9zB-n`gg|q&B%_2l>712%n$EHYcni5g9s89pG^|WJhkZ5;!|&6_HU+t=6KpY5^Keu)h)^ zLR?s1M0Q8DiKyO6y?HU1F_6s-`=Md|z2mex1@rQuGJ^671jvACn7cUK)X&NV)Q4R? zSo748<1z`)oqL_~a!)~PQMm#)>ZDx4lBm|O781Rc$uI*qOt-EN}tnO@9HAT^X|fc zg>VCW$;tIWcO+6bDI&W=&y;u!$LCtVoQhWgo3H5JA?!PNXU!(`W~>?J1yoMZ zw8)9$SHdmmwL_t-i-kW6nnXf@P@*YPk@EoMghmzMX4(6d_Y7dU-D1q0Fk%QTn(>(0 ze9eR`h7v=UT7)(c1M6FB8Dt~#A@fy5v!6<1etj|gXV&R6p&6VM$o7Tu?fGn1%bx2G z%<^d}lJzUhZG*o(a%Z&PP@1KoBGN2T)=u+jEG5&68*A;xU_~MQhwlLigND)VQ-?o|GsNz1bt zy5#vEUIA}GdgjfX&r_sx&~CG2y)l;uu8w-rDHHuVTCaH~sd$=!P&NJYCt1P!qNNqQ zXZ;GEeH}~I7&S&pO^JXxL7)*boO7WTvuAZ@l)u2TWtb|X#<6nP2Pl;fmQRlP#8jBU zfp&WQ(4sSTKBlJE<(hN3xv$9!`J2Cj94wn zz0=t!J&z$*;U%XTqby})-6F<83)yzYs=j%uJmq2KzRs9X{DCyy}50UE+6;VTX$TPXfYu^-LcQ>LzuRngA zEe6>(qu`LuZXS)$%XpzTpmn@nlk2Awp!4{re2?WV$9@rs4{D`AaAFwz z#Rs3REY}vC@g9#BM6<9wjTrEmJ5<1k^n094hfPbHw4JG>I)3^}|BnOs|{ zUXUCsRW8F&t^0NV^Sbf4(y2&Jz+swcq@KCVb>VmY`^rW9ItoF`1Wex--ikJMiJrvw zK>|5aXpan&bP2dwkzfBmv4R0(?10wA%Zp8efdJt$%+kBp0pCsV0V0TiTDn|KS-M-p zxhZ>kwjuDG4wk)dl~&97l2P2B%GNX%E9Ya^MZ|L_wHChPpE}5(Gl|(6w#t^5-s*jc zEnb=KvoU+tQ{^@iB=zVg&_1bRhTgx}n3JD%w0$P9PN&E9(Pc)dTu#}Lj#}5^)hLA- zHfa&4VC^JKbE1*6MbLCG)OVx&6mDBp%i(yi>YDMi`JDFCBw9oJWi5}!Df%ydtgY7# z(M8&z1*^A)0VNz+@){F*l4gQ!TgTJ67W#^?;In2~&6~9oU$VruJS=jA(<1=U`o_~6 z+6du_0Y<}Nq1i_GYh9;&gep6DD=XvZxN`Vm?PvG^*cs=Mwbw7Qt3devYWPnQEfO}U zQKNPhL|WclwNr4(;^nVuhI%k*6+Pc{74}rP7WVk%poMy8zh^IT%ifhPoqBR^Ju$wd z?{ls%Z$;du7$$^C!Yid+#=-sYq+IJ=!dRvjS1h!cR9iKo=wwIY30!Ksj~2ln>Gh|F za*{J?-8y{2A&{DnosBu}cf_3~5Gc6q>y$;8;^}WWvZz2Z-)5?B8A_%&_oew0C2D>E zhr+;_zS_H1eBxDho}!S9ULdb}Yq9H#R)a&W^^oX`<2v8Ulo@u~ssVj#$B)h( zkBNmfzB^DA5YGqF9ofe%D(g){Tob=Z*@zKV5dUllsVs*bei%{F6gRTdw(Nv_S4HymE;2Gos8@~J%m@ZNewmYb24fe`omOBO`VkCV%eybw zD+RyB8&;bBvAtz9e8PV`)Cj#XmmbkbEu0&+%qTy6L3M*6KR@pCr}wU-&4WCuKT~7v zU~7Y8H;cjPZ%Jo1E#-3m2BLocKL4#(?qOC=%lf%{LesIyN@if-%(WD}5`L*^hHG1A$&HVe0)BiO?Xhw^1-SFp%)Uw3Hc6b^lAm5{#~{DA4yZ^?!?*%#=g+3xz>!5 z0KISzz9%14<)y>Dh`rQ48N1}rDw$wN!+Qp^JY>-D{j>byppTg)6%u`4+ z&Hkmkl}XHxTqJoK&f|JO^yMRIj)H!vn!v;K;F#|r;T%OV(Dn(}Zso{sc(`XtVhMhV zCB^cI=so~`SbDiGU2bA@D6^Z(*?n9?6;eCfV)O^97skf_D{z;>CXIjO`hECxwhiOe zcSk{=%D@H3sA1UNNQ+DF#XoynuKAl4@=xBihOUhe%GLOyB;P3nYlld@9;q^){oVa+ zy*4PIJ-BXbYF3xE1q3Gq#*{@JH;_ps?}E3(0FfxAh6k^+*2X)97`gIE{vb%qzB2LI zeax_C=H%R?8rEBq<@QV8W%ji$#1(GTi-@jjbR6v8v?wU(1cwb!Qh>CfYKwQ@m}!<6 z+KT`~H46_f0BCN?Txl=&0`gxtQ~hJ#{nN7I)kNOUusUB%$u*ziV>K(D_>5wBsmkek z9rD`Vl`gkA=WwlWFhT~#RvdUZjdh4nrkm7w&D6=TH(#FK-DK=?$n>Hn+~uRQ zt+_U8;-;l*d9^SGWl0FRvgwhd!yI-i_rTPmY^A!=g?x*P1JB)3V=5k!#nUpH3ulZ=}jW~(fk|Oz$s5YJQ`P^zttMbL$h9$E~K4_O9$|#npGU!_fq}456!^a-hM;A z?Zh9+%0oSq3e1T3T&JU0m6PfomR#~|J%7fi+$8LD0*nVc1Y0i>&Tl73dI1E+n1~Pei79}+LZ5C=$nH7fkTS_2Qr^e><(}#^=-x`$OS}gL;G$Ck7EChSX-Y&yxmuEnCsGV7##{jdP$96APSR2gBy;B^JQ6adF+a&vmu^xHYw+)~UIOfx0JEi9^E zLZVKD1szZ@NF$`hQ~fP+;~mHpu{{FblyE@MTs_B^E13IM8tA{G&u2s0E3bx>(=I3o zbx6}#4pOlLrz%`0vi4+v0x6cGuQZY!4lf%h8Ok+PRms;C$RH1h^qG|{HsUJHqL^u4 zTb4!rtP|o03&CGV3%`6$uB;4?63ONqbavdeQ^ls2InA=ACr0oBJh$OaG3?qi_jNch z$pw(>Tuou{IHR@O#QHCXIG3M!_;&*aHU8wk&3Bwvkfhk8OW8$?VC* zr%kmn6W=fP-AadBdX(3wn5mD8TU?sj$WQ9Ry{=p%ZVkS1nyf{N%P=y4EfkLCl;+L| zztiU){L*$gUy-ZQ8|vPMUA{DjHZW?Bk-Jm9_L1-!1WLO_4CgvWCl4mA7`R5k?~pRcl0)OJt0pFFPP5xE=AAa7mDSP5(C?(8P0 zME{BN6*izJGQ(0!Tef?soONnyIXhyuMLhB1WGj<_gFA!qwz%Xzs zYp@;Zw72c$_I4&u+g=pGa$I+>e2OUH^!w`vT07yEb^ei_Fz1@B(p(2N!F15mj~N9= z$K60j#HthEl7X_IaF?UwgR@x^K;$VS=&2gs3}qWJrMBZXHw2A_Gz#jxmYP%?dYh~# zr?`J{_B?Pi#d6!~b^GB{j}k44_l4uy(p~v7o@rYAkKA$U<_e$1*>haMpK*|K%{+wl zRFJ{gkBnO7Ka?dgEwJ?;c`@C}7vc|UgE$l{h+@MV{Ij=Hp8WLBI*Ul8W6M}`toHmg zDmwzJ+sc}q!arYr%683C7yvM6?M=F!ob%8w{P)wO8=0>D@7A1u47l8TzQU zzHN#6T^Nmn|C^ILD2Es*<_(T5d!1Ai^%`J0LIkemLHP1y+&T>o9`sG~tMK@1yfS6y zbSRo;vGK?R?d|9U3%dJ>fby*jVYKRDnlm}>1if*IA2$Bo%!Aunl?5}Bw?^gfh6M!R z73(yL=TqIP^HQh7^mdJ|bxcG8%RuK??wMYb5uW4~)_`bcUG$Wc6hmj#q$Cb|qVThg zZR)W{JfvMQkov^=>Ak zbIhaO{CD4iB~RcsOJkeWyQ4RCd*3x!4i7#Vygc;T*LB#wovoeC@IiL?Yf(O7+R9!x z%_g>CwQO5L#L2FbWwbNZeZQD*=T=dChG;=0+aP+^XWFQ**}$Y5QoNQ@<>rybucfJ^ zJgAv;!;_ma14q3z4DB1XXhxKVorzcLrs$9C#P$3K_I3X0&NKY@a(e4htjpxSl~S+} z`8k_;K`<4v!%21sk^xMW>x-7XsaxMHSN}N7jC$Bxv+iB4AUOm9F`;L_<&X>LB3pCv zB`6~&%nuc0P29x3zy7z_eeM~X66=~t<{zd}cwq80{mrAJQT~r&0#xnjXd`_3u3#Ii zp0yh2joGys>E=`@$ZY1S5 z{=0eR41+%`6>J_!?DpoAGNF$fcJB;yj^J*xW$hTIF{PF2*r_q={WyNE(_&1vH~~H@ zh!k^ay7}FwMKo4*Ho4GKK3o4cWZ_qRi_njlubfE`QS#uPMj_MejoQs0Y(ZxZ^vGkO z+ROU}Go3Pa+#!Bh{QiB}Vdw7bY<6fulRj&+Rl#O-lcaD&{-}vzvd7BxoqnIM(;Rc| z57My35S_UvokU-}aL`69^?>oLq>oA^JFEcP%q64S{6 z5tp6>+MN-P>Tjo%Yq^SReypH6s;6qHpqBKUU>Y;HcqdtpTuYk>QyuA}X2V9kkL{e< z#vC-q+EDw;8t&{^V-L3#y&d{Oce+KtrN*Wc7hJ>$*QxR~^31C9Da>yZaMkO9-QW-M zmNX7^&y*x4*CB0>G){yAj(IEiWi=&M_^K3Mv5EXM3FW6x54TkjRN>@hZ(l908{V6F zY0#*9KQ=I~dxgp8eQ*q_VFOW23cX0yybK>WRcLWT3ZR$43*TXltey{^XDPU9%c{wQ zUJO^cHQjDWlrt~95Tj#?I{BnWv+r(a>T4P%+@Yrf3WA56T-iRV;;|Ae%G)2Iq4#T) z(eO+COIT2_OWZeGd-matzB7mfOoT8C)~Y*h)Nvf}i?`7yJ8Xs=@wcB~HTtamXV#ti zID0oh1dsXqrlwS>35%h7ginFlD;#}kafscOf9u5_iE{R$sfZ1+g3VZPA8dBol)y#g8C|GIY`_0A+Ia{A!_ia1b2&$wE#a+ z1sJ@nzx2*y6-;Z(_({U3%c%gaIf?U}232zi1a=vA!-%|-DTbwzzn$~VB_-BTOJwM2 z3p`#@QH2(J%Scfny_Zu-nYWUO__KN`{g2L`AO6e7U;3I!CQ*;3NbWZT$(I6p|N4Kv za(mX_`uUM;lKW{h_Ir+FW0OaIyX0`dDz2tvk+RyB0m@>uP9vJOYTsj}by92jz-gY< zFjrcqHpD1E;}?5Qe)UX?>YF@!DH}%R1M@N~6{D`v(X7kexTW%Ki@)xoYfdeoI;x%d zV)nj|f2e=H?s2&r!e>${>0Ozr)jsxzdAi6|v8;ajMyt)8YO_BZkv81y1M3FImO`>mz?6@p?W&Dp(tl2->A@PNd{_r(4(!ha4UBaJBVM{ zAo)4mTH94z)duqV%W*%MLAsJ!!YS!jCBFG@W(uq{t~8R#5w6wpQb3Bp7^)VcOqqi= zTT2#w1W`*Qk3^cXh!Hy7!WeL!&KhkD0`G2vqLfc7Q1?jWQF?4IYKXu$Mn}#fzcoyh zoodG8xbq{UwKlmQ@ktc^T3friwjY(W9amPvGc{!}CUtajwVYHcq8TrIbjq7^g-TU~ zcrM3{-9@w#S5F6219kW5n;YH%$qvsxS`C+*^n~+}YB|$5a>hz<*~fS-))i(_&g@n{ z{rmWY7^j?L%{1z4*%3xMKS<}*krhwksK_UNcxl(Wa9e&sJ?_`MNw_HB;k#o-C1z9khk$2Q zF1(**!z*B4y7@wBVGIDay(?1X4`(%{;!9>sGEW9++(}nx^sy<8p;KIO@xmSXi9VeT z^KXMye*Q=h>1>vZ4IVLNny@;Bq^crA1&C1!0P1Hl9OGXiMZdtJdAN&ASmibF>{1Nf zmmMv%xg+`Mwe&U++Z7bTroNR-{S$|gpTK~KkoTGrAUVwe+#6a-9x-MvkafR6%rOyW zLB=bdg1;Fl&Oi-Vm1qEQCK&((p+}efCYm?{R%vf~U=ct;mMNgwhy)gONl;M1o{1C{ z&_sI$f^FbY*ZD}OzM(A>87MW=D^NFME*S~~8ocWRqB0K$(_MvC${rJ$ESA6BBE2@+ zP#v~KSxySZTXMbG(D>W0%6uDdqf0L)F5o8U3Azk4>L--)8t?!!3l1`#E=r&e%kET% z2nSfsJgHi}O|x^rc8|rihc~e#hU4)oQ23OhxzUIB5$~&nnqcNFLPJyPJZ3<>|#Jx5y0Ls|K(-&o?`rqW;ORRM*9`67O z<#|_EA>OwfQ@&J@UT}He=2)eM$K*0Zzx{1HqE&*NQX63c|7`IqG5>0?`uYDhuhpo{G!!ZgX^{J7kBEmYl@?8+yP$?HC$y- z4fiOvGS(X2MweCs;wt!E2u2y&VC^y5_66I+Q1-EE- zpnOLVzzxs+dg!*?`?u;Zc>pje3YId%m7W1XpD{owI7m1<=Ys&7RDr)D0 zMIZVRtqmRkhB_A5$+G^M)hYGvjjB=hy{&^HU-BW^L1ocb0?8dC99zX)9x47{?Amd^ zf=T`x7Iuoc;4QOr*7@2nD;4$d8E!2scHM>dS&^2wlTS0}DbX-qfP#wGrUVH7`=sNix6E2y$N5fyo&f$kbq&ze&$4lik1M1+w6KmDrxzT^ z>6hc}wZ#|Xxr9~0J15m5@dyi%0VT>hPGjtc-Xe-AKcM2Z91I-d7)jpQRs28fxv))559x;VW;kXN*H8Wp?Oif3g*p^BIa3Z~l>k704;B zx{x86-^OiYzXcIR`RaCzaHePEL4w5>hx4CpcoE%~YlU2QwPOC#a*DI}-iv|f#GTLW z4!XJ*870MylnSV4m%WTyM@mqzO$P1wyoD0+)YT@|R5E3~9t2*Qw|;g;I{4*Fx;i32NDyA%vM9G?-lbNRitj*iiuA^YYAzcp&A@GQkIux##U z+3ggTp@!a=Vc0kgRPR@wZ|&rZg&W=sNGsH2+p%TNfvpS1bn~DKc7_w$MqYZ;_&T^} zD;6{NYW!U<vLRk&qXkS0?mv9VulXL7Hg;&KrY zG@-Ju51eZ2)N7{LYp4#;|(Su<}l_ zkPc_m!8bk=YlGo;MlS{IouhogXLD^nh0Lb$jB;k?Qzx|&E7W?z;Xzkz0?GHtL^97w zhtL?wmMyuC!N>HUvPo{Ccte?)?=n%*kLNS(!?V;=pJdnX>hMc!@P`Z&fECVxt#Cc3kwnI=S>5JTi?X>ldzF6!LnQ=@0(0Rq9>qgxEFZ zXGug5=;{BR^c$yYr*^Vto?UGXT}W`jwxkQSqB{BA)z9&d2}Xw5eV(C<={T1cvyF~s z^8%k`nTMqk^nWvL=?Jd&3?m%VMNP-_$?v^?^$Dinv07*v`*MY+=XUYG|9I#{j!y+Y z_WpbOXwdpgx=*LU`dr>zGV%+5#zb3otGxL)n1v1{wdmiJhNYH}PX32|f9_UY6L`ki zT5AA1nIzWc8YgGoKATM7iQ0me8xB|6Y>cD^T>oq#U}657YqO5mlwR=c>)868ePepw z>W-z(*;dJd*m4Nx$qlJCba8R{5Rb+y|Coqu;Zd^9|AE3f_=6iAy+7v+Ile}@xeu6| zgxle{?i3Dh-<%idIJ=(>wu($rzVxY}oR*LLxT4Q&vho6}Q||h4pF}aDeCNZ!qPcVE zxaTQlgClDKnbhICp=0IA4Vy1|kKgGIc@F;}EnNJ}UZ%MxMr}D2q(K7k363@`ES+2u zZMd9S;-CI|?7=qe!r!?9MwH=RTaI@GeLp+2|5ztq;eY{2xv~xXWZkpfo1VeBf>)Yp zieGodDzm_@(0BsC;|>J8919Ii2j#(?LS&UsPDJ@8l7fVrdgDX@B7-<6*D0*|P75lAv>Drt{{}=ZaiUH(SdhTpTquZ@#={#?}{20~m z8zKsk4>I3KO4i3DZbvto9+Vqvr^F*_u;+YLfnThHhE~yQ`#Xf=t#Kv`biVTZ*V|1? zl?}1yS-o%Mf=@&rPVwgIZTeO{>P%msto>6Z)8Fmcm%v%TFbETxPfyslVs44-2|Jj4 zyj~^ZJtp;w3JfAwTshn7y4ZhiVx-4dSJAh9;X*=0JMLCk4VvC;_u{F&W%xiAJ@T4A z9T|6LxRf9|mTUt*UM;=oBj7I-gQN;a-49AxD+AiAKSv$5h`E>0E#qc<*aR z3=NlvbsMk<`k0p#V31;^r3{HVTTi4ID3FB^fXP%-ylx7|KM!51Z;%%=wNH5T=;9=@ z7X9^Kfk*888F$kIyURf{MzQ+Nfcg-cV&`T6TCe`$y5HR*RHrF^T<1v0*D!~lN96Qd zCkL{&wvvq>lREk(p(R7{@tHT>;uTYQJzVv|gsLQSMv#@D-^1Oc56&2#q`rogmx1YJ zW6?KV5D!|NfP2>Y&m3;i;N^PzOcl+A6X>u(q9L`$#ok5u3{Uda6i7H~YxOF&_Bp74 z@n$irE`RgMH*gCW`Ty){0&!l zySdz3q-tqn^_PLlwmqUrk8$~;u{3(Jk%n-e8OqyZaIqbKQ@TS)1wrDwYd(?VE`pg@ z6H4zm|82^KWj7eI?Cze3++_2puc5tp%*p#zyqv*~g-}|_7|qyrBAm+dag_xarF{~l zNwHA**SG3^SjWYgIh?1wlJWSHf{6A?@XDi$o9n3zRAY=Me2QjKCEn%8T`+fV#8nVm zpv8D&06INQ4xa31`u9c%+Xr|!o?^}^HW0PXXLd~6g9o9{xxh*9 zkW~MPr;9i6RQ|xGs=pGc3`oY*#pnQ|Efi!0vj!1SVq9btWEfyQX93Qb007%l6{T%4 zR4*19!7f7zj9b8Q41jQu)npF7559VpgnqxKn^mg*4OmY)8nOr6O9fP(Xx^#piXB1} z6j`mIKK)Bw`C?OMt?J$*&dL$pTSMJW5nN~;9}stVzH${dKM%!EdUcJCBcKZW=VxjP zMJGe1Il73pMXdqnmYSV8EKI+%47LtvKv>lVm`CM`SnF12d7!uO719NtY*<)T6pDC; z=9($OE#!1E)~Mi&ni9Tt2op+)aIm((lRbS+fDR~9Cohsl?F`WNIIjwxn~Ydq|MF6f zXAl@g)q5$B0-5@5(mLxIID_F=Hw5+5c5c$=hcvA`E}z_q(_ZYlAIPP}F9#1&Rv^2F zNp!kC2mGVHmX3=h?q7JZi5rJi*s5};CWqJWEEVTT)XOV)kNtk%d=+Ts(p)wfEpw!} zL5Dh3EiLL~y|S%A-SBJ(9wL|{mgqUkWK^4_sHUhL^95GrTCK!aS52PWmv>_Mtt$Tw zBkTwgd~jwtbw5BpPDB;b^QUGif7ql0Rq;C9PU4*2#h(0fo$t~oSkw)f{jJ-YeScW7 zCB6mjCHTa$hNxrviwYESeq@N3S?O06BCrAKh8mYCuflaWugZa0-w}{st$ye}jyUFy z?c}5yBUNd{wpTtqEZ2wCwNwoX{mA7l(WK>~%Q7hNlgN6yj2@CieRo;b300pwe71!D zgN`F>Yj6zF)?&#@KCTgU6W~tUTs*Coj+cr6E+OqoD~Ni~k&8m0CVw*AL%m1wU^J+F zmkxW%Yj^PV_`pa>qCz*&&aGF4cpdw}@tHd67})uyJ#=J|0??epCf++HNga&@;LfK1 ztuV8*AHrSaky46b??YG%w544&Zm%R1%%Y(8YX4y!8pJ!vM_*0}n$n{g} zxP$H*f0J}!i{fJ*^G0O5y577pJgYAgxaTh%a5p>=k(-sY`qLDAR0@u&}oH=86ZP!oFj2}~bz z&>fo<79pqF@@Jk!ceHYhB@G4q6l=Mo^Bg@EtIOVIs_e>Ynp_2C`DSlJBLY-^;|m2o zI_BN>+(3`ijg($6-WPe3kGb{it?S}N_wQYGNeAD1N_9dA|Mv#nYE0dBv1aQ*f7a2( zE_sNIsJ5p2*IZc4!##U zb0gq(IZWuX?CwmK-x_Wj(pJi3POJ%3Wq!%O5}@M#H!H?4KY2=3h2I6-UE8sE6o0oc z%J$%dNWHi&YhQ=(+Om`$P5x(lR%-iiC+2TRefq~N>{mA0<@V{U-EdoZ1w4NEojnYc zlTrTjrNZ^TD7#6x*U6UIfbUE0mpW`9*@>v6s{5UJued7cUWM0P{GQKt%)@@OdN>j? z$d_O*uEb?YC{CxjjP$NWc4AE2k?r$4vC$tJ2l}e1w*#sI6G^|+?6S15rUe4415lT% z$Y{se&ls72XE?+op#)9IsJw~ks)4gErtu-f(K#(z;JzV4Pi}y1K;%EX-SskK4qIx1 z$K%hMS(QT`MpIJw^lr7Wev48ws)xh|t)gk&c7f7R(iJ)OqW(?cvJJAu&TjLAQoGOm z>bo>Dx3pWiK~5mm`BrZsg{R`VDi->v5PR`w9^_#@Bl=?>lr}6zO?aNdI-uk}>q~UY9m4$rPbO&US4ETyU zPHr%#X#Oqdbrt{hflVQ2-1X7FkjcYF!K_rrJdsR;64^z*@^O=;8+f6@Dc0Vsg@u+I zIrkcqV1s&UAsVD2DM1MBn>=z~PMF5q)!Ft0QP=!UEAuBMgP=%L8=+v8cMN5_tGeIJ z$IJ!0)RQDShxh#YvOinVZ-i)0yeyV#VkxbXuFKTd!mq#jJas3Lg4!IL9+~D-ULIdn z+h8m7Xa%@OnNnx&BK9T?i$DF9=gVBKErDVBlfjF@8 zr9_qDIJ>%38n@g_bSKl$#eNNJ`C~QVO%B2$ruh8#_ZzK620cCP)}6t{&(fd1zxQ7$ zX=Ha^T&FdE1M(1r1sV=pnHzNq@t~AakLXqTi|00NE!iHmS>^nUg__oO&r%+=>U`#% zEe4;FU{#M;?|f$8>jnq^Vxp{WG=46)rQfM73@Y{SL|p0yN}H}ar?e9XwI=6s9P2PH z^A%j^;$W4H*OtbGuiP4>(m|kKjm!V0{;={uJ)X;Iia{7os>`eT#eIwfS^1BYc?M_N zR^L|!-gbRZs*oc&FcJ4fVXI3MRrG+xY0SgVT>U;*&idRNY|E{J)nI!0TMnPt_t{~! zPPjo%o=vQbP=oYfE*;L_47(fJRF7>Hw4z=~sl*cYRW8!Z`vsr2N{!XV2x%pNHrOk> zIQzfbnf?#N+v2zNq4w%gy;Jh|zp--ZuI1tUGy6Kgj5J(*a#KhcioVZ@epzP{<#Ezb zB;nhB_yBxf8Xv)1T~)Zqs`VQ2yKJlIX&VC*{i;V=UtFg8KTE8Fh6>6bH6h1zb|F4s zCp@UF(gYzvKCFtr)2ncEa3JS7)E_-*6ims2zK}5Se`f>IT)I(w5Rg5^OBMgzD=>iF zR2-cP&7sLqIdL(IaIqO*#%ia~fYKu(f+`D&5R(Ut)Mts>m#Wi|G@OFW$|qMgaygyq z1Z-KU_3+O5f-Y<@jPuh&q7(6Z&yZ+r1jN$zc|32tq<>6s9y~6?SuD+1aM?(S|NVN8 zX5aTw_V^Re=~it4T5{8iTWY~Si>A2YZVwslE)zD`qCn_`zy1%@zWPo05rCzm5B@slkKEK~>ofKvYdKci*s(Dd zE@h>@w*oF}!eHV@TH{_qVxxYYjzhHjIhT+N*-S^3Q?q<&BM$zcEsIpC&j~i7Q)@m= zx~Xi-1NInBSe=YmQ#~!2icrqqxz=_F9fuGP6(30(-9dP2bbh>X@z0uU&dN6fb{3|5 zx+!LopFA2P6X8Ms@4rWLu2HM_1ERZ-%B4h>RN_{LdugP;w)i4eP>0i{H!D5j(d2QR zbW2qd;?a%?jX)07F)%4aHK_8(MxywV&Y%W{Ob)N>gz9>F{`~tel8yFFD;UJdVNo0c zh-~?85cs$nO&OWcEWaFXp_`=hbXfWVK1`{+TP)1H9cBZ@ zbOFKS(6*){tB6h~$R$XHJi-c*-0W zydq>r z7AHYqG!O@4YkrJbbm@Q`4OIo~s&M;{0#s4c+{`r-*@xjU#GMqSU*R^mQ(fEc z1GG4^n8Y9zsEAU-X>am_rV%$6nx&UH@}?CXD~K*5+^titwLYt~v)VvsMF8=KKl&!D zL351Ug9&TMkX=aj{6*CFJk@M!+vLd$x+3PnV9qR%(2Kht>o|uwbPt&$AZDw|PZ}S= zE?z-E8^?_*1Yw8~Cx5QKH^Oe9bTh5`LT7|__mezLtF(v@M-+==W&#@>$ z2SG}$j^Fb+_jG*(_pXsM7Al`xPDNwv%%5a9#qAlbOvBX-LV|%nO9b<49+_o^igfVF zxL`s0myvV=)k$?5Rc+SIBo(+jRKdu7wK$9d>R!x*)qTYl&OSXv9yDB!Ngjgb3$g8mOdHv+yHeI)DJO_Al#};uX)kbc-xe)GB z?<{}OH6r(v-@f7!TR1BrXum-E(t?Nz;0`IQZAjKWv1 zp!sob%h07RsJMmxT(E*+y6~O)qX$$q=2fQnaMoUVfki6*U+UrxTpW?v7a3PA8QZ9G zK|SIaKe*ITut07#@dk=|Vs_!&wlJCOIn5ga`y3W50sm@$!V4Lh}Iu|9dw4X0eve|2xP&a_CFOur-GErrIX^1P8aIc3f> zs`1Hk64Ym%1e?k=JqzzNQ%_Hkw<;DwS_c?{hFQ*AHe`if@N&W~6EknqjEdXuSC1tedJCss#9<4#g&99Rg3v z1^vvqA$jLA(TzYYPbF9WIA;Z9|p4YYzydd@A9qx7Rw^%dk3tcbl z%i9w_EP_BxEF39vtyn658vDd?gtNtwQLnHo};L@^krFrR- zOYeTY5NSQ#QWl2XvWw)b-a z%&$vPB8Pw%2S~)a-d}L&9^{kDh za=DiZ#0olv=U8_LI7@#KvW^|(KX)&}YQMwpuZ)pk_aGXiY6<7HW8wcJ>Ad5qdi+0r zxwuyLxR-0*Yg2Y)UHe{plT`K!+3Jey)itgaGOj&B$gGsT3fIVpO0JnvRw8_V=kxge z?+={Id5_oo`NSvYmQp?Hxp-?XrOP2W^z#m)@&D~|T;dzn;{z{cSDqx9nAY?T@7#U? zB(TdS0NCY+?@JfaM)|UfeSHyjz<>9U~3v=5a*CiYwvjrz3vZf-nk-pm$KxtDWO7k5pk+f7ST+xQEdrw(NbS=3UE z+7;qL#6LZPlK2b8U+4_Yjt{C*9>n$@ksmd_a#SZggv!GQw8th=R&gv zx|g@Kd9uyOMt%V6MnBsr_=(G72cjhl731tmqzB(zp(tkfmR6TCBHC5#$tJqJ)gIuL#FkvM^ z*VrbLMGgn2y)WPVZMr5ZJ)A2)4P#^Ea2Y{g zx;#`~Xd!i@VUXCL;WoCj#K4%d-lbMo=Iyy!iI#h@y;@PRSJQvCu$G}ZZ_|3dW)Y7H zayh}`2};mmz9L)cF1s_KoWImrTwW6A&e zd(Q%9YWD24ox2(>Gbyrn0}fxpJsPP8y&$#qche;9&b%KEW}+{@ZdRNRuEerc2V>d1 z??R7S6gfMUCy6Oj`(gSPwSYx?Vk&*$2qQQG_Y(>~0vuKQs(#5<405lAYxY9@=>CvH5ko0UIfOnwJ|WP_jvm$( zSGY!q`edgBCfI$v$y<_2$=DIRpfn0lSVB3-$3V~(SG?IrwB4GD+D&@CYJ2kjj^jzy z;6L(223*}HMd5G#xhy)?=MM|PM?oW3TYDH*r-qoFtod`t8SRC9gIp06JqG=GzUhP* zk`TokTnLhMT#L%<*{xtwMx?*0lqnm0ch8$e@3E4@=@9DD8_yETu}_H#{R6)O`p{gf z+s2MUcAGE~_;;Ol=f;`R&~0qGpO}3={Ouihpo#tr+>-8j85wzbpju?%Y?b@SCybyU zM4(BVt0FefIvx7(mrHsi0F~BM_8sef!w|9Mi7uFW5w%R#tM<3T=ou@E)n@HI&`B+e zc-|lKfkOi0Q0?iy`FN<(3^5M5M%DI)gbrzVpDTA6=uQghoX zrBhTDuq`3L^KJ4hLZJd6J|zT#7ho21=?KE8WmiskGMp>N!2Wcx|;PswZT}fQD+| zcTmOUhJFxLc*waUu&$#tlMTYT)Sj|QH^ZYIKb1Lq-f>bPkCe)g`HtV)J2!Vi=ez(2 z{4DC#X>ukTq2eaC5OD0wfkGHK`M|nUd<}#RyfxP>Sf)C6plH<3GajPt@~NhN>@u>= zT`N>QdjK}{)BweEO@{10ehElT6q?NJXDQlEW@N*aAP9uFy9VN@W(+!I*Z^upAH+2I1$W!IjUl#oi}F{#@GH=mO&4K5ldq+8&?L7`<6o}PiuvG|&d{B2wDu8BaP z?+LVfrsB#lTnSzm?s%~QUJf#rQyy4q%UQ~J3~g`@8t15dcuOr!7B&3$GgQIl*@1h~ zTb`btp+^^9GCGGZ{smsgAP@}-P2bjSEd)2SfWdrOZv^dtQ`39lw^@C`_NZqeL*Chltu zu7wjjXrv&$S^O|4TOO$_g0t7;3^5|eDW>nU-<<0455a~p~ z4=^wQp^C9=VliO!z7_jc`m01k%^)fe?2WJZXbBRU?W zjGdO^DtO|UA(8u1?Fo|6Vv0X^ul1h|6s>Q$o$`CfD{T4H^>Q}cH?>}R8<@`Z$1i_R zdUdOOE8uNA#{1U?(59cI`rpRK&GPEMUqX8{q@ltE8A483PxkQxfn(*N5w(f6&U9{L zZ{f@_j!kb!jFjxKy^ZzGhf&_kAe zsth?UrA#JKBafiJFQS*kQCDp`S*FzgZjDfdZKnGU)edBz@SCA%`!m$df68IX@N7mO z6M{x*`_-rb{szKXk0zseD=^4H(V@dVHG>%l;{L;a);txy!}`fw@6Qi^4cfUOHw`&I zQXvfxL*{h)S>sNdD7usJja2he%Xz7y?8&ji>V5B;W#e*fKRLeJsCzNg!ygm1f+IvMy(~oTXe41$i|Du@u&&Bp2`1`#GxBuo^Tt>v_ATvhADUdAR-59ZqVS>pb5g z2o?=HIp>?en9!QTV>ZUHN{5+&Q{eSUwV0Qq`P};BB->3W+_`J9>;|gNR{2MwV1pnu zlcyy3Nf)1{Rhek|vxi@_SwJEir2^gYo%p-I)y=5?JL;E8W}p9L4FR3}DV4EngGW;< z|NE-z3vp3wRJSO0zV$y4bXmXZ>7~{BgJdo)w}F6m&7u8oXN`4o&G9+|pKqw1!Suh1 zoLRiI+3&BW6MWI>ETAEF&+Z?baoet|Kxj7A4ZWV`7|;P?d~$G6J5yBDJGg6DcNf|5 zB!U>}baGGprPW(n{}yrOEH5flE(bC|`Pvd69MQI|+PEO@B7BbO8H{|`ba`@)Y zEPWR+-kMMs;Q;*92btSti@s%`mp~l&^81LjER)iJrlBi?b@!mMK*Ogq3t@cE7M1O9 zg^9%$EMq%&h4y#o=668ZgXP$8sCP`yi;i8w7tGDeJ>wR7_kdbz6n}?w= z==qGzCuGoh>Pf#tE+t5M+l0ogwOf^fuHMWOfK0)zF-7 zP@`YI6DE->Nea_*8uG8p94Szc;N0^ zP+ajb^7u~!0*PmN=2PiEiJ*jwsieaEi-=H#LYW!lHX(*+6T8^rcTd^?t&#G5nKoHg6#nQz@AfI)7~H26aE z#xuVT2%Kdf_Uy@9rC?Y6 zeZCov7f5yS;k6?HVz;}0>Q!DU5mLekvE%p-bjuL zT+oGC@KOBaa8?-cbvfKaqv*jkp6JQuI|KK46ZRLW`)?g~p7gH1DK8Cv&^jqIdweF4 zb4aUhvaXh3dcsaDn)Ji%<3{g;qGvxlYzyj3E~Q)IE;TNLiSowCkNmw`GABF6&319` zLEyp~sa>yY)SbP(XF+LBBstWN;!f9LeQy%q3XY%yQ5IPdqhcMl*<<;R~hn z%~6Vwk?rkoFT?~5?X1#Ffmcem1eiOp6utB-Q{0XeurS8-Ex*DnKD$=!ACVgUB6JsC zVv04Qc`lOSuLLxz=GIU)t7Z}cz}H&+48q~w%<)C*cV7r)0B=(^4V8kf;; zj0nL5nzYwu0Sh;P{A*a6xSisi5K(^yO#uEOhM2V*edhW%4BW z!W_~P!;Y&A?K4rmm`RtkaNGep*Pa#zu$u@mG>e8SVLcOaUn-^%C`1*N-c#}GW`~$B z3o9wmWCZdxWF;H`Ps+1^zN&BS9J4Ld%kXVX$l&`f8SR-CR{x>-qDZv_=DX|SgESx6 zhx1QX6D+jN6BPfGv+R8XsE!O|sd+(ZGB&uBpTm)+vlec41sHXd)y2S-!_!o1yzeOE zC`kl-u$q_e<*H(W&1B@;3o58^AE`ig++);8l<#FOXV>mLR)WmSGXSXuAaSSi)W~em zX+J+u9}fB+1zg}yn-azr)V+48pf2zAu`iRF-v%IY_$X0(mZ^I_Obf8ym0;2h1?DZq4iGtxne+LN*28tUUgVFT|1>JcAU4pBlI>Ll8WoWE$ouy6;t@ zWHc9BR0Bh%ZRG8xvzBDxzrDy=OXYi%#>qL^5=5_p={4~3pkUrsdJ}0+CP$JywdTkv z+aU2?Uo`MY?_~^-`0Smxr1)98rGMV25(9gg>M+mKiVy_zTVsroFKp5d~FJtj(X{!7%d+P~H4=si@PqZx-*&>-l> zApx8w3I!}rQUZx4w}{fc1RHV{qGC)m#K%m7fA3-oGz=$lsG+jDFgySTgswQgRWQ^~ z_uB1TpW{JHn7e?9~_lFS5T>Aa!#%zkDEUaPl3>#K4?Bo=makP!vHQZPueNRdF zh|YngVRm%;dW60YzXJHpadgGo}8aSY#4DQ-9$~9e!(kEza zo=rJlx04xoISjzSmhTi4nA69xPLj7iQ{G6WG2s9DmvP-HKTB85V)pKrCZ|zQB%7?1 z%Xr%>y2s`pg};Gzjt5nej+Q=^Ltl?*kc`1@f@=jYVRx6Au8xXh5}Qa}qE7%@+_s5m^0m~oX+{S)tuHf#;OMA)QN!~FKcaG;CXQ#-&MPW0p!&lUF}*NKz$`l0 zy`cEFW{y;9@+&;qLHh(*|`R!Bws} zIH@JZu(rgeof+u;u(q;QBDydg`x+T1;wyWnDQ|T0l{^dVEHayskhf!m?;4kV=>H|4 z_-jpPS8!*M<}pFbV;wx5e{;Hz54bi9`w@CR<#e>|ta?)A7LZ!_Sx_jTI@)M_3$_~7 zxjZBMqp*<3uNHukkwd)zHoLSGB3KFmf{|E~=_V?!il3laKu$82wX*W<=*Dvj_ecG1uPngwmhAQGN zrw&O=?4-HSsp6dbhvP=2*1ZXyK{Ri1my$E~6*d7;6XZ!|3e%T>b~LF#T$pTh!D1uwC9tiL`Oep6SFbPmy}5WVOG< zGNm&MX<&emXdc;q(;#C{(sH-h%%P_S&L4;!+zYB1k0(d$Vl5rJt_^kxYngoi!Mj*N z6qfYfp}i5*JK4ZNCBqZiq%0|`d?HfGNrai`X4Ho8DM8XJg?*_k3%u@WLY)o5_zaS{ zZ*yUCW8`;=?Jg9;DA6{K7sHFv0_Ae8fgf8L^X-a6MW2o1)92 zSMts$xED0-L(L`awln^cWBeSUWnmPa>I zR~(~fc5WL6X5R3MGvvSwBX4YZui`f9@8%*sM?@ap>mK%A9M(pDadY_bnHdwj*5PB} zJrwt;Ojl{|`?u#}Hzi(UI@$M87cT{;unUqEqa`_-ke?FheDo9F=hsdXv7Qzz!g!<* zMy2@}c3fvG59y@jsZWQv8Mt)G4 zMTc#z1EDOkGhLC(G}!ymNmJyItzOX}w1&37mL4*XM`sRnK8BPr&dVE`>4ffv)iI~W zmh`8feOdN|!ivdMZ60<$W_}J4z-H+GwP;IFJd518)e>zG(4?DzbXTdG6hM9PmU6e% z`uw(}mEvJ%q;tgJ0~l=V76*;Rc=T1%$|dEUP_}isX|r94U@MT(GB_zUHB6ezazS-b_*otWqW`Rx zkzBrEXyfiZUMkr+w+v*_-Ushl^zS?V^H3gM6U}mB$^8t%x|CpthB}1Wwf{sH5Bu{p ziLWMS5j#=`3RmLKOz&6vLVvpJ`eQx^ruwEQ9b0-jAwG?4^UMGGHmdp;cFl&E`l({nXvvI}VagY;;Z>Pz{#Ii2 z`4a~2hZ+-ryO((92|f7pkOtgZGp-MHlc~t|7o$s0HIiB2{cY#A(0g`_&ky#Dfox#w znpIjDEnV}tcFp)Q^NY~NqXeEbs>rr$MNFZ(f2UyhgPt90_E0Bb-(hlnDv0g+gD$

    ${S75Afa1&)BkDPc0N}IK6JU) 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

    +Q;fd+wr~axoWea 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 z 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 z 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�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ⅈ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 diff --git a/libs/network/doc/uri.rst b/libs/network/doc/uri.rst index 63aa2ace2..ad12c04ce 100644 --- a/libs/network/doc/uri.rst +++ b/libs/network/doc/uri.rst @@ -5,7 +5,7 @@ In addition to protocol implementations, the :mod:`cpp-netlib` provides a powerful URI class. The class implements a parser based on `RFC 3986`_ and `RFC 2732`_. -Generic URI Syntax Overview +Generic URI syntax overview ``````````````````````````` A generic URI will take the form:: @@ -13,8 +13,7 @@ A generic URI will take the form:: [scheme:]scheme-specific-part[#fragment] A URI is known as `absolute` if it specifies the scheme. Otherwise, -it is known as a relative URI. Currently, ``basic_uri`` supports -only absolute URIs. +it is known as a relative URI. Currently, ``uri`` supports only absolute URIs. URIs can be further classified according to whether they're hierarchical or opaque (non-hierarchical). @@ -69,9 +68,9 @@ constructor:: using namespace boost::network; uri::uri instance("http://cpp-netlib.github.com/"); - assert(boost::is_valid(instance)); - std::cout << "scheme: " << uri::scheme(instance) << std::endl - << "host: " << uri::host(instance) << std::endl; + assert(instance.is_valid()); + std::cout << "scheme: " << instance.scheme() << std::endl + << "host: " << instance.host() << std::endl; The command-line output of this program will be:: diff --git a/libs/network/doc/whats_new.rst b/libs/network/doc/whats_new.rst index e02c73313..d0e3b676c 100644 --- a/libs/network/doc/whats_new.rst +++ b/libs/network/doc/whats_new.rst @@ -7,6 +7,19 @@ :mod:`cpp-netlib` 0.9 --------------------- +v0.9.3 +~~~~~~ +* Updated URI parser. +* A new URI builder. +* URI support for IPv6 RFC 2732. +* Fix issue #67, #72, #78, #79, #80, #81, #82, #83. +* New examples for the HTTP client, including an Atom feed, an RSS feed and a + very simple client that uses the Twitter Search API. + +v0.9.2 +~~~~~~ +* Critial bug fixes to v0.9.1. + v0.9.1 ~~~~~~ * Introduced macro ``BOOST_NETWORK_DEFAULT_TAG`` to allow for programmatically @@ -18,13 +31,13 @@ v0.9.1 v0.9.0 ~~~~~~ -* **IMPORTANT BREAKING CHANGE**: By default all compile-time heavy parser +* **IMPORTANT BREAKING CHANGE**: By default all compile-time heavy parser implementations are now compiled to external static libraries. In order to use :mod:`cpp-netlib` in header-only mode, users must define the preprocessor macro ``BOOST_NETWORK_NO_LIB`` before including any :mod:`cpp-netlib` header. This breaks code that relied on the version 0.8.x line where the library is strictly header-only. -* Fix issue #41: Introduce a macro ``BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG`` +* Fix issue #41: Introduce a macro ``BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG`` which makes the default HTTP client use ``tags::http_async_8bit_udp_resolve`` as the tag. * Fix issue #40: Write the status line and headers in a single buffer write @@ -33,8 +46,8 @@ v0.9.0 response objects). * Refactoring of internal implementations to allow better separation of concerns and more manageable coding/documentation. -* Client and Server constructors that support Boost.Parameter named parameters. -* Client and Server cosntructors now take in an optional reference to a Boost.Asio +* Client and server constructors that support Boost.Parameter named parameters. +* Client and server constructors now take in an optional reference to a Boost.Asio ``io_service`` to use internally. * Documentation updates to reflect new APIs. @@ -46,7 +59,7 @@ v0.9.0 * Asynchronous HTTP Server that now supports running request handlers on a different thread pool. * An initial thread pool implementation, using Boost.Asio underneath. -* Adding a ready(...) wrapper to check whether a response object returned by +* Adding a ready(...) wrapper to check whether a response object returned by the asynchronous client in 0.7 already has all the parts available. * Some attempts at lowering compile time costs. diff --git a/libs/network/example/simple_wget.cpp b/libs/network/example/simple_wget.cpp index 2fda68008..baf9aaae6 100644 --- a/libs/network/example/simple_wget.cpp +++ b/libs/network/example/simple_wget.cpp @@ -10,7 +10,7 @@ features, such as content-type detection, but it does the fundamental things the same. - It demonstrates the use the `http::uri` and the `http::client`. + It demonstrates the use the `uri` and the `http::client`. */ From 4597b2d0aac4bcce7e8c972a026308ef3c7d64d3 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Wed, 14 Dec 2011 21:44:32 +0100 Subject: [PATCH 225/768] Removed section on header-only installation. --- README.rst | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/README.rst b/README.rst index d07b4cb3d..ae54ff768 100644 --- a/README.rst +++ b/README.rst @@ -33,23 +33,6 @@ You can find official release packages of the library at:: Building and Installing ----------------------- -Since cpp-netlib is a header-only library, there is nothing to build. To install -cpp-netlib, you can choose to copy the contents of the ``boost`` directory into -an existing Boost [#]_ distribution or to a different location. All that is -required is for projects that use cpp-netlib when building, have the directory -where cpp-netlib is installed as part of the include paths. - -.. [#] http://www.boost.org/ - -The recommended installation procedure would be to follow the steps below:: - - # On Linux/Mac, consider the `$` character as the shell prompt - $ sudo mkdir -p /usr/local/include/cpp-netlib - $ sudo cp -r cpp-netlib/boost /usr/local/include/cpp-netlib - -Don't forget to add ``/usr/local/include/cpp-netlib`` in your project's -compiler include directories to start using cpp-netlib. - Building with CMake ~~~~~~~~~~~~~~~~~~~ From e173b8a50080c0f3f443f9620d8dcf0f3405d076 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Thu, 15 Dec 2011 20:55:01 +0100 Subject: [PATCH 226/768] Marked basic_url_test as an expected failure. --- libs/network/test/uri/url_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/network/test/uri/url_test.cpp b/libs/network/test/uri/url_test.cpp index dae9589c4..fdc4b97ce 100644 --- a/libs/network/test/uri/url_test.cpp +++ b/libs/network/test/uri/url_test.cpp @@ -15,7 +15,7 @@ using namespace boost::network; - +BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(basic_uri_test, 1) BOOST_AUTO_TEST_CASE(basic_uri_test) { uri::uri instance("http://www.example.com/"); BOOST_REQUIRE(uri::valid(instance)); From 098299ce9a64ac3d134aa9276d35f97802a98613 Mon Sep 17 00:00:00 2001 From: firba-mi Date: Wed, 1 Feb 2012 11:54:21 +0100 Subject: [PATCH 227/768] Fixed an issue with chunked content - client was expecting too many bytes and could block forever. --- boost/network/protocol/http/client/connection/sync_base.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/boost/network/protocol/http/client/connection/sync_base.hpp b/boost/network/protocol/http/client/connection/sync_base.hpp index 290cf372f..7ea9966ff 100644 --- a/boost/network/protocol/http/client/connection/sync_base.hpp +++ b/boost/network/protocol/http/client/connection/sync_base.hpp @@ -132,6 +132,7 @@ namespace boost { namespace network { namespace http { namespace impl { bool stopping = false; do { std::size_t chunk_size_line = read_until(socket_, response_buffer, "\r\n", error); + std::size_t body_already_read = response_buffer.size() - chunk_size_line; if ((chunk_size_line == 0) && (error != boost::asio::error::eof)) throw boost::system::system_error(error); std::size_t chunk_size = 0; string_type data; @@ -148,7 +149,8 @@ namespace boost { namespace network { namespace http { namespace impl { } else { bool stopping_inner = false; do { - std::size_t chunk_bytes_read = read(socket_, response_buffer, boost::asio::transfer_at_least(chunk_size + 2), error); + BOOST_ASSERT( body_already_read <= chunk_size + 2 ); + std::size_t chunk_bytes_read = read(socket_, response_buffer, boost::asio::transfer_at_least(chunk_size + 2 - body_already_read), error); if (chunk_bytes_read == 0) { if (error != boost::asio::error::eof) throw boost::system::system_error(error); stopping_inner = true; From dedf2763fbc94444ef2ab9cee8562de019f52fe2 Mon Sep 17 00:00:00 2001 From: Dean Michael Berris Date: Sun, 12 Feb 2012 16:40:36 -0800 Subject: [PATCH 228/768] Fixing call to get_part_kind in MIME. --- boost/mime.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boost/mime.hpp b/boost/mime.hpp index 5f32f7d51..509a28b7c 100644 --- a/boost/mime.hpp +++ b/boost/mime.hpp @@ -658,7 +658,7 @@ class basic_mime { void check_subpart_index ( size_t idx ) const { if ( get_part_kind () == simple_part ) throw std::runtime_error ( "Simple Mime parts don't have sub-parts" ); - else if ( get_part_kind == multi_part ) { + else if ( get_part_kind () == multi_part ) { if ( idx >= m_subparts.size ()) throw std::runtime_error ( str ( boost::format ( "Trying to access part %d (of %d) sub-part to a multipart/xxx mime part" ) % idx % m_subparts.size ())); From 84dd2cc52ffec3eef4b0733901381ce2491dc245 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Thu, 15 Dec 2011 23:13:29 +0100 Subject: [PATCH 229/768] Updated documentation. --- README.rst | 7 +- libs/network/doc/atom_reader.rst | 40 +++++- libs/network/doc/examples_http.rst | 4 +- libs/network/doc/fileserver.rst | 11 ++ libs/network/doc/getting_started.rst | 4 +- libs/network/doc/hello_world_client.rst | 6 +- libs/network/doc/hello_world_server.rst | 4 +- libs/network/doc/index.rst | 1 - libs/network/doc/install.rst | 2 - libs/network/doc/reference_http_server.rst | 18 +-- libs/network/doc/references.rst | 2 + libs/network/doc/rss_reader.rst | 39 +++++- libs/network/doc/simple_wget.rst | 155 ++++++--------------- libs/network/doc/twitter_search.rst | 45 ++++++ libs/network/doc/uri.rst | 32 ++++- libs/network/doc/whats_new.rst | 2 +- libs/network/example/http_client1.cpp | 8 +- libs/network/example/twitter/search.cpp | 3 - 18 files changed, 232 insertions(+), 151 deletions(-) create mode 100644 libs/network/doc/fileserver.rst delete mode 100644 libs/network/doc/install.rst create mode 100644 libs/network/doc/twitter_search.rst diff --git a/README.rst b/README.rst index ae54ff768..b0f219767 100644 --- a/README.rst +++ b/README.rst @@ -105,10 +105,9 @@ you will need. These are: * A build tool (CMake [#]_ recommended, Boost.Build also an option) * OpenSSL headers (optional) -.. note:: This assumes that you have the cpp-netlib distribution package - unpacked somwhere in your home directory. This specifically assumes that you - have cpp-netlib at the toplevel of your home directory. -.. [#] http://www.cmake.org/ +.. note:: This assumes that you have cpp-netlib at the top-level of + your home directory. + [#] http://www.cmake.org/ Hacking on cpp-netlib --------------------- diff --git a/libs/network/doc/atom_reader.rst b/libs/network/doc/atom_reader.rst index 67edc3bc6..37a63385d 100644 --- a/libs/network/doc/atom_reader.rst +++ b/libs/network/doc/atom_reader.rst @@ -4,12 +4,44 @@ Atom reader ************* -The Code +The code ======== +.. code-block:: c++ -Building and Running The Code -============================= + #include "atom.hpp" + #include + #include + #include -Diving into the Code + int main(int argc, char * argv[]) { + using namespace boost::network; + + if (argc != 2) { + std::cout << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + + try { + http::client client; + http::client::request request(argv[1]); + request << header("Connection", "close"); + http::client::response response = client.get(request); + atom::feed feed(response); + + std::cout << "Feed: " << feed.title() + << " (" << feed.subtitle() << ")" << std::endl; + BOOST_FOREACH(const atom::entry &entry, feed) { + std::cout << entry.title() + << " (" << entry.published() << ")" << std::endl; + } + } + catch (std::exception &e) { + std::cerr << e.what() << std::endl; + } + + return 0; + } + +Diving into the code ==================== diff --git a/libs/network/doc/examples_http.rst b/libs/network/doc/examples_http.rst index 53aae22f9..30d949eda 100644 --- a/libs/network/doc/examples_http.rst +++ b/libs/network/doc/examples_http.rst @@ -8,10 +8,10 @@ embedded into larger applications. .. toctree:: :maxdepth: 2 - http_client.rst + simple_wget.rst hello_world_server.rst hello_world_client.rst - simple_wget.rst + fileserver.rst atom_reader.rst rss_reader.rst twitter_search.rst diff --git a/libs/network/doc/fileserver.rst b/libs/network/doc/fileserver.rst new file mode 100644 index 000000000..48aa2082b --- /dev/null +++ b/libs/network/doc/fileserver.rst @@ -0,0 +1,11 @@ +.. _fileserver_http: + +******************* + Fileserver (HTTP) +******************* + +The code +======== + +Diving into the code +==================== diff --git a/libs/network/doc/getting_started.rst b/libs/network/doc/getting_started.rst index 5543968a8..9a1e878b4 100644 --- a/libs/network/doc/getting_started.rst +++ b/libs/network/doc/getting_started.rst @@ -158,7 +158,7 @@ Building On Windows If you're using the Microsoft Visual C++ compiler or the Microsoft Visual Studio IDE and you would like to build cpp-netlib from within Visual Studio, you can look for the solution and project files as the artifacts of the call to -``cmake`` -- the file should be named ``cpp-netlib.sln`` (the solution) along +``cmake`` -- the file should be named ``CPP-NETLIB.sln`` (the solution) along with a number of project files for Visual Studio. Reporting Issues, Getting Support @@ -173,5 +173,5 @@ for the project at http://github.com/cpp-netlib/cpp-netlib/issues. You can also opt to join the developers mailing list for a more personal interaction with the developers of the project. You can join the mailing list -through https://groups.google.com/group/cpp-netlib. +through http://groups.google.com/forum/#!forum/cpp-netlib. diff --git a/libs/network/doc/hello_world_client.rst b/libs/network/doc/hello_world_client.rst index e3bf8e722..d6c81007b 100644 --- a/libs/network/doc/hello_world_client.rst +++ b/libs/network/doc/hello_world_client.rst @@ -51,7 +51,7 @@ Just like with the HTTP Server and HTTP client example before, we can build this example by doing the following on the shell: .. code-block:: bash - + $ cd ~/cpp-netlib $ g++ -o hello_world_client \ > libs/network/example/http/hello_world_client.cpp \ @@ -70,7 +70,7 @@ This example can be run from the command line as follows: .. note:: This assumes that you have the ``hello_world_server`` running on localhost port 8000. -Diving into the Code +Diving into the code ==================== All this example shows is how easy it is to write an HTTP client that connects @@ -92,7 +92,7 @@ perform the request via HTTP: http::client client; http::client::request request("http://my.webservice.com/"); - http::client::response = + http::client::response = client.post(request, "application/xml", some_xml_string); std::data = body(response); diff --git a/libs/network/doc/hello_world_server.rst b/libs/network/doc/hello_world_server.rst index 09a679859..ab9504813 100644 --- a/libs/network/doc/hello_world_server.rst +++ b/libs/network/doc/hello_world_server.rst @@ -59,7 +59,7 @@ simple response to any HTTP request. This is about a straightforward as server programming will get in C++. -Building the Server +Building the server =================== Just like with the HTTP client, we can build this example by doing the following @@ -86,7 +86,7 @@ a command line as follows: .. note:: If you're going to run the server on port 80, you may have to run it as an administrator. -Diving into the Code +Diving into the code ==================== Let's take a look at the code listing above in greater detail. diff --git a/libs/network/doc/index.rst b/libs/network/doc/index.rst index ef56ddb3c..be751dfb1 100644 --- a/libs/network/doc/index.rst +++ b/libs/network/doc/index.rst @@ -123,7 +123,6 @@ Contents in_depth.rst techniques.rst history.rst - install.rst reference.rst references.rst diff --git a/libs/network/doc/install.rst b/libs/network/doc/install.rst deleted file mode 100644 index 5de085221..000000000 --- a/libs/network/doc/install.rst +++ /dev/null @@ -1,2 +0,0 @@ -Full installation guide -======================= diff --git a/libs/network/doc/reference_http_server.rst b/libs/network/doc/reference_http_server.rst index d930cc56d..296b4b801 100644 --- a/libs/network/doc/reference_http_server.rst +++ b/libs/network/doc/reference_http_server.rst @@ -35,7 +35,7 @@ Handler function object. There are two different Handler concepts, one concept for `Synchronous Servers`_ and another for `Asynchronous Servers`. -The SynchronusHandler concept for `Synchronous Servers`_ is described by the +The SynchronousHandler concept for `Synchronous Servers`_ is described by the following table: --------------- @@ -145,7 +145,7 @@ API Documentation The following sections assume that the following file has been included: .. code-block:: c++ - + #include And that the following typedef's have been put in place: @@ -226,14 +226,14 @@ Constructor To use the above supported named parameters, you'll have code that looks like the following: .. code-block:: c++ - + using namespace boost::network::http; // parameters are in this namespace boost::asio::io_service my_io_service; boost::network::utils::thread_pool pool(2); handler handler_instance; async_server instance(_address="0.0.0.0", _port="80", _handler=handler_instance, _io_service=my_io_service, _thread_pool=pool, - _reuse_address=true); + _reuse_address=true); instance.run(); Public Members @@ -270,8 +270,8 @@ helpful in certain simple situations. ``response = http_server::response::stock_reply(status, body)`` Code like the above should go inside the handler's ``operator()`` overload. - The body parameter is an ``std::string``. The status parameter is any of - the following values from the ``http_server::response`` enum + The body parameter is an ``std::string``. The status parameter is any of + the following values from the ``http_server::response`` enum ``status_type``: .. code-block:: c++ @@ -313,7 +313,7 @@ which can be directly manipulated by the handler. .. [#] A header is a struct of type ``response_header``. An instance always has the members ``name`` and ``value`` both of which are of type ``string_type``. -.. [#] ``string_type`` is +.. [#] ``string_type`` is ``boost::network::string::type``. Asynchronous Servers @@ -358,7 +358,7 @@ synchronous server implementation. The general pattern for using the ``async_server`` template is shown below: .. code-block:: c++ - + struct handler; typedef boost::network::http::async_server http_server; @@ -367,7 +367,7 @@ The general pattern for using the ``async_server`` template is shown below: http_server::request const & req, http_server::connection_ptr connection ) { - // handle the request here, and use the connection to + // handle the request here, and use the connection to // either read more data or write data out to the client } }; diff --git a/libs/network/doc/references.rst b/libs/network/doc/references.rst index 09644e25b..7f2c97d4f 100644 --- a/libs/network/doc/references.rst +++ b/libs/network/doc/references.rst @@ -14,6 +14,7 @@ Other sources * `HTTP 1.0`_: The HTTP 1.0 specification. * `HTTP 1.1 (RFC 2616)`_: The HTTP 1.1 specification. * `URI Generic Syntax (RFC 3986)`_: Generic URI syntax specification. +* `Format for Literal IPv6 Addresses in URLs (RFC 2732)`_: Literal IPv6 Addresses in URLs. .. _`BoostCon 2010 Slides`: http://www.filetolink.com/b0e89d06 .. _`BoostCon 2010 Paper`: http://github.com/downloads/mikhailberis/cpp-netlib-boostcon-paper/cpp-netlib.pdf @@ -21,3 +22,4 @@ Other sources .. _`HTTP 1.0`: http://www.w3.org/Protocols/HTTP/1.0/spec.html .. _`HTTP 1.1 (RFC 2616)`: http://www.w3.org/Protocols/rfc2616/rfc2616.html .. _`URI Generic Syntax (RFC 3986)`: http://www.ietf.org/rfc/rfc3986.txt +.. _`Format for Literal IPv6 Addresses in URLs (RFC 2732)`: http://www.ietf.org/rfc/rfc2732.txt diff --git a/libs/network/doc/rss_reader.rst b/libs/network/doc/rss_reader.rst index 334c50f2a..9d89d000c 100644 --- a/libs/network/doc/rss_reader.rst +++ b/libs/network/doc/rss_reader.rst @@ -4,12 +4,41 @@ RSS reader ************ -The Code -======== +.. code-block:: c++ + #include "rss.hpp" + #include + #include + #include -Building and Running The Code -============================= + int main(int argc, char * argv[]) { + using namespace boost::network; -Diving into the Code + if (argc != 2) { + std::cout << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + + try { + http::client client; + http::client::request request(argv[1]); + request << header("Connection", "close"); + http::client::response response = client.get(request); + rss::channel channel(response); + + std::cout << "Channel: " << channel.title() + << " (" << channel.description() << ")" << std::endl; + BOOST_FOREACH(const rss::item &item, channel) { + std::cout << item.title() + << " (" << item.author() << ")" << std::endl; + } + } + catch (std::exception &e) { + std::cerr << e.what() << std::endl; + } + + return 0; + } + +Diving into the code ==================== diff --git a/libs/network/doc/simple_wget.rst b/libs/network/doc/simple_wget.rst index beb125fa5..7b7f8e0fa 100644 --- a/libs/network/doc/simple_wget.rst +++ b/libs/network/doc/simple_wget.rst @@ -4,120 +4,53 @@ Simple `wget` *************** -The first code example is the simplest thing you can do with the -:mod:`cpp-netlib`. The application is a simple HTTP client, which can -be found in the subdirectory ``libs/network/example/http_client.cpp``. -All we are doing is creating and sending an HTTP request to a server -and printing the response body. - The code ======== -Without further ado, the code to do this is as follows: - .. code-block:: c++ - #include - #include - - int main(int argc, char *argv[]) { - using namespace boost::network; - - if (argc != 2) { - std::cout << "Usage: " << argv[0] << " [url]" << std::endl; - return 1; - } - - http::client client; - http::client::request request(argv[1]); - request << header("Connection", "close"); - http::client::response response = client.get(request); - std::cout << body(response) << std::endl; - - return 0; - } - -Building and Running The Code -============================= - -To be build this example, you can follow the steps below without having to build -the whole :mod:`cpp-netlib` distribution:: - - $ cd ~/cpp-netlib - $ g++ -o http_client1 libs/network/example/http_client1.cpp \ - > -I. \ - > -I$BOOST_ROOT \ - > -L$BOOST_ROOT/stage/lib \ - > -lboost_system \ - > -pthread - -You can then run this to get the Boost_ website:: - - $ ./http_client1 http://www.boost.org/ - -.. _Boost: http://www.boost.org/ - -Diving into the Code + #include + #include + #include + #include + #include + + namespace http = boost::network::http; + namespace uri = boost::network::uri; + + namespace { + std::string get_filename(const uri::uri &url) { + std::string path = uri::path(url); + std::size_t index = path.find_last_of('/'); + std::string filename = path.substr(index + 1); + return filename.empty()? "index.html" : filename; + } + } // namespace + + int + main(int argc, char *argv[]) { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " url" << std::endl; + return 1; + } + + try { + http::client client; + http::client::request request(argv[1]); + http::client::response response = client.get(request); + + std::string filename = get_filename(request.uri()); + std::cout << "Saving to: " << filename << std::endl; + std::ofstream ofs(filename.c_str()); + ofs << static_cast(body(response)) << std::endl; + } + catch (std::exception &e) { + std::cerr << e.what() << std::endl; + return 1; + } + + return 0; + } + +Diving into the code ==================== - -Since this is the first example, each line will be presented and -explained in detail. - -.. code-block:: c++ - - #include - -All the code needed for the HTTP client resides in this header. - -.. code-block:: c++ - - http::client client; - -First we create a ``client`` object. The ``client`` abstracts all the -connection and protocol logic. The default HTTP client is version -1.1, as specified in `RFC 2616`_. - -.. code-block:: c++ - - http::client::request request(argv[1]); - -Next, we create a ``request`` object, with a URI string passed as a -constructor argument. - -.. code-block:: c++ - - request << header("Connection", "close"); - -:mod:`cpp-netlib` makes use of stream syntax and *directives* to allow -developers to build complex message structures with greater -flexibility and clarity. Here, we add the HTTP header "Connection: -close" to the request in order to signal that the connection will be -closed after the request has completed. - -.. code-block:: c++ - - http::client::response response = client.get(request); - -Once we've built the request, we then make an HTTP GET request -throught the ``http::client`` from which an ``http::response`` is -returned. ``http::client`` supports all common HTTP methods: GET, -POST, HEAD, DELETE. - -.. code-block:: c++ - - std::cout << body(response) << std::endl; - -Finally, though we don't do any error checking, the response body is -printed to the console using the ``body`` directive. - -That's all there is to the HTTP client. In fact, it's possible to -compress this to a single line: - -.. code-block:: c++ - - std::cout << body(http::client().get(http::request("http://www.boost.org/"))); - -Next we'll develop a simple client/server application using -``http::server`` and ``http::client``. - -.. _`RFC 2616`: http://www.w3.org/Protocols/rfc2616/rfc2616.html diff --git a/libs/network/doc/twitter_search.rst b/libs/network/doc/twitter_search.rst new file mode 100644 index 000000000..2433ba831 --- /dev/null +++ b/libs/network/doc/twitter_search.rst @@ -0,0 +1,45 @@ +.. _twitter_search: + +**************** + Twitter search +**************** + +The code +======== + +.. code-block:: c++ + + #include + #include + #include + + int main(int argc, char * argv[]) { + using namespace boost::network; + + if (argc != 2) { + std::cout << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + + try { + http::client client; + + uri::uri search_uri("http://search.twitter.com/search.json"); + + std::cout << "Searching Twitter for query: " << argv[1] << std::endl; + uri::uri search_1; + search_1 << search_uri << uri::query("q", uri::encoded(argv[1])); + http::client::request request(search_1); + http::client::response response = client.get(request); + + std::cout << body(response) << std::endl; + } + catch (std::exception &e) { + std::cerr << e.what() << std::endl; + } + + return 0; + } + +Diving into the code +==================== diff --git a/libs/network/doc/uri.rst b/libs/network/doc/uri.rst index ad12c04ce..aeea1e7cf 100644 --- a/libs/network/doc/uri.rst +++ b/libs/network/doc/uri.rst @@ -13,7 +13,8 @@ A generic URI will take the form:: [scheme:]scheme-specific-part[#fragment] A URI is known as `absolute` if it specifies the scheme. Otherwise, -it is known as a relative URI. Currently, ``uri`` supports only absolute URIs. +it is known as a relative URI. Currently, ``uri`` supports only +absolute URIs. URIs can be further classified according to whether they're hierarchical or opaque (non-hierarchical). @@ -66,6 +67,8 @@ As of version 0.9.3, ``uri`` supplies a URI parser and builder. To use the parser, it's as simple as supplying a string to the constructor:: +.. code-block:: c++ + using namespace boost::network; uri::uri instance("http://cpp-netlib.github.com/"); assert(instance.is_valid()); @@ -77,6 +80,32 @@ The command-line output of this program will be:: scheme: http host: cpp-netlib.github.com +The ``uri`` builder +``````````````````` + +``uri`` support a stream style syntax to create a URI from it's +elements. For example the program:: + +.. code-block:: c++ + + #include + #include + #include + using namespace boost::network; + + int main() { + uri::uri url; + url << uri::scheme("http") + << uri::host("www.github.com") + << uri::path("/cpp-netlib"); + std::cout << url << std::endl; + return 0; + } + +will output:: + + htp://www.github.com/cpp-netlib + ``URI Concept`` ``````````````` @@ -90,6 +119,7 @@ The command-line output of this program will be:: +----------------------------+----------------------+-----------------------------------------+ | Construct | Result | Description | + +============================+======================+=========================================+ | ``U(u)`` | Instance of U | Copy constructible. | +----------------------------+----------------------+-----------------------------------------+ diff --git a/libs/network/doc/whats_new.rst b/libs/network/doc/whats_new.rst index d0e3b676c..22164c82a 100644 --- a/libs/network/doc/whats_new.rst +++ b/libs/network/doc/whats_new.rst @@ -12,7 +12,7 @@ v0.9.3 * Updated URI parser. * A new URI builder. * URI support for IPv6 RFC 2732. -* Fix issue #67, #72, #78, #79, #80, #81, #82, #83. +* Fix issues #67, #72, #78, #79, #80, #81, #82, #83. * New examples for the HTTP client, including an Atom feed, an RSS feed and a very simple client that uses the Twitter Search API. diff --git a/libs/network/example/http_client1.cpp b/libs/network/example/http_client1.cpp index 015abad34..8bdbc0352 100644 --- a/libs/network/example/http_client1.cpp +++ b/libs/network/example/http_client1.cpp @@ -1,3 +1,9 @@ +// Copyright Dean Michael Berris 2011. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + #include #include @@ -11,7 +17,7 @@ int main(int argc, char * argv[]) { request << header("Connection", "close"); http::client::response response = client.get(request); std::cout << body(response) << std::endl; - + return 0; } diff --git a/libs/network/example/twitter/search.cpp b/libs/network/example/twitter/search.cpp index 010fc7ee7..30189a8bd 100644 --- a/libs/network/example/twitter/search.cpp +++ b/libs/network/example/twitter/search.cpp @@ -5,9 +5,6 @@ #include -#include -#include -#include #include #include From 2927002db2ef9bf5094d557c865900cb6962fbfc Mon Sep 17 00:00:00 2001 From: AmaiSaeta Date: Mon, 16 Jan 2012 03:44:22 +0900 Subject: [PATCH 230/768] Add a '::boost::' namespace specifier for fixing up a compile-error at Visual C++ 2010. --- boost/network/protocol/http/client/connection/ssl_delegate.ipp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 boost/network/protocol/http/client/connection/ssl_delegate.ipp diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.ipp b/boost/network/protocol/http/client/connection/ssl_delegate.ipp old mode 100644 new mode 100755 index c7ee5e573..3acd5addb --- a/boost/network/protocol/http/client/connection/ssl_delegate.ipp +++ b/boost/network/protocol/http/client/connection/ssl_delegate.ipp @@ -33,7 +33,7 @@ void boost::network::http::impl::ssl_delegate::connect( socket_.reset(new asio::ssl::stream(service_, *context_)); socket_->lowest_layer().async_connect( endpoint, - bind(&boost::network::http::impl::ssl_delegate::handle_connected, + ::boost::bind(&boost::network::http::impl::ssl_delegate::handle_connected, boost::network::http::impl::ssl_delegate::shared_from_this(), asio::placeholders::error, handler)); From 4a0ac354166d92a8a6a737ee4a5699013171a9db Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 11 Feb 2012 12:23:17 +0100 Subject: [PATCH 231/768] Added JSON parser to example. --- libs/network/example/atom/atom.cpp | 8 +- .../example/twitter/rapidjson/document.h | 806 ++++++++++++++++++ .../example/twitter/rapidjson/filestream.h | 46 + .../twitter/rapidjson/internal/pow10.h | 54 ++ .../twitter/rapidjson/internal/stack.h | 82 ++ .../twitter/rapidjson/internal/strfunc.h | 24 + .../example/twitter/rapidjson/prettywriter.h | 152 ++++ .../example/twitter/rapidjson/rapidjson.h | 512 +++++++++++ .../example/twitter/rapidjson/reader.h | 664 +++++++++++++++ .../example/twitter/rapidjson/stringbuffer.h | 49 ++ .../example/twitter/rapidjson/writer.h | 224 +++++ libs/network/example/twitter/search.cpp | 16 +- 12 files changed, 2629 insertions(+), 8 deletions(-) create mode 100644 libs/network/example/twitter/rapidjson/document.h create mode 100644 libs/network/example/twitter/rapidjson/filestream.h create mode 100644 libs/network/example/twitter/rapidjson/internal/pow10.h create mode 100644 libs/network/example/twitter/rapidjson/internal/stack.h create mode 100644 libs/network/example/twitter/rapidjson/internal/strfunc.h create mode 100644 libs/network/example/twitter/rapidjson/prettywriter.h create mode 100644 libs/network/example/twitter/rapidjson/rapidjson.h create mode 100644 libs/network/example/twitter/rapidjson/reader.h create mode 100644 libs/network/example/twitter/rapidjson/stringbuffer.h create mode 100644 libs/network/example/twitter/rapidjson/writer.h diff --git a/libs/network/example/atom/atom.cpp b/libs/network/example/atom/atom.cpp index 4c729b6ba..7555956b6 100644 --- a/libs/network/example/atom/atom.cpp +++ b/libs/network/example/atom/atom.cpp @@ -14,9 +14,9 @@ namespace boost { namespace network { namespace atom { feed::feed(const http::client::response &response) { - std::string response_body = body(response); + std::string response_body = body(response); rapidxml::xml_document<> doc; - doc.parse<0>(const_cast(response_body.c_str())); + doc.parse<0>(const_cast(response_body.c_str())); rapidxml::xml_node<> *feed = doc.first_node("feed"); if (!feed) { @@ -51,7 +51,7 @@ feed::feed(const http::client::response &response) { author_ = atom::author(name->first_node()->value(), email->first_node()->value()); } else if (name) { - author_ = atom::author(name->first_node()->value()); + author_ = atom::author(name->first_node()->value()); } } @@ -89,7 +89,7 @@ feed::feed(const http::client::response &response) { entries_.back().set_content(content->first_node()->value()); } - entry = entry->next_sibling(); + entry = entry->next_sibling(); } } } // namespace atom diff --git a/libs/network/example/twitter/rapidjson/document.h b/libs/network/example/twitter/rapidjson/document.h new file mode 100644 index 000000000..d70756a10 --- /dev/null +++ b/libs/network/example/twitter/rapidjson/document.h @@ -0,0 +1,806 @@ +#ifndef RAPIDJSON_DOCUMENT_H_ +#define RAPIDJSON_DOCUMENT_H_ + +#include "reader.h" +#include "internal/strfunc.h" + +namespace rapidjson { + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue + +//! Represents a JSON value. Use Value for UTF8 encoding and default allocator. +/*! + A JSON value can be one of 7 types. This class is a variant type supporting + these types. + + Use the Value if UTF8 and default allocator + + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. +*/ +#pragma pack (push, 4) +template > +class GenericValue { +public: + //! Name-value pair in an object. + struct Member { + GenericValue name; //!< name of member (must be a string) + GenericValue value; //!< value of member. + }; + + typedef Encoding EncodingType; //!< Encoding type from template parameter. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef Member* MemberIterator; //!< Member iterator for iterating in object. + typedef const Member* ConstMemberIterator; //!< Constant member iterator for iterating in object. + typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. + typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + + //!@name Constructors and destructor. + //@{ + + //! Default constructor creates a null value. + GenericValue() : flags_(kNullFlag) {} + + //! Copy constructor is not permitted. +private: + GenericValue(const GenericValue& rhs); + +public: + + //! Constructor with JSON value type. + /*! This creates a Value of specified type with default content. + \param type Type of the value. + \note Default content for number is zero. + */ + GenericValue(Type type) { + static const unsigned defaultFlags[7] = { + kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag, + kNumberFlag | kIntFlag | kUintFlag | kInt64Flag | kUint64Flag | kDoubleFlag + }; + RAPIDJSON_ASSERT(type <= kNumberType); + flags_ = defaultFlags[type]; + memset(&data_, 0, sizeof(data_)); + } + + //! Constructor for boolean value. + GenericValue(bool b) : flags_(b ? kTrueFlag : kFalseFlag) {} + + //! Constructor for int value. + GenericValue(int i) : flags_(kNumberIntFlag) { + data_.n.i64 = i; + if (i >= 0) + flags_ |= kUintFlag | kUint64Flag; + } + + //! Constructor for unsigned value. + GenericValue(unsigned u) : flags_(kNumberUintFlag) { + data_.n.u64 = u; + if (!(u & 0x80000000)) + flags_ |= kIntFlag | kInt64Flag; + } + + //! Constructor for int64_t value. + GenericValue(int64_t i64) : flags_(kNumberInt64Flag) { + data_.n.i64 = i64; + if (i64 >= 0) { + flags_ |= kNumberUint64Flag; + if (!(i64 & 0xFFFFFFFF00000000LL)) + flags_ |= kUintFlag; + if (!(i64 & 0xFFFFFFFF80000000LL)) + flags_ |= kIntFlag; + } + else if (i64 >= -2147483648LL) + flags_ |= kIntFlag; + } + + //! Constructor for uint64_t value. + GenericValue(uint64_t u64) : flags_(kNumberUint64Flag) { + data_.n.u64 = u64; + if (!(u64 & 0x8000000000000000L)) + flags_ |= kInt64Flag; + if (!(u64 & 0xFFFFFFFF00000000L)) + flags_ |= kUintFlag; + if (!(u64 & 0xFFFFFFFF80000000L)) + flags_ |= kIntFlag; + } + + //! Constructor for double value. + GenericValue(double d) : flags_(kNumberDoubleFlag) { data_.n.d = d; } + + //! Constructor for constant string (i.e. do not make a copy of string) + GenericValue(const Ch* s, SizeType length) { + RAPIDJSON_ASSERT(s != NULL); + flags_ = kConstStringFlag; + data_.s.str = s; + data_.s.length = length; + } + + //! Constructor for constant string (i.e. do not make a copy of string) + GenericValue(const Ch* s) { SetStringRaw(s, internal::StrLen(s)); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch* s, SizeType length, Allocator& allocator) { SetStringRaw(s, length, allocator); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch*s, Allocator& allocator) { SetStringRaw(s, internal::StrLen(s), allocator); } + + //! Destructor. + /*! Need to destruct elements of array, members of object, or copy-string. + */ + ~GenericValue() { + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + switch(flags_) { + case kArrayFlag: + for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) + v->~GenericValue(); + Allocator::Free(data_.a.elements); + break; + + case kObjectFlag: + for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) { + m->name.~GenericValue(); + m->value.~GenericValue(); + } + Allocator::Free(data_.o.members); + break; + + case kCopyStringFlag: + Allocator::Free((void*)data_.s.str); + break; + } + } + } + + //@} + + //!@name Assignment operators + //@{ + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. It will become a null value after assignment. + */ + GenericValue& operator=(GenericValue& rhs) { + RAPIDJSON_ASSERT(this != &rhs); + this->~GenericValue(); + memcpy(this, &rhs, sizeof(GenericValue)); + rhs.flags_ = kNullFlag; + return *this; + } + + //! Assignment with primitive types. + /*! \tparam T Either Type, int, unsigned, int64_t, uint64_t, const Ch* + \param value The value to be assigned. + */ + template + GenericValue& operator=(T value) { + this->~GenericValue(); + new (this) GenericValue(value); + return *this; + } + //@} + + //!@name Type + //@{ + + Type GetType() const { return static_cast(flags_ & kTypeMask); } + bool IsNull() const { return flags_ == kNullFlag; } + bool IsFalse() const { return flags_ == kFalseFlag; } + bool IsTrue() const { return flags_ == kTrueFlag; } + bool IsBool() const { return (flags_ & kBoolFlag) != 0; } + bool IsObject() const { return flags_ == kObjectFlag; } + bool IsArray() const { return flags_ == kArrayFlag; } + bool IsNumber() const { return (flags_ & kNumberFlag) != 0; } + bool IsInt() const { return (flags_ & kIntFlag) != 0; } + bool IsUint() const { return (flags_ & kUintFlag) != 0; } + bool IsInt64() const { return (flags_ & kInt64Flag) != 0; } + bool IsUint64() const { return (flags_ & kUint64Flag) != 0; } + bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; } + bool IsString() const { return (flags_ & kStringFlag) != 0; } + + //@} + + //!@name Null + //@{ + + GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } + + //@} + + //!@name Bool + //@{ + + bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; } + GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } + + //@} + + //!@name Object + //@{ + + //! Set this value as an empty object. + GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } + + //! Get the value associated with the object's name. + GenericValue& operator[](const Ch* name) { + if (Member* member = FindMember(name)) + return member->value; + else { + static GenericValue NullValue; + return NullValue; + } + } + const GenericValue& operator[](const Ch* name) const { return const_cast(*this)[name]; } + + //! Member iterators. + ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; } + ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; } + MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; } + MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; } + + //! Check whether a member exists in the object. + bool HasMember(const Ch* name) const { return FindMember(name) != 0; } + + //! Add a member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. + \return The value itself for fluent API. + \note The ownership of name and value will be transfered to this object if success. + */ + GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + Object& o = data_.o; + if (o.size >= o.capacity) { + if (o.capacity == 0) { + o.capacity = kDefaultObjectCapacity; + o.members = (Member*)allocator.Malloc(o.capacity * sizeof(Member)); + } + else { + SizeType oldCapacity = o.capacity; + o.capacity *= 2; + o.members = (Member*)allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member)); + } + } + o.members[o.size].name = name; + o.members[o.size].value = value; + o.size++; + return *this; + } + + GenericValue& AddMember(const char* name, Allocator& nameAllocator, GenericValue& value, Allocator& allocator) { + GenericValue n(name, internal::StrLen(name), nameAllocator); + return AddMember(n, value, allocator); + } + + GenericValue& AddMember(const char* name, GenericValue& value, Allocator& allocator) { + GenericValue n(name, internal::StrLen(name)); + return AddMember(n, value, allocator); + } + + template + GenericValue& AddMember(const char* name, T value, Allocator& allocator) { + GenericValue n(name, internal::StrLen(name)); + GenericValue v(value); + return AddMember(n, v, allocator); + } + + //! Remove a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note Removing member is implemented by moving the last member. So the ordering of members is changed. + */ + bool RemoveMember(const Ch* name) { + RAPIDJSON_ASSERT(IsObject()); + if (Member* m = FindMember(name)) { + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(data_.o.members != 0); + + if (data_.o.size > 1) { + // Move the last one to this place + Member* last = data_.o.members + (data_.o.size - 1); + m->name = last->name; + m->value = last->value; + } + else { + // Only one left, just destroy + m->name.~GenericValue(); + m->value.~GenericValue(); + } + --data_.o.size; + return true; + } + return false; + } + + //@} + + //!@name Array + //@{ + + //! Set this value as an empty array. + GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } + + //! Get the number of elements in array. + SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } + + //! Get the capacity of array. + SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } + + //! Check whether the array is empty. + bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } + + //! Remove all elements in the array. + /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. + */ + void Clear() { + RAPIDJSON_ASSERT(IsArray()); + for (SizeType i = 0; i < data_.a.size; ++i) + data_.a.elements[i].~GenericValue(); + data_.a.size = 0; + } + + //! Get an element from array by index. + /*! \param index Zero-based index of element. + \note +\code +Value a(kArrayType); +a.PushBack(123); +int x = a[0].GetInt(); // Error: operator[ is ambiguous, as 0 also mean a null pointer of const char* type. +int y = a[SizeType(0)].GetInt(); // Cast to SizeType will work. +int z = a[0u].GetInt(); // This works too. +\endcode + */ + GenericValue& operator[](SizeType index) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(index < data_.a.size); + return data_.a.elements[index]; + } + const GenericValue& operator[](SizeType index) const { return const_cast(*this)[index]; } + + //! Element iterator + ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; } + ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; } + ConstValueIterator Begin() const { return const_cast(*this).Begin(); } + ConstValueIterator End() const { return const_cast(*this).End(); } + + //! Request the array to have enough capacity to store elements. + /*! \param newCapacity The capacity that the array at least need to have. + \param allocator The allocator for allocating memory. It must be the same one use previously. + \return The value itself for fluent API. + */ + GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (newCapacity > data_.a.capacity) { + data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)); + data_.a.capacity = newCapacity; + } + return *this; + } + + //! Append a value at the end of the array. + /*! \param value The value to be appended. + \param allocator The allocator for allocating memory. It must be the same one use previously. + \return The value itself for fluent API. + \note The ownership of the value will be transfered to this object if success. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + */ + GenericValue& PushBack(GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (data_.a.size >= data_.a.capacity) + Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : data_.a.capacity * 2, allocator); + data_.a.elements[data_.a.size++] = value; + return *this; + } + + template + GenericValue& PushBack(T value, Allocator& allocator) { + GenericValue v(value); + return PushBack(v, allocator); + } + + //! Remove the last element in the array. + GenericValue& PopBack() { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(!Empty()); + data_.a.elements[--data_.a.size].~GenericValue(); + return *this; + } + //@} + + //!@name Number + //@{ + + int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i; } + unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u; } + int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; } + int64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.u64; } + + double GetDouble() const { + RAPIDJSON_ASSERT(IsNumber()); + if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. + if ((flags_ & kIntFlag) != 0) return data_.n.i; // int -> double + if ((flags_ & kUintFlag) != 0) return data_.n.u; // unsigned -> double + if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision) + RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision) + } + + GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } + GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } + GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } + GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } + GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } + + //@} + + //!@name String + //@{ + + const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return data_.s.str; } + + //! Get the length of string. + /*! Since rapidjson permits "\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). + */ + SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return data_.s.length; } + + //! Set this value as a string without copying source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string pointer. + \param length The length of source string, excluding the trailing null terminator. + \return The value itself for fluent API. + */ + GenericValue& SetString(const Ch* s, SizeType length) { this->~GenericValue(); SetStringRaw(s, length); return *this; } + + //! Set this value as a string without copying source string. + /*! \param s source string pointer. + \return The value itself for fluent API. + */ + GenericValue& SetString(const Ch* s) { return SetString(s, internal::StrLen(s)); } + + //! Set this value as a string by copying from source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string. + \param length The length of source string, excluding the trailing null terminator. + \param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator(). + \return The value itself for fluent API. + */ + GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, length, allocator); return *this; } + + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator(). + \return The value itself for fluent API. + */ + GenericValue& SetString(const Ch* s, Allocator& allocator) { SetString(s, internal::StrLen(s), allocator); return *this; } + + //@} + + //! Generate events of this value to a Handler. + /*! This function adopts the GoF visitor pattern. + Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. + It can also be used to deep clone this value via GenericDocument, which is also a Handler. + \tparam Handler type of handler. + \param handler An object implementing concept Handler. + */ + template + GenericValue& Accept(Handler& handler) { + switch(GetType()) { + case kNullType: handler.Null(); break; + case kFalseType: handler.Bool(false); break; + case kTrueType: handler.Bool(true); break; + + case kObjectType: + handler.StartObject(); + for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) { + handler.String(m->name.data_.s.str, m->name.data_.s.length, false); + m->value.Accept(handler); + } + handler.EndObject(data_.o.size); + break; + + case kArrayType: + handler.StartArray(); + for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) + v->Accept(handler); + handler.EndArray(data_.a.size); + break; + + case kStringType: + handler.String(data_.s.str, data_.s.length, false); + break; + + case kNumberType: + if (IsInt()) handler.Int(data_.n.i); + else if (IsUint()) handler.Uint(data_.n.u); + else if (IsInt64()) handler.Int64(data_.n.i64); + else if (IsUint64()) handler.Uint64(data_.n.i64); + else handler.Double(data_.n.d); + break; + } + return *this; + } + +private: + template + friend class GenericDocument; + + enum { + kBoolFlag = 0x100, + kNumberFlag = 0x200, + kIntFlag = 0x400, + kUintFlag = 0x800, + kInt64Flag = 0x1000, + kUint64Flag = 0x2000, + kDoubleFlag = 0x4000, + kStringFlag = 0x100000, + kCopyFlag = 0x200000, + + // Initial flags of different types. + kNullFlag = kNullType, + kTrueFlag = kTrueType | kBoolFlag, + kFalseFlag = kFalseType | kBoolFlag, + kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, + kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag, + kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, + kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, + kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, + kConstStringFlag = kStringType | kStringFlag, + kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, + kObjectFlag = kObjectType, + kArrayFlag = kArrayType, + + kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler + }; + + static const SizeType kDefaultArrayCapacity = 16; + static const SizeType kDefaultObjectCapacity = 16; + + struct String { + const Ch* str; + SizeType length; + unsigned hashcode; //!< reserved + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // By using proper binary layout, retrieval of different integer types do not need conversions. + union Number { +#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN + struct { + int i; + char padding[4]; + }; + struct { + unsigned u; + char padding2[4]; + }; +#else + struct { + char padding[4]; + int i; + }; + struct { + char padding2[4]; + unsigned u; + }; +#endif + int64_t i64; + uint64_t u64; + double d; + }; // 8 bytes + + struct Object { + Member* members; + SizeType size; + SizeType capacity; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + struct Array { + GenericValue* elements; + SizeType size; + SizeType capacity; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + union Data { + String s; + Number n; + Object o; + Array a; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + //! Find member by name. + Member* FindMember(const Ch* name) { + RAPIDJSON_ASSERT(name); + RAPIDJSON_ASSERT(IsObject()); + + Object& o = data_.o; + for (Member* member = o.members; member != data_.o.members + data_.o.size; ++member) + if (name[member->name.data_.s.length] == '\0' && memcmp(member->name.data_.s.str, name, member->name.data_.s.length * sizeof(Ch)) == 0) + return member; + + return 0; + } + const Member* FindMember(const Ch* name) const { return const_cast(*this).FindMember(name); } + + // Initialize this value as array with initial data, without calling destructor. + void SetArrayRaw(GenericValue* values, SizeType count, Allocator& alloctaor) { + flags_ = kArrayFlag; + data_.a.elements = (GenericValue*)alloctaor.Malloc(count * sizeof(GenericValue)); + memcpy(data_.a.elements, values, count * sizeof(GenericValue)); + data_.a.size = data_.a.capacity = count; + } + + //! Initialize this value as object with initial data, without calling destructor. + void SetObjectRaw(Member* members, SizeType count, Allocator& alloctaor) { + flags_ = kObjectFlag; + data_.o.members = (Member*)alloctaor.Malloc(count * sizeof(Member)); + memcpy(data_.o.members, members, count * sizeof(Member)); + data_.o.size = data_.o.capacity = count; + } + + //! Initialize this value as constant string, without calling destructor. + void SetStringRaw(const Ch* s, SizeType length) { + RAPIDJSON_ASSERT(s != NULL); + flags_ = kConstStringFlag; + data_.s.str = s; + data_.s.length = length; + } + + //! Initialize this value as copy string with initial data, without calling destructor. + void SetStringRaw(const Ch* s, SizeType length, Allocator& allocator) { + RAPIDJSON_ASSERT(s != NULL); + flags_ = kCopyStringFlag; + data_.s.str = (char *)allocator.Malloc(length + 1); + data_.s.length = length; + memcpy((void*)data_.s.str, s, length); + ((char*)data_.s.str)[length] = '\0'; + } + + //! Assignment without calling destructor + void RawAssign(GenericValue& rhs) { + memcpy(this, &rhs, sizeof(GenericValue)); + rhs.flags_ = kNullFlag; + } + + Data data_; + unsigned flags_; +}; +#pragma pack (pop) + +//! Value with UTF8 encoding. +typedef GenericValue > Value; + +/////////////////////////////////////////////////////////////////////////////// +// GenericDocument + +//! A document for parsing JSON text as DOM. +/*! + \implements Handler + \tparam Encoding encoding for both parsing and string storage. + \tparam Alloactor allocator for allocating memory for the DOM, and the stack during parsing. +*/ +template > +class GenericDocument : public GenericValue { +public: + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericValue ValueType; //!< Value type of the document. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + + //! Constructor + /*! \param allocator Optional allocator for allocating stack memory. + \param stackCapacity Initial capacity of stack in bytes. + */ + GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {} + + //! Parse JSON text from an input stream. + /*! \tparam parseFlags Combination of ParseFlag. + \param stream Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(Stream& stream) { + ValueType::SetNull(); // Remove existing root if exist + GenericReader reader; + if (reader.Parse(stream, *this)) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + RawAssign(*stack_.template Pop(1)); + parseError_ = 0; + errorOffset_ = 0; + } + else { + parseError_ = reader.GetParseError(); + errorOffset_ = reader.GetErrorOffset(); + ClearStack(); + } + return *this; + } + + //! Parse JSON text from a mutable string. + /*! \tparam parseFlags Combination of ParseFlag. + \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseInsitu(Ch* str) { + GenericInsituStringStream s(str); + return ParseStream(s); + } + + //! Parse JSON text from a read-only string. + /*! \tparam parseFlags Combination of ParseFlag (must not contain kParseInsituFlag). + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument& Parse(const Ch* str) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + GenericStringStream s(str); + return ParseStream(s); + } + + //! Whether a parse error was occured in the last parsing. + bool HasParseError() const { return parseError_ != 0; } + + //! Get the message of parsing error. + const char* GetParseError() const { return parseError_; } + + //! Get the offset in character of the parsing error. + size_t GetErrorOffset() const { return errorOffset_; } + + //! Get the allocator of this document. + Allocator& GetAllocator() { return stack_.GetAllocator(); } + + //! Get the capacity of stack in bytes. + size_t GetStackCapacity() const { return stack_.GetCapacity(); } + +private: + friend class GenericReader; // for Reader to call the following private handler functions + + // Implementation of Handler + void Null() { new (stack_.template Push()) ValueType(); } + void Bool(bool b) { new (stack_.template Push()) ValueType(b); } + void Int(int i) { new (stack_.template Push()) ValueType(i); } + void Uint(unsigned i) { new (stack_.template Push()) ValueType(i); } + void Int64(int64_t i) { new (stack_.template Push()) ValueType(i); } + void Uint64(uint64_t i) { new (stack_.template Push()) ValueType(i); } + void Double(double d) { new (stack_.template Push()) ValueType(d); } + + void String(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push()) ValueType(str, length); + } + + void StartObject() { new (stack_.template Push()) ValueType(kObjectType); } + + void EndObject(SizeType memberCount) { + typename ValueType::Member* members = stack_.template Pop(memberCount); + stack_.template Top()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator()); + } + + void StartArray() { new (stack_.template Push()) ValueType(kArrayType); } + + void EndArray(SizeType elementCount) { + ValueType* elements = stack_.template Pop(elementCount); + stack_.template Top()->SetArrayRaw(elements, elementCount, GetAllocator()); + } + + void ClearStack() { + if (Allocator::kNeedFree) + while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) + (stack_.template Pop(1))->~ValueType(); + else + stack_.Clear(); + } + + static const size_t kDefaultStackCapacity = 1024; + internal::Stack stack_; + const char* parseError_; + size_t errorOffset_; +}; + +typedef GenericDocument > Document; + +} // namespace rapidjson + +#endif // RAPIDJSON_DOCUMENT_H_ diff --git a/libs/network/example/twitter/rapidjson/filestream.h b/libs/network/example/twitter/rapidjson/filestream.h new file mode 100644 index 000000000..24573aa48 --- /dev/null +++ b/libs/network/example/twitter/rapidjson/filestream.h @@ -0,0 +1,46 @@ +#ifndef RAPIDJSON_FILESTREAM_H_ +#define RAPIDJSON_FILESTREAM_H_ + +#include + +namespace rapidjson { + +//! Wrapper of C file stream for input or output. +/*! + This simple wrapper does not check the validity of the stream. + \implements Stream +*/ +class FileStream { +public: + typedef char Ch; //!< Character type. Only support char. + + FileStream(FILE* fp) : fp_(fp), count_(0) { Read(); } + char Peek() const { return current_; } + char Take() { char c = current_; Read(); return c; } + size_t Tell() const { return count_; } + void Put(char c) { fputc(c, fp_); } + + // Not implemented + char* PutBegin() { return 0; } + size_t PutEnd(char*) { return 0; } + +private: + void Read() { + RAPIDJSON_ASSERT(fp_ != 0); + int c = fgetc(fp_); + if (c != EOF) { + current_ = (char)c; + count_++; + } + else + current_ = '\0'; + } + + FILE* fp_; + char current_; + size_t count_; +}; + +} // namespace rapidjson + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/libs/network/example/twitter/rapidjson/internal/pow10.h b/libs/network/example/twitter/rapidjson/internal/pow10.h new file mode 100644 index 000000000..0852539e7 --- /dev/null +++ b/libs/network/example/twitter/rapidjson/internal/pow10.h @@ -0,0 +1,54 @@ +#ifndef RAPIDJSON_POW10_ +#define RAPIDJSON_POW10_ + +namespace rapidjson { +namespace internal { + +//! Computes integer powers of 10 in double (10.0^n). +/*! This function uses lookup table for fast and accurate results. + \param n positive/negative exponent. Must <= 308. + \return 10.0^n +*/ +inline double Pow10(int n) { + static const double e[] = { // 1e-308...1e308: 617 * 8 bytes = 4936 bytes + 1e-308,1e-307,1e-306,1e-305,1e-304,1e-303,1e-302,1e-301,1e-300, + 1e-299,1e-298,1e-297,1e-296,1e-295,1e-294,1e-293,1e-292,1e-291,1e-290,1e-289,1e-288,1e-287,1e-286,1e-285,1e-284,1e-283,1e-282,1e-281,1e-280, + 1e-279,1e-278,1e-277,1e-276,1e-275,1e-274,1e-273,1e-272,1e-271,1e-270,1e-269,1e-268,1e-267,1e-266,1e-265,1e-264,1e-263,1e-262,1e-261,1e-260, + 1e-259,1e-258,1e-257,1e-256,1e-255,1e-254,1e-253,1e-252,1e-251,1e-250,1e-249,1e-248,1e-247,1e-246,1e-245,1e-244,1e-243,1e-242,1e-241,1e-240, + 1e-239,1e-238,1e-237,1e-236,1e-235,1e-234,1e-233,1e-232,1e-231,1e-230,1e-229,1e-228,1e-227,1e-226,1e-225,1e-224,1e-223,1e-222,1e-221,1e-220, + 1e-219,1e-218,1e-217,1e-216,1e-215,1e-214,1e-213,1e-212,1e-211,1e-210,1e-209,1e-208,1e-207,1e-206,1e-205,1e-204,1e-203,1e-202,1e-201,1e-200, + 1e-199,1e-198,1e-197,1e-196,1e-195,1e-194,1e-193,1e-192,1e-191,1e-190,1e-189,1e-188,1e-187,1e-186,1e-185,1e-184,1e-183,1e-182,1e-181,1e-180, + 1e-179,1e-178,1e-177,1e-176,1e-175,1e-174,1e-173,1e-172,1e-171,1e-170,1e-169,1e-168,1e-167,1e-166,1e-165,1e-164,1e-163,1e-162,1e-161,1e-160, + 1e-159,1e-158,1e-157,1e-156,1e-155,1e-154,1e-153,1e-152,1e-151,1e-150,1e-149,1e-148,1e-147,1e-146,1e-145,1e-144,1e-143,1e-142,1e-141,1e-140, + 1e-139,1e-138,1e-137,1e-136,1e-135,1e-134,1e-133,1e-132,1e-131,1e-130,1e-129,1e-128,1e-127,1e-126,1e-125,1e-124,1e-123,1e-122,1e-121,1e-120, + 1e-119,1e-118,1e-117,1e-116,1e-115,1e-114,1e-113,1e-112,1e-111,1e-110,1e-109,1e-108,1e-107,1e-106,1e-105,1e-104,1e-103,1e-102,1e-101,1e-100, + 1e-99, 1e-98, 1e-97, 1e-96, 1e-95, 1e-94, 1e-93, 1e-92, 1e-91, 1e-90, 1e-89, 1e-88, 1e-87, 1e-86, 1e-85, 1e-84, 1e-83, 1e-82, 1e-81, 1e-80, + 1e-79, 1e-78, 1e-77, 1e-76, 1e-75, 1e-74, 1e-73, 1e-72, 1e-71, 1e-70, 1e-69, 1e-68, 1e-67, 1e-66, 1e-65, 1e-64, 1e-63, 1e-62, 1e-61, 1e-60, + 1e-59, 1e-58, 1e-57, 1e-56, 1e-55, 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, 1e-49, 1e-48, 1e-47, 1e-46, 1e-45, 1e-44, 1e-43, 1e-42, 1e-41, 1e-40, + 1e-39, 1e-38, 1e-37, 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29, 1e-28, 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20, + 1e-19, 1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e+0, + 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, + 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, + 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, + 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, + 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, + 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, + 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, + 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, + 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, + 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, + 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, + 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, + 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, + 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, + 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, + 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 + }; + RAPIDJSON_ASSERT(n <= 308); + return n < -308 ? 0.0 : e[n + 308]; +} + +} // namespace internal +} // namespace rapidjson + +#endif // RAPIDJSON_POW10_ diff --git a/libs/network/example/twitter/rapidjson/internal/stack.h b/libs/network/example/twitter/rapidjson/internal/stack.h new file mode 100644 index 000000000..6faefdee7 --- /dev/null +++ b/libs/network/example/twitter/rapidjson/internal/stack.h @@ -0,0 +1,82 @@ +#ifndef RAPIDJSON_INTERNAL_STACK_H_ +#define RAPIDJSON_INTERNAL_STACK_H_ + +namespace rapidjson { +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// Stack + +//! A type-unsafe stack for storing different types of data. +/*! \tparam Allocator Allocator for allocating stack memory. +*/ +template +class Stack { +public: + Stack(Allocator* allocator, size_t stack_capacity) : allocator_(allocator), own_allocator_(0), stack_(0), stack_top_(0), stack_end_(0), stack_capacity_(stack_capacity) { + RAPIDJSON_ASSERT(stack_capacity_ > 0); + if (!allocator_) + own_allocator_ = allocator_ = new Allocator(); + stack_top_ = stack_ = (char*)allocator_->Malloc(stack_capacity_); + stack_end_ = stack_ + stack_capacity_; + } + + ~Stack() { + Allocator::Free(stack_); + delete own_allocator_; // Only delete if it is owned by the stack + } + + void Clear() { /*stack_top_ = 0;*/ stack_top_ = stack_; } + + template + T* Push(size_t count = 1) { + // Expand the stack if needed + if (stack_top_ + sizeof(T) * count >= stack_end_) { + size_t new_capacity = stack_capacity_ * 2; + size_t size = GetSize(); + size_t new_size = GetSize() + sizeof(T) * count; + if (new_capacity < new_size) + new_capacity = new_size; + stack_ = (char*)allocator_->Realloc(stack_, stack_capacity_, new_capacity); + stack_capacity_ = new_capacity; + stack_top_ = stack_ + size; + stack_end_ = stack_ + stack_capacity_; + } + T* ret = (T*)stack_top_; + stack_top_ += sizeof(T) * count; + return ret; + } + + template + T* Pop(size_t count) { + RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); + stack_top_ -= count * sizeof(T); + return (T*)stack_top_; + } + + template + T* Top() { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return (T*)(stack_top_ - sizeof(T)); + } + + template + T* Bottom() { return (T*)stack_; } + + Allocator& GetAllocator() { return *allocator_; } + size_t GetSize() const { /*return stack_top_;*/ return stack_top_ - stack_; } + size_t GetCapacity() const { return stack_capacity_; } + +private: + Allocator* allocator_; + Allocator* own_allocator_; + char *stack_; + char *stack_top_; + char *stack_end_; + size_t stack_capacity_; +}; + +} // namespace internal +} // namespace rapidjson + +#endif // RAPIDJSON_STACK_H_ diff --git a/libs/network/example/twitter/rapidjson/internal/strfunc.h b/libs/network/example/twitter/rapidjson/internal/strfunc.h new file mode 100644 index 000000000..47b8ac075 --- /dev/null +++ b/libs/network/example/twitter/rapidjson/internal/strfunc.h @@ -0,0 +1,24 @@ +#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ +#define RAPIDJSON_INTERNAL_STRFUNC_H_ + +namespace rapidjson { +namespace internal { + +//! Custom strlen() which works on different character types. +/*! \tparam Ch Character type (e.g. char, wchar_t, short) + \param s Null-terminated input string. + \return Number of characters in the string. + \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. +*/ +template +inline SizeType StrLen(const Ch* s) { + const Ch* p = s; + while (*p != '\0') + ++p; + return SizeType(p - s); +} + +} // namespace internal +} // namespace rapidjson + +#endif // RAPIDJSON_INTERNAL_STRFUNC_H_ diff --git a/libs/network/example/twitter/rapidjson/prettywriter.h b/libs/network/example/twitter/rapidjson/prettywriter.h new file mode 100644 index 000000000..6f282933d --- /dev/null +++ b/libs/network/example/twitter/rapidjson/prettywriter.h @@ -0,0 +1,152 @@ +#ifndef RAPIDJSON_PRETTYWRITER_H_ +#define RAPIDJSON_PRETTYWRITER_H_ + +#include "writer.h" + +namespace rapidjson { + +//! Writer with indentation and spacing. +/*! + \tparam Stream Type of ouptut stream. + \tparam Encoding Encoding of both source strings and output. + \tparam Allocator Type of allocator for allocating memory of stack. +*/ +template, typename Allocator = MemoryPoolAllocator<> > +class PrettyWriter : public Writer { +public: + typedef Writer Base; + typedef typename Base::Ch Ch; + + //! Constructor + /*! \param stream Output stream. + \param allocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of + */ + PrettyWriter(Stream& stream, Allocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(stream, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} + + //! Set custom indentation. + /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\t', '\n', '\r'). + \param indentCharCount Number of indent characters for each indentation level. + \note The default indentation is 4 spaces. + */ + PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { + RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); + indentChar_ = indentChar; + indentCharCount_ = indentCharCount; + return *this; + } + + //@name Implementation of Handler. + //@{ + + PrettyWriter& Null() { PrettyPrefix(kNullType); Base::WriteNull(); return *this; } + PrettyWriter& Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); Base::WriteBool(b); return *this; } + PrettyWriter& Int(int i) { PrettyPrefix(kNumberType); Base::WriteInt(i); return *this; } + PrettyWriter& Uint(unsigned u) { PrettyPrefix(kNumberType); Base::WriteUint(u); return *this; } + PrettyWriter& Int64(int64_t i64) { PrettyPrefix(kNumberType); Base::WriteInt64(i64); return *this; } + PrettyWriter& Uint64(uint64_t u64) { PrettyPrefix(kNumberType); Base::WriteUint64(u64); return *this; } + PrettyWriter& Double(double d) { PrettyPrefix(kNumberType); Base::WriteDouble(d); return *this; } + + PrettyWriter& String(const Ch* str, SizeType length, bool copy = false) { + PrettyPrefix(kStringType); + Base::WriteString(str, length); + return *this; + } + + PrettyWriter& StartObject() { + PrettyPrefix(kObjectType); + new (Base::level_stack_.template Push()) typename Base::Level(false); + Base::WriteStartObject(); + return *this; + } + + PrettyWriter& EndObject(SizeType memberCount = 0) { + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty) { + Base::stream_.Put('\n'); + WriteIndent(); + } + Base::WriteEndObject(); + return *this; + } + + PrettyWriter& StartArray() { + PrettyPrefix(kArrayType); + new (Base::level_stack_.template Push()) typename Base::Level(true); + Base::WriteStartArray(); + return *this; + } + + PrettyWriter& EndArray(SizeType memberCount = 0) { + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty) { + Base::stream_.Put('\n'); + WriteIndent(); + } + Base::WriteEndArray(); + return *this; + } + + //@} + + //! Simpler but slower overload. + PrettyWriter& String(const Ch* str) { return String(str, internal::StrLen(str)); } + +protected: + void PrettyPrefix(Type type) { + if (Base::level_stack_.GetSize() != 0) { // this value is not at root + typename Base::Level* level = Base::level_stack_.template Top(); + + if (level->inArray) { + if (level->valueCount > 0) { + Base::stream_.Put(','); // add comma if it is not the first element in array + Base::stream_.Put('\n'); + } + else + Base::stream_.Put('\n'); + WriteIndent(); + } + else { // in object + if (level->valueCount > 0) { + if (level->valueCount % 2 == 0) { + Base::stream_.Put(','); + Base::stream_.Put('\n'); + } + else { + Base::stream_.Put(':'); + Base::stream_.Put(' '); + } + } + else + Base::stream_.Put('\n'); + + if (level->valueCount % 2 == 0) + WriteIndent(); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else + RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType); + } + + void WriteIndent() { + size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; + PutN(Base::stream_, indentChar_, count); + } + + Ch indentChar_; + unsigned indentCharCount_; +}; + +} // namespace rapidjson + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/libs/network/example/twitter/rapidjson/rapidjson.h b/libs/network/example/twitter/rapidjson/rapidjson.h new file mode 100644 index 000000000..14b0c3a3c --- /dev/null +++ b/libs/network/example/twitter/rapidjson/rapidjson.h @@ -0,0 +1,512 @@ +#ifndef RAPIDJSON_RAPIDJSON_H_ +#define RAPIDJSON_RAPIDJSON_H_ + +// Copyright (c) 2011 Milo Yip (miloyip@gmail.com) +// Version 0.1 + +#include // malloc(), realloc(), free() +#include // memcpy() + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_INT64DEFINE + +// Here defines int64_t and uint64_t types in global namespace. +// If user have their own definition, can define RAPIDJSON_NO_INT64DEFINE to disable this. +#ifndef RAPIDJSON_NO_INT64DEFINE +#ifdef _MSC_VER +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +#include +#endif +#endif // RAPIDJSON_NO_INT64TYPEDEF + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ENDIAN +#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine +#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine + +//! Endianness of the machine. +/*! GCC provided macro for detecting endianness of the target machine. But other + compilers may not have this. User can define RAPIDJSON_ENDIAN to either + RAPIDJSON_LITTLEENDIAN or RAPIDJSON_BIGENDIAN. +*/ +#ifndef RAPIDJSON_ENDIAN +#ifdef __BYTE_ORDER__ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +#else +#define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +#endif // __BYTE_ORDER__ +#else +#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN // Assumes little endian otherwise. +#endif +#endif // RAPIDJSON_ENDIAN + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD + +// Enable SSE2 optimization. +//#define RAPIDJSON_SSE2 + +// Enable SSE4.2 optimization. +//#define RAPIDJSON_SSE42 + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) +#define RAPIDJSON_SIMD +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_SIZETYPEDEFINE + +#ifndef RAPIDJSON_NO_SIZETYPEDEFINE +namespace rapidjson { +//! Use 32-bit array/string indices even for 64-bit platform, instead of using size_t. +/*! User may override the SizeType by defining RAPIDJSON_NO_SIZETYPEDEFINE. +*/ +typedef unsigned SizeType; +} // namespace rapidjson +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ASSERT + +//! Assertion. +/*! By default, rapidjson uses C assert() for assertion. + User can override it by defining RAPIDJSON_ASSERT(x) macro. +*/ +#ifndef RAPIDJSON_ASSERT +#include +#define RAPIDJSON_ASSERT(x) assert(x) +#endif // RAPIDJSON_ASSERT + +namespace rapidjson { + +/////////////////////////////////////////////////////////////////////////////// +// Allocator + +/*! \class rapidjson::Allocator + \brief Concept for allocating, resizing and freeing memory block. + + Note that Malloc() and Realloc() are non-static but Free() is static. + + So if an allocator need to support Free(), it needs to put its pointer in + the header of memory block. + +\code +concept Allocator { + static const bool kNeedFree; //!< Whether this allocator needs to call Free(). + + // Allocate a memory block. + // \param size of the memory block in bytes. + // \returns pointer to the memory block. + void* Malloc(size_t size); + + // Resize a memory block. + // \param originalPtr The pointer to current memory block. Null pointer is permitted. + // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) + // \param newSize the new size in bytes. + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); + + // Free a memory block. + // \param pointer to the memory block. Null pointer is permitted. + static void Free(void *ptr); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// CrtAllocator + +//! C-runtime library allocator. +/*! This class is just wrapper for standard C library memory routines. + \implements Allocator +*/ +class CrtAllocator { +public: + static const bool kNeedFree = true; + void* Malloc(size_t size) { return malloc(size); } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { return realloc(originalPtr, newSize); } + static void Free(void *ptr) { free(ptr); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// MemoryPoolAllocator + +//! Default memory allocator used by the parser and DOM. +/*! This allocator allocate memory blocks from pre-allocated memory chunks. + + It does not free memory blocks. And Realloc() only allocate new memory. + + The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. + + User may also supply a buffer as the first chunk. + + If the user-buffer is full then additional chunks are allocated by BaseAllocator. + + The user-buffer is not deallocated by this allocator. + + \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. + \implements Allocator +*/ +template +class MemoryPoolAllocator { +public: + static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) + + //! Constructor with chunkSize. + /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + if (!baseAllocator_) + ownBaseAllocator_ = baseAllocator_ = new BaseAllocator(); + AddChunk(chunk_capacity_); + } + + //! Constructor with user-supplied buffer. + /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. + + The user buffer will not be deallocated when this allocator is destructed. + + \param buffer User supplied buffer. + \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). + \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(char *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0) + { + RAPIDJSON_ASSERT(buffer != 0); + RAPIDJSON_ASSERT(size > sizeof(ChunkHeader)); + chunkHead_ = (ChunkHeader*)buffer; + chunkHead_->capacity = size - sizeof(ChunkHeader); + chunkHead_->size = 0; + chunkHead_->next = 0; + } + + //! Destructor. + /*! This deallocates all memory chunks, excluding the user-supplied buffer. + */ + ~MemoryPoolAllocator() { + Clear(); + delete ownBaseAllocator_; + } + + //! Deallocates all memory chunks, excluding the user-supplied buffer. + void Clear() { + while(chunkHead_ != 0 && chunkHead_ != (ChunkHeader *)userBuffer_) { + ChunkHeader* next = chunkHead_->next; + baseAllocator_->Free(chunkHead_); + chunkHead_ = next; + } + } + + //! Computes the total capacity of allocated memory chunks. + /*! \return total capacity in bytes. + */ + size_t Capacity() { + size_t capacity = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + capacity += c->capacity; + return capacity; + } + + //! Computes the memory blocks allocated. + /*! \return total used bytes. + */ + size_t Size() { + size_t size = 0; + for (ChunkHeader* c = chunkHead_; c != 0; c = c->next) + size += c->size; + return size; + } + + //! Allocates a memory block. (concept Allocator) + void* Malloc(size_t size) { + if (chunkHead_->size + size > chunkHead_->capacity) + AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); + + char *buffer = (char *)(chunkHead_ + 1) + chunkHead_->size; + chunkHead_->size += size; + return buffer; + } + + //! Resizes a memory block (concept Allocator) + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + if (originalPtr == 0) + return Malloc(newSize); + + // Do not shrink if new size is smaller than original + if (originalSize >= newSize) + return originalPtr; + + // Simply expand it if it is the last allocation and there is sufficient space + if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) { + size_t increment = newSize - originalSize; + if (chunkHead_->size + increment <= chunkHead_->capacity) { + chunkHead_->size += increment; + return originalPtr; + } + } + + // Realloc process: allocate and copy memory, do not free original buffer. + void* newBuffer = Malloc(newSize); + RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly. + return memcpy(newBuffer, originalPtr, originalSize); + } + + //! Frees a memory block (concept Allocator) + static void Free(void *ptr) {} // Do nothing + +private: + //! Creates a new chunk. + /*! \param capacity Capacity of the chunk in bytes. + */ + void AddChunk(size_t capacity) { + ChunkHeader* chunk = (ChunkHeader*)baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity); + chunk->capacity = capacity; + chunk->size = 0; + chunk->next = chunkHead_; + chunkHead_ = chunk; + } + + static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. + + //! Chunk header for perpending to each chunk. + /*! Chunks are stored as a singly linked list. + */ + struct ChunkHeader { + size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). + size_t size; //!< Current size of allocated memory in bytes. + ChunkHeader *next; //!< Next chunk in the linked list. + }; + + ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation. + size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. + char *userBuffer_; //!< User supplied buffer. + BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. + BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object. +}; + +/////////////////////////////////////////////////////////////////////////////// +// Encoding + +/*! \class rapidjson::Encoding + \brief Concept for encoding of Unicode characters. + +\code +concept Encoding { + typename Ch; //! Type of character. + + //! \brief Encode a Unicode codepoint to a buffer. + //! \param buffer pointer to destination buffer to store the result. It should have sufficient size of encoding one character. + //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. + //! \returns the pointer to the next character after the encoded data. + static Ch* Encode(Ch *buffer, unsigned codepoint); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// UTF8 + +//! UTF-8 encoding. +/*! http://en.wikipedia.org/wiki/UTF-8 + \tparam CharType Type for storing 8-bit UTF-8 data. Default is char. + \implements Encoding +*/ +template +struct UTF8 { + typedef CharType Ch; + + static Ch* Encode(Ch *buffer, unsigned codepoint) { + if (codepoint <= 0x7F) + *buffer++ = codepoint & 0xFF; + else if (codepoint <= 0x7FF) { + *buffer++ = 0xC0 | ((codepoint >> 6) & 0xFF); + *buffer++ = 0x80 | ((codepoint & 0x3F)); + } + else if (codepoint <= 0xFFFF) { + *buffer++ = 0xE0 | ((codepoint >> 12) & 0xFF); + *buffer++ = 0x80 | ((codepoint >> 6) & 0x3F); + *buffer++ = 0x80 | (codepoint & 0x3F); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + *buffer++ = 0xF0 | ((codepoint >> 18) & 0xFF); + *buffer++ = 0x80 | ((codepoint >> 12) & 0x3F); + *buffer++ = 0x80 | ((codepoint >> 6) & 0x3F); + *buffer++ = 0x80 | (codepoint & 0x3F); + } + return buffer; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF16 + +//! UTF-16 encoding. +/*! http://en.wikipedia.org/wiki/UTF-16 + \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. + \implements Encoding +*/ +template +struct UTF16 { + typedef CharType Ch; + + static Ch* Encode(Ch* buffer, unsigned codepoint) { + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + *buffer++ = codepoint; + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + *buffer++ = (v >> 10) + 0xD800; + *buffer++ = (v & 0x3FF) + 0xDC00; + } + return buffer; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF32 + +//! UTF-32 encoding. +/*! http://en.wikipedia.org/wiki/UTF-32 + \tparam Ch Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. + \implements Encoding +*/ +template +struct UTF32 { + typedef CharType Ch; + + static Ch *Encode(Ch* buffer, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + *buffer++ = codepoint; + return buffer; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// Stream + +/*! \class rapidjson::Stream + \brief Concept for reading and writing characters. + + For read-only stream, no need to implement PutBegin(), Put() and PutEnd(). + + For write-only stream, only need to implement Put(). + +\code +concept Stream { + typename Ch; //!< Character type of the stream. + + //! Read the current character from stream without moving the read cursor. + Ch Peek() const; + + //! Read the current character from stream and moving the read cursor to next character. + Ch Take(); + + //! Get the current read cursor. + //! \return Number of characters read from start. + size_t Tell(); + + //! Begin writing operation at the current read pointer. + //! \return The begin writer pointer. + Ch* PutBegin(); + + //! Write a character. + void Put(Ch c); + + //! End the writing operation. + //! \param begin The begin write pointer returned by PutBegin(). + //! \return Number of characters written. + size_t PutEnd(Ch* begin); +} +\endcode +*/ + +//! Put N copies of a character to a stream. +template +inline void PutN(Stream& stream, Ch c, size_t n) { + for (size_t i = 0; i < n; i++) + stream.Put(c); +} + +/////////////////////////////////////////////////////////////////////////////// +// StringStream + +//! Read-only string stream. +/*! \implements Stream +*/ +template +struct GenericStringStream { + typedef typename Encoding::Ch Ch; + + GenericStringStream(const Ch *src) : src_(src), head_(src) {} + + Ch Peek() const { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() const { return src_ - head_; } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch c) { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch* begin) { RAPIDJSON_ASSERT(false); return 0; } + + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. +}; + +typedef GenericStringStream > StringStream; + +/////////////////////////////////////////////////////////////////////////////// +// InsituStringStream + +//! A read-write string stream. +/*! This string stream is particularly designed for in-situ parsing. + \implements Stream +*/ +template +struct GenericInsituStringStream { + typedef typename Encoding::Ch Ch; + + GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} + + // Read + Ch Peek() { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() { return src_ - head_; } + + // Write + Ch* PutBegin() { return dst_ = src_; } + void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } + size_t PutEnd(Ch* begin) { return dst_ - begin; } + + Ch* src_; + Ch* dst_; + Ch* head_; +}; + +typedef GenericInsituStringStream > InsituStringStream; + +/////////////////////////////////////////////////////////////////////////////// +// Type + +//! Type of JSON value +enum Type { + kNullType = 0, //!< null + kFalseType = 1, //!< false + kTrueType = 2, //!< true + kObjectType = 3, //!< object + kArrayType = 4, //!< array + kStringType = 5, //!< string + kNumberType = 6, //!< number +}; + +} // namespace rapidjson + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/libs/network/example/twitter/rapidjson/reader.h b/libs/network/example/twitter/rapidjson/reader.h new file mode 100644 index 000000000..a01649781 --- /dev/null +++ b/libs/network/example/twitter/rapidjson/reader.h @@ -0,0 +1,664 @@ +#ifndef RAPIDJSON_READER_H_ +#define RAPIDJSON_READER_H_ + +// Copyright (c) 2011 Milo Yip (miloyip@gmail.com) +// Version 0.1 + +#include "rapidjson.h" +#include "internal/pow10.h" +#include "internal/stack.h" +#include + +#ifdef RAPIDJSON_SSE42 +#include +#elif defined(RAPIDJSON_SSE2) +#include +#endif + +#ifndef RAPIDJSON_PARSE_ERROR +#define RAPIDJSON_PARSE_ERROR(msg, offset) do { parseError_ = msg; errorOffset_ = offset; longjmp(jmpbuf_, 1); } while(false) +#endif + +namespace rapidjson { + +/////////////////////////////////////////////////////////////////////////////// +// ParseFlag + +//! Combination of parseFlags +enum ParseFlag { + kParseDefaultFlags = 0, //!< Default parse flags. Non-destructive parsing. Text strings are decoded into allocated buffer. + kParseInsituFlag = 1 //!< In-situ(destructive) parsing. +}; + +/////////////////////////////////////////////////////////////////////////////// +// Handler + +/*! \class rapidjson::Handler + \brief Concept for receiving events from GenericReader upon parsing. +\code +concept Handler { + typename Ch; + + void Null(); + void Bool(bool b); + void Int(int i); + void Uint(unsigned i); + void Int64(int64_t i); + void Uint64(uint64_t i); + void Double(double d); + void String(const Ch* str, SizeType length, bool copy); + void StartObject(); + void EndObject(SizeType memberCount); + void StartArray(); + void EndArray(SizeType elementCount); +}; +\endcode +*/ +/////////////////////////////////////////////////////////////////////////////// +// BaseReaderHandler + +//! Default implementation of Handler. +/*! This can be used as base class of any reader handler. + \implements Handler +*/ +template > +struct BaseReaderHandler { + typedef typename Encoding::Ch Ch; + + void Default() {} + void Null() { Default(); } + void Bool(bool b) { Default(); } + void Int(int i) { Default(); } + void Uint(unsigned i) { Default(); } + void Int64(int64_t i) { Default(); } + void Uint64(uint64_t i) { Default(); } + void Double(double d) { Default(); } + void String(const Ch* str, SizeType length, bool copy) { Default(); } + void StartObject() { Default(); } + void EndObject(SizeType memberCount) { Default(); } + void StartArray() { Default(); } + void EndArray(SizeType elementCount) { Default(); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// SkipWhitespace + +//! Skip the JSON white spaces in a stream. +/*! \param stream A input stream for skipping white spaces. + \note This function has SSE2/SSE4.2 specialization. +*/ +template +void SkipWhitespace(Stream& stream) { + Stream s = stream; // Use a local copy for optimization + while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') + s.Take(); + stream = s; +} + +#ifdef RAPIDJSON_SSE42 +//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + static const char whitespace[16] = " \n\r\t"; + __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]); + + for (;;) { + __m128i s = _mm_loadu_si128((const __m128i *)p); + unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); + if (r == 0) // all 16 characters are whitespace + p += 16; + else { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + if (_BitScanForward(&offset, r)) + return p + offset; +#else + if (r != 0) + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +#elif defined(RAPIDJSON_SSE2) + +//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + static const char whitespaces[4][17] = { + " ", + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", + "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r", + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"}; + + __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]); + __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]); + __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]); + __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]); + + for (;;) { + __m128i s = _mm_loadu_si128((const __m128i *)p); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = ~_mm_movemask_epi8(x); + if (r == 0) // all 16 characters are whitespace + p += 16; + else { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + if (_BitScanForward(&offset, r)) + return p + offset; +#else + if (r != 0) + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +#endif // RAPIDJSON_SSE2 + +#ifdef RAPIDJSON_SIMD +//! Template function specialization for InsituStringStream +template<> inline void SkipWhitespace(InsituStringStream& stream) { + stream.src_ = const_cast(SkipWhitespace_SIMD(stream.src_)); +} + +//! Template function specialization for StringStream +template<> inline void SkipWhitespace(StringStream& stream) { + stream.src_ = SkipWhitespace_SIMD(stream.src_); +} +#endif // RAPIDJSON_SIMD + +/////////////////////////////////////////////////////////////////////////////// +// GenericReader + +//! SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator. +/*! GenericReader parses JSON text from a stream, and send events synchronously to an + object implementing Handler concept. + + It needs to allocate a stack for storing a single decoded string during + non-destructive parsing. + + For in-situ parsing, the decoded string is directly written to the source + text string, no temporary buffer is required. + + A GenericReader object can be reused for parsing multiple JSON text. + + \tparam Encoding Encoding of both the stream and the parse output. + \tparam Allocator Allocator type for stack. +*/ +template > +class GenericReader { +public: + typedef typename Encoding::Ch Ch; + + //! Constructor. + /*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) + \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) + */ + GenericReader(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {} + + //! Parse JSON text. + /*! \tparam parseFlags Combination of ParseFlag. + \tparam Stream Type of input stream. + \tparam Handler Type of handler which must implement Handler concept. + \param stream Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + bool Parse(Stream& stream, Handler& handler) { + parseError_ = 0; + errorOffset_ = 0; + + if (setjmp(jmpbuf_)) { + stack_.Clear(); + return false; + } + + SkipWhitespace(stream); + + if (stream.Peek() == '\0') + RAPIDJSON_PARSE_ERROR("Text only contains white space(s)", stream.Tell()); + else { + switch (stream.Peek()) { + case '{': ParseObject(stream, handler); break; + case '[': ParseArray(stream, handler); break; + default: RAPIDJSON_PARSE_ERROR("Expect either an object or array at root", stream.Tell()); return false; + } + SkipWhitespace(stream); + + if (stream.Peek() != '\0') + RAPIDJSON_PARSE_ERROR("Nothing should follow the root object or array.", stream.Tell()); + } + + return true; + } + + bool HasParseError() const { return parseError_ != 0; } + const char* GetParseError() const { return parseError_; } + size_t GetErrorOffset() const { return errorOffset_; } + +private: + // Parse object: { string : value, ... } + template + void ParseObject(Stream& stream, Handler& handler) { + RAPIDJSON_ASSERT(stream.Peek() == '{'); + stream.Take(); // Skip '{' + handler.StartObject(); + SkipWhitespace(stream); + + if (stream.Peek() == '}') { + stream.Take(); + handler.EndObject(0); // empty object + return; + } + + for (SizeType memberCount = 0;;) { + if (stream.Peek() != '"') { + RAPIDJSON_PARSE_ERROR("Name of an object member must be a string", stream.Tell()); + break; + } + + ParseString(stream, handler); + SkipWhitespace(stream); + + if (stream.Take() != ':') { + RAPIDJSON_PARSE_ERROR("There must be a colon after the name of object member", stream.Tell()); + break; + } + SkipWhitespace(stream); + + ParseValue(stream, handler); + SkipWhitespace(stream); + + ++memberCount; + + switch(stream.Take()) { + case ',': SkipWhitespace(stream); break; + case '}': handler.EndObject(memberCount); return; + default: RAPIDJSON_PARSE_ERROR("Must be a comma or '}' after an object member", stream.Tell()); + } + } + } + + // Parse array: [ value, ... ] + template + void ParseArray(Stream& stream, Handler& handler) { + RAPIDJSON_ASSERT(stream.Peek() == '['); + stream.Take(); // Skip '[' + handler.StartArray(); + SkipWhitespace(stream); + + if (stream.Peek() == ']') { + stream.Take(); + handler.EndArray(0); // empty array + return; + } + + for (SizeType elementCount = 0;;) { + ParseValue(stream, handler); + ++elementCount; + SkipWhitespace(stream); + + switch (stream.Take()) { + case ',': SkipWhitespace(stream); break; + case ']': handler.EndArray(elementCount); return; + default: RAPIDJSON_PARSE_ERROR("Must be a comma or ']' after an array element.", stream.Tell()); + } + } + } + + template + void ParseNull(Stream& stream, Handler& handler) { + RAPIDJSON_ASSERT(stream.Peek() == 'n'); + stream.Take(); + + if (stream.Take() == 'u' && stream.Take() == 'l' && stream.Take() == 'l') + handler.Null(); + else + RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1); + } + + template + void ParseTrue(Stream& stream, Handler& handler) { + RAPIDJSON_ASSERT(stream.Peek() == 't'); + stream.Take(); + + if (stream.Take() == 'r' && stream.Take() == 'u' && stream.Take() == 'e') + handler.Bool(true); + else + RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell()); + } + + template + void ParseFalse(Stream& stream, Handler& handler) { + RAPIDJSON_ASSERT(stream.Peek() == 'f'); + stream.Take(); + + if (stream.Take() == 'a' && stream.Take() == 'l' && stream.Take() == 's' && stream.Take() == 'e') + handler.Bool(false); + else + RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1); + } + + // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). + template + unsigned ParseHex4(Stream& stream) { + Stream s = stream; // Use a local copy for optimization + unsigned codepoint = 0; + for (int i = 0; i < 4; i++) { + Ch c = s.Take(); + codepoint <<= 4; + codepoint += c; + if (c >= '0' && c <= '9') + codepoint -= '0'; + else if (c >= 'A' && c <= 'F') + codepoint -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + codepoint -= 'a' - 10; + else { + RAPIDJSON_PARSE_ERROR("Incorrect hex digit after \\u escape", s.Tell() - 1); + return 0; + } + } + stream = s; // Restore stream + return codepoint; + } + + // Parse string, handling the prefix and suffix double quotes and escaping. + template + void ParseString(Stream& stream, Handler& handler) { +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + static const Ch escape[256] = { + Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', + Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, + 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, + 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 + }; +#undef Z16 + + Stream s = stream; // Use a local copy for optimization + RAPIDJSON_ASSERT(s.Peek() == '\"'); + s.Take(); // Skip '\"' + Ch *head; + SizeType len; + if (parseFlags & kParseInsituFlag) + head = s.PutBegin(); + else + len = 0; + +#define RAPIDJSON_PUT(x) \ + do { \ + if (parseFlags & kParseInsituFlag) \ + s.Put(x); \ + else { \ + *stack_.template Push() = x; \ + ++len; \ + } \ + } while(false) + + for (;;) { + Ch c = s.Take(); + if (c == '\\') { // Escape + Ch e = s.Take(); + if ((sizeof(Ch) == 1 || e < 256) && escape[(unsigned char)e]) + RAPIDJSON_PUT(escape[(unsigned char)e]); + else if (e == 'u') { // Unicode + unsigned codepoint = ParseHex4(s); + if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { // Handle UTF-16 surrogate pair + if (s.Take() != '\\' || s.Take() != 'u') { + RAPIDJSON_PARSE_ERROR("Missing the second \\u in surrogate pair", s.Tell() - 2); + return; + } + unsigned codepoint2 = ParseHex4(s); + if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) { + RAPIDJSON_PARSE_ERROR("The second \\u in surrogate pair is invalid", s.Tell() - 2); + return; + } + codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; + } + + Ch buffer[4]; + SizeType count = SizeType(Encoding::Encode(buffer, codepoint) - &buffer[0]); + + if (parseFlags & kParseInsituFlag) + for (SizeType i = 0; i < count; i++) + s.Put(buffer[i]); + else { + memcpy(stack_.template Push(count), buffer, count * sizeof(Ch)); + len += count; + } + } + else { + RAPIDJSON_PARSE_ERROR("Unknown escape character", stream.Tell() - 1); + return; + } + } + else if (c == '"') { // Closing double quote + if (parseFlags & kParseInsituFlag) { + size_t length = s.PutEnd(head); + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + RAPIDJSON_PUT('\0'); // null-terminate the string + handler.String(head, SizeType(length), false); + } + else { + RAPIDJSON_PUT('\0'); + handler.String(stack_.template Pop(len), len - 1, true); + } + stream = s; // restore stream + return; + } + else if (c == '\0') { + RAPIDJSON_PARSE_ERROR("lacks ending quotation before the end of string", stream.Tell() - 1); + return; + } + else if ((unsigned)c < 0x20) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF + RAPIDJSON_PARSE_ERROR("Incorrect unescaped character in string", stream.Tell() - 1); + return; + } + else + RAPIDJSON_PUT(c); // Normal character, just copy + } +#undef RAPIDJSON_PUT + } + + template + void ParseNumber(Stream& stream, Handler& handler) { + Stream s = stream; // Local copy for optimization + // Parse minus + bool minus = false; + if (s.Peek() == '-') { + minus = true; + s.Take(); + } + + // Parse int: zero / ( digit1-9 *DIGIT ) + unsigned i; + bool try64bit = false; + if (s.Peek() == '0') { + i = 0; + s.Take(); + } + else if (s.Peek() >= '1' && s.Peek() <= '9') { + i = s.Take() - '0'; + + if (minus) + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i >= 214748364) { // 2^31 = 2147483648 + if (i != 214748364 || s.Peek() > '8') { + try64bit = true; + break; + } + } + i = i * 10 + (s.Take() - '0'); + } + else + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i >= 429496729) { // 2^32 - 1 = 4294967295 + if (i != 429496729 || s.Peek() > '5') { + try64bit = true; + break; + } + } + i = i * 10 + (s.Take() - '0'); + } + } + else { + RAPIDJSON_PARSE_ERROR("Expect a value here.", stream.Tell()); + return; + } + + // Parse 64bit int + uint64_t i64; + bool useDouble = false; + if (try64bit) { + i64 = i; + if (minus) + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i64 >= 922337203685477580uLL) // 2^63 = 9223372036854775808 + if (i64 != 922337203685477580uLL || s.Peek() > '8') { + useDouble = true; + break; + } + i64 = i64 * 10 + (s.Take() - '0'); + } + else + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (i64 >= 1844674407370955161uLL) // 2^64 - 1 = 18446744073709551615 + if (i64 != 1844674407370955161uLL || s.Peek() > '5') { + useDouble = true; + break; + } + i64 = i64 * 10 + (s.Take() - '0'); + } + } + + // Force double for big integer + double d; + if (useDouble) { + d = (double)i64; + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (d >= 1E307) { + RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell()); + return; + } + d = d * 10 + (s.Take() - '0'); + } + } + + // Parse frac = decimal-point 1*DIGIT + int expFrac = 0; + if (s.Peek() == '.') { + if (!useDouble) { + d = try64bit ? (double)i64 : (double)i; + useDouble = true; + } + s.Take(); + + if (s.Peek() >= '0' && s.Peek() <= '9') { + d = d * 10 + (s.Take() - '0'); + --expFrac; + } + else { + RAPIDJSON_PARSE_ERROR("At least one digit in fraction part", stream.Tell()); + return; + } + + while (s.Peek() >= '0' && s.Peek() <= '9') { + if (expFrac > -16) { + d = d * 10 + (s.Peek() - '0'); + --expFrac; + } + s.Take(); + } + } + + // Parse exp = e [ minus / plus ] 1*DIGIT + int exp = 0; + if (s.Peek() == 'e' || s.Peek() == 'E') { + if (!useDouble) { + d = try64bit ? (double)i64 : (double)i; + useDouble = true; + } + s.Take(); + + bool expMinus = false; + if (s.Peek() == '+') + s.Take(); + else if (s.Peek() == '-') { + s.Take(); + expMinus = true; + } + + if (s.Peek() >= '0' && s.Peek() <= '9') { + exp = s.Take() - '0'; + while (s.Peek() >= '0' && s.Peek() <= '9') { + exp = exp * 10 + (s.Take() - '0'); + if (exp > 308) { + RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell()); + return; + } + } + } + else { + RAPIDJSON_PARSE_ERROR("At least one digit in exponent", s.Tell()); + return; + } + + if (expMinus) + exp = -exp; + } + + // Finish parsing, call event according to the type of number. + if (useDouble) { + d *= internal::Pow10(exp + expFrac); + handler.Double(minus ? -d : d); + } + else { + if (try64bit) { + if (minus) + handler.Int64(-(int64_t)i64); + else + handler.Uint64(i64); + } + else { + if (minus) + handler.Int(-(int)i); + else + handler.Uint(i); + } + } + + stream = s; // restore stream + } + + // Parse any JSON value + template + void ParseValue(Stream& stream, Handler& handler) { + switch (stream.Peek()) { + case 'n': ParseNull (stream, handler); break; + case 't': ParseTrue (stream, handler); break; + case 'f': ParseFalse (stream, handler); break; + case '"': ParseString(stream, handler); break; + case '{': ParseObject(stream, handler); break; + case '[': ParseArray (stream, handler); break; + default : ParseNumber(stream, handler); + } + } + + static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. + internal::Stack stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. + jmp_buf jmpbuf_; //!< setjmp buffer for fast exit from nested parsing function calls. + const char* parseError_; + size_t errorOffset_; +}; // class GenericReader + +//! Reader with UTF8 encoding and default allocator. +typedef GenericReader > Reader; + +} // namespace rapidjson + +#endif // RAPIDJSON_READER_H_ diff --git a/libs/network/example/twitter/rapidjson/stringbuffer.h b/libs/network/example/twitter/rapidjson/stringbuffer.h new file mode 100644 index 000000000..d69e3d1cc --- /dev/null +++ b/libs/network/example/twitter/rapidjson/stringbuffer.h @@ -0,0 +1,49 @@ +#ifndef RAPIDJSON_STRINGBUFFER_H_ +#define RAPIDJSON_STRINGBUFFER_H_ + +#include "rapidjson.h" +#include "internal/stack.h" + +namespace rapidjson { + +//! Represents an in-memory output stream. +/*! + \tparam Encoding Encoding of the stream. + \tparam Allocator type for allocating memory buffer. + \implements Stream +*/ +template +struct GenericStringBuffer { + typedef typename Encoding::Ch Ch; + + GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + + void Put(Ch c) { *stack_.template Push() = c; } + + void Clear() { stack_.Clear(); } + + const char* GetString() const { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.template Pop(1); + + return stack_.template Bottom(); + } + + size_t Size() const { return stack_.Size(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; +}; + +typedef GenericStringBuffer > StringBuffer; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { + memset(stream.stack_.Push(n), c, n * sizeof(c)); +} + +} // namespace rapidjson + +#endif // RAPIDJSON_STRINGBUFFER_H_ diff --git a/libs/network/example/twitter/rapidjson/writer.h b/libs/network/example/twitter/rapidjson/writer.h new file mode 100644 index 000000000..1d028cc69 --- /dev/null +++ b/libs/network/example/twitter/rapidjson/writer.h @@ -0,0 +1,224 @@ +#ifndef RAPIDJSON_WRITER_H_ +#define RAPIDJSON_WRITER_H_ + +#include "rapidjson.h" +#include "internal/stack.h" +#include "internal/strfunc.h" +#include // snprintf() or _sprintf_s() +#include // placement new + +namespace rapidjson { + +//! JSON writer +/*! Writer implements the concept Handler. + It generates JSON text by events to an output stream. + + User may programmatically calls the functions of a writer to generate JSON text. + + On the other side, a writer can also be passed to objects that generates events, + + for example Reader::Parse() and Document::Accept(). + + \tparam Stream Type of ouptut stream. + \tparam Encoding Encoding of both source strings and output. + \implements Handler +*/ +template, typename Allocator = MemoryPoolAllocator<> > +class Writer { +public: + typedef typename Encoding::Ch Ch; + + Writer(Stream& stream, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : + stream_(stream), level_stack_(allocator, levelDepth * sizeof(Level)) {} + + //@name Implementation of Handler + //@{ + Writer& Null() { Prefix(kNullType); WriteNull(); return *this; } + Writer& Bool(bool b) { Prefix(b ? kTrueType : kFalseType); WriteBool(b); return *this; } + Writer& Int(int i) { Prefix(kNumberType); WriteInt(i); return *this; } + Writer& Uint(unsigned u) { Prefix(kNumberType); WriteUint(u); return *this; } + Writer& Int64(int64_t i64) { Prefix(kNumberType); WriteInt64(i64); return *this; } + Writer& Uint64(uint64_t u64) { Prefix(kNumberType); WriteUint64(u64); return *this; } + Writer& Double(double d) { Prefix(kNumberType); WriteDouble(d); return *this; } + + Writer& String(const Ch* str, SizeType length, bool copy = false) { + Prefix(kStringType); + WriteString(str, length); + return *this; + } + + Writer& StartObject() { + Prefix(kObjectType); + new (level_stack_.template Push()) Level(false); + WriteStartObject(); + return *this; + } + + Writer& EndObject(SizeType memberCount = 0) { + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + WriteEndObject(); + return *this; + } + + Writer& StartArray() { + Prefix(kArrayType); + new (level_stack_.template Push()) Level(true); + WriteStartArray(); + return *this; + } + + Writer& EndArray(SizeType elementCount = 0) { + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + WriteEndArray(); + return *this; + } + //@} + + //! Simpler but slower overload. + Writer& String(const Ch* str) { return String(str, internal::StrLen(str)); } + +protected: + //! Information for each nested level + struct Level { + Level(bool inArray) : inArray(inArray), valueCount(0) {} + bool inArray; //!< true if in array, otherwise in object + size_t valueCount; //!< number of values in this level + }; + + static const size_t kDefaultLevelDepth = 32; + + void WriteNull() { + stream_.Put('n'); stream_.Put('u'); stream_.Put('l'); stream_.Put('l'); + } + + void WriteBool(bool b) { + if (b) { + stream_.Put('t'); stream_.Put('r'); stream_.Put('u'); stream_.Put('e'); + } + else { + stream_.Put('f'); stream_.Put('a'); stream_.Put('l'); stream_.Put('s'); stream_.Put('e'); + } + } + + void WriteInt(int i) { + if (i < 0) { + stream_.Put('-'); + i = -i; + } + WriteUint((unsigned)i); + } + + void WriteUint(unsigned u) { + char buffer[10]; + char *p = buffer; + do { + *p++ = (u % 10) + '0'; + u /= 10; + } while (u > 0); + + do { + --p; + stream_.Put(*p); + } while (p != buffer); + } + + void WriteInt64(int64_t i64) { + if (i64 < 0) { + stream_.Put('-'); + i64 = -i64; + } + WriteUint64((uint64_t)i64); + } + + void WriteUint64(uint64_t u64) { + char buffer[20]; + char *p = buffer; + do { + *p++ = char(u64 % 10) + '0'; + u64 /= 10; + } while (u64 > 0); + + do { + --p; + stream_.Put(*p); + } while (p != buffer); + } + + //! \todo Optimization with custom double-to-string converter. + void WriteDouble(double d) { + char buffer[100]; +#if _MSC_VER + int ret = sprintf_s(buffer, sizeof(buffer), "%g", d); +#else + int ret = snprintf(buffer, sizeof(buffer), "%g", d); +#endif + RAPIDJSON_ASSERT(ret >= 1); + for (int i = 0; i < ret; i++) + stream_.Put(buffer[i]); + } + + void WriteString(const Ch* str, SizeType length) { + static const char hexDigits[] = "0123456789ABCDEF"; + static const char escape[256] = { +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + Z16, Z16, // 30~4F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF +#undef Z16 + }; + + stream_.Put('\"'); + for (const Ch* p = str; p != str + length; ++p) { + if ((sizeof(Ch) == 1 || *p < 256) && escape[(unsigned char)*p]) { + stream_.Put('\\'); + stream_.Put(escape[(unsigned char)*p]); + if (escape[(unsigned char)*p] == 'u') { + stream_.Put('0'); + stream_.Put('0'); + stream_.Put(hexDigits[(*p) >> 4]); + stream_.Put(hexDigits[(*p) & 0xF]); + } + } + else + stream_.Put(*p); + } + stream_.Put('\"'); + } + + void WriteStartObject() { stream_.Put('{'); } + void WriteEndObject() { stream_.Put('}'); } + void WriteStartArray() { stream_.Put('['); } + void WriteEndArray() { stream_.Put(']'); } + + void Prefix(Type type) { + if (level_stack_.GetSize() != 0) { // this value is not at root + Level* level = level_stack_.template Top(); + if (level->valueCount > 0) { + if (level->inArray) + stream_.Put(','); // add comma if it is not the first element in array + else // in object + stream_.Put((level->valueCount % 2 == 0) ? ',' : ':'); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else + RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType); + } + + Stream& stream_; + internal::Stack level_stack_; +}; + +} // namespace rapidjson + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/libs/network/example/twitter/search.cpp b/libs/network/example/twitter/search.cpp index 30189a8bd..f66e43171 100644 --- a/libs/network/example/twitter/search.cpp +++ b/libs/network/example/twitter/search.cpp @@ -6,13 +6,17 @@ #include #include +#include "rapidjson/rapidjson.h" +#include "rapidjson/document.h" +#include "rapidjson/prettywriter.h" +#include "rapidjson/filestream.h" #include // This example uses the Twitter Search API. // // https://dev.twitter.com/docs/using-search -int main(int argc, char * argv[]) { +int main(int argc, char *argv[]) { using namespace boost::network; if (argc != 2) { @@ -25,13 +29,18 @@ int main(int argc, char * argv[]) { uri::uri search_uri("http://search.twitter.com/search.json"); - std::cout << "Searching Twitter for query: " << argv[1] << std::endl; + std::cout << "Searching Twitter for query: " << argv[1] << std::endl; uri::uri search_1; search_1 << search_uri << uri::query("q", uri::encoded(argv[1])); http::client::request request(search_1); http::client::response response = client.get(request); - std::cout << body(response) << std::endl; + rapidjson::Document d; + if (!d.Parse<0>(response.body().c_str()).HasParseError()) { + rapidjson::FileStream f(stdout); + rapidjson::PrettyWriter writer(f); + d.Accept(writer); + } } catch (std::exception &e) { std::cerr << e.what() << std::endl; @@ -39,4 +48,3 @@ int main(int argc, char * argv[]) { return 0; } - From 2643c7c1ba139d713aeb412ae530838db3394ac0 Mon Sep 17 00:00:00 2001 From: Glyn Matthews Date: Sat, 11 Feb 2012 13:23:16 +0100 Subject: [PATCH 232/768] Updated documentation for 0.9.3 --- libs/network/doc/examples_http.rst | 1 + libs/network/doc/html/.buildinfo | 2 +- .../html/_images/{boost6.png => boost1.png} | Bin .../html/_images/{boost7.png => boost2.png} | Bin libs/network/doc/html/_images/boost3.png | Bin 0 -> 13364 bytes libs/network/doc/html/_images/ftp_uri1.png | Bin 0 -> 25570 bytes libs/network/doc/html/_images/ftp_uri10.png | Bin 0 -> 25570 bytes libs/network/doc/html/_images/ftp_uri11.png | Bin 0 -> 25570 bytes libs/network/doc/html/_images/ftp_uri12.png | Bin 0 -> 25570 bytes libs/network/doc/html/_images/ftp_uri13.png | Bin 0 -> 25570 bytes libs/network/doc/html/_images/ftp_uri3.png | Bin 0 -> 25570 bytes libs/network/doc/html/_images/ftp_uri4.png | Bin 0 -> 25570 bytes libs/network/doc/html/_images/ftp_uri5.png | Bin 0 -> 25570 bytes libs/network/doc/html/_images/ftp_uri6.png | Bin 0 -> 25570 bytes libs/network/doc/html/_images/ftp_uri7.png | Bin 0 -> 25570 bytes libs/network/doc/html/_images/ftp_uri8.png | Bin 0 -> 25570 bytes libs/network/doc/html/_images/ftp_uri9.png | Bin 0 -> 25570 bytes libs/network/doc/html/_images/http_uri1.png | Bin 0 -> 20719 bytes libs/network/doc/html/_images/http_uri10.png | Bin 0 -> 20719 bytes libs/network/doc/html/_images/http_uri11.png | Bin 0 -> 20719 bytes libs/network/doc/html/_images/http_uri12.png | Bin 0 -> 20719 bytes libs/network/doc/html/_images/http_uri13.png | Bin 0 -> 20719 bytes libs/network/doc/html/_images/http_uri3.png | Bin 0 -> 20719 bytes libs/network/doc/html/_images/http_uri4.png | Bin 0 -> 20719 bytes libs/network/doc/html/_images/http_uri5.png | Bin 0 -> 20719 bytes libs/network/doc/html/_images/http_uri6.png | Bin 0 -> 20719 bytes libs/network/doc/html/_images/http_uri7.png | Bin 0 -> 20719 bytes libs/network/doc/html/_images/http_uri8.png | Bin 0 -> 20719 bytes libs/network/doc/html/_images/http_uri9.png | Bin 0 -> 20719 bytes libs/network/doc/html/_images/mailto_uri1.png | Bin 0 -> 10220 bytes .../network/doc/html/_images/mailto_uri10.png | Bin 0 -> 10220 bytes .../network/doc/html/_images/mailto_uri11.png | Bin 0 -> 10220 bytes .../network/doc/html/_images/mailto_uri12.png | Bin 0 -> 10220 bytes .../network/doc/html/_images/mailto_uri13.png | Bin 0 -> 10220 bytes libs/network/doc/html/_images/mailto_uri3.png | Bin 0 -> 10220 bytes libs/network/doc/html/_images/mailto_uri4.png | Bin 0 -> 10220 bytes libs/network/doc/html/_images/mailto_uri5.png | Bin 0 -> 10220 bytes libs/network/doc/html/_images/mailto_uri6.png | Bin 0 -> 10220 bytes libs/network/doc/html/_images/mailto_uri7.png | Bin 0 -> 10220 bytes libs/network/doc/html/_images/mailto_uri8.png | Bin 0 -> 10220 bytes libs/network/doc/html/_images/mailto_uri9.png | Bin 0 -> 10220 bytes .../network/doc/html/_sources/atom_reader.txt | 47 + libs/network/doc/html/_sources/examples.txt | 4 +- .../doc/html/_sources/examples_http.txt | 5 + libs/network/doc/html/_sources/fileserver.txt | 11 + .../doc/html/_sources/generic_message.txt | 6 - .../doc/html/_sources/getting_started.txt | 4 +- .../doc/html/_sources/hello_world_client.txt | 6 +- .../doc/html/_sources/hello_world_server.txt | 4 +- libs/network/doc/html/_sources/http.txt | 39 +- .../network/doc/html/_sources/http_client.txt | 31 +- libs/network/doc/html/_sources/index.txt | 1 - libs/network/doc/html/_sources/install.txt | 2 - .../html/_sources/reference_http_server.txt | 18 +- libs/network/doc/html/_sources/references.txt | 2 + libs/network/doc/html/_sources/rss_reader.txt | 44 + .../network/doc/html/_sources/simple_wget.txt | 56 + .../doc/html/_sources/twitter_search.txt | 45 + libs/network/doc/html/_sources/uri.txt | 66 +- libs/network/doc/html/_sources/whats_new.txt | 23 +- libs/network/doc/html/_static/background.jpg | Bin 787242 -> 0 bytes libs/network/doc/html/_static/contents.png | Bin 202 -> 115 bytes libs/network/doc/html/_static/file.png | Bin 392 -> 312 bytes libs/network/doc/html/_static/jquery.js | 9113 ++++++++++++++++- libs/network/doc/html/_static/minus.png | Bin 199 -> 118 bytes libs/network/doc/html/_static/navigation.png | Bin 218 -> 142 bytes libs/network/doc/html/_static/plus.png | Bin 199 -> 118 bytes libs/network/doc/html/_static/searchtools.js | 2 +- libs/network/doc/html/_static/underscore.js | 823 +- libs/network/doc/html/atom_reader.html | 191 + libs/network/doc/html/directives.html | 12 +- libs/network/doc/html/examples.html | 21 +- libs/network/doc/html/examples_http.html | 46 +- .../html/{install.html => fileserver.html} | 60 +- libs/network/doc/html/generic_message.html | 130 - libs/network/doc/html/genindex.html | 12 +- libs/network/doc/html/getting_started.html | 18 +- libs/network/doc/html/hello_world_client.html | 22 +- libs/network/doc/html/hello_world_server.html | 26 +- libs/network/doc/html/history.html | 22 +- libs/network/doc/html/http.html | 57 +- libs/network/doc/html/http_client.html | 61 +- libs/network/doc/html/http_client_tags.html | 14 +- libs/network/doc/html/in_depth.html | 32 +- libs/network/doc/html/index.html | 32 +- libs/network/doc/html/message.html | 30 +- libs/network/doc/html/objects.inv | Bin 338 -> 449 bytes libs/network/doc/html/polymorphism.html | 10 +- libs/network/doc/html/reference.html | 22 +- .../doc/html/reference_http_client.html | 10 +- .../doc/html/reference_http_request.html | 21 +- .../doc/html/reference_http_response.html | 10 +- .../doc/html/reference_http_server.html | 12 +- libs/network/doc/html/references.html | 15 +- libs/network/doc/html/rss_reader.html | 187 + libs/network/doc/html/search.html | 12 +- libs/network/doc/html/searchindex.js | 2 +- libs/network/doc/html/simple_wget.html | 200 + libs/network/doc/html/tag_metafunctions.html | 10 +- libs/network/doc/html/techniques.html | 14 +- libs/network/doc/html/twitter_search.html | 189 + libs/network/doc/html/uri.html | 90 +- libs/network/doc/html/whats_new.html | 37 +- libs/network/doc/http_client_tags.rst | 43 + libs/network/doc/uri.rst | 5 +- 105 files changed, 11282 insertions(+), 748 deletions(-) rename libs/network/doc/html/_images/{boost6.png => boost1.png} (100%) rename libs/network/doc/html/_images/{boost7.png => boost2.png} (100%) create mode 100644 libs/network/doc/html/_images/boost3.png create mode 100644 libs/network/doc/html/_images/ftp_uri1.png create mode 100644 libs/network/doc/html/_images/ftp_uri10.png create mode 100644 libs/network/doc/html/_images/ftp_uri11.png create mode 100644 libs/network/doc/html/_images/ftp_uri12.png create mode 100644 libs/network/doc/html/_images/ftp_uri13.png create mode 100644 libs/network/doc/html/_images/ftp_uri3.png create mode 100644 libs/network/doc/html/_images/ftp_uri4.png create mode 100644 libs/network/doc/html/_images/ftp_uri5.png create mode 100644 libs/network/doc/html/_images/ftp_uri6.png create mode 100644 libs/network/doc/html/_images/ftp_uri7.png create mode 100644 libs/network/doc/html/_images/ftp_uri8.png create mode 100644 libs/network/doc/html/_images/ftp_uri9.png create mode 100644 libs/network/doc/html/_images/http_uri1.png create mode 100644 libs/network/doc/html/_images/http_uri10.png create mode 100644 libs/network/doc/html/_images/http_uri11.png create mode 100644 libs/network/doc/html/_images/http_uri12.png create mode 100644 libs/network/doc/html/_images/http_uri13.png create mode 100644 libs/network/doc/html/_images/http_uri3.png create mode 100644 libs/network/doc/html/_images/http_uri4.png create mode 100644 libs/network/doc/html/_images/http_uri5.png create mode 100644 libs/network/doc/html/_images/http_uri6.png create mode 100644 libs/network/doc/html/_images/http_uri7.png create mode 100644 libs/network/doc/html/_images/http_uri8.png create mode 100644 libs/network/doc/html/_images/http_uri9.png create mode 100644 libs/network/doc/html/_images/mailto_uri1.png create mode 100644 libs/network/doc/html/_images/mailto_uri10.png create mode 100644 libs/network/doc/html/_images/mailto_uri11.png create mode 100644 libs/network/doc/html/_images/mailto_uri12.png create mode 100644 libs/network/doc/html/_images/mailto_uri13.png create mode 100644 libs/network/doc/html/_images/mailto_uri3.png create mode 100644 libs/network/doc/html/_images/mailto_uri4.png create mode 100644 libs/network/doc/html/_images/mailto_uri5.png create mode 100644 libs/network/doc/html/_images/mailto_uri6.png create mode 100644 libs/network/doc/html/_images/mailto_uri7.png create mode 100644 libs/network/doc/html/_images/mailto_uri8.png create mode 100644 libs/network/doc/html/_images/mailto_uri9.png create mode 100644 libs/network/doc/html/_sources/atom_reader.txt create mode 100644 libs/network/doc/html/_sources/fileserver.txt delete mode 100644 libs/network/doc/html/_sources/generic_message.txt delete mode 100644 libs/network/doc/html/_sources/install.txt create mode 100644 libs/network/doc/html/_sources/rss_reader.txt create mode 100644 libs/network/doc/html/_sources/simple_wget.txt create mode 100644 libs/network/doc/html/_sources/twitter_search.txt delete mode 100644 libs/network/doc/html/_static/background.jpg create mode 100644 libs/network/doc/html/atom_reader.html rename libs/network/doc/html/{install.html => fileserver.html} (56%) delete mode 100644 libs/network/doc/html/generic_message.html create mode 100644 libs/network/doc/html/rss_reader.html create mode 100644 libs/network/doc/html/simple_wget.html create mode 100644 libs/network/doc/html/twitter_search.html create mode 100644 libs/network/doc/http_client_tags.rst diff --git a/libs/network/doc/examples_http.rst b/libs/network/doc/examples_http.rst index 30d949eda..e95c9386c 100644 --- a/libs/network/doc/examples_http.rst +++ b/libs/network/doc/examples_http.rst @@ -8,6 +8,7 @@ embedded into larger applications. .. toctree:: :maxdepth: 2 + http_client.rst simple_wget.rst hello_world_server.rst hello_world_client.rst diff --git a/libs/network/doc/html/.buildinfo b/libs/network/doc/html/.buildinfo index 18dff07e8..c51a1108e 100644 --- a/libs/network/doc/html/.buildinfo +++ b/libs/network/doc/html/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: 294e91682c0e3ff7b18061aac92d5585 +config: b7e1e528834ec7f8854f986b38772a4f tags: fbb0d17656682115ca4d033fb2f83ba1 diff --git a/libs/network/doc/html/_images/boost6.png b/libs/network/doc/html/_images/boost1.png similarity index 100% rename from libs/network/doc/html/_images/boost6.png rename to libs/network/doc/html/_images/boost1.png diff --git a/libs/network/doc/html/_images/boost7.png b/libs/network/doc/html/_images/boost2.png similarity index 100% rename from libs/network/doc/html/_images/boost7.png rename to libs/network/doc/html/_images/boost2.png diff --git a/libs/network/doc/html/_images/boost3.png b/libs/network/doc/html/_images/boost3.png new file mode 100644 index 0000000000000000000000000000000000000000..0714ca2004bbf91389d33166afc449cba84b39be GIT binary patch literal 13364 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 literal 0 HcmV?d00001 diff --git a/libs/network/doc/html/_images/ftp_uri1.png b/libs/network/doc/html/_images/ftp_uri1.png new file mode 100644 index 0000000000000000000000000000000000000000..f77d3c87b891e86d794e2ee60255b1f95baf2ddc GIT binary patch literal 25570 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 a2mxf!g&w=m$}B@S{Y@E>Fk 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 a2mxf!g&w=m$}B@S{Y@E>Fk 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 a2mxf!g&w=m$}B@S{Y@E>Fk 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 a2mxf!g&w=m$}B@S{Y@E>Fk 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 a2mxf!g&w=m$}B@S{Y@E>Fk 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 a2mxf!g&w=m$}B@S{Y@E>Fk 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 a2mxf!g&w=m$}B@S{Y@E>Fk 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 a2mxf!g&w=m$}B@S{Y@E>Fk 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 a2mxf!g&w=m$}B@S{Y@E>Fk zO$BMB55ttd;SU%VDhjelH;8}oTHYnWE4N)0^*!M2Q;1*4(#%;t@FM1OrN?rZv)IUY zsHxA#wl9&8Xpod-rL=u!w~TG|o+=Oq+P{4NUJoC?I`~$U8F~y+O&&M-XZf0wd16C8 zon+>y7ITHzX+KA9<|w}6_wV^AP{u{mt^$X=otN%Ky}vthA+{lWvNJPrJTyEsJUqn8 z-9zf*kN+|>)a~NfX(;E>XW0$z9xm$vBFC9p^gn<8_{;oT)KIJT*ifstpTOAu*|b5i zf+^?Vz?#Zoh~e$+-OBCb&)?nCBdxBEhjf>O1k=gM>3wPGKCTuPb8mMy4KwpC^<42a z!@^{}R)1kWets4I`L)5c{ndU#lZ-W55@BIspYubOmoH!5B_evYxM|XZf?$Kb#*n*puvGrT#%L) zx#8K=hf&<^jg8kyOzNqpbGQ@&W=ox6Vh#V|qklHJSoS9}GBY#Z9XE7#ez?G8iZAND z)6Lm-*~wNf!3CdKP4qYck=nc3I|E82VyY>YlV zzs+gd`YJ9CkDZG(b?5i zV?R+s@RsTBttV9`j~Eyjw5P+V`5lNd1zq0AMc+%=6r-l5j-h%)K9VbuHhAf?$BcuE z8>@MuMfFw73V!RhF?^rTWj@;_o|@>h_ioSka$UEbIpK`nm6a84k9F0#k8Y^HK6}5e zso@@wTkXSd_O!6DSlr!> z>+4gD%;@+0`@?)VTbT6G3qI$$j~#*!@WK?;)Z~x;e9tc`LPJtiR+g?bXb3#@681Z; zc;(#Ppsw*`O{whg^k77S+iOctyUL_Rb|Wl2ymMiJ8lG~UA^|hby`+y))GNj%hMLrN zI6LIShldpv6{|l=wcg#CZF1pUvw2rg@bYn%K)%~bkI&H`;!FXj0YPTG=F`hF-ui|H z#%oYz(nURV38^CO?@OJS2QJ|RU# z3^C;V%F7=U6A3Wzs9^hEC?-qz>>>G`?1V|u1WVGyi{K%V^VtPMC1c&R1zg-?)BPZ8 zVnQ`rZy)-5;@!$n2JhbSaZlH4y!_JA$lG>7jYTfu7Q3rn}S-5)gDk@^2#5%^uH4ET#yj@TC%+24{ zSoU^KP7-00Jd{;ayMvSm>z>a4EVbJ=BO@bS)ceC|rn94C%-3iV%Zuafy@LZ(B<(Wo z+s}SfNWB&DWEe)&?#@CR9?}ynt*(D-gJB67rcu?^TotBmR2>~1J|{c(V`5{?t*yhL z5(?yF$u*B$=D$R)^u}S^tA2^SzP@mQ9Z@yEXz@QIFflQ?g@q+;XU9xHNN8?n7qP$6 zYq>RD^F%`f|3_?ebXTqQV0>0qw6Mpz85Gb*|1+MLn3!s(p8|YNvqaG(oZ(GPf+Aj9 z5pXTULm|1Y^x$R-xuL{xBN|6XM`ya$8hdBHB|115iIj{i-(zE#RLGTP=-ao!Y!)jU z8w=RFkKVgf(2W}J)b6KeWSGx?@wJ=!@JrWHJ|`zf$ny`8w6t_PX=p+MemD-hO?djZ>Ryp3=v;14L4cH?&k7Qsi4H_LI^JQLl&dlgPxPeCqiH^oDQO|wT-Yz-) z^QR^J6clt%g?`;4z!!9%n1^b8DW1_lOPyu4kj{YhicEd*n`;kXog zz0^U>6%+3@=$r2u@$>ViXJygz@YGIYRSMx@1n>O%Y`Hm_uX#jAM_28&Z2-MW3%3oA zCiD8v{c2#TjMSEkliii}5LB}mDJ7-bKv#0_)ZV`8y}G?vEuRI}Skc)UyTyLVksvjEY(TQha} zWvoAK(i0P3;!%q)&eYig61N|0j36VCk&*da9CIM$0p>^t8K|uT;lsL3PfwcxB_WCz z1qEfa-d<~Zc9u1nky;|KJCcwIQDQ(oK=lRizRjsB>h+Oa&cl_IFd$sBvwv&1aByS+ z=^Y&%_kOyxkBbkn5S?JxO zVO~DIS1m1%9G#p1*BK7P3=Itcvu>qU9p-Q=*Z$3FaKVJsEfW7EN zG|tvmOhIh|E*TG+VWVRQ6b7*xM}H{v$@$UWcTaBhORK8ld@yQ$sg(4fUkq>zhmny{ zR!**Ccvwx@3`sKS!DBO9+tJgN&6GLvl*W(&8c#++(Q+2Rl3BgWxUD@OKCb2RJ)^R2q&ID&Rf; zGkF^XfDGJ-*Y+%Wh$Ip=Ha0xPKoNC_WH9V#A>s{Do^>|g%$%LyXuVU*xA~T7H<}kR zc@}+-qjO^T9E}( z9&K_l6%rPv<>0_Q+4&_i^}(3i^N;pYv%I`KthyGP1I0 z$6GU~@F-9;of8vvs-nje@6^XWc|P+$KfJxOvl9XRpTefQxVrjEDip&U+TBzxWM`(1 zNiA1A_UvGT9zF?_;#b%vxBX=~gxd5w-byI#R(&f%%xg2$UTxm>O7#Vh+Vm$+wiic# z!iI)aS*|;pG2up+fJvV`efl*|Ds;3|iwW*wxg!*_Z)m6+z$dD*kBGRaw6KtVRRcI% z3V;EP)fWUF!TqS*~?d@%iN(25&kQfBL4&Ter{rvoUKj6> z-M=3T_0j>_1r+Yr!8A^Uyu+aoz=6e#-%OHQ0=?QdGNJ%Qq4En41RXvpDf4R8SE-4T z$4lGWv8$_AaFu@Toa3Ee*qE4@^-e$U1zjDHfX1r!-Zgn&Ufwl6P5|YRbU-@8o7;zn?*M~zvZIBa{W#rU;r8A!5)u_%$ql;h0D4D&Jwj0fFDCm^ zNoFLRA8$tkI0E7mAOtD62->^15aoZk{gcGm*_puo8+;--2xJB9p?*+o46paJn2efGiy zekB$67rMt`fF>v?X!Ow)IhH~&JTx>^wvh?i+t${WUB4C$=(nrw<~n+B&$U9Y2BpdQ z*GnK%5YO6;(h=M};62EY))yDsVdpZ0{{8!xo|8ibs+}t7HPmYzi&jZ>BAuXMT4`x% z$|j|Yi%UsCK_}(?`})q#A13z?51-pOI}eMAi4mE+bNbncgM`}thFZd;z_zci55dKj z;8)o9MMtuQlQ<0O70uuF#!=VZxi6yli(kf6qoWz1O>3&Q7e}nT zJUkY_N}9b`SXk4bIWykAy|1F8LYNwKei*5*r&s+gOEB%!7brMAJUm>R+AM|}`bNO4 z9qGZ{Td%AiXY!eY>`G#O_PvZ4z%fb4yYtm;RXMq^O5@Ku>jAI}0}hk#X+3k;p=wF= znI1iQOGZI4So{}^5HBGiq1VCsW1ZA=VUGt{0#4*?%*^p3skyl$paYrZree6)cXoz9 zJ^$SaoK^g0ZEdXvAi5S5zw&)89UU9Mw$2+6L^#3SO>uE?wxE^d#4nEiPGvMV`$o<; z0WUc2%r#d4Ol$$3Yc5DqLTOkcBvso!cuvH=MMp;`DW!quvtVIi;qgt#&!_zyaM3tf z15Ty{fU5(q+wFKuzoe>)^WYO;7%(ty(!~ykVPmqN@tw@fOh*uzL!+bd=xAunj?_J* z6xW^HX<1C_?b#Kgq%skWxZ93C;zF9%BL;P8+(j6 zuQJ(~_R!b@!~uub6`*1NBtF&(tWgEfpnIICuy74Ppkm7BPoH?8)4=Z1AAAAbRy*I~ z$M)p}P;xq+R_4`J1Kc9kU-fLEgwpr#tAS|yirdKf9jZa`STt$b*gSYPnumOFbd(}; ze0}Ao(-s)8zPrm==hEP^kb`&!U{vV}T*>O!Cr?XXUtgZx&!FoBfI=-E6&4p;*UT%u zA1x~_Rbo-4G%_+;<;mR5NBp@4bo4+aAt`AeusX2`(}M@$l}62pZ-v}mu5E0jZIU%Q z{~Ex+A$_uZ@>o&PY<6~b3rv_?qYCtwzL!^Hbp=?Zp|LTIm$&&HCKdn8fyk(Vroz7Q z^YP(AA{Z(JLfir&La=dmaZv|ouEZtf>FL>M)lYCcTr=||^)>KDUAb-*YXxt>`SbNZ ze^^gW6B$*~Q&Nak)YNQT7Fw-KN=h6TS_6s$OF$L$Q@#hxtb=V-Od-}`$j;6#8hD_Z z-agyt#Fl?LU=av%oRu)l3n;+xbZ<$HXCJCJWv0phU>z40F{FD@`d;0AeurdPeN9b* za>J$%o!8lkiJjyEj(xyGQI6P9Zlzv7CMUJ0kLQ}iz(q$A&#Ju@sfnYOxTk-zksD+K z0`RGxEflb0PYf9k`s>uxd!If3rVbr|>a@CZetxn$;VBwYc2?x#;)-VrChiy+ ziMu-gTcv7h+NL+a`)(8pC++v2KlhaUe*E~c1xSPSm))Q~qEfF$dc6j0ZXMLrfLNnh z$4k0cc1AhSYZFsbX)~$7%3wzW8Cz|zI@ft6xO-C5n; zH7%Owaa)%C0mdop(h*Qe6QjI<3y{j|{LsGiAGlzZO{6e<0)kE?MV9(pi6EP&rN$Y+2_BL~HF6xJ6bMgRMn*a3cDNy`R8CWq zWxtJ$jg=9J8}_G?X&_oL?odWRy|7jEo|!?(bb*}VH2ES4aUHB5J_*Td=+Y%$$I<%x`%S}ah}TNcf+5i`TOZ2M164(`FbL!fc<^-k1Jd5kFVUrwYt7TM zvyS%!?0+}TbTq-eA zHl2!7hcD-sX9r&g%FjR_A8yTPnX@D8EEt?3yB2WSa^s(%b^*r5KDt?kJ!AsVO8I-D zm;5;j;9Ct0?pBz)*rP`^-~r*f`A|PtXHUV^prM3xo&X($a}DQn*$ky4TUuHI;mdZ) zv2k-hBfRPyeLL2a}d4glz`5`}_BAh!sk>f;H|zlNQbG zb%S?f<&8iDSX?|jiSCB1IP~=Nuu%x}V*SsU)hab~nX3;}06i^jemB{zsF!JJB$<5n zFF_Ne>V^EQv3&hX<_n#kzJ3R6I5Z@c?oFAg%YK?j6rTkaa<2x&9t! zL+q>6)1VZWE*75R z+fSI)_?%(MH8nNi0gCA+M(Q1BG;Nxbk_f?G;8Rh(0pr*S3-IB?hX@F#z^owRP?o@? z%*-f|QGrcf9L^U=MDP30TvC&NKn2CZ`h*<;Tt`EXg`M1-ECi_#t0NumAU?8cj0wyEl=S2Z>Ef?PeC{0fYOK<=kU*W zY*frUuONMaylwD1Yvk?Qw;_{y_~WH=7^-GhXXj{(pZDt88ZAFRv4ewy5TuJBToWLH zgX_r{8{Zcf7w56Giy9AtdkzPZP)@eCvdV+-0O$v`=goa=aQu^HPq9J9BH~mKyVfRb z^z<_3)ue)V)4q#C&@9&&S6f>U}lIUg6oKM=TcWB$_8D1dpyZ+cX)b#--b+iovg z01bkBW%HUWZ)j+UZ+_wHy9CLGqKZlv)D5@OEFZXP3)p?0lr}Iw42+CRlcidl3vCkY z92|&ShEVd=t5Sc4YFyxcm7Tvdy+Oq^*Mw>lsVMJpND@=fu+Sn)nh``CqrTN8p zjYVpK00RR9rX_Nvb}hi$h%CHq^O{1?xf|9(quG5;^KBb2IKjwsN+DMyr`dX`SaSZw z&CLjyi}Xcz1zQOCuX%E!h7PIj30| zlK>54LK#R8e)|0Rv-a_Qx34Ww>C%jbsY@1Mg4U!lYpSb*qoS}7n7Zs?SZ^0HJ*|h- zzByJn2GxZF+0AFK?M~>+XdDZO(cBVhORCv3xGgctv`gu{Y2O9iT$C zNWpH{hyy_sXOiF1<`^n43oGHX18`jk;?K}m!!m3~B-t>Vp}UYa?;!y^f(tiqAQBru zu{1?NZ5`0;^d*n8bR6VLKDxTQCuS_=3%R22*-h}}c9mgAxmB|?; zO8WZxe+=F3-a;!jP*lK&9exb~1aUK#$NK_;$hiLHOoJY~XHYw-i#cn^B zh@wFNn}c-&D3gVlA!8!$qqPgDM7_4aM@VLnGm-LG-GYhN$@k4bnCwh{@#RGt*gJsb z!6D~Uv@ss0V-e>f?42^8)xfVrjkj-^oSJ%FQu5$~Y1_5j$@S$~-RR4#^mM(7!^A9>(SKB_4VBXJ0SOoGFdok#jz#u>P4gL zQYT#@-Ws|t3)U&fhy;qQc+kHP$riut1dHDdp0Te)HG>YH11{8;{q}7}adEM%WC}av z32De?tgNh9yh0Hx?{WhzfUwwWcrO4*^nrm?i1Svrw%C_8C2WT&*SEHY5aXm1F~BYX zXxx%_@0f62-NMGU1aV{ye90~(q_^%1=%=cyo96j@T(0x>d{0lfu&AhtwN!i<_%Q4` z1=Soeee++Zr#?UOq)Ohl%&f&QCm`IQr!5of|&$wS$DJx_B{Nh{J z8GJt|CASt3T40I*4Xibmi%dBBoK=Wi|WMwS+Cr_wx zD<3l=O{f6fxdnY(jOAbYv^;glHkCvP|yAP0qn67~2 za|`g>vEwEBR-D9jyx~-D?`wo>v1v@o%cFt&`S$UG_LTF>>-~i(+GC;hS85v~I`iy09Z^h^isiHfs+?W^6QafgzLj;0l7m_m;W{eq=yUTnICpbn$>sod@?G z8bv@Hh+R1eVtaIQQWnHDO!KXB-c?q{LP9|cZCCK^HO%eEcx{ND8R&?;FJ@+QfTKCcuWNXJ~nO`72L5z)ZcC7yQ7F7{D8wfBzx^Or*O6 z1TSIGkp~~JIoHe!a}O5EN}Vc``|uDw5NdNd&j}$iRj{Z&hnx7|D!A>(8NT=)ATsh0 zFoPv(Z=*mFZoxPgs0|^rAgmfIRv}qBKuj+I#WsIbW_9vBd-iOpZwAQY#fulx67L{) z98fKwf-O)6`Tbs63IRyY2h2&A2oi^dcv7m#`0DlRF3_xi z_T4b_B0g7u_PFIiDDL|YoQ-6DZfSWr8`MfT0hE>l1;_Z$81kS3 zNJc<@Y3Mb=@roEq;aWW%{5t@sMCT&V#2vqW8PlCufc8P0WGVG3Giv66dG%|2dih0| zj3K7oFf2?+O$`S)LY!(qu$_1G*CXP+S}a*BH!x^s_ZU6a$wW zje>##5q;a(*nsVp1$zghLXZpL&^gLy#4yg-P3N_}0~=IrH%3?Q{EHl9Y!?K1h|>^{ z{Epk_=cz!aCx5a9puR&X6r7irr%4gk6Gx2)c%AQ3}mm|cdA%H9vt9=QG2{vpm1{gm7>q{~)4TvfF_0@?fjF#k=>U7{t2+)rL zBzvQ6K|x_V%+|;dTB&C8-G@GER93d^uNV0hl88*oAhyCR)NiC8+&y)REtf*oMI3Y~;#3@ck(71iHdJ@Iefa>Pgu z4iBdaAAzQiM4VUx?~LdbaP@Hb1PkJAgx6adpobyoD@Z0Fl8pd!TnH(=-TW6};MZ!) z-aE}GP3~(0FxRMZjmqK<2g!F&^i~HP5}*)pL`*r0bm$Vp5ND$xXl67?+=hc1?~R&k zUlC{=4GlN-UHhx3Lz?p&p@!38d}z7CRIb6@x=V zWfDfjV3)rHUXepU&#Hr@4+0f&2n_PHMGy@jc4Poo!^$H8?^R#gr6eckfjT+dWmQc= z2|)rnt!`)ttE{XfYH@~tQ-J!hQacfZSPBwdd1ypw85s>YLKTMX;krvVT$IMHPse=( zDK~@1CsjDz1QpN=bccxKAu>V*!OO+ZA68n*0#hohhcD>f0H>_LFF2Uc0ZkEwlUb%& zj5VAqfd_M#Y>6N$phU3QQn0S0FyRfuUj%I%3aP;H_D{qyG%Q`LpKzv(sM2G*vmwk! zdXJb*hlYtsq2O^U+{x3_?CcoG)>4H=!K2Eh-?jv0tErVAHTxcd@V%p>uV5u#v6aGv zj2O~i$h%PIe*Lm$odV$|2kE~n95Trk^}Yi)(f93J7`Rm!ZoCBfHMo`}ARut-&YkeA zEDCr_7+aVp44+|T-B<2{OK@EuB4aoCLQ2S_CJQ@bZf+g|AK5WChd3W{diXmj89UhL z;^W7Uw{$~S^O&PU8XFs3i`$^?%)rk+(bZLe(nQSQA!*Tm$r))n0rdsU+zp3x5a+kx zX*#;Q(E#KCQEKN@?}~bDNkUv>jj=#Pf?z_(M-cpv2!#~WB4LgY10$=l-Hr8itdxY# zTGBkZ+m}~YHGU_~l#gBzf%t;d>VfLx#|R<>yPBtmJW(hg+X=O+vWjxTm@ekagNA|( zU{>O)uM7E^(H9?l#4!L6lJW8JNYFZnF*Hz37zBOd{-?okNtP)t{V(og1#$%bdQ??t zc4JX653~d~@*cJrf`S^C1#!g49%jo)gA-8FQ4ftjwZnsg^X>tomS0tcr=_KZIH}ln zeO@l@Ye=4kI{f`TL#-9m(&+c^UjZ8t2dg$WH``%p72Z%vfxUHw_;{(zv35>DA%>Ke zPt29AiI{kCpuZ2=*c>LJ)Aja*5Jj4snIXZavm1XR0%l6^eGA7OZ?_JR6@RR~d6%8C zZn$MA(w2&h@LfPx?LU8BWc@mT={uY~leDt3iY(AWZvXM)9^f};jdfaY5GG=;p=Mr{ zPWt!<0U}euT=3FCDp+hl0-z|bswxh|rjp*y&ENm-01nB(>gU{QSHVuaJH*7qVIK@{-Xbo>ZsaOE{oPOFi4{!31Zdz6xrhx5M;-+p-6TMSppF+qh`KOCNDa z3Z`U0>1dM84d1?fgJ4p}ru_Bw6D$rqh_wMLq0gym^M(YG|KFcY^4I=*`G5Xi*UtC< z{utuV#0LNSwz#P1jggQ?en@1|!h3Ks7jtVC-Tz$sl{5tbO8qm;K7EZsY1&8k?dB#xv*Eii7P|<1mowdiHq0DEb#T?c0dpR%0Xi4R_>8+WV zM}9r`4hH+1u@)RRbeNi?#*sAgIW40I6l^sJd60g3_=hX1pM&RGWRL|wHaaP;VsT`OdFaBb2K~KXG zTVwp0^x3$ql`QC}zrRMN(zpWxKBa{qTc$lE&XxB~cCoVM^;$-=^!yuT<)x?BUzL>B zo1R2yyfS5qI6KwrtSceW!_NNxQQ(cS4e^Yx9T_SH9>zlxv>zYPdt#8wbkkf=hWlxA zAxsUyqwX7Ww!6jWj03rxNS(XC*xows-TSz94pAkzf4`$%x4nNkcOWL#NBPK};Oax4 z8O|*nH0L=a=Xo@L|MxAzljWH84(Rocw@FEnV#&vTRMS2wzn6D;|5p(@3XN!1j-aSv zz1xk4yPbnBO6gggB^%}F+vchur&cc?Mc-l8NXM!2YD%8F>O4HT#4N0XpBJ9obh zJimQ|)fvITHmy>E6|gfcSPuP#>O2q{$! zWzlXocRtZTc9?olP-UDIk?-&n-z}0Yij{Se1s&y#f+@bX)-LHN>!-)SpC$k{S?Y#o z(TyUWiXBrEg_Y(qe^l2Z1xO2rM_8O{YT7@0cgHNRFg8_GxZL=sutp}&4WtyGgawtC z;y>>HDP*uhv^!@+Lmw)jrgU={Dd2l4Cxgnxi#qhp{_iNV-Ot9Y)^bTCA3umL@wJFu zyp4@D9S!SguDgynoXwt=60qbi8+r+F2k27>GUHR{6}=;=!UGX(*JAQW(lpnnAq4sB z-Si9%!vLrA*ch~&NAxnXRt(z`{zwD_b{99SGFbT)s$Z18aC|*6Fc>#XVV%U7D=AYR z(fY_C5%i#$;2y@8K#qT=PjyN@CUk^G3(WiDc6Y~jx^Lc%Pn5QvowX|B;w}6(o$f;+ z7*VAYd#-OzJ~&kLjA(v*T=w~cYf&~8zV<~7RU{VTKYyO%sfABgs`MoG#M<+6<+WaN z;LvMm9DXxtDL7s}wXi5qoL^my4{XOh{3w-MQWD|S{Zm~fy47WB9IyG2awz^kId zqdGl<{4FzJhF>BGdk3b8jDI2*_pT5+=#t!DEFX2OE*h?Cf^A>54}SErpK+&l8vqx3+@M z4kD%Y@6tYcODg-Ek6Y1s#Yk2>uqeUVVD^M$bYOr^CHG6Ls7YyJJq5~%p}xM=72z$r z$@EO+`<%iVb~`HyGxs%=ZgX+dn)f={*c4~Et1IUHPGeG!5WYB5Dkj69PpW%4S)r7g zPR`%Q%IGY&F|RULDS7E_K6S^f+;?f)uga&gO!-T`v$2vl-F^%j21YmbQCdS{^sZx9XO@CNucD3T=0#;@wLw0P;d()<83In>nPt2k_|4#A6UM(Vz z%^Ym-g=*xOTgjrL+1e(qeTC79>&BgL7zcU)3%E+L5v2J5_coZ3K(1byG z|Mv?<$$cUNH!EAhj+Vg3oK=+^zcDq6qqYwI9fYj(vhWWtcEFcNWcz-7o*?SXhyCyS2kkd5Ocb! zyxi!v&nSE+=wj!0MScs9>6zfWTa#7ls-JAt|9wlg?I6CT7}D}0r7;*OVYJF1MWi$V zf6OuIft8cvXr5i$UKO(2nr`agt&J6SaW3XJaUSMDwr-}j``gddLxMON9uNc(c@rxs z(p-Oi{MX%&m{@5+W4Kbr|3z|^4oU8VwLp@z4Qty8-dC^UsmYt%J}8%zz!0!#?p}_~ z&F1`wn2iJF;z7mAr>xb@rXHh@c@FcbRU0|4QkGvckJT7OngkID?|U5XG^qv z5@DfJQmSWUB8-&?P)0q0=giNuRxw*wJ)4-y6;E*cJ4(CUf%KcuX?FBSEn`4$CchlT z2Il~7Vr?zM@8Z4GM7rjU)r`~BG$sco=ZSHGW_>_R|Jmtu3^`o#OVac9wwuJy@5@+m zh5k&^l2p*j*p=9BsO8yDxF7W~>e{stjg19|qBc{D1*#7H+ii;^+h5c$iBD5duB_r@ zdDrBOe^8+v=^yhz4Q*??bf?a?{ralC#*&UCZnnX`G0#x27K@DRiWK>o80($o<-YUf z-%8J&%_Jux+AgJgTfX$+vWsLAb=6pgTwf`TEq2HxSf5q3G5avFMq%tcn~Ivl)za!G zai4m)Tq-Z$tsZoh^5-A3MBflvPaG4OpgqAE`prJ(ewe$^lgnc)4#}Z|G*i1tkRllw z@QtRCzTpxw3|-w!1B?j#XZ8u!@QplF#xAettHgR##F*Z@iJj-`xZm;^88uehN*?Ij z_P)6~uDd11Du9K>tYI~TX z?ZQCnuzPpUxQ#z`6XL{0p@syL{>yokxc28y`|)lUOS5wf|%@ar4DjgGFqz4fWMQnf{z|P(x_@!JceB}_2 z3aQy*dx7&`bFP?v;1^sxs{j2tgr!+gK-*pI{qJr6Ih_BWgF!f+uvEmS|Mz28l@TRq?ZtLKL;%;K3vr;h}f6ABl>*;G;^H7Pg^0<50e`gSE+C9N(ZEgRz zmOKI9-P#SS=QBHTHprYDe&d3;X~@OfTl|8fu`B1&QhS<|nxEK#m@QS;eEc+?W(iLsQa9H>7k&aOuqtZs8T5OI(hlcFF$62zmj zj#WtuZgP>kVN%CPeYo~B3^T4)(o10UvtVUAzauGEfJn6qb$p6kssUA0LN<<-O`u#@ zDk{KxTvSA{p>jOUs3X^tAln zc4w%9{^IqDj#+>)-q@h{C>?hxGNi;ujhm zK+&mOZo3~>3msc)jLpY)+PKtF$liWbMb6JKDEb_!On2j_0zMr**iD8g**70xS)rbq z@{7>w9po;quaKcLu*1SN<73(+@=9+DiJ(~aCi1IL4Zo$oX;V%Cz1nA6#08>V=5_GJ zNyxNbd*7{ep@f_;8Rv(K+qjhCIFu4<18^Fo{aaRWE->){P7gv=sc`nXu z%`SarM!assjd}T!+09yBActZeplQu_kdE2uFJAc-c)EF`nsaJg35;aqR-Ky6)v>Te zU&oQ5z6#r~-zx;KDilNoP8g)8g~evj_cF;is?{W2I6Bk*HJah>pC9P6jf_;~1#|_v z-roPHF@qP)77uLQnV!vRXQm$f>#GuAcx5H^_s6C88K(@*-LZkD#T9h)=U*y(0(?8` zZ0oCZwg=~17;394R>w{*f7sivmS_n1ym2Gt3a(K~B2`hg0BET>J0L?PJvg!^n63@u z_VDPT5;NO6uhV=lRhl zVL6f$`Dg3b;PhfgjOXs~bX8l_Kvx$Tg?RSBXK&lBg`m>QbI+bXllWtih4l9~HouOj zYY&rJD#VRnmFwEVA^sj7-s0T4ykKs1^&a^cnoJ(<{Efqdq>8kx!Rg-<&z%$$dU$vu zj_Vu9F0Q=G2q^}q|Etq>;(30+6+N=hAWquL^#kW>v?sh zwBvCJCk|$vjvO#(%~7;9jA*hlm09ZrU3f~0y7eT3-?NKmp^4IH-t8tf;N^8-zvHo? z*&H3csuD*g^NQ(BmSE|JMghyn$byTfA5_=q6{3h%VsLsyyzjLv4!fX&89*?95z38_&0PExk2H4DpRK0lx0{^H)nE}tYC z>EH3N8sCEm4b&KZC*`Q~$x^;*R9P%1=ZBA0UftGi_2s<+lltc7?A`mWL5uYdAG#^6 zSymtj)zs|UGc%W3@cE-nAl>A`+vt4%2>;E7wRPlXZD4@rOX0N??jCaf#Px-k$QVp8 zOQ{}Mm2d9+I{2-{3K7$4XbAF604qe%lhhUB5{>NV(rW~qWCLa< zlHS}LCLLbsd?>QaUSi^iUB&OE2f*1{l4>AxyNZ!p-#SLpir$-^sklz)h9qD99`XtgJC>8_@$<{Pfsir;q6A z<)~qLp3|JdBr7-OUDK4tz9IiiN-9ygI5DwadN4i0*By%k)7Y3*T^;`F{B@&1Y_f27 zcZA4Cp+=`dcWUb28@gKbYua-bFMcN~o~_Fln41?>Ltq}SZ6`dG^LP#Ojw0K4qt|Kt zTz`KVo>KzT7b;8$Qt?NfQoc^(j9iF3Se!HJDbqHu&|>O;hC}_3po~$&&eOB_BI?bZ z`zx5r#3Vl(xl2B%>F~IT1wAy(H*QdFlpfsg?ZnznX0d7^R#3b1i;yO;FNBv|NF;G< zcz_N)qR{ir^;AVdARYh$*QZ%gsw|DcT!!Kl&qdTR_$Tie{R`3E*eEoAIkmo zX<5)g$@?#EmiU}27)vn;(zsk+oAIljAIS#d@0#NaE9w~}22G9?N}ADByV1)%J=x{_ z_xN-#MCXcJ+-Nq}y!+OyRem*|{9BRwxHyuOv$KTV?n=YFE=4!-bMlLcoRURxxu2Y|pL|-ouv?mTz)Qs95-L->IkPOPjW@bXRyX-tm+vsUD&d8`N{NuAA$Mf;eO`9;IKb+W#>*6qBXOdCA4N5TpOw zYrOtllS{*qEG9Ca*)n3+rI)J>Ym!gj?-@5s|E80cQL;1CM~3|Vapse6d#)Nt?Pw)iX4|1f%%gSJc<92`16?GHoenspPmFNVP`I%1U&rPdLuBSz78<9F>N? z^G;JxiHIk2FgHi6h?Ogsr&vJ1%-G^v5q#9ZOFeC!=Gs-s$M-&pFiKUKbk{r27YY0s z4H-DuE)21^|IlB!oF{{+X(w#b%ffhemi%Y?)J@YL7ng;rk-eQ|kcGwnLRS_I4XL!W zR*N`Qj%GTVq{!&^rlP{}?i>sGDM^~3fISKhIa;=mRIS;Z5CUCeP_h%s>7>U#|J{5- zBPtoK@9T?fI~-4EsHZ+LQ5djfw3huaIhV6klqC@xms~MtFyG5*_FYNTKxdbdnxGxc zRprS}3Kc{DMNjs!5l#->i)gRyJ`qtDs#r8CafaCIW2dpr9QwXm43d^B{tp~@C>>30 zOmVdx!*3ZX3JdMg>|AcHa*8z>m8>%dBh!-TKa2NPNchK7IkHIG)A^?)2Y-$Jee&l! z-KT{nymY?EcZD}1LdCL%hT6x+96&0ayM6d(T^Rk8>84Sg;iy!^*x6#qB%U|LJ_qte zR!7@xes$G%C!Rzl=s(}LDENHzSI#{EEDl-`T_JN$Zkj?5eEE?lCtH}_k7hg{)tYzz zC`H>r_?L5gFlQQnRBJ

    !r&#eJ|pGzXW1<#!FXzJU0$@qtERnk@W4fwB%k^>+{ZH zqHDZJ?Nn4}TGu0Y)iLvpeAU(2w`!ESxN|mTTKjm$*EcweVq|fE5DP0p$!S`We!Ns` z&@|C|xOjbn3EzWQq0*qV@eW7ebY3B4; z>ob$uUi89VJcgjh`OdGYX7P8-7Z-z7TH_gwsT}qKe~z9Nz?e_Tc5$xhI$BZvop)Nu^c+m7PRr=x|!K} z-sC27xCnXSOgBWk6MCQ$xDl0LKYsj&>+GzyN;f@x5T&G~TM`S)N`1w>b!9ow%#@Io z6#|$;zi;FY67wP#3o_={=<#Nl@U3b4pe2;%UOoN(*6<2sQku4#z0=)%H_O?D&rG6B zP3*4jn*L#OZV@9oZvH0~fcJ2*X7w^Y^ukvVS zgU%WBug~g=7T1nHed<Rzb4}|1%U2f$5DE z-cNK&ey4U$Jz32i{`I+fT;nvOuC}O(*PY>v`>n9d?!!PAsvBI_+p}L&CJGf;s9vrN zW>f#1sVnF(a^*UsaKEDE(Oebi;uvWE*5`Kg(P};HB2Fk^V7UXdnur%e&c93H#U)x_ zcCIJK!bW>=XfScjdw1MK%%nsPd)D2(&w!Mek)^Ho4Kezw$b*&w3va+xst01(Iewk5 zqQ>TpB-ksMh#5(&`a9>0G};D7NcyFE-ap>nVkUL@&T6(}l;^RL*iXK1nq@@_zz!28;Q*5p#1Hd-6n-gG^nWv17+5 zF*lbN?YG|~ugm2s<5IwU{K(j@U7}+%W>5~q{Cvi4-J<+!Tzu$RNWYJf5v5JyQND2N7JZ)@H7MoO&6|w%>nFgqXpkt+YwzAfCtM!l?%k<;)-1|}$E7Us_NMYyt)x?9afz{mgGJ?U-%>74B_&El z$Klf_#`N^06Hs5jPS>bkUot$GIq-S2a zQu>&c6&(}Lsn22aW;)iS3CXa({-XS``ubG9b}h*<#we{7CpY`{r9M7$CVig`8>AP{ z;?k`FlwwO9+&Th_7fY5WCyUMzPuX|*vglh^t48@{ot%hY6_$fFYf?RK;fBJpYuGT! z@`)2g3%^{s!q~=*|Ib7F?i~sIn>R_pb8(?0z4CGizIsK1b;SzGhbGRr($h&nF1%%B zQR42x<%M&}-oH;TuzIz0vgGJ!>GK~yCI&3)o}WH377-y`&LsjDf1ka3=>s1>E}5X8 zNBMz3KsjVJG(-uc-@GA36(D6%JQwZTx1xa+K%FTyl{&PV8ZCZs>z1hgojb%}D^(KZ z^>lZq0SE>83F z=81BO8W>3CdrV3aCD*sKBzl*H8ap{)-B&hX)BTCnp-@ty(3WBbMtED^?JF zb1Ql!B+zv>Z#*K;Zaf`lic}ux`@&GA4vuBgxi!m|~j2Iz0Ub{Bw zC508N!Z0w9T*#@s;>r~=u5j;HqXrofFJGp`51gI<*WUTFGz>*i{3ePR5u{2>-CSKn zRCIDIIJme8POjooI*Irt9K=uH;3z6Cg0l$zfeO|^D7AvErG-`mjdeI&Uy??#`l2?y zKPZK^mYAe@FYlgvjyv&hWySq_zQ4y!fN5gi&Cg>jSX;y2jE`ds;^XPJSm=Dr&Z_N7 zB-HD3a|leiyTkTzfI@#iZgPr6B*bw@1Amv(S9gEkoy2JvNI~Np=X4rLwfz3r7{=Xd z73UQ%8d(;$fzP9K8t<7V7O85rx>2u7JF3uPlu9UBIdkfBIh57CoszGw@ZpR`l|{(e z88qSXxPJ-g@zLEG{u3${l}zYw?MW#J zKc!HBlyGzuc5Jo{UFyI}%zl@f8^{$i z8GW7l|DD@gXkeW>+HBS>(R_Y}CF|-cWO$_#9uE%~H?vvDFAol&vkd~6*_ z=bH~!X@-stG)(KJv-5p2OXO?{69geVl*>wlzrBsS@tGOfFJXflvx0E!5CkV&%>6G# z-KQrN8gg*~%dS>w2Ky~8FNrob+|74huCL)y`W@92%yE8Nd-|?LtxJ4~2 zKzbL6p!|P&3O9<7_)^OXtssOA%R+g{FmN&3+Y3$`CHxI1CnzNj55tzNQh`Q}Cmn*I zlcOV~h!UYMVR>0!T=I9Bn85SkAQB@N7v(s4>FI$jX)1+^T`~#V#zX=Zsa;(}hlj`> a2mxf!g&w=m$}B@S{Y@E>Fk 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 a2mxf!g&w=m$}B@S{Y@E>Fk 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 c6AV1V + #include + #include + + int main(int argc, char * argv[]) { + using namespace boost::network; + + if (argc != 2) { + std::cout << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + + try { + http::client client; + http::client::request request(argv[1]); + request << header("Connection", "close"); + http::client::response response = client.get(request); + atom::feed feed(response); + + std::cout << "Feed: " << feed.title() + << " (" << feed.subtitle() << ")" << std::endl; + BOOST_FOREACH(const atom::entry &entry, feed) { + std::cout << entry.title() + << " (" << entry.published() << ")" << std::endl; + } + } + catch (std::exception &e) { + std::cerr << e.what() << std::endl; + } + + return 0; + } + +Diving into the code +==================== diff --git a/libs/network/doc/html/_sources/examples.txt b/libs/network/doc/html/_sources/examples.txt index f1cfbd7b8..bbc06282b 100644 --- a/libs/network/doc/html/_sources/examples.txt +++ b/libs/network/doc/html/_sources/examples.txt @@ -5,10 +5,10 @@ The :mod:`cpp-netlib` is a practical library that is designed to aid the development of applications for that need to communicate using common networking protocols. The following set of examples describe a series of realistic examples that use the :mod:`cpp-netlib` for these -kinds of application. +kinds of application. All examples are built using CMake. .. toctree:: :maxdepth: 2 examples_http.rst -.. examples_xmpp.rst + diff --git a/libs/network/doc/html/_sources/examples_http.txt b/libs/network/doc/html/_sources/examples_http.txt index ace423ab1..e95c9386c 100644 --- a/libs/network/doc/html/_sources/examples_http.txt +++ b/libs/network/doc/html/_sources/examples_http.txt @@ -9,5 +9,10 @@ embedded into larger applications. :maxdepth: 2 http_client.rst + simple_wget.rst hello_world_server.rst hello_world_client.rst + fileserver.rst + atom_reader.rst + rss_reader.rst + twitter_search.rst diff --git a/libs/network/doc/html/_sources/fileserver.txt b/libs/network/doc/html/_sources/fileserver.txt new file mode 100644 index 000000000..48aa2082b --- /dev/null +++ b/libs/network/doc/html/_sources/fileserver.txt @@ -0,0 +1,11 @@ +.. _fileserver_http: + +******************* + Fileserver (HTTP) +******************* + +The code +======== + +Diving into the code +==================== diff --git a/libs/network/doc/html/_sources/generic_message.txt b/libs/network/doc/html/_sources/generic_message.txt deleted file mode 100644 index 8c7ec6fb1..000000000 --- a/libs/network/doc/html/_sources/generic_message.txt +++ /dev/null @@ -1,6 +0,0 @@ -Generic message -=============== - -.. todo:: - - Is this section repeated? diff --git a/libs/network/doc/html/_sources/getting_started.txt b/libs/network/doc/html/_sources/getting_started.txt index 5543968a8..9a1e878b4 100644 --- a/libs/network/doc/html/_sources/getting_started.txt +++ b/libs/network/doc/html/_sources/getting_started.txt @@ -158,7 +158,7 @@ Building On Windows If you're using the Microsoft Visual C++ compiler or the Microsoft Visual Studio IDE and you would like to build cpp-netlib from within Visual Studio, you can look for the solution and project files as the artifacts of the call to -``cmake`` -- the file should be named ``cpp-netlib.sln`` (the solution) along +``cmake`` -- the file should be named ``CPP-NETLIB.sln`` (the solution) along with a number of project files for Visual Studio. Reporting Issues, Getting Support @@ -173,5 +173,5 @@ for the project at http://github.com/cpp-netlib/cpp-netlib/issues. You can also opt to join the developers mailing list for a more personal interaction with the developers of the project. You can join the mailing list -through https://groups.google.com/group/cpp-netlib. +through http://groups.google.com/forum/#!forum/cpp-netlib. diff --git a/libs/network/doc/html/_sources/hello_world_client.txt b/libs/network/doc/html/_sources/hello_world_client.txt index e3bf8e722..d6c81007b 100644 --- a/libs/network/doc/html/_sources/hello_world_client.txt +++ b/libs/network/doc/html/_sources/hello_world_client.txt @@ -51,7 +51,7 @@ Just like with the HTTP Server and HTTP client example before, we can build this example by doing the following on the shell: .. code-block:: bash - + $ cd ~/cpp-netlib $ g++ -o hello_world_client \ > libs/network/example/http/hello_world_client.cpp \ @@ -70,7 +70,7 @@ This example can be run from the command line as follows: .. note:: This assumes that you have the ``hello_world_server`` running on localhost port 8000. -Diving into the Code +Diving into the code ==================== All this example shows is how easy it is to write an HTTP client that connects @@ -92,7 +92,7 @@ perform the request via HTTP: http::client client; http::client::request request("http://my.webservice.com/"); - http::client::response = + http::client::response = client.post(request, "application/xml", some_xml_string); std::data = body(response); diff --git a/libs/network/doc/html/_sources/hello_world_server.txt b/libs/network/doc/html/_sources/hello_world_server.txt index 09a679859..ab9504813 100644 --- a/libs/network/doc/html/_sources/hello_world_server.txt +++ b/libs/network/doc/html/_sources/hello_world_server.txt @@ -59,7 +59,7 @@ simple response to any HTTP request. This is about a straightforward as server programming will get in C++. -Building the Server +Building the server =================== Just like with the HTTP client, we can build this example by doing the following @@ -86,7 +86,7 @@ a command line as follows: .. note:: If you're going to run the server on port 80, you may have to run it as an administrator. -Diving into the Code +Diving into the code ==================== Let's take a look at the code listing above in greater detail. diff --git a/libs/network/doc/html/_sources/http.txt b/libs/network/doc/html/_sources/http.txt index a3f808815..65424bb3f 100644 --- a/libs/network/doc/html/_sources/http.txt +++ b/libs/network/doc/html/_sources/http.txt @@ -99,7 +99,7 @@ returns, in the default case, a multimap of strings to strings: response_headers headers_ = headers(response); for (iterator it = headers_.begin(); it != headers_.end(); ++it) { std::cout << it->first << ": " << it->second << std::endl; - } + } std::cout << std::endl; @@ -145,9 +145,9 @@ implementation while the user-visible implementation is the namespace boost { namespace network { namespace http { template - class server : + class server : public basic_server {}; - + }}} To use the forwarding server type you just supply the request handler @@ -178,36 +178,3 @@ Here, all we're doing is returning the original request body with an HTTP OK response (200). We are also printing the IP address from where the request came from. Notice that we are using a wrapper to access the source of the request. - -HTTP URI -```````` - -:mod:`cpp-netlib` provides a specialization and ``typedef`` for an -HTTP URI: - -.. code-block:: c++ - - namespace http { - template class basic_uri; - typedef basic_uri uri; - } - -``basic_uri`` provides a parser which breaks down a URI string passed -to it's constructor into different parts. - -.. code-block:: c++ - - using namespace boost::network::uri; - http::uri uri_("http://www.boost.org/"); - assert(valid(uri_)); - assert(scheme(uri_) == "http"); - assert(host(uri_) == "www.boost.org") - assert(port(uri_) == 80) - assert(path(uri_) == "/"); - -The syntax of the HTTP URI are defined in RFC 1738 section 3.3 [#]_ -and the default URI provided with cpp-netlib conforms to this. In -such a way, specializations that conform to any URI scheme can be -provided. - -.. [#] http://tools.ietf.org/html/rfc1738 diff --git a/libs/network/doc/html/_sources/http_client.txt b/libs/network/doc/html/_sources/http_client.txt index 3041239d9..6e254c66a 100644 --- a/libs/network/doc/html/_sources/http_client.txt +++ b/libs/network/doc/html/_sources/http_client.txt @@ -7,10 +7,10 @@ The first code example is the simplest thing you can do with the :mod:`cpp-netlib`. The application is a simple HTTP client, which can be found in the subdirectory ``libs/network/example/http_client.cpp``. -All we are doing is creating and sending an HTTP request to a server -and printing the response body. +All this example doing is creating and sending an HTTP request to a server +and printing the response body. -The Code +The code ======== Without further ado, the code to do this is as follows: @@ -19,37 +19,26 @@ Without further ado, the code to do this is as follows: #include #include - + int main(int argc, char *argv[]) { using namespace boost::network; - + if (argc != 2) { std::cout << "Usage: " << argv[0] << " [url]" << std::endl; return 1; } - + http::client client; http::client::request request(argv[1]); request << header("Connection", "close"); http::client::response response = client.get(request); std::cout << body(response) << std::endl; - + return 0; } -Building and Running The Code -============================= - -To be build this example, you can follow the steps below without having to build -the whole :mod:`cpp-netlib` distribution:: - - $ cd ~/cpp-netlib - $ g++ -o http_client1 libs/network/example/http_client1.cpp \ - > -I. \ - > -I$BOOST_ROOT \ - > -L$BOOST_ROOT/stage/lib \ - > -lboost_system \ - > -pthread +Running the example +=================== You can then run this to get the Boost_ website:: @@ -57,7 +46,7 @@ You can then run this to get the Boost_ website:: .. _Boost: http://www.boost.org/ -Diving into the Code +Diving into the code ==================== Since this is the first example, each line will be presented and diff --git a/libs/network/doc/html/_sources/index.txt b/libs/network/doc/html/_sources/index.txt index ef56ddb3c..be751dfb1 100644 --- a/libs/network/doc/html/_sources/index.txt +++ b/libs/network/doc/html/_sources/index.txt @@ -123,7 +123,6 @@ Contents in_depth.rst techniques.rst history.rst - install.rst reference.rst references.rst diff --git a/libs/network/doc/html/_sources/install.txt b/libs/network/doc/html/_sources/install.txt deleted file mode 100644 index 5de085221..000000000 --- a/libs/network/doc/html/_sources/install.txt +++ /dev/null @@ -1,2 +0,0 @@ -Full installation guide -======================= diff --git a/libs/network/doc/html/_sources/reference_http_server.txt b/libs/network/doc/html/_sources/reference_http_server.txt index d930cc56d..296b4b801 100644 --- a/libs/network/doc/html/_sources/reference_http_server.txt +++ b/libs/network/doc/html/_sources/reference_http_server.txt @@ -35,7 +35,7 @@ Handler function object. There are two different Handler concepts, one concept for `Synchronous Servers`_ and another for `Asynchronous Servers`. -The SynchronusHandler concept for `Synchronous Servers`_ is described by the +The SynchronousHandler concept for `Synchronous Servers`_ is described by the following table: --------------- @@ -145,7 +145,7 @@ API Documentation The following sections assume that the following file has been included: .. code-block:: c++ - + #include And that the following typedef's have been put in place: @@ -226,14 +226,14 @@ Constructor To use the above supported named parameters, you'll have code that looks like the following: .. code-block:: c++ - + using namespace boost::network::http; // parameters are in this namespace boost::asio::io_service my_io_service; boost::network::utils::thread_pool pool(2); handler handler_instance; async_server instance(_address="0.0.0.0", _port="80", _handler=handler_instance, _io_service=my_io_service, _thread_pool=pool, - _reuse_address=true); + _reuse_address=true); instance.run(); Public Members @@ -270,8 +270,8 @@ helpful in certain simple situations. ``response = http_server::response::stock_reply(status, body)`` Code like the above should go inside the handler's ``operator()`` overload. - The body parameter is an ``std::string``. The status parameter is any of - the following values from the ``http_server::response`` enum + The body parameter is an ``std::string``. The status parameter is any of + the following values from the ``http_server::response`` enum ``status_type``: .. code-block:: c++ @@ -313,7 +313,7 @@ which can be directly manipulated by the handler. .. [#] A header is a struct of type ``response_header``. An instance always has the members ``name`` and ``value`` both of which are of type ``string_type``. -.. [#] ``string_type`` is +.. [#] ``string_type`` is ``boost::network::string::type``. Asynchronous Servers @@ -358,7 +358,7 @@ synchronous server implementation. The general pattern for using the ``async_server`` template is shown below: .. code-block:: c++ - + struct handler; typedef boost::network::http::async_server http_server; @@ -367,7 +367,7 @@ The general pattern for using the ``async_server`` template is shown below: http_server::request const & req, http_server::connection_ptr connection ) { - // handle the request here, and use the connection to + // handle the request here, and use the connection to // either read more data or write data out to the client } }; diff --git a/libs/network/doc/html/_sources/references.txt b/libs/network/doc/html/_sources/references.txt index 09644e25b..7f2c97d4f 100644 --- a/libs/network/doc/html/_sources/references.txt +++ b/libs/network/doc/html/_sources/references.txt @@ -14,6 +14,7 @@ Other sources * `HTTP 1.0`_: The HTTP 1.0 specification. * `HTTP 1.1 (RFC 2616)`_: The HTTP 1.1 specification. * `URI Generic Syntax (RFC 3986)`_: Generic URI syntax specification. +* `Format for Literal IPv6 Addresses in URLs (RFC 2732)`_: Literal IPv6 Addresses in URLs. .. _`BoostCon 2010 Slides`: http://www.filetolink.com/b0e89d06 .. _`BoostCon 2010 Paper`: http://github.com/downloads/mikhailberis/cpp-netlib-boostcon-paper/cpp-netlib.pdf @@ -21,3 +22,4 @@ Other sources .. _`HTTP 1.0`: http://www.w3.org/Protocols/HTTP/1.0/spec.html .. _`HTTP 1.1 (RFC 2616)`: http://www.w3.org/Protocols/rfc2616/rfc2616.html .. _`URI Generic Syntax (RFC 3986)`: http://www.ietf.org/rfc/rfc3986.txt +.. _`Format for Literal IPv6 Addresses in URLs (RFC 2732)`: http://www.ietf.org/rfc/rfc2732.txt diff --git a/libs/network/doc/html/_sources/rss_reader.txt b/libs/network/doc/html/_sources/rss_reader.txt new file mode 100644 index 000000000..9d89d000c --- /dev/null +++ b/libs/network/doc/html/_sources/rss_reader.txt @@ -0,0 +1,44 @@ +.. _rss_reader: + +************ + RSS reader +************ + +.. code-block:: c++ + + #include "rss.hpp" + #include + #include + #include + + int main(int argc, char * argv[]) { + using namespace boost::network; + + if (argc != 2) { + std::cout << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + + try { + http::client client; + http::client::request request(argv[1]); + request << header("Connection", "close"); + http::client::response response = client.get(request); + rss::channel channel(response); + + std::cout << "Channel: " << channel.title() + << " (" << channel.description() << ")" << std::endl; + BOOST_FOREACH(const rss::item &item, channel) { + std::cout << item.title() + << " (" << item.author() << ")" << std::endl; + } + } + catch (std::exception &e) { + std::cerr << e.what() << std::endl; + } + + return 0; + } + +Diving into the code +==================== diff --git a/libs/network/doc/html/_sources/simple_wget.txt b/libs/network/doc/html/_sources/simple_wget.txt new file mode 100644 index 000000000..7b7f8e0fa --- /dev/null +++ b/libs/network/doc/html/_sources/simple_wget.txt @@ -0,0 +1,56 @@ +.. _simple_wget: + +*************** + Simple `wget` +*************** + +The code +======== + +.. code-block:: c++ + + #include + #include + #include + #include + #include + + namespace http = boost::network::http; + namespace uri = boost::network::uri; + + namespace { + std::string get_filename(const uri::uri &url) { + std::string path = uri::path(url); + std::size_t index = path.find_last_of('/'); + std::string filename = path.substr(index + 1); + return filename.empty()? "index.html" : filename; + } + } // namespace + + int + main(int argc, char *argv[]) { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " url" << std::endl; + return 1; + } + + try { + http::client client; + http::client::request request(argv[1]); + http::client::response response = client.get(request); + + std::string filename = get_filename(request.uri()); + std::cout << "Saving to: " << filename << std::endl; + std::ofstream ofs(filename.c_str()); + ofs << static_cast(body(response)) << std::endl; + } + catch (std::exception &e) { + std::cerr << e.what() << std::endl; + return 1; + } + + return 0; + } + +Diving into the code +==================== diff --git a/libs/network/doc/html/_sources/twitter_search.txt b/libs/network/doc/html/_sources/twitter_search.txt new file mode 100644 index 000000000..2433ba831 --- /dev/null +++ b/libs/network/doc/html/_sources/twitter_search.txt @@ -0,0 +1,45 @@ +.. _twitter_search: + +**************** + Twitter search +**************** + +The code +======== + +.. code-block:: c++ + + #include + #include + #include + + int main(int argc, char * argv[]) { + using namespace boost::network; + + if (argc != 2) { + std::cout << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + + try { + http::client client; + + uri::uri search_uri("http://search.twitter.com/search.json"); + + std::cout << "Searching Twitter for query: " << argv[1] << std::endl; + uri::uri search_1; + search_1 << search_uri << uri::query("q", uri::encoded(argv[1])); + http::client::request request(search_1); + http::client::response response = client.get(request); + + std::cout << body(response) << std::endl; + } + catch (std::exception &e) { + std::cerr << e.what() << std::endl; + } + + return 0; + } + +Diving into the code +==================== diff --git a/libs/network/doc/html/_sources/uri.txt b/libs/network/doc/html/_sources/uri.txt index 257416003..45559d75a 100644 --- a/libs/network/doc/html/_sources/uri.txt +++ b/libs/network/doc/html/_sources/uri.txt @@ -1,11 +1,11 @@ -The URI template -================ +The URI class +============= In addition to protocol implementations, the :mod:`cpp-netlib` -provides a powerful URI template. The URI template implements a -parser based on `RFC 3986`_. +provides a powerful URI class. The class implements a parser based +on `RFC 3986`_ and `RFC 2732`_. -Generic URI Syntax Overview +Generic URI syntax overview ``````````````````````````` A generic URI will take the form:: @@ -13,8 +13,8 @@ A generic URI will take the form:: [scheme:]scheme-specific-part[#fragment] A URI is known as `absolute` if it specifies the scheme. Otherwise, -it is known as a relative URI. Currently, ``basic_uri`` supports -only absolute URIs. +it is known as a relative URI. Currently, ``uri`` supports only +absolute URIs. URIs can be further classified according to whether they're hierarchical or opaque (non-hierarchical). @@ -60,30 +60,51 @@ elements. Another example, using HTTP is given below: The difference here between the path in a hierarchical URI and that in the example above for the non-hierarchical URI. -``basic_uri`` -````````````` +The ``uri`` class +````````````````` -The ``basic_uri`` definition is consistent with that of -``basic_message``:: - - template - class basic_uri; - -As it stands, the template only supplies a URI parser and no builder. +As of version 0.9.3, ``uri`` supplies a URI parser and builder. To use the parser, it's as simple as supplying a string to the -constructor:: +constructor: + +.. code-block:: c++ - boost::network::uri::uri instance("http://cpp-netlib.github.com/"); - assert(boost::is_valid(instance)); - std::cout << "scheme: " << boost::network::uri::scheme(instance) << std::endl - << "host: " << boost::network::uri::host(instance) << std::endl; + using namespace boost::network; + uri::uri instance("http://cpp-netlib.github.com/"); + assert(instance.is_valid()); + std::cout << "scheme: " << instance.scheme() << std::endl + << "host: " << instance.host() << std::endl; The command-line output of this program will be:: scheme: http host: cpp-netlib.github.com -A future version of ``basic_uri`` will provide a full builder API. +The ``uri`` builder +``````````````````` + +``uri`` support a stream style syntax to create a URI from it's +elements. For example the program: + +.. code-block:: c++ + + #include + #include + #include + using namespace boost::network; + + int main() { + uri::uri url; + url << uri::scheme("http") + << uri::host("www.github.com") + << uri::path("/cpp-netlib"); + std::cout << url << std::endl; + return 0; + } + +will output:: + + htp://www.github.com/cpp-netlib ``URI Concept`` ``````````````` @@ -127,3 +148,4 @@ A future version of ``basic_uri`` will provide a full builder API. .. _`RFC 3986`: http://tools.ietf.org/html/rfc3986 .. _`RFC 2368`: http://tools.ietf.org/html/rfc2368 .. _`RFC 3513`: http://tools.ietf.org/html/rfc3513 +.. _`RFC 2732`: http://tools.ietf.org/html/rfc2732 diff --git a/libs/network/doc/html/_sources/whats_new.txt b/libs/network/doc/html/_sources/whats_new.txt index e02c73313..22164c82a 100644 --- a/libs/network/doc/html/_sources/whats_new.txt +++ b/libs/network/doc/html/_sources/whats_new.txt @@ -7,6 +7,19 @@ :mod:`cpp-netlib` 0.9 --------------------- +v0.9.3 +~~~~~~ +* Updated URI parser. +* A new URI builder. +* URI support for IPv6 RFC 2732. +* Fix issues #67, #72, #78, #79, #80, #81, #82, #83. +* New examples for the HTTP client, including an Atom feed, an RSS feed and a + very simple client that uses the Twitter Search API. + +v0.9.2 +~~~~~~ +* Critial bug fixes to v0.9.1. + v0.9.1 ~~~~~~ * Introduced macro ``BOOST_NETWORK_DEFAULT_TAG`` to allow for programmatically @@ -18,13 +31,13 @@ v0.9.1 v0.9.0 ~~~~~~ -* **IMPORTANT BREAKING CHANGE**: By default all compile-time heavy parser +* **IMPORTANT BREAKING CHANGE**: By default all compile-time heavy parser implementations are now compiled to external static libraries. In order to use :mod:`cpp-netlib` in header-only mode, users must define the preprocessor macro ``BOOST_NETWORK_NO_LIB`` before including any :mod:`cpp-netlib` header. This breaks code that relied on the version 0.8.x line where the library is strictly header-only. -* Fix issue #41: Introduce a macro ``BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG`` +* Fix issue #41: Introduce a macro ``BOOST_NETWORK_HTTP_CLIENT_DEFAULT_TAG`` which makes the default HTTP client use ``tags::http_async_8bit_udp_resolve`` as the tag. * Fix issue #40: Write the status line and headers in a single buffer write @@ -33,8 +46,8 @@ v0.9.0 response objects). * Refactoring of internal implementations to allow better separation of concerns and more manageable coding/documentation. -* Client and Server constructors that support Boost.Parameter named parameters. -* Client and Server cosntructors now take in an optional reference to a Boost.Asio +* Client and server constructors that support Boost.Parameter named parameters. +* Client and server constructors now take in an optional reference to a Boost.Asio ``io_service`` to use internally. * Documentation updates to reflect new APIs. @@ -46,7 +59,7 @@ v0.9.0 * Asynchronous HTTP Server that now supports running request handlers on a different thread pool. * An initial thread pool implementation, using Boost.Asio underneath. -* Adding a ready(...) wrapper to check whether a response object returned by +* Adding a ready(...) wrapper to check whether a response object returned by the asynchronous client in 0.7 already has all the parts available. * Some attempts at lowering compile time costs. diff --git a/libs/network/doc/html/_static/background.jpg b/libs/network/doc/html/_static/background.jpg deleted file mode 100644 index fc7edde076049b492166895a5d8b4428e3ae9486..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 787242 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 x=w3@Ej!B?vRAbXA_Q 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

    ${S75Afa1&)BkDPc0N}IK6JU) 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

    +Q;fd+wr~axoWea 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�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ⅈ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 diff --git a/libs/network/doc/html/_static/contents.png b/libs/network/doc/html/_static/contents.png index 7fb82154a1748d507925865d3fbf7508d62483e5..b8725d36a9c2429ef5a539775a076a9f252ddaea 100644 GIT binary patch delta 85 zcmV-b0IL7W0dtTfPdZ6NK~#9!b;er`01ylXQTtyodi$WHf`s`vnUslI0E|Oi`BA|R rU(iM*zysc>2J%1;%&~>tG;h)YVCbEsukOo@00000NkvXXu0mjf4kjeR delta 173 zcmXRu#W+Ewp0PN{-HBn{IhmIX3=EtF9+AZi4BWyX%*Zfnjs#GUy~NYkmHh@Iuc(;0 zbM=-pKq1Kz*N775{M_8syb=cIqSVBa)D(sC%#sWRcTeAd@J2pypdxcm7sn8e>q~nr z`4|)!4n_U@A1ACHd!?dBPsM?GN>nsMlaLgPx+2qJ3s;#F^K@6|e>*%kU;ItX%LmI? Vy(g^X7X+HY;OXk;vd$@?2>`BJH8cPK diff --git a/libs/network/doc/html/_static/file.png b/libs/network/doc/html/_static/file.png index d18082e397e7e54f20721af768c4c2983258f1b4..4d6c7e7768fedd6d181e4eab4f3c32233834d64e 100644 GIT binary patch delta 296 zcmV+@0oVSB1GoZ^8Gi!+001a04^sdD0B=xCR7C&)0D*ylm6es5nVFT9m1uK>X>^8d zd5>*+l5TsFZhMn*pU;7TfrgBfiIk#=n5~JKu8Nwknz-1g!py+b#KgqJ#l^+O#>U6T z$Li|p>+9?6?CkCBW}0US|u z008`nFaa53ttH}+!91tw6?<><1lVO|pK|8hc61^ZT|eiCGF9(`)4f+1;qh67(fvDEhv1eJ8B5z|D(=6?jwT?@G*xx{!8|7v!a z`RAJ*84Ly&S(Y8pPKRL_o&yj?k!hWIP^Jc2 zYmy`>H54Tx^m@I@E>7_g1VJM~ot$D}kziJH5%|7eGw~f`7O*UGAGHtxw@&0P_ z3IJPcpX_XQxp8@XAxYJ=@cw!9I|0D(cF5_SAR>(4t^u$Ymtmj^o`nO-iXV{!3p~ Wt8{-jMt;Wt0000)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, -Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& -(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, -a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== -"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, -function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
    a"; -var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, -parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= -false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= -s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, -applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; -else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, -a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== -w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, -cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= -c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); -a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, -function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); -k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), -C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= -e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& -f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; -if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", -e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, -"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, -d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, -e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); -t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| -g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, -CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, -g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, -text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, -setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= -h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== -"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, -h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& -q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; -if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

    ";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); -(function(){var g=s.createElement("div");g.innerHTML="
    ";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: -function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= -{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== -"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", -d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? -a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== -1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
    ","
    "];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, -""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); -return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", -""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= -c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? -c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= -function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= -Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, -"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= -a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= -a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== -"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
    ").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, -serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), -function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, -global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& -e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? -"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== -false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= -false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", -c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| -d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); -g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== -1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== -"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; -if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== -"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| -c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; -this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= -this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, -e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
    "; -a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); -c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, -d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- -f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": -"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in -e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z])/ig, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.6.2", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery._Deferred(); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return (new Function( "return " + data ))(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + // (xml & tmp used internally) + parseXML: function( data , xml , tmp ) { + + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + + tmp = xml.documentElement; + + if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { + jQuery.error( "Invalid XML: " + data ); + } + + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Converts a dashed string to camelCased string; + // Used by both the css and data modules + camelCase: function( string ) { + return string.replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + + if ( indexOf ) { + return indexOf.call( array, elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +var // Promise methods + promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ), + // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + // make sure args are available (#8421) + args = args || []; + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + always: function() { + return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + pipe: function( fnDone, fnFail ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject ); + } else { + newDefer[ action ]( returned ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + }); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = arguments, + i = 0, + length = args.length, + count = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + // Strange bug in FF4: + // Values changed onto the arguments object sometimes end up as undefined values + // outside the $.when method. Cloning the object into a fresh array solves the issue + deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); + } + }; + } + if ( length > 1 ) { + for( ; i < length; i++ ) { + if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return deferred.promise(); + } +}); + + + +jQuery.support = (function() { + + var div = document.createElement( "div" ), + documentElement = document.documentElement, + all, + a, + select, + opt, + input, + marginDiv, + support, + fragment, + body, + testElementParent, + testElement, + testElementStyle, + tds, + events, + eventName, + i, + isSupported; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
    a"; + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName( "tbody" ).length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName( "link" ).length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute( "href" ) === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains it's value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + div.innerHTML = ""; + + // Figure out if the W3C box model works as expected + div.style.width = div.style.paddingLeft = "1px"; + + body = document.getElementsByTagName( "body" )[ 0 ]; + // We use our own, invisible, body unless the body is already present + // in which case we use a div (#9239) + testElement = document.createElement( body ? "div" : "body" ); + testElementStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0 + }; + if ( body ) { + jQuery.extend( testElementStyle, { + position: "absolute", + left: -1000, + top: -1000 + }); + } + for ( i in testElementStyle ) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild( div ); + testElementParent = body || documentElement; + testElementParent.insertBefore( testElement, testElementParent.firstChild ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
    "; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.innerHTML = "
    t
    "; + tds = div.getElementsByTagName( "td" ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( document.defaultView && document.defaultView.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Remove the body element we added + testElement.innerHTML = ""; + testElementParent.removeChild( testElement ); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + } ) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + // Null connected elements to avoid leaks in IE + testElement = fragment = select = opt = body = marginDiv = div = input = null; + + return support; +})(); + +// Keep track of boxModel +jQuery.boxModel = jQuery.support.boxModel; + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([a-z])([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + return getByName ? + // Check for both converted-to-camel and non-converted data property names + thisCache[ jQuery.camelCase( name ) ] || thisCache[ name ] : + thisCache; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !isEmptyDataObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + if ( jQuery.support.deleteExpando || cache != window ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON +// property to be considered empty objects; this property always exists in +// order to make sure JSON.stringify does not expose internal metadata +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery.data( elem, deferDataKey, undefined, true ); + if ( defer && + ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) && + ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery.data( elem, queueDataKey, undefined, true ) && + !jQuery.data( elem, markDataKey, undefined, true ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.resolve(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = (type || "fx") + "mark"; + jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); + if ( count ) { + jQuery.data( elem, key, count, true ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + if ( elem ) { + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type, undefined, true ); + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data), true ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + defer; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { + count++; + tmp.done( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + rinvalidChar = /\:|^on/, + formHook, boolHook; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = (value || "").split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return undefined; + } + + var isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attrFix: { + // Always normalize to ensure hook usage + tabindex: "tabIndex" + }, + + attr: function( elem, name, value, pass ) { + var nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( !("getAttribute" in elem) ) { + return jQuery.prop( elem, name, value ); + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // Normalize the name if needed + if ( notxml ) { + name = jQuery.attrFix[ name ] || name; + + hooks = jQuery.attrHooks[ name ]; + + if ( !hooks ) { + // Use boolHook for boolean attributes + if ( rboolean.test( name ) ) { + + hooks = boolHook; + + // Use formHook for forms and if the name contains certain characters + } else if ( formHook && name !== "className" && + (jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ) { + + hooks = formHook; + } + } + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return undefined; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, name ) { + var propName; + if ( elem.nodeType === 1 ) { + name = jQuery.attrFix[ name ] || name; + + if ( jQuery.support.getSetAttribute ) { + // Use removeAttribute in browsers that support it + elem.removeAttribute( name ); + } else { + jQuery.attr( elem, name, "" ); + elem.removeAttributeNode( elem.getAttributeNode( name ) ); + } + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) { + elem[ propName ] = false; + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabIndex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + }, + // Use the value property for back compat + // Use the formHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( formHook && jQuery.nodeName( elem, "button" ) ) { + return formHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( formHook && jQuery.nodeName( elem, "button" ) ) { + return formHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return (elem[ name ] = value); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: {} +}); + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + return jQuery.prop( elem, name ) ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !jQuery.support.getSetAttribute ) { + + // propFix is more comprehensive and contains all fixes + jQuery.attrFix = jQuery.propFix; + + // Use this for any attribute on a form in IE6/7 + formHook = jQuery.attrHooks.name = jQuery.attrHooks.title = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + // Return undefined if nodeValue is empty string + return ret && ret.nodeValue !== "" ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Check form objects in IE (multiple bugs related) + // Only use nodeValue if the attribute node exists on the form + var ret = elem.getAttributeNode( name ); + if ( ret ) { + ret.nodeValue = value; + return value; + } + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return (elem.style.cssText = "" + value); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }); +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0); + } + } + }); +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspaces = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } else if ( !handler ) { + // Fixes bug #7229. Fix recommended by jdalton + return; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery._data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events, + eventHandle = elemData.handle; + + if ( !events ) { + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem, undefined, true ); + } + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Event object or event type + var type = event.type || event, + namespaces = [], + exclusive; + + if ( type.indexOf("!") >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.exclusive = exclusive; + event.namespace = namespaces.join("."); + event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); + + // triggerHandler() and global events don't bubble or run the default action + if ( onlyHandlers || !elem ) { + event.preventDefault(); + event.stopPropagation(); + } + + // Handle a global trigger + if ( !elem ) { + // TODO: Stop taunting the data cache; remove global events and always attach to document + jQuery.each( jQuery.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = jQuery.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[ type ] ) { + jQuery.event.trigger( event, data, internalCache.handle.elem ); + } + }); + return; + } + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + event.target = elem; + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + var cur = elem, + // IE doesn't like method names with a colon (#3533, #8272) + ontype = type.indexOf(":") < 0 ? "on" + type : ""; + + // Fire event on the current element, then bubble up the DOM tree + do { + var handle = jQuery._data( cur, "handle" ); + + event.currentTarget = cur; + if ( handle ) { + handle.apply( cur, data ); + } + + // Trigger an inline bound script + if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { + event.result = false; + event.preventDefault(); + } + + // Bubble up to document, then to window + cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; + } while ( cur && !event.isPropagationStopped() ); + + // If nobody prevented the default action, do it now + if ( !event.isDefaultPrevented() ) { + var old, + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction)() check here because IE6/7 fails that test. + // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. + try { + if ( ontype && elem[ type ] ) { + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + jQuery.event.triggered = type; + elem[ type ](); + } + } catch ( ieError ) {} + + if ( old ) { + elem[ ontype ] = old; + } + + jQuery.event.triggered = undefined; + } + } + + return event.result; + }, + + handle: function( event ) { + event = jQuery.event.fix( event || window.event ); + // Snapshot the handlers list since a called handler may add/remove events. + var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), + run_all = !event.exclusive && !event.namespace, + args = Array.prototype.slice.call( arguments, 0 ); + + // Use the fix-ed Event rather than the (read-only) native event + args[0] = event; + event.currentTarget = this; + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Triggered event must 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event. + if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + // Fixes #1925 where srcElement might not be defined either + event.target = event.srcElement || document; + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var eventDocument = event.target.ownerDocument || document, + doc = eventDocument.documentElement, + body = eventDocument.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + + // Check if mouse(over|out) are still within the same parent element + var related = event.relatedTarget, + inside = false, + eventType = event.type; + + event.type = event.data; + + if ( related !== this ) { + + if ( related ) { + inside = jQuery.contains( this, related ); + } + + if ( !inside ) { + + jQuery.event.handle.apply( this, arguments ); + + event.type = eventType; + } + } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( !jQuery.nodeName( this, "form" ) ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( jQuery.nodeName( elem, "select" ) ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery._data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery._data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) { + testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery._data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + // Don't pass args or remember liveFired; they apply to the donor event. + var event = jQuery.extend( {}, args[ 0 ] ); + event.type = type; + event.originalEvent = {}; + event.liveFired = undefined; + jQuery.event.handle.call( elem, event ); + if ( event.isDefaultPrevented() ) { + args[ 0 ].preventDefault(); + } +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + + function handler( donor ) { + // Donor event is always a native one; fix it and switch its type. + // Let focusin/out handler cancel the donor focus/blur event. + var e = jQuery.event.fix( donor ); + e.type = fix; + e.originalEvent = {}; + jQuery.event.trigger( e, null, e.target ); + if ( e.isDefaultPrevented() ) { + donor.preventDefault(); + } + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + var handler; + + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( arguments.length === 2 || data === false ) { + fn = data; + data = undefined; + } + + if ( name === "one" ) { + handler = function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }; + handler.guid = fn.guid || jQuery.guid++; + } else { + handler = fn; + } + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( name === "die" && !types && + origSelector && origSelector.charAt(0) === "." ) { + + context.unbind( origSelector ); + + return this; + } + + if ( data === false || jQuery.isFunction( data ) ) { + fn = data || returnFalse; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( liveMap[ type ] ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + elems = [], + selectors = [], + events = jQuery._data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) + if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + + // Make sure not to accidentally match a child element with the same selector + if ( related && jQuery.contains( elem, related ) ) { + related = elem; + } + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var match, + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var found, item, + filter = Expr.filter[ type ], + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + var first = match[2], + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

    "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
    "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( typeof selector === "string" ? + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[ selector ] ) { + matches[ selector ] = POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[ selector ]; + + if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /", "" ], + legend: [ 1, "
    ", "
    " ], + thead: [ 1, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + col: [ 2, "", "
    " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and + + + + + + + + + + + + +
    +
    +
    +

    cpp-netlib v0.9.3 documentation

    + +
    + +
    +
    +
    +
    + +
    +

    Atom reader

    +
    +

    The code

    +
    #include "atom.hpp"
    +#include <boost/network/protocol/http/client.hpp>
    +#include <boost/foreach.hpp>
    +#include <iostream>
    +
    +int main(int argc, char * argv[]) {
    +    using namespace boost::network;
    +
    +    if (argc != 2) {
    +        std::cout << "Usage: " << argv[0] << " <url>" << std::endl;
    +        return 1;
    +    }
    +
    +    try {
    +        http::client client;
    +        http::client::request request(argv[1]);
    +        request << header("Connection", "close");
    +        http::client::response response = client.get(request);
    +        atom::feed feed(response);
    +
    +        std::cout << "Feed: " << feed.title()
    +                  << " (" << feed.subtitle() << ")" << std::endl;
    +        BOOST_FOREACH(const atom::entry &entry, feed) {
    +            std::cout << entry.title()
    +                      << " (" << entry.published() << ")" << std::endl;
    +        }
    +    }
    +    catch (std::exception &e) {
    +        std::cerr << e.what() << std::endl;
    +    }
    +
    +    return 0;
    +}
    +
    +
    +
    +
    +

    Diving into the code

    +
    +
    + + +
    +
    +
    + + + +
    + +
    + +
    +
    + +
    +
    + + + + \ No newline at end of file diff --git a/libs/network/doc/html/directives.html b/libs/network/doc/html/directives.html index 1a200b0e9..f4094a2bd 100644 --- a/libs/network/doc/html/directives.html +++ b/libs/network/doc/html/directives.html @@ -7,13 +7,13 @@ - Directives — cpp-netlib v0.9 documentation + Directives — cpp-netlib v0.9.3 documentation - + @@ -46,7 +46,7 @@

    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 z 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 z zxm`lLsXYP6tm0_Nx9)rngOGlesv}@yDNv`Xlh4+iuE8WlBLKvDFU$3;>{1XO2Gg95 zO)CRq#~9CH`kER9Ng9^~FRfCGWH({z0LcF7{#?^q36lri{^=lom8I@ORw0qbS$(-R z7cC+LU{Ob|59TUTESV%lz+=~e{OZvS4Z4)bRx`qp)~(9n2-vl01S<#)z{du<>7{K< zs!88LrbaGEthwJplF*LcGO?a{-OUkt4ZTT2g6uKIMkrFdCd9<5a~EeJi4!9_CY<=uHL;Z-I_~O6a8(VkfvsG%x@L4)K6}=&3ajQF1fPW!=U)bDynn za$TJ~)+ILRum)~}uhzA6l2;?1?0%gT3oOe&C=?O(IjwNejo&d9r7JE{Id1mAV_v!7 z`&Lt`lx&NQJ#JP~Bl(-FbsqJ`k+am6*@$*w{40=s>!yyHkv*(6uOyRdW9M^MDvnOb zN(pK!+b-Nb0W~g_tWucNxLwTHIIc3hIcZ38$yq;X32W9TuRrjRao1J~#e{{UX4&g^#3mO&gVg*kkT z{&=SBiCT^z?A*Mu$-wu`IG|+EN)|<8K0q)B`&`#mHfGSW&I`P)*x)GZil+6rMRXYj z+ey3;f(8@uG%4K;#>Inb(kc)>T<&A|RjO^1%#h*)DU6^pO?uPs-S$L9QNW~^kL!BCrkKZGecH4%;2IcQD;H2e&ba6XkuUPNq-OL+W% z2>vYowdhi&ppH4qn1=nLXm&CAiR63K)=8r2CwrX5?YukkycJWCUR zaIcOk;SS|CB(mGZ3jmv$aCdj-710|YNwb{RJW`f2ypTpb(aUG2L;e(dTRWq+mLHpQ z!#*SU#^&!*oxjyXBX4CKWc<6a`BIO(?se7u+)_NEOOHO}Jcqa$uGp(1#GJXMsp`HT zI%Kxd%&5DSeL5CVoYOj0JDHw4)1%ex(r5rzQZfhq^G^Dh)unWC8t;TJG}s}WA2K;( z4oK{Baz9GZHn%vcP}4)2HKD>ciev{A0J!y_X$yf!s|OSeZ~~D@3P9^X+8q*td8FA? z<8nh7>?&?<>7rO79QxGBn$e_bSioLo7|+(Zs!GW9Xi|4K(#=r;VZbLJjd8hL?Xf!A zAOL6a^&+x!V9}vxW4W+bkMYezkgRk*9JGol-LMV_P=6fOa&3)hcG_*g5|(4eG6%Iu zoQ{Ux<@Ywugk$k0tDMEezx}GwKq8T{bA$9Ew}jn{T|I7OUc1c;E^t6OKj-N~X7ERf zd}FeX&gQ{GhBL%wm%+zhCv(*d}a85_$NUW+x$4ni`p`1n)PuD*A z&2uzp)rqwm+naqe&4_h45A`{yj8`>=wkcd(&hl@Jd9jRcKj-OG;*qVaS+JHtC@h

    -
    +

    Todo

    An example using a directive.

    @@ -166,7 +166,7 @@

    Browse

    You are here:

    • - cpp-netlib v0.9 documentation + cpp-netlib v0.9.3 documentation
      • Techniques diff --git a/libs/network/doc/html/examples.html b/libs/network/doc/html/examples.html index a4adc6ea8..503ade016 100644 --- a/libs/network/doc/html/examples.html +++ b/libs/network/doc/html/examples.html @@ -7,13 +7,13 @@ - Examples — cpp-netlib v0.9 documentation + Examples — cpp-netlib v0.9.3 documentation - + - + @@ -46,7 +46,7 @@
        -

        cpp-netlib v0.9 documentation

        +

        cpp-netlib v0.9.3 documentation

    -
    -

    Wrappers

    +
    +

    Wrappers

    This section details the provided request wrappers that come with cpp-netlib. Wrappers are used to convert a message into a different type, usually providing accessor operations to retrieve just part of the message. This @@ -428,7 +431,7 @@

    Browse

    You are here:

    +

    Last update:

    +

    Feb 05, 2013

    diff --git a/libs/network/doc/html/reference/http_response.html b/libs/network/doc/html/reference/http_response.html index f6cc61c5f..379313d6a 100644 --- a/libs/network/doc/html/reference/http_response.html +++ b/libs/network/doc/html/reference/http_response.html @@ -1,19 +1,21 @@ - + - HTTP Response — cpp-netlib v0.9.4 + HTTP Response — cpp-netlib v0.9.5 + + - + @@ -43,10 +45,11 @@ +
    -

    cpp-netlib v0.9.4

    +

    cpp-netlib v0.9.5