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