HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
timeCodeRange.h
Go to the documentation of this file.
1 //
2 // Copyright 2019 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_USD_USD_UTILS_TIME_CODE_RANGE_H
25 #define PXR_USD_USD_UTILS_TIME_CODE_RANGE_H
26 
27 /// \file usdUtils/timeCodeRange.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/usdUtils/api.h"
31 
32 #include "pxr/base/gf/math.h"
33 #include "pxr/base/tf/diagnostic.h"
35 #include "pxr/usd/usd/timeCode.h"
36 
37 #include <iosfwd>
38 #include <iterator>
39 #include <string>
40 
41 
43 
44 
45 #define USDUTILS_TIME_CODE_RANGE_TOKENS \
46  ((EmptyTimeCodeRange, "NONE")) \
47  ((RangeSeparator, ":")) \
48  ((StrideSeparator, "x"))
49 
51  UsdUtilsTimeCodeRangeTokens,
54 
55 
56 /// \class UsdUtilsTimeCodeRange
57 ///
58 /// Represents a range of UsdTimeCode values as start and end time codes and a
59 /// stride value.
60 ///
61 /// A UsdUtilsTimeCodeRange can be iterated to retrieve all time code values in
62 /// the range. The range may be empty, it may contain a single time code, or it
63 /// may represent multiple time codes from start to end. The interval defined
64 /// by the start and end time codes is closed on both ends.
65 ///
66 /// Note that when constructing a UsdUtilsTimeCodeRange,
67 /// UsdTimeCode::EarliestTime() and UsdTimeCode::Default() cannot be used as
68 /// the start or end time codes. Also, the end time code cannot be less than
69 /// the start time code for positive stride values, and the end time code
70 /// cannot be greater than the start time code for negative stride values.
71 /// Finally, the stride value cannot be zero. If any of these conditions are
72 /// not satisfied, then an invalid empty range will be returned.
74 {
75 public:
76 
77  /// \class const_iterator
78  ///
79  /// A forward iterator into a UsdUtilsTimeCodeRange.
81  {
82  public:
83  using iterator_category = std::forward_iterator_tag;
85  using reference = const UsdTimeCode&;
86  using pointer = const UsdTimeCode*;
87  using difference_type = std::ptrdiff_t;
88 
89  /// Returns the UsdTimeCode referenced by this iterator.
91  return _currTimeCode;
92  }
93 
94  /// Returns a pointer to the UsdTimeCode referenced by this iterator.
96  return &_currTimeCode;
97  }
98 
99  /// Pre-increment operator. Advances this iterator to the next
100  /// UsdTimeCode in the range.
101  ///
102  /// This iterator is returned.
104  if (_timeCodeRange) {
105  ++_currStep;
106  _currTimeCode =
107  UsdTimeCode(
108  _timeCodeRange->_startTimeCode.GetValue() +
109  _timeCodeRange->_stride * _currStep);
110  }
111  _InvalidateIfExhausted();
112  return *this;
113  }
114 
115  /// Post-increment operator. Advances this iterator to the next
116  /// UsdTimeCode in the range.
117  ///
118  /// A copy of this iterator prior to the increment is returned.
120  const_iterator preAdvanceIter = *this;
121  ++(*this);
122  return preAdvanceIter;
123  }
124 
125  /// Return true if this iterator is equivalent to \p other.
126  bool operator ==(const const_iterator& other) const {
127  return _timeCodeRange == other._timeCodeRange &&
128  _currStep == other._currStep;
129  }
130 
131  /// Return true if this iterator is not equivalent to \p other.
132  bool operator !=(const const_iterator& other) const {
133  return !(*this == other);
134  }
135 
136  private:
137  friend class UsdUtilsTimeCodeRange;
138 
139  const_iterator(const UsdUtilsTimeCodeRange* timeCodeRange) :
140  _timeCodeRange(timeCodeRange),
141  _currStep(0u),
142  _maxSteps(0u),
143  _currTimeCode()
144  {
145  if (_timeCodeRange) {
146  const double startVal = _timeCodeRange->_startTimeCode.GetValue();
147  const double endVal = _timeCodeRange->_endTimeCode.GetValue();
148  const double stride = _timeCodeRange->_stride;
149 
150  _maxSteps = static_cast<size_t>(
151  GfFloor((endVal - startVal + stride) / stride));
152  _currTimeCode = _timeCodeRange->_startTimeCode;
153  }
154 
155  _InvalidateIfExhausted();
156  }
157 
158  void _InvalidateIfExhausted() {
159  bool finished = false;
160  if (!_timeCodeRange) {
161  finished = true;
162  } else if (_currStep >= _maxSteps) {
163  finished = true;
164  }
165 
166  if (finished) {
167  _timeCodeRange = nullptr;
168  _currStep = 0u;
169  _maxSteps = 0u;
170  _currTimeCode = UsdTimeCode();
171  }
172  }
173 
174  const UsdUtilsTimeCodeRange* _timeCodeRange;
175  size_t _currStep;
176  size_t _maxSteps;
177  UsdTimeCode _currTimeCode;
178  };
179 
181 
182  /// Create a time code range from \p frameSpec.
183  ///
184  /// A FrameSpec is a compact string representation of a time code range.
185  /// A FrameSpec may contain up to three floating point values for the start
186  /// time code, end time code, and stride values of a time code range.
187  ///
188  /// A FrameSpec containing just a single floating point value represents
189  /// a time code range containing only that time code.
190  ///
191  /// A FrameSpec containing two floating point values separated by the range
192  /// separator (':') represents a time code range from the first value as
193  /// the start time code to the second values as the end time code.
194  ///
195  /// A FrameSpec that specifies both a start and end time code value may
196  /// also optionally specify a third floating point value as the stride,
197  /// separating it from the first two values using the stride separator
198  /// ('x').
199  ///
200  /// The following are examples of valid FrameSpecs:
201  /// 123
202  /// 101:105
203  /// 105:101
204  /// 101:109x2
205  /// 101:110x2
206  /// 101:104x0.5
207  ///
208  /// An empty string corresponds to an invalid empty time code range.
209  ///
210  /// A coding error will be issued if the given string is malformed.
213  const std::string& frameSpec);
214 
215  /// Construct an invalid empty range.
216  ///
217  /// The start time code will be initialized to zero, and any iteration of
218  /// the range will yield no time codes.
220  {
221  _Invalidate();
222  }
223 
224  /// Construct a range containing only the given \p timeCode.
225  ///
226  /// An iteration of the range will yield only that time code.
228  UsdUtilsTimeCodeRange(timeCode, timeCode)
229  {
230  }
231 
232  /// Construct a range containing the time codes from \p startTimeCode to
233  /// \p endTimeCode.
234  ///
235  /// If \p endTimeCode is greater than or equal to \p startTimeCode, then
236  /// the stride will be 1.0. Otherwise, the stride will be -1.0.
238  const UsdTimeCode startTimeCode,
239  const UsdTimeCode endTimeCode) :
241  startTimeCode,
242  endTimeCode,
243  (endTimeCode >= startTimeCode) ? 1.0 : -1.0)
244  {
245  }
246 
247  /// Construct a range containing the time codes from \p startTimeCode to
248  /// \p endTimeCode using the stride value \p stride.
249  ///
250  /// UsdTimeCode::EarliestTime() and UsdTimeCode::Default() cannot be used
251  /// as \p startTimeCode or \p endTimeCode. If \p stride is a positive
252  /// value, then \p endTimeCode cannot be less than \p startTimeCode. If
253  /// \p stride is a negative value, then \p endTimeCode cannot be greater
254  /// than \p startTimeCode. Finally, the stride value cannot be zero. If any
255  /// of these conditions are not satisfied, then a coding error will be
256  /// issued and an invalid empty range will be returned.
258  const UsdTimeCode startTimeCode,
259  const UsdTimeCode endTimeCode,
260  const double stride) :
261  _startTimeCode(startTimeCode),
262  _endTimeCode(endTimeCode),
263  _stride(stride)
264  {
265  if (_startTimeCode.IsEarliestTime()) {
267  "startTimeCode cannot be UsdTimeCode::EarliestTime()");
268  _Invalidate();
269  return;
270  }
271  if (_startTimeCode.IsDefault()) {
273  "startTimeCode cannot be UsdTimeCode::Default()");
274  _Invalidate();
275  return;
276  }
277  if (_endTimeCode.IsEarliestTime()) {
279  "endTimeCode cannot be UsdTimeCode::EarliestTime()");
280  _Invalidate();
281  return;
282  }
283  if (_endTimeCode.IsDefault()) {
285  "endTimeCode cannot be UsdTimeCode::Default()");
286  _Invalidate();
287  return;
288  }
289 
290  if (_stride > 0.0) {
291  if (_endTimeCode < _startTimeCode) {
293  "endTimeCode cannot be less than startTimeCode with "
294  "positive stride");
295  _Invalidate();
296  return;
297  }
298  } else if (_stride < 0.0) {
299  if (_endTimeCode > _startTimeCode) {
301  "endTimeCode cannot be greater than startTimeCode with "
302  "negative stride");
303  _Invalidate();
304  return;
305  }
306  } else {
307  TF_CODING_ERROR("stride cannot be zero");
308  _Invalidate();
309  return;
310  }
311  }
312 
313  /// Return the start time code of this range.
315  return _startTimeCode;
316  }
317 
318  /// Return the end time code of this range.
320  return _endTimeCode;
321  }
322 
323  /// Return the stride value of this range.
324  double GetStride() const {
325  return _stride;
326  }
327 
328  /// Return an iterator to the start of this range.
329  iterator begin() const {
330  return iterator(this);
331  }
332 
333  /// Return a const_iterator to the start of this range.
335  return const_iterator(this);
336  }
337 
338  /// Return the past-the-end iterator for this range.
339  iterator end() const {
340  return iterator(nullptr);
341  }
342 
343  /// Return the past-the-end const_iterator for this range.
345  return const_iterator(nullptr);
346  }
347 
348  /// Return true if this range contains no time codes, or false otherwise.
349  bool empty() const {
350  return begin() == end();
351  }
352 
353  /// Return true if this range contains one or more time codes, or false
354  /// otherwise.
355  bool IsValid() const {
356  return !empty();
357  }
358 
359  /// Return true if this range contains one or more time codes, or false
360  /// otherwise.
361  explicit operator bool() const {
362  return IsValid();
363  }
364 
365  /// Return true if this range is equivalent to \p other.
366  bool operator ==(const UsdUtilsTimeCodeRange& other) const {
367  return _startTimeCode == other._startTimeCode &&
368  _endTimeCode == other._endTimeCode &&
369  _stride == other._stride;
370  }
371 
372  /// Return true if this range is not equivalent to \p other.
373  bool operator !=(const UsdUtilsTimeCodeRange& other) const {
374  return !(*this == other);
375  }
376 
377 private:
378 
379  /// Sets the range such that it yields no time codes.
380  void _Invalidate() {
381  _startTimeCode = UsdTimeCode(0.0);
382  _endTimeCode = UsdTimeCode(-1.0);
383  _stride = 1.0;
384  }
385 
386  UsdTimeCode _startTimeCode;
387  UsdTimeCode _endTimeCode;
388  double _stride;
389 };
390 
391 // Stream I/O operators.
392 
393 /// Stream insertion operator.
395 std::ostream& operator<<(
396  std::ostream& os,
397  const UsdUtilsTimeCodeRange& timeCodeRange);
398 
399 /// Stream extraction operator.
401 std::istream& operator>>(
402  std::istream& is,
403  UsdUtilsTimeCodeRange& timeCodeRange);
404 
405 
407 
408 
409 #endif
UsdUtilsTimeCodeRange(const UsdTimeCode timeCode)
double GetValue() const
Definition: timeCode.h:151
reference operator*()
Returns the UsdTimeCode referenced by this iterator.
Definition: timeCodeRange.h:90
bool operator==(const UsdUtilsTimeCodeRange &other) const
Return true if this range is equivalent to other.
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
#define TF_CODING_ERROR
UsdTimeCode GetEndTimeCode() const
Return the end time code of this range.
iterator begin() const
Return an iterator to the start of this range.
static USDUTILS_API UsdUtilsTimeCodeRange CreateFromFrameSpec(const std::string &frameSpec)
bool IsEarliestTime() const
Definition: timeCode.h:133
UsdUtilsTimeCodeRange(const UsdTimeCode startTimeCode, const UsdTimeCode endTimeCode)
const_iterator cbegin() const
Return a const_iterator to the start of this range.
iterator end() const
Return the past-the-end iterator for this range.
pointer operator->()
Returns a pointer to the UsdTimeCode referenced by this iterator.
Definition: timeCodeRange.h:95
bool operator!=(const UsdUtilsTimeCodeRange &other) const
Return true if this range is not equivalent to other.
UsdUtilsTimeCodeRange(const UsdTimeCode startTimeCode, const UsdTimeCode endTimeCode, const double stride)
bool IsDefault() const
Definition: timeCode.h:139
GLint GLenum GLboolean GLsizei stride
Definition: glcorearb.h:872
#define USDUTILS_TIME_CODE_RANGE_TOKENS
Definition: timeCodeRange.h:45
const_iterator cend() const
Return the past-the-end const_iterator for this range.
bool empty() const
Return true if this range contains no time codes, or false otherwise.
bool operator==(const const_iterator &other) const
Return true if this iterator is equivalent to other.
TF_DECLARE_PUBLIC_TOKENS(UsdUtilsTimeCodeRangeTokens, USDUTILS_API, USDUTILS_TIME_CODE_RANGE_TOKENS)
USDUTILS_API std::istream & operator>>(std::istream &is, UsdUtilsTimeCodeRange &timeCodeRange)
Stream extraction operator.
double GfFloor(double f)
Definition: math.h:101
bool operator!=(const const_iterator &other) const
Return true if this iterator is not equivalent to other.
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1432
const_iterator iterator
std::forward_iterator_tag iterator_category
Definition: timeCodeRange.h:83
bool IsValid() const
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
UsdTimeCode GetStartTimeCode() const
Return the start time code of this range.
#define USDUTILS_API
Definition: api.h:40
USDUTILS_API std::ostream & operator<<(std::ostream &os, const UsdUtilsTimeCodeRange &timeCodeRange)
Stream insertion operator.
double GetStride() const
Return the stride value of this range.