Coverage Report

Created: 2026-10-28 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/Fast-DDS/include/fastdds/rtps/common/SequenceNumber.hpp
Line
Count
Source
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
19.4k
    {
47
19.4k
        high = 0;
48
19.4k
        low = 0;
49
19.4k
    }
50
51
    /*!
52
     * @param hi
53
     * @param lo
54
     */
55
    SequenceNumber_t(
56
            int32_t hi,
57
            uint32_t lo) noexcept
58
14.4k
        : high(hi)
59
14.4k
        , low(lo)
60
14.4k
    {
61
14.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
            increase_high_or_cap(*this);
88
0
        }
89
90
0
        return *this;
91
0
    }
92
93
    SequenceNumber_t operator ++(
94
            int) noexcept
95
0
    {
96
0
        SequenceNumber_t result(*this);
97
0
        ++(*this);
98
0
        return result;
99
0
    }
100
101
    /**
102
     * Increase SequenceNumber.
103
     * @param inc Number to add to the SequenceNumber
104
     */
105
    SequenceNumber_t& operator +=(
106
            int inc) noexcept
107
0
    {
108
0
        assert(inc >= 0);
109
0
        uint32_t aux_low = low;
110
0
        low += static_cast<uint32_t>(inc);
111
0
112
0
        if (low < aux_low)
113
0
        {
114
0
            // Being the type of the parameter an 'int', the increment of 'high' will be as much as 1.
115
0
            increase_high_or_cap(*this);
116
0
        }
117
0
118
0
        return *this;
119
0
    }
120
121
    static SequenceNumber_t unknown() noexcept
122
2.14k
    {
123
2.14k
        return {-1, 0};
124
2.14k
    }
125
126
    static inline void increase_high_or_cap(
127
            SequenceNumber_t& seq) noexcept
128
249
    {
129
249
        if (seq.high < std::numeric_limits<int32_t>::max())
130
249
        {
131
249
            ++seq.high;
132
249
        }
133
0
        else
134
0
        {
135
0
            seq.low = std::numeric_limits<uint32_t>::max();
136
0
        }
137
249
    }
138
139
    static void decrease_high_or_cap(
140
            SequenceNumber_t& seq) noexcept
141
219
    {
142
219
        if (seq.high > 0)
143
219
        {
144
219
            --seq.high;
145
219
        }
146
0
        else
147
0
        {
148
0
            seq.low = 0;
149
0
        }
150
219
    }
151
152
};
153
154
#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
155
156
/**
157
 * Compares two SequenceNumber_t.
158
 * @param sn1 First SequenceNumber_t to compare
159
 * @param sn2 Second SequenceNumber_t to compare
160
 * @return True if equal
161
 */
162
inline bool operator ==(
163
        const SequenceNumber_t& sn1,
164
        const SequenceNumber_t& sn2) noexcept
165
0
{
166
0
    return (sn1.low == sn2.low) && (sn1.high == sn2.high);
167
0
}
168
169
/**
170
 * Compares two SequenceNumber_t.
171
 * @param sn1 First SequenceNumber_t to compare
172
 * @param sn2 Second SequenceNumber_t to compare
173
 * @return True if not equal
174
 */
175
inline bool operator !=(
176
        const SequenceNumber_t& sn1,
177
        const SequenceNumber_t& sn2) noexcept
178
987
{
179
987
    return (sn1.low != sn2.low) || (sn1.high != sn2.high);
180
987
}
181
182
/**
183
 * Checks if a SequenceNumber_t is greater than other.
184
 * @param seq1 First SequenceNumber_t to compare
185
 * @param seq2 Second SequenceNumber_t to compare
186
 * @return True if the first SequenceNumber_t is greater than the second
187
 */
188
inline bool operator >(
189
        const SequenceNumber_t& seq1,
190
        const SequenceNumber_t& seq2) noexcept
