diff --git a/boost/network/protocol/http/request/request.hpp b/boost/network/protocol/http/request/request.hpp index 641324e53..a506d63ab 100644 --- a/boost/network/protocol/http/request/request.hpp +++ b/boost/network/protocol/http/request/request.hpp @@ -18,8 +18,6 @@ namespace boost { namespace network { namespace http { struct request_pimpl; struct request : request_base { - // FIXME Implement all these! - // We support full value semantics. request(); explicit request(std::string const & url); @@ -27,6 +25,7 @@ struct request : request_base { request(request const &); request& operator=(request); void swap(request & other); + bool equals(request const &other) const; // From message_base... // Mutators @@ -82,6 +81,14 @@ inline void swap(request &l, request &r) { l.swap(r); } +inline bool operator==(request const &l, request const &r) { + return l.equals(r); +} + +inline bool operator!=(request const &l, request const &r) { + return !l.equals(r); +} + } // namespace http } // namespace network diff --git a/boost/network/protocol/http/request/request.ipp b/boost/network/protocol/http/request/request.ipp index fe5e04ad8..930e0a4f6 100644 --- a/boost/network/protocol/http/request/request.ipp +++ b/boost/network/protocol/http/request/request.ipp @@ -27,7 +27,7 @@ struct request_pimpl { , headers_() {} - request_pimpl* clone() { + request_pimpl* clone() const { return new (std::nothrow) request_pimpl(*this); } @@ -94,6 +94,13 @@ struct request_pimpl { read_offset_ += bytes; } + bool equals(request_pimpl const &other) const { + return uri_ == other.uri_ && + read_offset_ == other.read_offset_ && + source_ == other.source_ && + headers_ == other.headers_; + } + private: typedef std::multimap headers_type; @@ -130,6 +137,11 @@ request& request::operator=(request rhs) { rhs.swap(*this); } +bool request::equals(request const &other) const { + return pimpl_->equals(*other.pimpl_) && + request_storage_base::equals(other); +} + void request::swap(request & other) { std::swap(this->pimpl_, other.pimpl_); } diff --git a/boost/network/protocol/http/request/request_base.hpp b/boost/network/protocol/http/request/request_base.hpp index c7e37f662..4837dd1db 100644 --- a/boost/network/protocol/http/request/request_base.hpp +++ b/boost/network/protocol/http/request/request_base.hpp @@ -31,6 +31,7 @@ struct request_storage_base { virtual size_t read(char *destination, size_t offset, size_t size) const; virtual void flatten(std::string &destination) const; virtual void clear(); + virtual bool equals(request_storage_base const &other) const; virtual ~request_storage_base(); private: diff --git a/boost/network/protocol/http/request/request_base.ipp b/boost/network/protocol/http/request/request_base.ipp index 409c9f49d..ea702fb5a 100644 --- a/boost/network/protocol/http/request/request_base.ipp +++ b/boost/network/protocol/http/request/request_base.ipp @@ -24,6 +24,7 @@ struct request_storage_base_pimpl { size_t read(char *destination, size_t offset, size_t size) const; void flatten(std::string &destination) const; void clear(); + bool equals(request_storage_base_pimpl const &other) const; ~request_storage_base_pimpl(); private: @@ -63,6 +64,10 @@ void request_storage_base::clear() { pimpl_->clear(); } +bool request_storage_base::equals(request_storage_base const &other) const { + return pimpl_->equals(*other.pimpl_); +} + request_storage_base_pimpl::request_storage_base_pimpl(size_t chunk_size) : chunk_size_(chunk_size) , chunks_() @@ -154,6 +159,19 @@ void request_storage_base_pimpl::clear() { chunks_vector().swap(chunks_); } +bool request_storage_base_pimpl::equals(request_storage_base_pimpl const &other) const { + if (other.chunk_size_ != chunk_size_) return false; + if (other.chunks_.size() != chunks_.size()) return false; + chunks_vector::const_iterator chunk_iterator = chunks_.begin(); + chunks_vector::const_iterator other_iterator = other.chunks_.begin(); + for (; chunk_iterator != chunks_.begin() && other_iterator != other.chunks_.end(); + ++chunk_iterator, ++other_iterator) { + if (chunk_iterator->second != other_iterator->second) return false; + if (strncmp(chunk_iterator->first, other_iterator->first, chunk_iterator->second)) return false; + } + return true; +} + request_storage_base_pimpl::~request_storage_base_pimpl() { clear(); } diff --git a/libs/network/test/http/request_test.cpp b/libs/network/test/http/request_test.cpp index 225417f82..0d2e389a7 100644 --- a/libs/network/test/http/request_test.cpp +++ b/libs/network/test/http/request_test.cpp @@ -18,6 +18,30 @@ BOOST_AUTO_TEST_CASE(request_construction) { http::request other(request); } +BOOST_AUTO_TEST_CASE(request_value_semantics) { + // First let's default construct a request. + http::request original; + // Next let's copy the request. + http::request copy(original); + // Next let's compare the requests. + BOOST_CHECK(original == copy); + // Next let's assign the original to another request. + http::request assigned; + assigned = original; + // Next we modify the assigned object and make sure it's not the same as the + // original. + assigned.set_uri("http://www.google.com/"); + std::string original_uri, assigned_uri; + original.get_uri(original_uri); + assigned.get_uri(assigned_uri); + BOOST_CHECK_NE(original_uri, assigned_uri); + BOOST_CHECK(original != assigned); + // Next we swap the assigned and copy. + std::swap(assigned, copy); + BOOST_CHECK(copy != assigned); + BOOST_CHECK(assigned == original); +} + BOOST_AUTO_TEST_CASE(request_uri_test) { http::request request; request.set_uri("http://www.google.com/");