swift
timestampobjectlist.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 2015 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #ifndef SWIFT_MISC_TIMESTAMPOBJECTLIST_H
7 #define SWIFT_MISC_TIMESTAMPOBJECTLIST_H
8 
9 #include <algorithm>
10 
11 #include <QtGlobal>
12 
13 #include "config/buildconfig.h"
14 #include "misc/predicates.h"
15 #include "misc/swiftmiscexport.h"
16 #include "misc/timestampbased.h"
17 #include "misc/verify.h"
18 
19 class QDateTime;
20 
21 namespace swift::misc
22 {
25  {
26  qint64 min;
27  qint64 max;
28  double mean;
29 
31  bool isValid() const { return min >= 0 && max >= 0; }
32 
34  void reset()
35  {
36  min = -1;
37  max = -1;
38  mean = -1;
39  }
40 
42  QString asString() const
43  {
44  return QStringLiteral("Min: %1ms Max: %2ms Mean: %3ms").arg(min).arg(max).arg(mean, 0, 'f', 2);
45  }
46  };
47 
50  template <class OBJ, class CONTAINER>
52  {
53  static_assert(std::is_base_of_v<ITimestampBased, OBJ>, "OBJ needs to implement ITimestampBased");
54 
55  public:
58  {
59  NoTimestampSortHint,
60  TimestampLatestFirst,
61  TimestampLatestLast
62  };
63 
65  CONTAINER findBefore(const QDateTime &dateTime) const { return this->findBefore(dateTime.toMSecsSinceEpoch()); }
66 
68  CONTAINER findBefore(qint64 msSinceEpoch) const
69  {
70  return this->container().findBy([&](const OBJ &obj) { return obj.isOlderThan(msSinceEpoch); });
71  }
72 
74  OBJ findObjectBeforeOrDefault(qint64 msSinceEpoch) const
75  {
76  const CONTAINER before = this->findBefore(msSinceEpoch);
77  if (before.isEmpty()) { return OBJ(); }
78  return before.latestObject();
79  }
80 
82  CONTAINER findBeforeAndRemove(qint64 msSinceEpoch)
83  {
84  CONTAINER result(findBefore(msSinceEpoch));
85  this->removeBefore(msSinceEpoch);
86  return result;
87  }
88 
90  CONTAINER findBeforeNowMinusOffset(qint64 msOffset) const
91  {
92  return this->findBefore(QDateTime::currentMSecsSinceEpoch() - msOffset);
93  }
94 
96  CONTAINER findAfter(const QDateTime &dateTime) const { return this->findAfter(dateTime.toMSecsSinceEpoch()); }
97 
99  CONTAINER findAfter(qint64 msSinceEpoch) const
100  {
101  return this->container().findBy([&](const OBJ &obj) { return obj.isNewerThan(msSinceEpoch); });
102  }
103 
105  CONTAINER findAfterNowMinusOffset(qint64 msOffset) const
106  {
107  return this->findAfter(QDateTime::currentMSecsSinceEpoch() - msOffset);
108  }
109 
111  OBJ findObjectAfterOrDefault(qint64 msSinceEpoch) const
112  {
113  const CONTAINER after = this->findAfter(msSinceEpoch);
114  if (after.isEmpty()) { return OBJ(); }
115  return after.oldestObject();
116  }
117 
119  CONTAINER findInvalidTimestamps() const
120  {
121  return this->container().findBy([&](const OBJ &obj) { return !obj.hasValidTimestamp(); });
122  }
123 
125  OBJ findClosestTimeDistance(qint64 msSinceEpoch) const
126  {
127  if (this->container().isEmpty()) { return OBJ(); }
128  const auto closest = std::min_element(this->container().cbegin(), this->container().cend(),
129  [=](const ITimestampBased &a, const ITimestampBased &b) {
130  return qAbs(a.getTimeDifferenceMs(msSinceEpoch)) <
131  qAbs(b.getTimeDifferenceMs(msSinceEpoch));
132  });
133  return *closest;
134  }
135 
137  bool hasInvalidTimestamps() const { return this->container().contains(&OBJ::hasValidTimestamp, false); }
138 
141  {
142  for (ITimestampBased &tsObj : this->container()) { tsObj.setCurrentUtcTime(); }
143  }
144 
146  void setUtcTime(qint64 msSinceEpoch)
147  {
148  for (ITimestampBased &tsObj : this->container()) { tsObj.setMSecsSinceEpoch(msSinceEpoch); }
149  }
150 
153  {
154  for (ITimestampBased &tsObj : this->container())
155  {
156  if (tsObj.hasValidTimestamp()) { continue; }
157  tsObj.setCurrentUtcTime();
158  }
159  }
160 
163  {
164  if (this->container().isEmpty()) { return {}; }
165  return this->latestObject().getUtcTimestamp();
166  }
167 
170  {
171  const QDateTime dt(latestTimestamp());
172  return dt.isValid() ? dt.toMSecsSinceEpoch() : -1;
173  }
174 
177  {
178  if (this->container().isEmpty()) { return {}; }
179  return this->oldestObject().getUtcTimestamp();
180  }
181 
184  {
185  const QDateTime dt(oldestTimestamp());
186  return dt.isValid() ? dt.toMSecsSinceEpoch() : -1;
187  }
188 
190  OBJ latestObject() const
191  {
192  if (this->container().isEmpty()) { return OBJ(); }
193  const auto latest =
194  std::max_element(this->container().begin(), this->container().end(), [](const OBJ &a, const OBJ &b) {
195  return a.getMSecsSinceEpoch() < b.getMSecsSinceEpoch();
196  });
197  return *latest;
198  }
199 
201  OBJ oldestObject() const
202  {
203  if (this->container().isEmpty()) { return OBJ(); }
204  const auto oldest =
205  std::min_element(this->container().begin(), this->container().end(), [](const OBJ &a, const OBJ &b) {
206  return a.getMSecsSinceEpoch() < b.getMSecsSinceEpoch();
207  });
208  return *oldest;
209  }
210 
212  int removeBefore(const QDateTime &dateTime) { return this->removeBefore(dateTime.toMSecsSinceEpoch()); }
213 
215  int removeBefore(qint64 msSinceEpoch)
216  {
217  return this->container().removeIf([&](const OBJ &obj) { return obj.isOlderThan(msSinceEpoch); });
218  }
219 
221  int removeOlderThanNowMinusOffset(qint64 offsetMs)
222  {
223  const qint64 epoch = QDateTime::currentMSecsSinceEpoch() - offsetMs;
224  return this->container().removeIf([&](const OBJ &obj) { return obj.isOlderThan(epoch); });
225  }
226 
229  {
230  this->container().sortOldestFirst();
231  this->container().reverse();
232  }
233 
235  void sortOldestFirst() { this->container().sort(predicates::MemberLess(&OBJ::getMSecsSinceEpoch)); }
236 
238  void push_frontKeepLatestFirst(const OBJ &value, bool replaceSameTimestamp = true, int maxElements = -1)
239  {
240  Q_ASSERT_X(maxElements < 0 || maxElements > 1, Q_FUNC_INFO, "Max.value wrong range");
241  CONTAINER &c = this->container();
242  if (replaceSameTimestamp && !c.isEmpty() && c[0].getMSecsSinceEpoch() == value.getMSecsSinceEpoch())
243  {
244  c[0] = value;
245  if (maxElements > 0) { c.truncate(maxElements); }
246  }
247  else
248  {
249  if (maxElements > 0) { c.truncate(maxElements - 1); }
250  const bool needSort = !c.isEmpty() && value.isOlderThan(c.front());
251  c.push_front(value);
252  if (needSort) { ITimestampObjectList::sortLatestFirst(); }
253  }
254 
255  // crosscheck
257  {
258  Q_ASSERT_X(this->isSortedLatestFirst(), Q_FUNC_INFO, "Wrong sort order");
259  }
260  }
261 
264  void push_backIncreaseTimestamp(const OBJ &newObject)
265  {
266  if (this->container().isEmpty())
267  {
268  this->container().push_back(newObject);
269  return;
270  }
271  const qint64 newMs = newObject.getMSecsSinceEpoch();
272  const qint64 oldMs = this->container().back().getMSecsSinceEpoch();
273  if (newMs > oldMs)
274  {
275  this->container().push_back(newObject);
276  return;
277  }
278  this->push_backOverrideTimestamp(newObject, oldMs + 1);
279  }
280 
282  void push_backOverrideTimestamp(const OBJ &newObject, qint64 newTsMsSinceEpoch)
283  {
284  OBJ newObjectCopy(newObject);
285  newObjectCopy.setMSecsSinceEpoch(newTsMsSinceEpoch);
286  this->container().push_back(newObjectCopy);
287  }
288 
290  void setNewTimestampStartingLast(qint64 startTimeStampMs, qint64 deltaTimeMs)
291  {
292  if (this->container().isEmpty()) { return; }
293  qint64 currentMs = startTimeStampMs;
294  for (auto it = this->container().rbegin(); it != this->container().rend(); ++it)
295  {
296  it->setMSecsSinceEpoch(currentMs);
297  currentMs += deltaTimeMs;
298  }
299  }
300 
302  int replaceIfSameTimestamp(const OBJ &newObject)
303  {
304  int c = 0;
305  for (OBJ &obj : this->container())
306  {
307  if (obj.getMSecsSinceEpoch() == newObject.getMSecsSinceEpoch())
308  {
309  obj = newObject;
310  c++;
311  }
312  }
313  return c;
314  }
315 
318  bool isSortedLatestLast() const
319  {
320  if (this->container().size() < 2) { return true; }
321  qint64 max = -1;
322  for (const ITimestampBased &obj : this->container())
323  {
324  if (!obj.hasValidTimestamp()) { return false; }
325  if (obj.getMSecsSinceEpoch() < max) { return false; }
326  max = obj.getMSecsSinceEpoch();
327  }
328  return true;
329  }
330 
333  bool isSortedLatestFirst() const
334  {
335  if (this->container().size() < 2) { return true; }
336  qint64 min = std::numeric_limits<qint64>::max();
337  for (const ITimestampBased &obj : this->container())
338  {
339  if (!obj.hasValidTimestamp()) { return false; }
340  if (obj.getMSecsSinceEpoch() > min) { return false; }
341  min = obj.getMSecsSinceEpoch();
342  }
343  return true;
344  }
345 
347  void addMsecs(qint64 msToAdd)
348  {
349  if (msToAdd == 0) { return; }
350  for (ITimestampBased &obj : this->container()) { obj.addMsecs(msToAdd); }
351  }
352 
355 
359  {
361  mmm.reset();
362  const CONTAINER &container = this->container();
363  if (container.size() < 2) { return mmm; }
364 
365  // Do not confuse with adjusted sort hint!
366  if (container.m_tsSortHint == NoTimestampSortHint)
367  {
368  CONTAINER copy(container);
369  copy.sortLatestFirst();
370  copy.m_tsSortHint = TimestampLatestFirst;
371  return copy.getTimestampDifferenceMinMaxMean();
372  }
373 
374  mmm.max = std::numeric_limits<qint64>::min();
375  mmm.min = std::numeric_limits<qint64>::max();
376  qint64 mean = 0;
377  int c = 0;
378  OBJ last;
379 
380  for (const OBJ &object : container)
381  {
382  if (c > 0)
383  {
384  const ITimestampBased &l = last;
385  const ITimestampBased &o = object;
386  const qint64 diff = l.getAbsTimeDifferenceMs(o);
387  mmm.max = std::max(diff, mmm.max);
388  mmm.min = std::min(diff, mmm.min);
389  mean += diff;
390  }
391  c++;
392  last = object;
393  }
394 
395  mmm.mean = mean / c;
396  return mmm;
397  }
398 
399  protected:
401  ITimestampObjectList() = default;
402 
404  const CONTAINER &container() const { return static_cast<const CONTAINER &>(*this); }
405 
407  CONTAINER &container() { return static_cast<CONTAINER &>(*this); }
408 
409  HintTimestampSort m_tsSortHint = NoTimestampSortHint;
410  };
411 
414  template <class OBJ, class CONTAINER>
416  {
417  static_assert(std::is_base_of_v<ITimestampWithOffsetBased, OBJ>, "OBJ needs to implement ITimestampBased");
418 
419  public:
422  {
423  NoAdjustedTimestampSortHint,
424  AdjustedTimestampLatestFirst
425  };
426 
429  {
430  this->container().sortAdjustedOldestFirst();
431  this->container().reverse();
432  }
433 
436  {
437  CONTAINER copy(this->container());
438  copy.sortAdjustedLatestFirst();
439  return copy;
440  }
441 
443  CONTAINER getLatestAdjustedTwoObjects(bool alreadySortedLatestFirst = false) const
444  {
445  if (this->container().size() < 2) { return CONTAINER(); }
446  CONTAINER copy(alreadySortedLatestFirst ? this->container() :
448  copy.truncate(2);
449  return copy;
450  }
451 
454  {
455  this->container().sort(predicates::MemberLess(&OBJ::getAdjustedMSecsSinceEpoch));
456  }
457 
460  {
461  return std::any_of(this->container().begin(), this->container().end(),
462  [](const ITimestampWithOffsetBased &obj) { return obj.getTimeOffsetMs() <= 0; });
463  }
464 
467  {
468  return std::any_of(this->container().begin(), this->container().end(),
469  [](const ITimestampWithOffsetBased &obj) { return obj.getTimeOffsetMs() < 0; });
470  }
471 
473  void addMsecsToOffset(qint64 msToAdd)
474  {
475  for (ITimestampWithOffsetBased &obj : this->container()) { obj.addMsecsToOffsetTime(msToAdd); }
476  }
477 
479  void push_frontKeepLatestAdjustedFirst(const OBJ &value, bool replaceSameTimestamp = true, int maxElements = -1)
480  {
481  Q_ASSERT_X(maxElements < 0 || maxElements > 1, Q_FUNC_INFO, "Max.value wrong range");
482  CONTAINER &c = this->container();
483  if (replaceSameTimestamp && !c.isEmpty() && c[0].getMSecsSinceEpoch() == value.getMSecsSinceEpoch())
484  {
485  c[0] = value;
486  if (maxElements > 0) { c.truncate(maxElements); }
487  return;
488  }
489 
490  if (maxElements > 0) { c.truncate(maxElements - 1); }
491  const bool needSort = !c.isEmpty() && value.isOlderThanAdjusted(c.front());
492  c.push_front(value);
494  }
495 
498  void push_frontKeepLatestFirstAdjustOffset(const OBJ &value, bool replaceSameTimestamp = true,
499  int maxElements = -1)
500  {
502  maxElements);
503 
504  // now sorted by timestamp
505  // this reflects normally the incoming order
506  // ts
507  // 8: os 2 adj 12 => min os 4
508  // 6: os 2 adj 11 => min os 5
509  // 5: os 5 adj 10
510  // 0: os 5 adj 5
511  CONTAINER &c = this->container();
512  if (c.size() < 2) { return; }
513  ITimestampWithOffsetBased &front = c.front();
514  const ITimestampWithOffsetBased &second = c[1];
515  if (!front.isNewerThanAdjusted(second))
516  {
517  // const qint64 minOs = qMin(front.getTimeOffsetMs(), second.getTimeOffsetMs());
518  const qint64 minReqOs =
519  second.getAdjustedMSecsSinceEpoch() - front.getMSecsSinceEpoch(); // minimal required
520  const qint64 avgOs = (front.getTimeOffsetMs() + second.getTimeOffsetMs()) / 2;
521  const qint64 os = qMax(minReqOs + 1, avgOs); // at least +1, as value must be > (greater)
522  front.setTimeOffsetMs(os);
523  }
524 
526  {
527  SWIFT_VERIFY_X(front.isNewerThanAdjusted(second), Q_FUNC_INFO, "Front/second timestamp");
528  SWIFT_VERIFY_X(this->isSortedAdjustedLatestFirst(), Q_FUNC_INFO, "Wrong sort order");
529  }
530  }
531 
533  void push_frontKeepLatestFirstIgnoreOverlapping(const OBJ &value, bool replaceSameTimestamp = true,
534  int maxElements = -1)
535  {
536  CONTAINER &c = this->container();
537  if (c.size() > 1)
538  {
539  const ITimestampWithOffsetBased front = c.front();
540  if (value.getAdjustedMSecsSinceEpoch() <= front.getAdjustedMSecsSinceEpoch()) { return; }
541  }
543  maxElements);
544  }
545 
547  void prefillLatestAdjustedFirst(const OBJ &value, int elements, qint64 deltaTimeMs = -1)
548  {
549  this->container().clear();
550  const qint64 osTime = value.getTimeOffsetMs();
551  const qint64 os = -1 * qAbs(deltaTimeMs < 0 ? osTime : deltaTimeMs);
553  {
554  SWIFT_VERIFY_X(os < 0, Q_FUNC_INFO, "Need negative offset time to prefill time");
555  }
556  this->container().push_front(value);
557  for (int i = 1; i < elements; i++)
558  {
559  OBJ copy(value);
560  copy.addMsecs(os * i);
561  this->container().push_back(copy);
562  }
563  this->setAdjustedSortHint(ITimestampWithOffsetObjectList::AdjustedTimestampLatestFirst);
564  }
565 
569  {
570  if (this->container().isEmpty()) { return false; }
571  if (this->container().size() < 2) { return true; }
572  qint64 max = -1;
573  for (const ITimestampWithOffsetBased &obj : this->container())
574  {
575  if (!obj.hasValidTimestamp()) { return false; }
576  if (obj.getAdjustedMSecsSinceEpoch() < max) { return false; }
577  max = obj.getAdjustedMSecsSinceEpoch();
578  }
579  return true;
580  }
581 
585  {
586  if (this->container().size() < 2) { return true; }
587  qint64 min = std::numeric_limits<qint64>::max();
588  for (const ITimestampWithOffsetBased &obj : this->container())
589  {
590  if (!obj.hasValidTimestamp()) { return false; }
591  if (obj.getAdjustedMSecsSinceEpoch() > min) { return false; }
592  min = obj.getAdjustedMSecsSinceEpoch();
593  }
594  return true;
595  }
596 
598  CONTAINER findAfterAdjusted(qint64 msSinceEpoch) const
599  {
600  return this->container().findBy(
601  [&](const ITimestampWithOffsetBased &obj) { return obj.isNewerThanAdjusted(msSinceEpoch); });
602  }
603 
605  OBJ findObjectAfterAdjustedOrDefault(qint64 msSinceEpoch) const
606  {
607  const CONTAINER after = this->findAfterAdjusted(msSinceEpoch);
608  if (after.isEmpty()) { return OBJ(); }
609  return after.oldestAdjustedObject();
610  }
611 
613  CONTAINER findBeforeAdjusted(qint64 msSinceEpoch) const
614  {
615  return this->container().findBy(
616  [&](const ITimestampWithOffsetBased &obj) { return obj.isOlderThanAdjusted(msSinceEpoch); });
617  }
618 
620  OBJ findObjectBeforeAdjustedOrDefault(qint64 msSinceEpoch) const
621  {
622  const CONTAINER before = this->findBeforeAdjusted(msSinceEpoch);
623  if (before.isEmpty()) { return OBJ(); }
624  return before.latestAdjustedObject();
625  }
626 
628  OBJ findClosestTimeDistanceAdjusted(qint64 msSinceEpoch) const
629  {
630  if (this->container().isEmpty()) { return OBJ(); }
631  const auto closest =
632  std::min_element(this->container().cbegin(), this->container().cend(),
633  [=](const ITimestampWithOffsetBased &a, const ITimestampWithOffsetBased &b) {
634  return qAbs(a.getAdjustedTimeDifferenceMs(msSinceEpoch)) <
635  qAbs(b.getAdjustedTimeDifferenceMs(msSinceEpoch));
636  });
637  return *closest;
638  }
639 
642  {
643  if (this->container().isEmpty()) { return OBJ(); }
644  if (this->container().m_tsAdjustedSortHint == AdjustedTimestampLatestFirst)
645  {
646  return this->container().front();
647  }
648  const auto latest =
649  std::max_element(this->container().begin(), this->container().end(), [](const OBJ &a, const OBJ &b) {
650  return a.getAdjustedMSecsSinceEpoch() < b.getAdjustedMSecsSinceEpoch();
651  });
652  return *latest;
653  }
654 
657  {
658  if (this->container().isEmpty()) { return OBJ(); }
659  if (this->container().m_tsAdjustedSortHint == AdjustedTimestampLatestFirst)
660  {
661  return this->container().back();
662  }
663  const auto oldest =
664  std::min_element(this->container().begin(), this->container().end(), [](const OBJ &a, const OBJ &b) {
665  return a.getAdjustedMSecsSinceEpoch() < b.getAdjustedMSecsSinceEpoch();
666  });
667  return *oldest;
668  }
669 
672  {
673  if (this->container().isEmpty()) { return {}; }
674  return this->latestAdjustedObject().getUtcTimestamp();
675  }
676 
679  {
680  if (this->container().isEmpty()) { return {}; }
681  return this->oldestAdjustedObject().getUtcTimestamp();
682  }
683 
686  {
687  if (this->container().isEmpty()) { return -1; }
688  const QDateTime dt(this->latestAdjustedTimestamp());
689  return dt.isValid() ? dt.toMSecsSinceEpoch() : -1;
690  }
691 
694  {
695  if (this->container().isEmpty()) { return -1; }
697  return dt.isValid() ? dt.toMSecsSinceEpoch() : -1;
698  }
699 
701  void setAdjustedSortHint(HintAdjustedTimestampSort hint) { this->container().m_tsAdjustedSortHint = hint; }
702 
706  {
708  mmm.reset();
709  const CONTAINER &container = this->container();
710  if (container.size() < 1) { return mmm; }
711 
712  mmm.max = std::numeric_limits<qint64>::min();
713  mmm.min = std::numeric_limits<qint64>::max();
714  qint64 mean = 0;
715  int c = 0;
716 
717  for (const ITimestampWithOffsetBased &object : container)
718  {
719  if (!object.hasNonZeroOffsetTime()) { continue; }
720  const qint64 os = object.getTimeOffsetMs();
721  mmm.max = std::max(os, mmm.max);
722  mmm.min = std::min(os, mmm.min);
723  mean += os;
724  c++;
725  }
726 
727  if (c > 0) { mmm.mean = mean / c; }
728  return mmm;
729  }
730 
731  protected:
734 
735  HintAdjustedTimestampSort m_tsAdjustedSortHint = NoAdjustedTimestampSortHint;
736  };
737 } // namespace swift::misc
738 
739 #endif // SWIFT_MISC_TIMESTAMPOBJECTLIST_H
static bool isLocalDeveloperDebugBuild()
Local build for developers.
Entity with timestamp.
qint64 getMSecsSinceEpoch() const
Timestamp as ms value.
qint64 getTimeDifferenceMs(qint64 compareTime) const
Time difference in ms.
qint64 getAbsTimeDifferenceMs(qint64 compareTime) const
Time difference in ms.
List of objects with timestamp. Such objects should implement.
OBJ findObjectBeforeOrDefault(qint64 msSinceEpoch) const
Object before timestamp or default (older)
qint64 latestTimestampMsecsSinceEpoch() const
Latest timestamp.
QDateTime latestTimestamp() const
Latest timestamp.
void push_backOverrideTimestamp(const OBJ &newObject, qint64 newTsMsSinceEpoch)
Push back, but set new timestamp.
void setSortHint(HintTimestampSort hint)
Set the hint.
HintTimestampSort m_tsSortHint
sort hint
void sortOldestFirst()
Sort by timestamp.
OBJ oldestObject() const
Latest object.
int removeBefore(qint64 msSinceEpoch)
Remove objects with timestamp before dateTime.
CONTAINER findBeforeNowMinusOffset(qint64 msOffset) const
List of objects before now - offset.
int replaceIfSameTimestamp(const OBJ &newObject)
Replace if an object has the same timestamp.
CONTAINER findAfter(const QDateTime &dateTime) const
List of objects after dateTime (newer)
void addMsecs(qint64 msToAdd)
Adds a time to all values.
const CONTAINER & container() const
Container.
qint64 oldestTimestampMsecsSinceEpoch() const
Oldest timestamp.
CONTAINER findBeforeAndRemove(qint64 msSinceEpoch)
Get objects before msSinceEpoch and remove those.
MillisecondsMinMaxMean getTimestampDifferenceMinMaxMean() const
Difference of timestamp values.
CONTAINER findAfter(qint64 msSinceEpoch) const
List of objects after msSinceEpoch (newer)
ITimestampObjectList()=default
Constructor.
void setCurrentUtcTime()
Set all timestamps to now.
OBJ findObjectAfterOrDefault(qint64 msSinceEpoch) const
List of objects after msSinceEpoch (newer)
void setInvalidTimestampsToCurrentUtcTime()
Set invalid timestamps to now.
OBJ latestObject() const
Latest object.
void sortLatestFirst()
Sort by timestamp.
HintTimestampSort
Hint if the list is sorted.
void push_backIncreaseTimestamp(const OBJ &newObject)
Push back and increase the timestamp at least by +1ms if equal to last element.
int removeBefore(const QDateTime &dateTime)
Remove objects with timestamp before dateTime.
int removeOlderThanNowMinusOffset(qint64 offsetMs)
Remove objects older than seconds.
bool isSortedLatestLast() const
Is completely sorted: latest last.
void push_frontKeepLatestFirst(const OBJ &value, bool replaceSameTimestamp=true, int maxElements=-1)
Insert as first element by keeping maxElements and the latest first.
QDateTime oldestTimestamp() const
Oldest timestamp.
CONTAINER findBefore(const QDateTime &dateTime) const
List of objects before dateTime (older)
CONTAINER findBefore(qint64 msSinceEpoch) const
List of objects before msSinceEpoch (older)
bool hasInvalidTimestamps() const
Has invalid timestamp.
void setUtcTime(qint64 msSinceEpoch)
Set all timestamps to given time.
CONTAINER findInvalidTimestamps() const
Objects without valid timestamp.
bool isSortedLatestFirst() const
Is completely sorted: latest last.
void setNewTimestampStartingLast(qint64 startTimeStampMs, qint64 deltaTimeMs)
Set new timestamps starting with the last element.
CONTAINER findAfterNowMinusOffset(qint64 msOffset) const
List of objects before now - offset.
OBJ findClosestTimeDistance(qint64 msSinceEpoch) const
Find closest (or default)
qint64 getAdjustedMSecsSinceEpoch() const
Timestamp with offset added for interpolation.
qint64 getTimeOffsetMs() const
Milliseconds to add to timestamp for interpolation.
bool isNewerThanAdjusted(const ITimestampWithOffsetBased &otherTimestampObj) const
Is this newer than other?
bool isOlderThanAdjusted(const ITimestampWithOffsetBased &otherTimestampObj) const
Is this older than other?
qint64 getAdjustedTimeDifferenceMs(qint64 compareTime) const
Time difference in ms (this -> compare)
void setTimeOffsetMs(qint64 offset)
Milliseconds to add to timestamp for interpolation.
List of objects with timestamp and offset. Such objects should implement.
OBJ findClosestTimeDistanceAdjusted(qint64 msSinceEpoch) const
Closest adjusted time difference.
bool containsZeroOrNegativeOffsetTime() const
Any negative or zero offset time?
CONTAINER getLatestAdjustedTwoObjects(bool alreadySortedLatestFirst=false) const
Get the latest 2 values.
HintAdjustedTimestampSort
Hint if the list is sorted.
QDateTime oldestAdjustedTimestamp() const
Oldest adjusted timestamp.
bool isSortedAdjustedLatestFirst() const
Is completely sorted: latest last.
OBJ findObjectBeforeAdjustedOrDefault(qint64 msSinceEpoch) const
Object before timestamp (older)
void setAdjustedSortHint(HintAdjustedTimestampSort hint)
Set the hint.
CONTAINER findBeforeAdjusted(qint64 msSinceEpoch) const
List of objects before msSinceEpoch (older)
OBJ latestAdjustedObject() const
Latest adjusted object.
bool isSortedAdjustedLatestLast() const
Is completely sorted: latest last.
MillisecondsMinMaxMean getOffsetMinMaxMean() const
Difference of timestamp values.
void addMsecsToOffset(qint64 msToAdd)
Adds a time to all offset values.
void push_frontKeepLatestAdjustedFirst(const OBJ &value, bool replaceSameTimestamp=true, int maxElements=-1)
Insert as first element by keeping maxElements and the latest first.
qint64 oldestAdjustedTimestampMsecsSinceEpoch() const
Oldest adjusted timestamp.
void sortAdjustedLatestFirst()
Sort by adjusted timestamp.
bool containsNegativeOffsetTime() const
Any negative offset time?
CONTAINER getSortedAdjustedLatestFirst() const
As sorted copy.
void prefillLatestAdjustedFirst(const OBJ &value, int elements, qint64 deltaTimeMs=-1)
Prefill with elements.
QDateTime latestAdjustedTimestamp() const
Latest adjusted timestamp.
OBJ oldestAdjustedObject() const
Oldest adjusted object.
void push_frontKeepLatestFirstAdjustOffset(const OBJ &value, bool replaceSameTimestamp=true, int maxElements=-1)
Insert as first element by keeping maxElements and the latest first.
HintAdjustedTimestampSort m_tsAdjustedSortHint
sort hint
void push_frontKeepLatestFirstIgnoreOverlapping(const OBJ &value, bool replaceSameTimestamp=true, int maxElements=-1)
Add value, but ignore overlapping (past) values.
qint64 latestAdjustedTimestampMsecsSinceEpoch() const
Latest adjusted timestamp.
CONTAINER findAfterAdjusted(qint64 msSinceEpoch) const
List of objects after msSinceEpoch (newer)
OBJ findObjectAfterAdjustedOrDefault(qint64 msSinceEpoch) const
List of objects after msSinceEpoch (newer)
ITimestampWithOffsetObjectList()=default
Constructor.
void sortAdjustedOldestFirst()
Sort by adjusted timestamp.
auto MemberLess(Ts... vs)
Predicate which compares the return values of some member functions of two objects.
Definition: predicates.h:43
Free functions in swift::misc.
T::const_iterator begin(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
Definition: lockfree.h:332
T::const_iterator end(const LockFreeReader< T > &reader)
Non-member begin() and end() for so LockFree containers can be used in ranged for loops.
Definition: lockfree.h:338
qint64 currentMSecsSinceEpoch()
bool isValid() const const
qint64 toMSecsSinceEpoch() const const
QString arg(Args &&... args) const const
Milliseconds minimum/maximum/mean.
QString asString() const
As string.
#define SWIFT_VERIFY_X(COND, WHERE, WHAT)
A weaker kind of assert.
Definition: verify.h:26