Skip to content

Commit 855349b

Browse files
authored
Merge pull request #163 from jgaa/boost-1.87-fixes
Boost 1.87 fixes Closes #161 #162
2 parents 5470ee3 + ba9ddd4 commit 855349b

32 files changed

+394
-137
lines changed

CMakeLists.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ if (DEFINED ENV{RESTC_CPP_VERSION})
55
endif()
66

77
if (NOT DEFINED RESTC_CPP_VERSION)
8-
set(RESTC_CPP_VERSION 0.101.1)
8+
set(RESTC_CPP_VERSION 0.102.0)
99
endif()
1010

1111
if(NOT DEFINED RESTC_BOOST_VERSION)
@@ -38,6 +38,8 @@ option(RESTC_CPP_AUTORUN_UNIT_TESTS "Run Unit Tests automatically after build" O
3838

3939
option(RESTC_CPP_WITH_FUNCTIONALT_TESTS "Enable Functional Testing" ON)
4040

41+
option(RESTC_USE_LEGACY_BOOST_FIND "Use the old Boost find module" OFF)
42+
4143
set(GTEST_TAG "main" CACHE STRING "Gtest branch to use. Required on older Linux versions because newer gtest requure newer cmake!")
4244
set(LOGFAULT_TAG "master" CACHE STRING "Logfault branch to use. Required on older Linux versions because newer gtest requure newer cmake!")
4345

@@ -218,6 +220,7 @@ set(ACTUAL_SOURCES
218220
src/RequestBodyStringImpl.cpp
219221
src/RequestBodyFileImpl.cpp
220222
src/url_encode.cpp
223+
src/boost_compitability.cpp
221224
${LOGGING_SRC}
222225
)
223226

@@ -248,7 +251,10 @@ endif()
248251

249252
if (NOT EMBEDDED_RESTC_CPP)
250253

251-
if(CMAKE_VERSION VERSION_GREATER "3.28")
254+
if (RESTC_USE_LEGACY_BOOST_FIND)
255+
unset(restc_cpp_boost_find_config)
256+
message("Using legacy Boost find config")
257+
elseif(CMAKE_VERSION VERSION_GREATER "3.28")
252258
set(restc_cpp_boost_find_config CONFIG)
253259
message("Using new Boost find config")
254260
endif()

ci/jenkins/Jenkinsfile.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pipeline {
44
agent { label 'main' }
55

66
environment {
7-
RESTC_CPP_VERSION = "0.101.0"
7+
RESTC_CPP_VERSION = "0.102.0"
88

99
// It is not possible to get the current IP number when running in the sandbox, and
1010
// Jenkinsfiles always runs in the sandbox.

examples/logip/logip.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
#include <boost/log/expressions.hpp>
2121
#endif
2222

23+
#include <boost/exception/all.hpp>
24+
#include <boost/exception/diagnostic_information.hpp>
25+
2326
#include "restc-cpp/restc-cpp.h"
2427
#include "restc-cpp/RequestBuilder.h"
2528
#include "restc-cpp/SerializeJson.h"

include/restc-cpp/DataReader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class DataReader {
4444
virtual ~DataReader() = default;
4545

4646
virtual bool IsEof() const = 0;
47-
virtual boost::asio::const_buffers_1 ReadSome() = 0;
47+
virtual boost_const_buffer ReadSome() = 0;
4848
virtual void Finish() = 0; // Make sure there are no pending data for the current request
4949

5050
static ptr_t CreateIoReader(const Connection::ptr_t& conn,

include/restc-cpp/DataReaderStream.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ class DataReaderStream : public DataReader {
3434
}
3535

3636
/*! Read whatever we have buffered or can get downstream */
37-
boost::asio::const_buffers_1 ReadSome() override;
37+
boost_const_buffer ReadSome() override;
3838

3939
/*! Read up to maxBytes from whatever we have buffered or can get downstream.*/
40-
boost::asio::const_buffers_1 GetData(size_t maxBytes);
40+
boost_const_buffer GetData(size_t maxBytes);
4141

4242
/*! Get one char
4343
*

include/restc-cpp/DataWriter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ class DataWriter {
4444
virtual ~DataWriter() = default;
4545

4646
/*! Write some data */
47-
virtual void Write(boost::asio::const_buffers_1 buffers) = 0;
47+
virtual void Write(boost_const_buffer buffers) = 0;
4848

4949
/*! Write without altering the data (headers) */
50-
virtual void WriteDirect(boost::asio::const_buffers_1 buffers) = 0;
50+
virtual void WriteDirect(boost_const_buffer buffers) = 0;
5151

5252
/*! Write some data */
5353
virtual void Write(const write_buffers_t& buffers) = 0;

include/restc-cpp/RapidJsonReader.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <assert.h>
88

9+
#include "restc-cpp/boost_compatibility.h"
910
#include "rapidjson/reader.h"
1011
#include "restc-cpp/restc-cpp.h"
1112

@@ -96,7 +97,7 @@ class RapidJsonReader {
9697
const auto len = boost::asio::buffer_size(buffer);
9798

9899
if (len) {
99-
ch_ = boost::asio::buffer_cast<const char*>(buffer);
100+
ch_ = boost_buffer_cast(buffer);
100101
end_ = ch_ + len;
101102
} else {
102103
ch_ = end_ = nullptr;

include/restc-cpp/Socket.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <boost/system/error_code.hpp>
1313

14+
#include "restc-cpp/boost_compatibility.h"
1415
#include "restc-cpp/typename.h"
1516
#include "restc-cpp/logging.h"
1617

@@ -34,21 +35,21 @@ class Socket
3435

3536
virtual const boost::asio::ip::tcp::socket& GetSocket() const = 0;
3637

37-
virtual std::size_t AsyncReadSome(boost::asio::mutable_buffers_1 buffers,
38+
virtual std::size_t AsyncReadSome(boost_mutable_buffer buffers,
3839
boost::asio::yield_context& yield) = 0;
3940

40-
virtual std::size_t AsyncRead(boost::asio::mutable_buffers_1 buffers,
41+
virtual std::size_t AsyncRead(boost_mutable_buffer buffers,
4142
boost::asio::yield_context& yield) = 0;
4243

43-
virtual void AsyncWrite(const boost::asio::const_buffers_1& buffers,
44+
virtual void AsyncWrite(const boost_const_buffer& buffers,
4445
boost::asio::yield_context& yield) = 0;
4546

4647
virtual void AsyncWrite(const write_buffers_t& buffers,
4748
boost::asio::yield_context& yield) = 0;
4849

4950
template <typename T>
5051
void AsyncWriteT(const T& buffer, boost::asio::yield_context& yield) {
51-
boost::asio::const_buffers_1 b{buffer.data(), buffer.size()};
52+
boost_const_buffer b{buffer.data(), buffer.size()};
5253
AsyncWrite(b, yield);
5354
}
5455

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
#pragma once
2+
3+
#include <boost/asio.hpp>
4+
#include <boost/version.hpp>
5+
#include <boost/asio/ip/address_v4.hpp>
6+
7+
/**
8+
* @file
9+
* @brief Compatibility layer for handling breaking changes in Boost.Asio across versions.
10+
*
11+
* Boost frequently introduces breaking changes in its Asio library, with a backward
12+
* compatibility window of about 5 years. This header helps maintain compatibility with
13+
* multiple Boost versions, making it easier to support older versions without requiring
14+
* extensive refactoring.
15+
*/
16+
17+
#if BOOST_VERSION >= 107000
18+
#include <boost/coroutine/exceptions.hpp>
19+
/// Macro for catching exceptions in Boost Coroutine, ensuring required handling for `forced_unwind`.
20+
#define RESTC_CPP_IN_COROUTINE_CATCH_ALL \
21+
catch (boost::coroutines::detail::forced_unwind const&) { \
22+
throw; /* required for Boost Coroutine! */ \
23+
} catch (...)
24+
#elif BOOST_VERSION >= 106000
25+
#include <boost/coroutine2/detail/forced_unwind.hpp>
26+
/// Macro for catching exceptions in Boost Coroutine, ensuring required handling for `forced_unwind`.
27+
#define RESTC_CPP_IN_COROUTINE_CATCH_ALL \
28+
catch (boost::coroutines::detail::forced_unwind const&) { \
29+
throw; /* required for Boost Coroutine! */ \
30+
} catch (...)
31+
#else
32+
static_assert(false, "Unsupported boost version");
33+
catch (...)
34+
#endif
35+
36+
#if BOOST_VERSION >= 108100
37+
/// Macro for handling function signature changes in Boost 1.86 and later.
38+
#define RESTC_CPP_SPAWN_TRAILER \
39+
, boost::asio::detached
40+
#else
41+
#define RESTC_CPP_SPAWN_TRAILER
42+
#endif
43+
44+
45+
namespace restc_cpp {
46+
47+
#if BOOST_VERSION >= 107000
48+
/// Type alias for constant buffer in Boost 1.70 and later.
49+
using boost_const_buffer = boost::asio::const_buffer;
50+
/// Type alias for mutable buffer in Boost 1.70 and later.
51+
using boost_mutable_buffer = boost::asio::mutable_buffer;
52+
#else
53+
/// Type alias for constant buffer in Boost versions earlier than 1.70.
54+
using boost_const_buffer = boost::asio::const_buffers_1;
55+
/// Type alias for mutable buffer in Boost versions earlier than 1.70.
56+
using boost_mutable_buffer = boost::asio::mutable_buffers_1;
57+
#endif
58+
59+
#if BOOST_VERSION >= 106600
60+
/// Type alias for IO service in Boost 1.66 and later.
61+
using boost_io_service = boost::asio::io_context;
62+
/// Type alias for work guard in Boost 1.66 and later.
63+
using boost_work = boost::asio::executor_work_guard<boost::asio::io_context::executor_type>;
64+
#else
65+
/// Type alias for IO service in Boost versions earlier than 1.66.
66+
using boost_io_service = boost::asio::io_service;
67+
/// Type alias for work guard in Boost versions earlier than 1.66.
68+
using boost_work = boost::asio::io_service::work;
69+
#endif
70+
71+
/**
72+
* @brief Extracts a const char pointer from a Boost buffer.
73+
*
74+
* @tparam Buffer The type of the buffer.
75+
* @param buffer The buffer to extract the pointer from.
76+
* @return A const char pointer to the data in the buffer.
77+
*/
78+
template <typename Buffer>
79+
const char* boost_buffer_cast(const Buffer& buffer) {
80+
#if BOOST_VERSION >= 107000
81+
return static_cast<const char*>(buffer.data());
82+
#else
83+
return boost::asio::buffer_cast<const char*>(buffer);
84+
#endif
85+
}
86+
87+
/**
88+
* @brief Retrieves the size of a Boost buffer.
89+
*
90+
* @tparam Buffer The type of the buffer.
91+
* @param buffer The buffer to measure.
92+
* @return The size of the buffer in bytes.
93+
*/
94+
template <typename Buffer>
95+
std::size_t boost_buffer_size(const Buffer& buffer) {
96+
#if BOOST_VERSION >= 107000
97+
return buffer.size();
98+
#else
99+
return boost::asio::buffer_size(buffer);
100+
#endif
101+
}
102+
103+
/**
104+
* @brief Dispatches a handler to the IO service.
105+
*
106+
* @tparam IOService The type of the IO service.
107+
* @tparam Handler The type of the handler.
108+
* @param io_service The IO service to use.
109+
* @param handler The handler to dispatch.
110+
*/
111+
template <typename IOService, typename Handler>
112+
void boost_dispatch(IOService *io_service, Handler&& handler) {
113+
#if BOOST_VERSION >= 106600
114+
io_service->get_executor().dispatch(
115+
std::forward<Handler>(handler),
116+
std::allocator<void>() // Default allocator
117+
);
118+
#else
119+
io_service->dispatch(std::forward<Handler>(handler));
120+
#endif
121+
}
122+
123+
/**
124+
* @brief Wrapper for Boost resolver results for compatibility with older Boost versions.
125+
*
126+
* @tparam Iterator The type of the iterator used for results.
127+
*/
128+
template <typename Iterator>
129+
class ResolverResultsWrapper {
130+
public:
131+
/**
132+
* @brief Constructor.
133+
* @param begin The beginning iterator of the results.
134+
* @param end The end iterator of the results.
135+
*/
136+
explicit ResolverResultsWrapper(const Iterator& begin, const Iterator& end)
137+
: begin_(begin), end_(end) {}
138+
139+
/**
140+
* @brief Returns the beginning iterator of the results.
141+
* @return The beginning iterator.
142+
*/
143+
Iterator begin() const { return begin_; }
144+
145+
/**
146+
* @brief Returns the end iterator of the results.
147+
* @return The end iterator.
148+
*/
149+
Iterator end() const { return end_; }
150+
151+
private:
152+
Iterator begin_;
153+
Iterator end_;
154+
};
155+
156+
template <typename Resolver, typename YieldContext>
157+
#if BOOST_VERSION >= 106600
158+
/// Type alias for resolver results in Boost 1.66 and later.
159+
using ResolverResults = boost::asio::ip::tcp::resolver::results_type;
160+
#else
161+
/// Type alias for resolver results in Boost versions earlier than 1.66.
162+
using ResolverResults = ResolverResultsWrapper<boost::asio::ip::tcp::resolver::iterator>;
163+
#endif
164+
165+
/**
166+
* @brief Resolves a host and service to endpoints, with compatibility for multiple Boost versions.
167+
*
168+
* @tparam Resolver The type of the resolver.
169+
* @tparam YieldContext The type of the yield context.
170+
* @param resolver The resolver to use for the operation.
171+
* @param host The host to resolve.
172+
* @param service The service to resolve.
173+
* @param yield The yield context for asynchronous operations.
174+
* @return The resolver results, wrapped if necessary for older Boost versions.
175+
*/
176+
template <typename Resolver, typename YieldContext>
177+
ResolverResults<Resolver, YieldContext> boost_resolve(
178+
Resolver& resolver,
179+
const std::string& host,
180+
const std::string& service,
181+
YieldContext yield)
182+
{
183+
#if BOOST_VERSION >= 107000
184+
return resolver.async_resolve(host, service, yield);
185+
#elif BOOST_VERSION >= 106600
186+
return resolver.async_resolve(host, service, yield);
187+
#else
188+
boost::asio::ip::tcp::resolver::query query(host, service);
189+
auto it = resolver.async_resolve(query, yield);
190+
auto end = boost::asio::ip::tcp::resolver::iterator();
191+
return ResolverResultsWrapper(it, end);
192+
#endif
193+
}
194+
195+
/**
196+
* @brief Creates a Boost endpoint from an IP address and port.
197+
* @param ip_address The IP address as a string.
198+
* @param port The port number.
199+
* @return A Boost TCP endpoint.
200+
*/
201+
boost::asio::ip::tcp::endpoint boost_create_endpoint(const std::string& ip_address, unsigned short port);
202+
203+
/**
204+
* @brief Converts an IPv4 address from string format to a 32-bit unsigned integer.
205+
* @param ip_address The IPv4 address as a string.
206+
* @return The IPv4 address as a 32-bit unsigned integer.
207+
*/
208+
uint32_t boost_convert_ipv4_to_uint(const std::string& ip_address);
209+
210+
/**
211+
* @brief Creates a work guard for the given IO service.
212+
* @param ioservice The IO service to manage.
213+
* @return A unique pointer to the work guard.
214+
*/
215+
std::unique_ptr<boost_work> boost_make_work(boost_io_service& ioservice);
216+
217+
} // namespace restc_cpp

include/restc-cpp/helper.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,17 @@ class ToBuffer
5959
{
6060
}
6161

62-
operator boost::asio::const_buffers_1 () const {
62+
#if BOOST_VERSION >= 107000
63+
// For Boost 1.70 and newer
64+
operator boost::asio::const_buffer() const {
65+
return {buf_.data(), buf_.size()};
66+
}
67+
#else
68+
// For Boost versions older than 1.70
69+
operator boost::asio::const_buffers_1() const {
6370
return {buf_.c_str(), buf_.size()};
6471
}
72+
#endif
6573

6674
operator const boost::string_ref() const {
6775
return buf_;

0 commit comments

Comments
 (0)