This file is indexed.

/usr/include/thunderbird/TimeVarying.h is in thunderbird-dev 1:38.6.0+build1-0ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef MOZILLA_TIMEVARYING_H_
#define MOZILLA_TIMEVARYING_H_

#include "nsTArray.h"

namespace mozilla {

/**
 * This is just for CTOR/DTOR tracking. We can't put this in
 * TimeVarying directly because the different template instances have
 * different sizes and that confuses things.
 */
class TimeVaryingBase {
protected:
  TimeVaryingBase()
  {
    MOZ_COUNT_CTOR(TimeVaryingBase);
  }
  ~TimeVaryingBase()
  {
    MOZ_COUNT_DTOR(TimeVaryingBase);
  }
};

/**
 * Objects of this class represent values that can change over time ---
 * a mathematical function of time.
 * Time is the type of time values, T is the value that changes over time.
 * There are a finite set of "change times"; at each change time, the function
 * instantly changes to a new value. ReservedChanges should be set to the
 * expected number of change events that the object is likely to contain.
 * This value should be 0 for all consumers unless you know that a higher value
 * would be a benefit.
 * There is also a "current time" which must always advance (not go backward).
 * The function is constant for all times less than the current time.
 * When the current time is advanced, the value of the function at the new
 * current time replaces the values for all previous times.
 *
 * The implementation records a mCurrent (the value at the current time)
 * and an array of "change times" (greater than the current time) and the
 * new value for each change time. This is a simple but dumb implementation.
 * We maintain the invariant that each change entry in the array must have
 * a different value to the value in the previous change entry (or, for
 * the first change entry, mCurrent).
 */
template <typename Time, typename T, uint32_t ReservedChanges>
class TimeVarying : public TimeVaryingBase {
public:
  explicit TimeVarying(const T& aInitial) : mCurrent(aInitial) {}
  /**
   * This constructor can only be called if mCurrent has a no-argument
   * constructor.
   */
  TimeVarying() : mCurrent() {}

