Line | Count | Source (jump to first uncovered line) |
1 | | /* SPDX-License-Identifier: MPL-2.0 */ |
2 | | |
3 | | #ifndef __ZMQ_BLOB_HPP_INCLUDED__ |
4 | | #define __ZMQ_BLOB_HPP_INCLUDED__ |
5 | | |
6 | | #include "macros.hpp" |
7 | | #include "err.hpp" |
8 | | |
9 | | #include <stdlib.h> |
10 | | #include <string.h> |
11 | | #include <algorithm> |
12 | | #include <ios> |
13 | | |
14 | | #if __cplusplus >= 201103L || defined(_MSC_VER) && _MSC_VER > 1700 |
15 | | #define ZMQ_HAS_MOVE_SEMANTICS |
16 | 0 | #define ZMQ_MAP_INSERT_OR_EMPLACE(k, v) emplace (k, v) |
17 | 0 | #define ZMQ_PUSH_OR_EMPLACE_BACK emplace_back |
18 | 0 | #define ZMQ_MOVE(x) std::move (x) |
19 | | #else |
20 | | #if defined __SUNPRO_CC |
21 | | template <typename K, typename V> |
22 | | std::pair<const K, V> make_pair_fix_const (const K &k, const V &v) |
23 | | { |
24 | | return std::pair<const K, V> (k, v); |
25 | | } |
26 | | |
27 | | #define ZMQ_MAP_INSERT_OR_EMPLACE(k, v) insert (make_pair_fix_const (k, v)) |
28 | | #else |
29 | | #define ZMQ_MAP_INSERT_OR_EMPLACE(k, v) insert (std::make_pair (k, v)) |
30 | | #endif |
31 | | |
32 | | #define ZMQ_PUSH_OR_EMPLACE_BACK push_back |
33 | | #define ZMQ_MOVE(x) (x) |
34 | | #endif |
35 | | |
36 | | namespace zmq |
37 | | { |
38 | | struct reference_tag_t |
39 | | { |
40 | | }; |
41 | | |
42 | | // Object to hold dynamically allocated opaque binary data. |
43 | | // On modern compilers, it will be movable but not copyable. Copies |
44 | | // must be explicitly created by set_deep_copy. |
45 | | // On older compilers, it is copyable for syntactical reasons. |
46 | | struct blob_t |
47 | | { |
48 | | // Creates an empty blob_t. |
49 | 0 | blob_t () : _data (0), _size (0), _owned (true) {} |
50 | | |
51 | | // Creates a blob_t of a given size, with uninitialized content. |
52 | | explicit blob_t (const size_t size_) : |
53 | 0 | _data (static_cast<unsigned char *> (malloc (size_))), |
54 | 0 | _size (size_), |
55 | 0 | _owned (true) |
56 | 0 | { |
57 | 0 | alloc_assert (!_size || _data); |
58 | 0 | } |
59 | | |
60 | | // Creates a blob_t of a given size, an initializes content by copying |
61 | | // from another buffer. |
62 | | blob_t (const unsigned char *const data_, const size_t size_) : |
63 | 0 | _data (static_cast<unsigned char *> (malloc (size_))), |
64 | 0 | _size (size_), |
65 | 0 | _owned (true) |
66 | 0 | { |
67 | 0 | alloc_assert (!size_ || _data); |
68 | 0 | if (size_ && _data) { |
69 | 0 | memcpy (_data, data_, size_); |
70 | 0 | } |
71 | 0 | } |
72 | | |
73 | | // Creates a blob_t for temporary use that only references a |
74 | | // pre-allocated block of data. |
75 | | // Use with caution and ensure that the blob_t will not outlive |
76 | | // the referenced data. |
77 | | blob_t (unsigned char *const data_, const size_t size_, reference_tag_t) : |
78 | 0 | _data (data_), _size (size_), _owned (false) |
79 | 0 | { |
80 | 0 | } |
81 | | |
82 | | // Returns the size of the blob_t. |
83 | 0 | size_t size () const { return _size; } |
84 | | |
85 | | // Returns a pointer to the data of the blob_t. |
86 | 0 | const unsigned char *data () const { return _data; } |
87 | | |
88 | | // Returns a pointer to the data of the blob_t. |
89 | 0 | unsigned char *data () { return _data; } |
90 | | |
91 | | // Defines an order relationship on blob_t. |
92 | | bool operator< (blob_t const &other_) const |
93 | 0 | { |
94 | 0 | const int cmpres = |
95 | 0 | memcmp (_data, other_._data, std::min (_size, other_._size)); |
96 | 0 | return cmpres < 0 || (cmpres == 0 && _size < other_._size); |
97 | 0 | } |
98 | | |
99 | | // Sets a blob_t to a deep copy of another blob_t. |
100 | | void set_deep_copy (blob_t const &other_) |
101 | 0 | { |
102 | 0 | clear (); |
103 | 0 | _data = static_cast<unsigned char *> (malloc (other_._size)); |
104 | 0 | alloc_assert (!other_._size || _data); |
105 | 0 | _size = other_._size; |
106 | 0 | _owned = true; |
107 | 0 | if (_size && _data) { |
108 | 0 | memcpy (_data, other_._data, _size); |
109 | 0 | } |
110 | 0 | } |
111 | | |
112 | | // Sets a blob_t to a copy of a given buffer. |
113 | | void set (const unsigned char *const data_, const size_t size_) |
114 | 0 | { |
115 | 0 | clear (); |
116 | 0 | _data = static_cast<unsigned char *> (malloc (size_)); |
117 | 0 | alloc_assert (!size_ || _data); |
118 | 0 | _size = size_; |
119 | 0 | _owned = true; |
120 | 0 | if (size_ && _data) { |
121 | 0 | memcpy (_data, data_, size_); |
122 | 0 | } |
123 | 0 | } |
124 | | |
125 | | // Empties a blob_t. |
126 | | void clear () |
127 | 0 | { |
128 | 0 | if (_owned) { |
129 | 0 | free (_data); |
130 | 0 | } |
131 | 0 | _data = 0; |
132 | 0 | _size = 0; |
133 | 0 | } |
134 | | |
135 | | ~blob_t () |
136 | 0 | { |
137 | 0 | if (_owned) { |
138 | 0 | free (_data); |
139 | 0 | } |
140 | 0 | } |
141 | | |
142 | | #ifdef ZMQ_HAS_MOVE_SEMANTICS |
143 | | blob_t (const blob_t &) = delete; |
144 | | blob_t &operator= (const blob_t &) = delete; |
145 | | |
146 | 0 | blob_t (blob_t &&other_) ZMQ_NOEXCEPT : _data (other_._data), |
147 | 0 | _size (other_._size), |
148 | 0 | _owned (other_._owned) |
149 | 0 | { |
150 | 0 | other_._owned = false; |
151 | 0 | } |
152 | | blob_t &operator= (blob_t &&other_) ZMQ_NOEXCEPT |
153 | 0 | { |
154 | 0 | if (this != &other_) { |
155 | 0 | clear (); |
156 | 0 | _data = other_._data; |
157 | 0 | _size = other_._size; |
158 | 0 | _owned = other_._owned; |
159 | 0 | other_._owned = false; |
160 | 0 | } |
161 | 0 | return *this; |
162 | 0 | } |
163 | | #else |
164 | | blob_t (const blob_t &other) : _owned (false) { set_deep_copy (other); } |
165 | | blob_t &operator= (const blob_t &other) |
166 | | { |
167 | | if (this != &other) { |
168 | | clear (); |
169 | | set_deep_copy (other); |
170 | | } |
171 | | return *this; |
172 | | } |
173 | | #endif |
174 | | |
175 | | private: |
176 | | unsigned char *_data; |
177 | | size_t _size; |
178 | | bool _owned; |
179 | | }; |
180 | | } |
181 | | |
182 | | #endif |