191
0
{
192
0
    if (seq1.high == seq2.high)
193
0
    {
194
0
        return seq1.low > seq2.low;
195
0
    }
196
197
0
    return seq1.high > seq2.high;
198
0
}
199
200
/**
201
 * Checks if a SequenceNumber_t is less than other.
202
 * @param seq1 First SequenceNumber_t to compare
203
 * @param seq2 Second SequenceNumber_t to compare
204
 * @return True if the first SequenceNumber_t is less than the second
205
 */
206
inline bool operator <(
207
        const SequenceNumber_t& seq1,
208
        const SequenceNumber_t& seq2) noexcept
209
2.93k
{
210
2.93k
    if (seq1.high == seq2.high)
211
2.23k
    {
212
2.23k
        return seq1.low < seq2.low;
213
2.23k
    }
214
215
700
    return seq1.high < seq2.high;
216
2.93k
}
217
218
/**
219
 * Checks if a SequenceNumber_t is greater or equal than other.
220
 * @param seq1 First SequenceNumber_t to compare
221
 * @param seq2 Second SequenceNumber_t to compare
222
 * @return True if the first SequenceNumber_t is greater or equal than the second
223
 */
224
inline bool operator >=(
225
        const SequenceNumber_t& seq1,
226
        const SequenceNumber_t& seq2) noexcept
227
0
{
228
0
    if (seq1.high == seq2.high)
229
0
    {
230
0
        return seq1.low >= seq2.low;
231
0
    }
232
233
0
    return seq1.high > seq2.high;
234
0
}
235
236
/**
237
 * Checks if a SequenceNumber_t is less or equal than other.
238
 * @param seq1 First SequenceNumber_t to compare
239
 * @param seq2 Second SequenceNumber_t to compare
240
 * @return True if the first SequenceNumber_t is less or equal than the second
241
 */
242
inline bool operator <=(
243
        const SequenceNumber_t& seq1,
244
        const SequenceNumber_t& seq2) noexcept
245
7.97k
{
246
7.97k
    if (seq1.high == seq2.high)
247
2.20k
    {
248
2.20k
        return seq1.low <= seq2.low;
249
2.20k
    }
250
251
5.77k
    return seq1.high < seq2.high;
252
7.97k
}
253
254
/**
255
 * Subtract one uint32_t from a SequenceNumber_t
256
 * @param seq Base SequenceNumber_t
257
 * @param inc uint32_t to subtract
258
 * @return Result of the subtraction
259
 */
260
inline SequenceNumber_t operator -(
261
        const SequenceNumber_t& seq,
262
        const uint32_t inc) noexcept
263
987
{
264
987
    SequenceNumber_t res(seq.high, seq.low - inc);
265
266
987
    if (inc > seq.low)
267
219
    {
268
        // Being the type of the parameter an 'uint32_t', the decrement of 'high' will be as much as 1.
269
219
        SequenceNumber_t::decrease_high_or_cap(res);
270
219
    }
271
272
987
    return res;
273
987
}
274
275
/**
276
 * Add one uint32_t to a SequenceNumber_t
277
 * @param [in] seq Base sequence number
278
 * @param inc value to add to the base
279
 * @return Result of the addition
280
 */
281
inline SequenceNumber_t operator +(
282
        const SequenceNumber_t& seq,
283
        const uint32_t inc) noexcept
284
5.36k
{
285
5.36k
    SequenceNumber_t res(seq.high, seq.low + inc);
286
287
5.36k
    if (res.low < seq.low)
288
249
    {
289
        // Being the type of the parameter an 'uint32_t', the increment of 'high' will be as much as 1.
290
249
        SequenceNumber_t::increase_high_or_cap(res);
291
249
    }
292
293
5.36k
    return res;
294
5.36k
}
295
296
/**
297
 * Subtract one SequenceNumber_t to another
298
 * @param minuend Minuend. Has to be greater than or equal to subtrahend.
299
 * @param subtrahend Subtrahend.
300
 * @return Result of the subtraction
301
 */
