data_abstract_sparse_ids.h 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. template <typename IdsContainer>
  9. class AbstractSparseIds {
  10. public:
  11. using Id = typename IdsContainer::value_type;
  12. AbstractSparseIds() = default;
  13. AbstractSparseIds(
  14. const IdsContainer &ids,
  15. std::optional<int> fullCount,
  16. std::optional<int> skippedBefore,
  17. std::optional<int> skippedAfter)
  18. : _ids(ids)
  19. , _fullCount(fullCount)
  20. , _skippedBefore(skippedBefore)
  21. , _skippedAfter(skippedAfter) {
  22. }
  23. [[nodiscard]] std::optional<int> fullCount() const {
  24. return _fullCount;
  25. }
  26. [[nodiscard]] std::optional<int> skippedBefore() const {
  27. return _skippedBefore;
  28. }
  29. [[nodiscard]] std::optional<int> skippedAfter() const {
  30. return _skippedAfter;
  31. }
  32. [[nodiscard]] std::optional<int> indexOf(Id id) const {
  33. const auto it = ranges::find(_ids, id);
  34. if (it != _ids.end()) {
  35. return (it - _ids.begin());
  36. }
  37. return std::nullopt;
  38. }
  39. [[nodiscard]] int size() const {
  40. return _ids.size();
  41. }
  42. [[nodiscard]] Id operator[](int index) const {
  43. Expects(index >= 0 && index < size());
  44. return *(_ids.begin() + index);
  45. }
  46. [[nodiscard]] std::optional<int> distance(Id a, Id b) const {
  47. if (const auto i = indexOf(a)) {
  48. if (const auto j = indexOf(b)) {
  49. return *j - *i;
  50. }
  51. }
  52. return std::nullopt;
  53. }
  54. [[nodiscard]] std::optional<Id> nearest(Id id) const {
  55. static_assert(std::is_same_v<IdsContainer, base::flat_set<Id>>);
  56. if (const auto it = ranges::lower_bound(_ids, id); it != _ids.end()) {
  57. return *it;
  58. } else if (_ids.empty()) {
  59. return std::nullopt;
  60. }
  61. return _ids.back();
  62. }
  63. void reverse() {
  64. ranges::reverse(_ids);
  65. std::swap(_skippedBefore, _skippedAfter);
  66. }
  67. friend inline bool operator==(
  68. const AbstractSparseIds&,
  69. const AbstractSparseIds&) = default;
  70. private:
  71. IdsContainer _ids;
  72. std::optional<int> _fullCount;
  73. std::optional<int> _skippedBefore;
  74. std::optional<int> _skippedAfter;
  75. };