Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/doctor/RollingNumber.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef mozilla_RollingNumber_h_
8
#define mozilla_RollingNumber_h_
9
10
#include "mozilla/Attributes.h"
11
#include <limits>
12
13
namespace mozilla {
14
15
// Unsigned number suited to index elements in a never-ending queue, as
16
// order-comparison behaves nicely around the overflow.
17
//
18
// Additive operators work the same as for the underlying value type, but
19
// expect "small" jumps, as should normally happen when manipulating indices.
20
//
21
// Comparison functions are different, they keep the ordering based on the
22
// distance between numbers, modulo the value type range:
23
// If the distance is less than half the range of the value type, the usual
24
// ordering stays.
25
// 0 < 1, 2^23 < 2^24
26
// However if the distance is more than half the range, we assume that we are
27
// continuing along the queue, and therefore consider the smaller number to
28
// actually be greater!
29
// uint(-1) < 0.
30
//
31
// The expected usage is to always work on nearby rolling numbers: slowly
32
// incrementing/decrementing them, and translating&comparing them within a
33
// small window.
34
// To enforce this usage during development, debug-build assertions catch API
35
// calls involving distances of more than a *quarter* of the type range.
36
// In non-debug builds, all APIs will still work as consistently as possible
37
// without crashing, but performing operations on "distant" nunbers could lead
38
// to unexpected results.
39
template<typename T>
40
class RollingNumber
41
{
42
  static_assert(!std::numeric_limits<T>::is_signed,
43
                "RollingNumber only accepts unsigned number types");
44
45
public:
46
  using ValueType = T;
47
48
  RollingNumber()
49
    : mIndex(0)
50
0
  {
51
0
  }
Unexecuted instantiation: mozilla::RollingNumber<unsigned int>::RollingNumber()
Unexecuted instantiation: mozilla::RollingNumber<unsigned char>::RollingNumber()
52
53
  explicit RollingNumber(ValueType aIndex)
54
    : mIndex(aIndex)
55
0
  {
56
0
  }
Unexecuted instantiation: mozilla::RollingNumber<unsigned int>::RollingNumber(unsigned int)
Unexecuted instantiation: mozilla::RollingNumber<unsigned char>::RollingNumber(unsigned char)
57
58
  RollingNumber(const RollingNumber&) = default;
59
  RollingNumber& operator=(const RollingNumber&) = default;
60
61
0
  ValueType Value() const { return mIndex; }
Unexecuted instantiation: mozilla::RollingNumber<unsigned int>::Value() const
Unexecuted instantiation: mozilla::RollingNumber<unsigned char>::Value() const
62
63
  // Normal increments/decrements.
64
65
  RollingNumber& operator++()
66
0
  {
67
0
    ++mIndex;
68
0
    return *this;
69
0
  }
Unexecuted instantiation: mozilla::RollingNumber<unsigned int>::operator++()
Unexecuted instantiation: mozilla::RollingNumber<unsigned char>::operator++()
70
71
0
  RollingNumber operator++(int) { return RollingNumber{ mIndex++ }; }
72
73
  RollingNumber& operator--()
74
0
  {
75
0
    --mIndex;
76
0
    return *this;
77
0
  }
78
79
0
  RollingNumber operator--(int) { return RollingNumber{ mIndex-- }; }
80
81
  RollingNumber& operator+=(const ValueType& aIncrement)
82
0
  {
83
0
    MOZ_ASSERT(aIncrement <= MaxDiff);
84
0
    mIndex += aIncrement;
85
0
    return *this;
86
0
  }
Unexecuted instantiation: mozilla::RollingNumber<unsigned int>::operator+=(unsigned int const&)
Unexecuted instantiation: mozilla::RollingNumber<unsigned char>::operator+=(unsigned char const&)
87
88
  RollingNumber operator+(const ValueType& aIncrement) const
89
0
  {
90
0
    RollingNumber n = *this;
91
0
    return n += aIncrement;
92
0
  }
Unexecuted instantiation: mozilla::RollingNumber<unsigned int>::operator+(unsigned int const&) const
Unexecuted instantiation: mozilla::RollingNumber<unsigned char>::operator+(unsigned char const&) const
93
94
  RollingNumber& operator-=(const ValueType& aDecrement)
95
0
  {
96
0
    MOZ_ASSERT(aDecrement <= MaxDiff);
97
0
    mIndex -= aDecrement;
98
0
    return *this;
99
0
  }
100
101
  // Translate a RollingNumber by a negative value.
102
  RollingNumber operator-(const ValueType& aDecrement) const
103
0
  {
104
0
    RollingNumber n = *this;
105
0
    return n -= aDecrement;
106
0
  }
107
108
  // Distance between two RollingNumbers, giving a value.
109
  ValueType operator-(const RollingNumber& aOther) const
110
0
  {
111
0
    ValueType diff = mIndex - aOther.mIndex;
112
0
    MOZ_ASSERT(diff <= MaxDiff);
113
0
    return diff;
114
0
  }
Unexecuted instantiation: mozilla::RollingNumber<unsigned int>::operator-(mozilla::RollingNumber<unsigned int> const&) const
Unexecuted instantiation: mozilla::RollingNumber<unsigned char>::operator-(mozilla::RollingNumber<unsigned char> const&) const
115
116
  // Normal (in)equality operators.
117
118
  bool operator==(const RollingNumber& aOther) const
119
0
  {
120
0
    return mIndex == aOther.mIndex;
121
0
  }
Unexecuted instantiation: mozilla::RollingNumber<unsigned int>::operator==(mozilla::RollingNumber<unsigned int> const&) const
Unexecuted instantiation: mozilla::RollingNumber<unsigned char>::operator==(mozilla::RollingNumber<unsigned char> const&) const
122
  bool operator!=(const RollingNumber& aOther) const
123
0
  {
124
0
    return !(*this == aOther);
125
0
  }
126
127
  // Modified comparison operators.
128
129
  bool operator<(const RollingNumber& aOther) const
130
0
  {
131
0
    const T& a = mIndex;
132
0
    const T& b = aOther.mIndex;
133
0
    // static_cast needed because of possible integer promotion
134
0
    // (e.g., from uint8_t to int, which would make the test useless).
135
0
    const bool lessThanOther = static_cast<ValueType>(a - b) > MidWay;
136
0
    MOZ_ASSERT((lessThanOther ? (b - a) : (a - b)) <= MaxDiff);
137
0
    return lessThanOther;
138
0
  }
Unexecuted instantiation: mozilla::RollingNumber<unsigned int>::operator<(mozilla::RollingNumber<unsigned int> const&) const
Unexecuted instantiation: mozilla::RollingNumber<unsigned char>::operator<(mozilla::RollingNumber<unsigned char> const&) const
139
140
  bool operator<=(const RollingNumber& aOther) const
141
0
  {
142
0
    const T& a = mIndex;
143
0
    const T& b = aOther.mIndex;
144
0
    const bool lessishThanOther = static_cast<ValueType>(b - a) <= MidWay;
145
0
    MOZ_ASSERT((lessishThanOther ? (b - a) : (a - b)) <= MaxDiff);
146
0
    return lessishThanOther;
147
0
  }
Unexecuted instantiation: mozilla::RollingNumber<unsigned int>::operator<=(mozilla::RollingNumber<unsigned int> const&) const
Unexecuted instantiation: mozilla::RollingNumber<unsigned char>::operator<=(mozilla::RollingNumber<unsigned char> const&) const
148
149
  bool operator>=(const RollingNumber& aOther) const
150
0
  {
151
0
    const T& a = mIndex;
152
0
    const T& b = aOther.mIndex;
153
0
    const bool greaterishThanOther = static_cast<ValueType>(a - b) <= MidWay;
154
0
    MOZ_ASSERT((greaterishThanOther ? (a - b) : (b - a)) <= MaxDiff);
155
0
    return greaterishThanOther;
156
0
  }
Unexecuted instantiation: mozilla::RollingNumber<unsigned int>::operator>=(mozilla::RollingNumber<unsigned int> const&) const
Unexecuted instantiation: mozilla::RollingNumber<unsigned char>::operator>=(mozilla::RollingNumber<unsigned char> const&) const
157
158
  bool operator>(const RollingNumber& aOther) const
159
0
  {
160
0
    const T& a = mIndex;
161
0
    const T& b = aOther.mIndex;
162
0
    const bool greaterThanOther = static_cast<ValueType>(b - a) > MidWay;
163
0
    MOZ_ASSERT((greaterThanOther ? (a - b) : (b - a)) <= MaxDiff);
164
0
    return greaterThanOther;
165
0
  }
Unexecuted instantiation: mozilla::RollingNumber<unsigned int>::operator>(mozilla::RollingNumber<unsigned int> const&) const
Unexecuted instantiation: mozilla::RollingNumber<unsigned char>::operator>(mozilla::RollingNumber<unsigned char> const&) const
166
167
private:
168
  // MidWay is used to split the type range in two, to decide how two numbers
169
  // are ordered.
170
  static const T MidWay = std::numeric_limits<T>::max() / 2;
171
#ifdef DEBUG
172
  // MaxDiff is the expected maximum difference between two numbers, either
173
  // during comparisons, or when adding/subtracting.
174
  // This is only used during debugging, to highlight algorithmic issues.
175
  static const T MaxDiff = std::numeric_limits<T>::max() / 4;
176
#endif
177
  ValueType mIndex;
178
};
179
180
} // namespace mozilla
181
182
#endif // mozilla_RollingNumber_h_