302
inline SequenceNumber_t operator -(
303
        const SequenceNumber_t& minuend,
304
        const SequenceNumber_t& subtrahend) noexcept
305
0
{
306
0
    assert(minuend >= subtrahend);
307
0
    SequenceNumber_t res(minuend.high - subtrahend.high, minuend.low - subtrahend.low);
308
309
0
    if (minuend.low < subtrahend.low)
310
0
    {
311
0
        SequenceNumber_t::decrease_high_or_cap(res);
312
0
    }
313
314
0
    return res;
315
0
}
316
317
#endif // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
318
319
const SequenceNumber_t c_SequenceNumber_Unknown{-1, 0};
320
321
#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
322
323
/**
324
 * Sorts two instances of SequenceNumber_t
325
 * @param s1 First SequenceNumber_t to compare
326
 * @param s2 First SequenceNumber_t to compare
327
 * @return True if s1 is less than s2
328
 */
329
inline bool sort_seqNum(
330
        const SequenceNumber_t& s1,
331
        const SequenceNumber_t& s2) noexcept
332
0
{
333
0
    return s1 < s2;
334
0
}
335
336
/**
337
 *
338
 * @param output
339
 * @param seqNum
340
 * @return
341
 */
342
inline std::ostream& operator <<(
343
        std::ostream& output,
344
        const SequenceNumber_t& seqNum)
345
0
{
346
0
    return output << seqNum.to64long();
347
0
}
348
349
inline std::ostream& operator <<(
350
        std::ostream& output,
351
        const std::vector<SequenceNumber_t>& seqNumSet)
352
0
{
353
0
    for (const SequenceNumber_t& sn : seqNumSet)
354
0
    {
355
0
        output << sn << " ";
356
0
    }
357
0
358
0
    return output;
359
0
}
360
361
/*!
362
 * @brief Defines the STL hash function for type SequenceNumber_t.
363
 */
364
struct SequenceNumberHash
365
{
366
    std::size_t operator ()(
367
            const SequenceNumber_t& sequence_number) const noexcept
368
0
    {
369
0
        return static_cast<std::size_t>(sequence_number.to64long());
370
0
    }
371
372
};
373
374
struct SequenceNumberDiff
375
{
376
    uint32_t operator ()(
377
            const SequenceNumber_t& a,
378
            const SequenceNumber_t& b) const noexcept
379
0
    {
380
0
        SequenceNumber_t diff = a - b;
381
0
        return diff.low;
382
0
    }
383
384
};
385
386
#endif // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
387
388
//! Structure SequenceNumberSet_t, contains a group of sequencenumbers.
389
using SequenceNumberSet_t = BitmapRange<SequenceNumber_t, SequenceNumberDiff, 256>;
390
391
#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
392
393
/**
394
 * Prints a sequence Number set
395
 * @param output Output Stream
396
 * @param sns SequenceNumber set
397
 * @return OStream.
398
 */
399
inline std::ostream& operator <<(
400
        std::ostream& output,
401
        const SequenceNumberSet_t& sns)
402
0
{
403
0
    output << sns.base().to64long() << ":";
404
0
    sns.for_each([&output](
405
0
                SequenceNumber_t it)
406
0
            {
407
0
                output << it.to64long() << "-";
408
0
            });
409
0
410
0
    return output;
411
0
}
412
413
/**
414
 *
415
 * @param input
416
 * @param seqNum
417
 * @return
418
 */
419
inline std::istream& operator >>(
420
        std::istream& input,
421
        SequenceNumber_t& seqNum)
422
0
{
423
0
    uint64_t aux;
424
425
0
    if (input >> aux)
426
0
    {
427
0
        seqNum = SequenceNumber_t(aux);
428
0
    }
429
430
0
    return input;
431
0
}
432
433
#endif // DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
434
435
} // namespace rtps
436
} // namespace fastdds
437
} // namespace eprosima
438
439
#endif // FASTDDS_RTPS_COMMON__SEQUENCENUMBER_HPP