Coverage Report

Created: 2025-06-13 06:46

/src/Fast-DDS/include/fastdds/rtps/common/SequenceNumber.hpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
 * @file SequenceNumber.hpp
17
 */
18
19
#ifndef FASTDDS_RTPS_COMMON__SEQUENCENUMBER_HPP
20
#define FASTDDS_RTPS_COMMON__SEQUENCENUMBER_HPP
21
22
#include <algorithm>
23
#include <cassert>
24
#include <limits>
25
#include <vector>
26
27
#include <fastdds/fastdds_dll.hpp>
28
#include <fastdds/rtps/common/Types.hpp>
29
#include <fastdds/utils/fixed_size_bitmap.hpp>
30
31
namespace eprosima {
32
namespace fastdds {
33
namespace rtps {
34
35
//!@brief Structure SequenceNumber_t, different for each change in the same writer.
36
//!@ingroup COMMON_MODULE
37
struct FASTDDS_EXPORTED_API SequenceNumber_t
38
{
39
    //!
40
    int32_t high = 0;
41
    //!
42
    uint32_t low = 0;
43
44
    //! Default constructor
45
    SequenceNumber_t() noexcept
46
27.7k
    {
47
27.7k
        high = 0;
48
27.7k
        low = 0;
49
27.7k
    }
50
51
    /*!
52
     * @param hi
53
     * @param lo
54
     */
55
    SequenceNumber_t(
56
            int32_t hi,
57
            uint32_t lo) noexcept
58
18.4k
        : high(hi)
59
18.4k
        , low(lo)
60
18.4k
    {
61
18.4k
    }
62
63
    /*!
64
     * @param u
65
     */
66
    explicit SequenceNumber_t(
67
            uint64_t u) noexcept
68
0
        : high(static_cast<int32_t>(u >> 32u))
69
0
        , low(static_cast<uint32_t>(u))
70
0
    {
71
0
    }
72
73
    /*! Convert the number to 64 bit.
74
     * @return 64 bit representation of the SequenceNumber
75
     */
76
    uint64_t to64long() const noexcept
77
0
    {
78
0
        return (static_cast<uint64_t>(high) << 32u) + low;
79
0
    }
80
81
    //! Increase SequenceNumber in 1.
82
    SequenceNumber_t& operator ++() noexcept
83
0
    {
84
0
        ++low;
85
0
        if (low == 0)
86
0
        {
87
0
            assert(std::numeric_limits<decltype(high)>::max() > high);
88
0
            ++high;
89
0
        }
90
91
0
        return *this;
92
0
    }
93
94
    SequenceNumber_t operator ++(
95
            int) noexcept
96
0
    {
97
0
        SequenceNumber_t result(*this);
98
0
        ++(*this);
99
0
        return result;
100
0
    }
101
102
    /**
103
     * Increase SequenceNumber.
104
     * @param inc Number to add to the SequenceNumber
105
     */
106
    SequenceNumber_t& operator +=(
107
            int inc) noexcept
108
0
    {
109
0
        assert(inc >= 0);
110
0
        uint32_t aux_low = low;
111
0
        low += static_cast<uint32_t>(inc);
112
0
113
0
        if (low < aux_low)
114
0
        {
115
0
            // Being the type of the parameter an 'int', the increment of 'high' will be as much as 1.
116
0
            assert(std::numeric_limits<decltype(high)>::max() > high);
117
0
            ++high;
118
0
        }
119
0
120
0
        return *this;
121
0
    }
122
123
    static SequenceNumber_t unknown() noexcept
124
8
    {
125
8
        return {-1, 0};
126
8
    }
127
128
};
129
130
#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
131
132
/**
133
 * Compares two SequenceNumber_t.
134
 * @param sn1 First SequenceNumber_t to compare
135
 * @param sn2 Second SequenceNumber_t to compare
136
 * @return True if equal
137
 */
138
inline bool operator ==(
139
        const SequenceNumber_t& sn1,
140
        const SequenceNumber_t& sn2) noexcept
141
0
{
142
0
    return (sn1.low == sn2.low) && (sn1.high == sn2.high);
143
0
}
144
145
/**
146
 * Compares two SequenceNumber_t.
147
 * @param sn1 First SequenceNumber_t to compare
148
 * @param sn2 Second SequenceNumber_t to compare
149
 * @return True if not equal
150
 */
151
inline bool operator !=(
152
        const SequenceNumber_t& sn1,
153
        const SequenceNumber_t& sn2) noexcept
154
1.23k
{
155
1.23k
    return (sn1.low != sn2.low) || (sn1.high != sn2.high);
156
1.23k
}
157
158
/**
159
 * Checks if a SequenceNumber_t is greater than other.
160
 * @param seq1 First SequenceNumber_t to compare
161
 * @param seq2 Second SequenceNumber_t to compare
162
 * @return True if the first SequenceNumber_t is greater than the second
163
 */
164
inline bool operator >(
165
        const SequenceNumber_t& seq1,
166
        const SequenceNumber_t& seq2) noexcept
167
0
{
168
0
    if (seq1.high == seq2.high)
169
0
    {
170
0
        return seq1.low > seq2.low;
171
0
    }
172
173
0
    return seq1.high > seq2.high;
174
0
}
175
176
/**
177
 * Checks if a SequenceNumber_t is less than other.
178
 * @param seq1 First SequenceNumber_t to compare
179
 * @param seq2 Second SequenceNumber_t to compare
180
 * @return True if the first SequenceNumber_t is less than the second
181
 */
182
inline bool operator <(
183
        const SequenceNumber_t& seq1,
184
        const SequenceNumber_t& seq2) noexcept
185
3.59k
{
186
3.59k
    if (seq1.high == seq2.high)
187
2.29k
    {
188
2.29k
        return seq1.low < seq2.low;
189
2.29k
    }
190
191
1.30k
    return seq1.high < seq2.high;
192
3.59k
}
193
194
/**
195
 * Checks if a SequenceNumber_t is greater or equal than other.
196
 * @param seq1 First SequenceNumber_t to compare
197
 * @param seq2 Second SequenceNumber_t to compare
198
 * @return True if the first SequenceNumber_t is greater or equal than the second
199
 */
200
inline bool operator >=(
201
        const SequenceNumber_t& seq1,
202
        const SequenceNumber_t& seq2) noexcept
203
0
{
204
0
    if (seq1.high == seq2.high)
205
0
    {
206
0
        return seq1.low >= seq2.low;
207
0
    }
208
209
0
    return seq1.high > seq2.high;
210
0
}
211
212
/**
213
 * Checks if a SequenceNumber_t is less or equal than other.
214
 * @param seq1 First SequenceNumber_t to compare
215
 * @param seq2 Second SequenceNumber_t to compare
216
 * @return True if the first SequenceNumber_t is less or equal than the second
217
 */
218
inline bool operator <=(
219
        const SequenceNumber_t& seq1,
220
        const SequenceNumber_t& seq2) noexcept
221
11.8k
{
222
11.8k
    if (seq1.high == seq2.high)
223
2.80k
    {
224
2.80k
        return seq1.low <= seq2.low;
225
2.80k
    }
226
227
9.02k
    return seq1.high < seq2.high;
228
11.8k
}
229
230
/**
231
 * Subtract one uint32_t from a SequenceNumber_t
232
 * @param seq Base SequenceNumber_t
233
 * @param inc uint32_t to subtract
234
 * @return Result of the subtraction
235
 */
236
inline SequenceNumber_t operator -(
237
        const SequenceNumber_t& seq,
238
        const uint32_t inc) noexcept
239
1.23k
{
240
1.23k
    SequenceNumber_t res(seq.high, seq.low - inc);
241
242
1.23k
    if (inc > seq.low)
243
408
    {
244
        // Being the type of the parameter an 'uint32_t', the decrement of 'high' will be as much as 1.
245
408
        assert(0 < res.high);
246
408
        --res.high;
247
408
    }
248
249
1.23k
    return res;
250
1.23k
}
251
252
/**
253
 * Add one uint32_t to a SequenceNumber_t
254
 * @param [in] seq Base sequence number
255
 * @param inc value to add to the base
256
 * @return Result of the addition
257
 */
258
inline SequenceNumber_t operator +(
259
        const SequenceNumber_t& seq,
260
        const uint32_t inc) noexcept
261
8.45k
{
262
8.45k
    SequenceNumber_t res(seq.high, seq.low + inc);
263
264
8.45k
    if (res.low < seq.low)
265
352
    {
266
        // Being the type of the parameter an 'uint32_t', the increment of 'high' will be as much as 1.
267
352
        assert(std::numeric_limits<decltype(res.high)>::max() > res.high);
268
352
        ++res.high;
269
352
    }
270
271
8.45k
    return res;
272
8.45k
}
273
274
/**
275
 * Subtract one SequenceNumber_t to another
276
 * @param minuend Minuend. Has to be greater than or equal to subtrahend.
277
 * @param subtrahend Subtrahend.
278
 * @return Result of the subtraction
279
 */
280
inline SequenceNumber_t operator -(
281
        const SequenceNumber_t& minuend,
282
        const SequenceNumber_t& subtrahend) noexcept
283
0
{
284
0
    assert(minuend >= subtrahend);
285
0
    SequenceNumber_t res(minuend.high - subtrahend.high, minuend.low - subtrahend.low);
286
287
0
    if (minuend.low < subtrahend.low)
288
0
    {
289
0
        assert(0 < res.high);
290
0
        --res.high;
291
0
    }
292
293
0
    return res;
294
0
}
295
296
#endif // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
297
298
const SequenceNumber_t c_SequenceNumber_Unknown{-1, 0};
299
300
#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
301
302
/**
303
 * Sorts two instances of SequenceNumber_t
304
 * @param s1 First SequenceNumber_t to compare
305
 * @param s2 First SequenceNumber_t to compare
306
 * @return True if s1 is less than s2
307
 */
308
inline bool sort_seqNum(
309
        const SequenceNumber_t& s1,
310
        const SequenceNumber_t& s2) noexcept
311
0
{
312
0
    return s1 < s2;
313
0
}
314
315
/**
316
 *
317
 * @param output
318
 * @param seqNum
319
 * @return
320
 */
321
inline std::ostream& operator <<(
322
        std::ostream& output,
323
        const SequenceNumber_t& seqNum)
324
0
{
325
0
    return output << seqNum.to64long();
326
0
}
327
328
inline std::ostream& operator <<(
329
        std::ostream& output,
330
        const std::vector<SequenceNumber_t>& seqNumSet)
331
0
{
332
0
    for (const SequenceNumber_t& sn : seqNumSet)
333
0
    {
334
0
        output << sn << " ";
335
0
    }
336
0
337
0
    return output;
338
0
}
339
340
/*!
341
 * @brief Defines the STL hash function for type SequenceNumber_t.
342
 */
343
struct SequenceNumberHash
344
{
345
    std::size_t operator ()(
346
            const SequenceNumber_t& sequence_number) const noexcept
347
0
    {
348
0
        return static_cast<std::size_t>(sequence_number.to64long());
349
0
    }
350
351
};
352
353
struct SequenceNumberDiff
354
{
355
    uint32_t operator ()(
356
            const SequenceNumber_t& a,
357
            const SequenceNumber_t& b) const noexcept
358
0
    {
359
0
        SequenceNumber_t diff = a - b;
360
0
        return diff.low;
361
0
    }
362
363
};
364
365
#endif // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
366
367
//! Structure SequenceNumberSet_t, contains a group of sequencenumbers.
368
using SequenceNumberSet_t = BitmapRange<SequenceNumber_t, SequenceNumberDiff, 256>;
369
370
#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
371
372
/**
373
 * Prints a sequence Number set
374
 * @param output Output Stream
375
 * @param sns SequenceNumber set
376
 * @return OStream.
377
 */
378
inline std::ostream& operator <<(
379
        std::ostream& output,
380
        const SequenceNumberSet_t& sns)
381
0
{
382
0
    output << sns.base().to64long() << ":";
383
0
    sns.for_each([&output](
384
0
                SequenceNumber_t it)
385
0
            {
386
0
                output << it.to64long() << "-";
387
0
            });
388
0
389
0
    return output;
390
0
}
391
392
/**
393
 *
394
 * @param input
395
 * @param seqNum
396
 * @return
397
 */
398
inline std::istream& operator >>(
399
        std::istream& input,
400
        SequenceNumber_t& seqNum)
401
0
{
402
0
    uint64_t aux;
403
404
0
    if (input >> aux)
405
0
    {
406
0
        seqNum = SequenceNumber_t(aux);
407
0
    }
408
409
0
    return input;
410
0
}
411
412
#endif // DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
413
414
} // namespace rtps
415
} // namespace fastdds
416
} // namespace eprosima
417
418
#endif // FASTDDS_RTPS_COMMON__SEQUENCENUMBER_HPP