range_map.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-3.0-or-later
  3. #pragma once
  4. #include <map>
  5. #include <type_traits>
  6. #include "common/common_types.h"
  7. namespace Common {
  8. template <typename KeyTBase, typename ValueT>
  9. class RangeMap {
  10. private:
  11. using KeyT =
  12. std::conditional_t<std::is_signed_v<KeyTBase>, KeyTBase, std::make_signed_t<KeyTBase>>;
  13. public:
  14. explicit RangeMap(ValueT null_value_) : null_value{null_value_} {
  15. container.emplace(std::numeric_limits<KeyT>::min(), null_value);
  16. };
  17. ~RangeMap() = default;
  18. void Map(KeyTBase address, KeyTBase address_end, ValueT value) {
  19. KeyT new_address = static_cast<KeyT>(address);
  20. KeyT new_address_end = static_cast<KeyT>(address_end);
  21. if (new_address < 0) {
  22. new_address = 0;
  23. }
  24. if (new_address_end < 0) {
  25. new_address_end = 0;
  26. }
  27. InternalMap(new_address, new_address_end, value);
  28. }
  29. void Unmap(KeyTBase address, KeyTBase address_end) {
  30. Map(address, address_end, null_value);
  31. }
  32. [[nodiscard]] size_t GetContinuousSizeFrom(KeyTBase address) const {
  33. const KeyT new_address = static_cast<KeyT>(address);
  34. if (new_address < 0) {
  35. return 0;
  36. }
  37. return ContinuousSizeInternal(new_address);
  38. }
  39. [[nodiscard]] ValueT GetValueAt(KeyT address) const {
  40. const KeyT new_address = static_cast<KeyT>(address);
  41. if (new_address < 0) {
  42. return null_value;
  43. }
  44. return GetValueInternal(new_address);
  45. }
  46. private:
  47. using MapType = std::map<KeyT, ValueT>;
  48. using IteratorType = typename MapType::iterator;
  49. using ConstIteratorType = typename MapType::const_iterator;
  50. size_t ContinuousSizeInternal(KeyT address) const {
  51. const auto it = GetFirstElementBeforeOrOn(address);
  52. if (it == container.end() || it->second == null_value) {
  53. return 0;
  54. }
  55. const auto it_end = std::next(it);
  56. if (it_end == container.end()) {
  57. return std::numeric_limits<KeyT>::max() - address;
  58. }
  59. return it_end->first - address;
  60. }
  61. ValueT GetValueInternal(KeyT address) const {
  62. const auto it = GetFirstElementBeforeOrOn(address);
  63. if (it == container.end()) {
  64. return null_value;
  65. }
  66. return it->second;
  67. }
  68. ConstIteratorType GetFirstElementBeforeOrOn(KeyT address) const {
  69. auto it = container.lower_bound(address);
  70. if (it == container.begin()) {
  71. return it;
  72. }
  73. if (it != container.end() && (it->first == address)) {
  74. return it;
  75. }
  76. --it;
  77. return it;
  78. }
  79. ValueT GetFirstValueWithin(KeyT address) {
  80. auto it = container.lower_bound(address);
  81. if (it == container.begin()) {
  82. return it->second;
  83. }
  84. if (it == container.end()) [[unlikely]] { // this would be a bug
  85. return null_value;
  86. }
  87. --it;
  88. return it->second;
  89. }
  90. ValueT GetLastValueWithin(KeyT address) {
  91. auto it = container.upper_bound(address);
  92. if (it == container.end()) {
  93. return null_value;
  94. }
  95. if (it == container.begin()) [[unlikely]] { // this would be a bug
  96. return it->second;
  97. }
  98. --it;
  99. return it->second;
  100. }
  101. void InternalMap(KeyT address, KeyT address_end, ValueT value) {
  102. const bool must_add_start = GetFirstValueWithin(address) != value;
  103. const ValueT last_value = GetLastValueWithin(address_end);
  104. const bool must_add_end = last_value != value;
  105. auto it = container.lower_bound(address);
  106. const auto it_end = container.upper_bound(address_end);
  107. while (it != it_end) {
  108. it = container.erase(it);
  109. }
  110. if (must_add_start) {
  111. container.emplace(address, value);
  112. }
  113. if (must_add_end) {
  114. container.emplace(address_end, last_value);
  115. }
  116. }
  117. ValueT null_value;
  118. MapType container;
  119. };
  120. } // namespace Common