File: array.h

package info (click to toggle)
amqp-cpp 4.3.27-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,384 kB
  • sloc: cpp: 10,021; ansic: 191; makefile: 95
file content (258 lines) | stat: -rw-r--r-- 5,163 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
/**
 *  AMQP field array
 *
 *  @copyright 2014 - 2020 Copernica BV
 */

/**
 *  Include guard
 */
#pragma once

/**
 *  Dependencies
 */
#include "field.h"
#include "fieldproxy.h"
#include <vector>
#include <ostream>

/**
 *  Set up namespace
 */
namespace AMQP {

/**
 *  AMQP field array
 */
class Array : public Field
{
private:
    /**
     *  Definition of an array as a vector
     *  @typedef
     */
    typedef std::vector<std::unique_ptr<Field>> FieldArray;

    /**
     *  The actual fields
     *  @var FieldArray
     */
    FieldArray _fields;

public:
    /**
     *  Constructor to construct an array from a received frame
     *
     *  @param  frame   received frame
     */
    Array(InBuffer &frame);

    /**
     *  Copy constructor
     *  @param  array
     */
    Array(const Array &array);

    /**
     *  Move constructor
     *  @param  array
     */
    Array(Array &&array) : _fields(std::move(array._fields)) {}

    /**
     *  Constructor for an empty Array
     */
    Array() {}

    /**
     * Destructor
     */
    virtual ~Array() {}

    /**
     *  Create a new instance of this object
     *  @return Field*
     */
    virtual std::unique_ptr<Field> clone() const override
    {
        return std::unique_ptr<Array>(new Array(*this));
    }

    /**
     *  Get the size this field will take when
     *  encoded in the AMQP wire-frame format
     *  @return size_t
     */
    virtual size_t size() const override;

    /**
     *  Set a field
     *
     *  @param  index   field index
     *  @param  value   field value
     *  @return Array
     */
    Array set(uint8_t index, const Field &value)
    {
        // make a copy
        auto ptr = value.clone();

        // should we overwrite an existing record?
        if (index >= _fields.size())
        {
            // append index
            _fields.push_back(std::move(ptr));
        }
        else
        {
            // overwrite pointer
            _fields[index] = std::move(ptr);
        }

        // allow chaining
        return *this;
    }

    /**
     *  Get a field
     *
     *  If the field does not exist, an empty string is returned
     *
     *  @param  index   field index
     *  @return Field
     */
    const Field &get(uint8_t index) const;

    /**
     *  Get number of elements on this array
     *
     *  @return array size
     */
    uint32_t count() const;

    /**
     *  Remove last element from array
     */
    void pop_back();

    /**
     *  Add field to end of array
     *
     *  @param value
     */
    void push_back(const Field &value);

    /**
     *  Get a field
     *
     *  @param  index   field index
     *  @return ArrayFieldProxy
     */
    ArrayFieldProxy operator[](uint8_t index)
    {
        return ArrayFieldProxy(this, index);
    }

    /**
     *  Get a const field
     *  @param  index   field index
     *  @return Field
     */
    const Field &operator[](uint8_t index) const
    {
        return get(index);
    }

    /**
     *  Write encoded payload to the given buffer.
     *  @param  buffer
     */
    virtual void fill(OutBuffer& buffer) const override;

    /**
     *  Get the type ID that is used to identify this type of
     *  field in a field table
     *  @return char
     */
    virtual char typeID() const override
    {
        return 'A';
    }

    /**
     *  We are an array field
     *
     *  @return true, because we are an array
     */
    bool isArray() const override
    {
        return true;
    }

    /**
     *  Output the object to a stream
     *  @param std::ostream
     */
    virtual void output(std::ostream &stream) const override
    {
        // prefix
        stream << "array(";

        // is this the first iteration
        bool first = true;

        // loop through all members
        for (auto &iter : _fields)
        {
            // split with comma
            if (!first) stream << ",";

            // show output
            stream << *iter;

            // no longer first iter
            first = false;
        }

        // postfix
        stream << ")";
    }

    /**
     *  Cast to array.
     *
     *  @note:  This function may look silly and unnecessary. We are, after all, already
     *          an array. The whole reason we still have this function is that it is virtual
     *          and if we do not declare a cast to array on a pointer to base (i.e. Field)
     *          will return an empty field instead of the expected array.
     *
     *          Yes, clang gets this wrong and gives incorrect warnings here. See
     *          https://llvm.org/bugs/show_bug.cgi?id=28263 for more information
     *
     *  @return Ourselves
     */
    virtual operator const Array& () const override
    {
        // this already is an array, so no cast is necessary
        return *this;
    }
};

/**
 *  Custom output stream operator
 *  @param  stream
 *  @param  field
 *  @return ostream
 */
inline std::ostream &operator<<(std::ostream &stream, const ArrayFieldProxy &field)
{
    // get underlying field, and output that
    return stream << field.get();
}

/**
 *  end namespace
 */
}