  /**
   * Sets the value for all times >= aTime to aValue.
   */
  void SetAtAndAfter(Time aTime, const T& aValue)
  {
    for (int32_t i = mChanges.Length() - 1; i >= 0; --i) {
      NS_ASSERTION(i == int32_t(mChanges.Length() - 1),
                   "Always considering last element of array");
      if (aTime > mChanges[i].mTime) {
        if (mChanges[i].mValue != aValue) {
          mChanges.AppendElement(Entry(aTime, aValue));
        }
        return;
      }
      if (aTime == mChanges[i].mTime) {
        if ((i > 0 ? mChanges[i - 1].mValue : mCurrent) == aValue) {
          mChanges.RemoveElementAt(i);
          return;
        }
        mChanges[i].mValue = aValue;
        return;
      }
      mChanges.RemoveElementAt(i);
    }
    if (mCurrent == aValue) {
      return;
    }
    mChanges.InsertElementAt(0, Entry(aTime, aValue));
  }
  /**
   * Returns the final value of the function. If aTime is non-null,
   * sets aTime to the time at which the function changes to that final value.
   * If there are no changes after the current time, returns INT64_MIN in aTime.
   */
  const T& GetLast(Time* aTime = nullptr) const
  {
    if (mChanges.IsEmpty()) {
      if (aTime) {
        *aTime = INT64_MIN;
      }
      return mCurrent;
    }
    if (aTime) {
      *aTime = mChanges[mChanges.Length() - 1].mTime;
    }
    return mChanges[mChanges.Length() - 1].mValue;
  }
  /**
   * Returns the value of the function just before time aTime.
   */
  const T& GetBefore(Time aTime) const
  {
    if (mChanges.IsEmpty() || aTime <= mChanges[0].mTime) {
      return mCurrent;
    }
    int32_t changesLength = mChanges.Length();
    if (mChanges[changesLength - 1].mTime < aTime) {
      return mChanges[changesLength - 1].mValue;
    }
    for (uint32_t i = 1; ; ++i) {
      if (aTime <= mChanges[i].mTime) {
        NS_ASSERTION(mChanges[i].mValue != mChanges[i - 1].mValue,
                     "Only changed values appear in array");
        return mChanges[i - 1].mValue;
      }
    }
  }
  /**
   * Returns the value of the function at time aTime.
   * If aEnd is non-null, sets *aEnd to the time at which the function will
   * change from the returned value to a new value, or INT64_MAX if that
   * never happens.
   * If aStart is non-null, sets *aStart to the time at which the function
   * changed to the returned value, or INT64_MIN if that happened at or
   * before the current time.
   *
   * Currently uses a linear search, but could use a binary search.
   */
  const T& GetAt(Time aTime, Time* aEnd = nullptr, Time* aStart = nullptr) const
  {
    if (mChanges.IsEmpty() || aTime < mChanges[0].mTime) {
      if (aStart) {
        *aStart = INT64_MIN;
      }
      if (aEnd) {
        *aEnd = mChanges.IsEmpty() ? INT64_MAX : mChanges[0].mTime;
      }
      return mCurrent;
    }
    int32_t changesLength = mChanges.Length();
    if (mChanges[changesLength - 1].mTime <= aTime) {
      if (aEnd) {
        *aEnd = INT64_MAX;
      }
      if (aStart) {
        *aStart = mChanges[changesLength - 1].mTime;
      }
      return mChanges[changesLength - 1].mValue;
    }

    for (uint32_t i = 1; ; ++i) {
      if (aTime < mChanges[i].mTime) {
        if (aEnd) {
          *aEnd = mChanges[i].mTime;
        }
        if (aStart) {
          *aStart = mChanges[i - 1].mTime;
        }
        NS_ASSERTION(mChanges[i].mValue != mChanges[i - 1].mValue,
                     "Only changed values appear in array");
        return mChanges[i - 1].mValue;
      }
    }
  }
  /**
   * Advance the current time to aTime.
   */
  void AdvanceCurrentTime(Time aTime)
  {
    for (uint32_t i = 0; i < mChanges.Length(); ++i) {
      if (aTime < mChanges[i].mTime) {
        mChanges.RemoveElementsAt(0, i);
        return;
      }
      mCurrent = mChanges[i].mValue;
    }
    mChanges.Clear();
  }
  /**
   * Make all currently pending changes happen aDelta later than their
   * current change times.
   */
  void InsertTimeAtStart(Time aDelta)
  {
    for (uint32_t i = 0; i < mChanges.Length(); ++i) {
      mChanges[i].mTime += aDelta;
    }
  }

  /**
   * Replace the values of this function at aTimeOffset and later with the
   * values of aOther taken from zero, so if aOther is V at time T >= 0
   * then this function will be V at time T + aTimeOffset. aOther's current
   * time must be >= 0.
   */
  void Append(const TimeVarying& aOther, Time aTimeOffset)
  {
    NS_ASSERTION(aOther.mChanges.IsEmpty() || aOther.mChanges[0].mTime >= 0,
                 "Negative time not allowed here");
    NS_ASSERTION(&aOther != this, "Can't self-append");
    SetAtAndAfter(aTimeOffset, aOther.mCurrent);
    for (uint32_t i = 0; i < aOther.mChanges.Length(); ++i) {
      const Entry& e = aOther.mChanges[i];
      SetAtAndAfter(aTimeOffset + e.mTime, e.mValue);
    }
  }

  size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
  {
    return mChanges.SizeOfExcludingThis(aMallocSizeOf);
  }

private:
  struct Entry {
    Entry(Time aTime, const T& aValue) : mTime(aTime), mValue(aValue) {}

    // The time at which the value changes to mValue
    Time mTime;
    T mValue;
  };
  nsAutoTArray<Entry, ReservedChanges> mChanges;
  T mCurrent;
};

}

#endif /* MOZILLA_TIMEVARYING_H_ */