Coverage Report

Created: 2025-08-26 06:06

/src/libzmq/src/blob.hpp
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