Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/cppalliance/http_proto
8 : //
9 :
10 : #ifndef SRC_SERVICE_STREAM_CAST_HPP
11 : #define SRC_SERVICE_STREAM_CAST_HPP
12 :
13 : #include <boost/http_proto/detail/config.hpp>
14 : #include <boost/http_proto/service/zlib_service.hpp>
15 : #include <zlib.h>
16 : #include <cstddef>
17 :
18 : namespace boost {
19 : namespace http_proto {
20 : namespace zlib {
21 :
22 : //------------------------------------------------
23 :
24 : #define SAME_FIELD(T1,T2,M) \
25 : offsetof(T1,M)==offsetof(T2,M) && \
26 : sizeof(decltype(T1::M)) == sizeof(decltype(T2::M))
27 :
28 : template<class T1, class T2>
29 : constexpr
30 : bool
31 : is_layout_identical()
32 : {
33 : return
34 : sizeof(T1) == sizeof(T2) &&
35 : SAME_FIELD(T1, T2, next_in) &&
36 : SAME_FIELD(T1, T2, avail_in) &&
37 : SAME_FIELD(T1, T2, total_in) &&
38 : SAME_FIELD(T1, T2, next_out) &&
39 : SAME_FIELD(T1, T2, avail_out) &&
40 : SAME_FIELD(T1, T2, total_out) &&
41 : SAME_FIELD(T1, T2, msg) &&
42 : SAME_FIELD(T1, T2, state) &&
43 : SAME_FIELD(T1, T2, zalloc) &&
44 : SAME_FIELD(T1, T2, zfree) &&
45 : SAME_FIELD(T1, T2, opaque) &&
46 : SAME_FIELD(T1, T2, data_type) &&
47 : SAME_FIELD(T1, T2, adler) &&
48 : SAME_FIELD(T1, T2, reserved)
49 : ;
50 : }
51 :
52 : //------------------------------------------------
53 :
54 : template<bool isLayoutIdentical =
55 : is_layout_identical<stream_t, z_stream_s>()>
56 : struct stream_cast_impl
57 : {
58 : explicit
59 : stream_cast_impl(
60 : stream_t& st)
61 : : pzs_(reinterpret_cast<z_stream_s*>(&st))
62 : , st_(st)
63 : {
64 : zs_.next_in = st_.next_in;
65 : zs_.avail_in = st_.avail_in;
66 : zs_.total_in = st_.total_in;
67 : zs_.next_out = st_.next_out;
68 : zs_.avail_out = st_.avail_out;
69 : zs_.total_out = st_.total_out;
70 : zs_.msg = nullptr;
71 : zs_.state = reinterpret_cast<
72 : internal_state*>(st_.state);
73 : zs_.zalloc = st_.zalloc;
74 : zs_.zfree = st_.zfree;
75 : zs_.opaque = st_.opaque;
76 : zs_.data_type = st_.data_type;
77 : zs_.adler = st_.adler;
78 : zs_.reserved = st_.reserved;
79 : }
80 :
81 : ~stream_cast_impl()
82 : {
83 : st_.next_in = zs_.next_in;
84 : st_.avail_in = zs_.avail_in;
85 : st_.total_in = zs_.total_in;
86 : st_.next_out = zs_.next_out;
87 : st_.avail_out = zs_.avail_out;
88 : st_.total_out = zs_.total_out;
89 : st_.msg = zs_.msg;
90 : st_.state = zs_.state;
91 : st_.zalloc = zs_.zalloc;
92 : st_.zfree = zs_.zfree;
93 : st_.opaque = zs_.opaque;
94 : st_.data_type = zs_.data_type;
95 : st_.adler = zs_.adler;
96 : st_.reserved = zs_.reserved;
97 : }
98 :
99 : z_stream_s*
100 : get() noexcept
101 : {
102 : return pzs_;
103 : }
104 :
105 : private:
106 : z_stream_s* pzs_ = nullptr;
107 : stream_t& st_;
108 : z_stream_s zs_;
109 : };
110 :
111 : //------------------------------------------------
112 :
113 : template<>
114 : struct stream_cast_impl<true>
115 : {
116 : explicit
117 0 : stream_cast_impl(
118 : stream_t& st)
119 : // VFALCO A pinch of undefined behavior here
120 0 : : pzs_(reinterpret_cast<z_stream_s*>(&st))
121 : {
122 :
123 0 : }
124 :
125 : z_stream_s*
126 0 : get() noexcept
127 : {
128 0 : return pzs_;
129 : }
130 :
131 : private:
132 : z_stream_s* pzs_;
133 : };
134 :
135 : //------------------------------------------------
136 :
137 : using stream_cast = stream_cast_impl<>;
138 :
139 : } // zlib
140 : } // http_proto
141 : } // boost
142 :
143 : #endif
|