relational_value_store.h 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_BASE_RELATIONAL_VALUE_STORE_H_
  5. #define CARBON_TOOLCHAIN_BASE_RELATIONAL_VALUE_STORE_H_
  6. #include <optional>
  7. #include "common/check.h"
  8. #include "toolchain/base/value_store.h"
  9. #include "toolchain/base/value_store_types.h"
  10. namespace Carbon {
  11. // A ValueStore that builds a 1:1 relationship between two IDs.
  12. // * `RelatedStoreT` represents a related ValueStore with ids that can be used
  13. // to find values in this store.
  14. // * `IdT` is the actual ID of values in this store, and `IdT::ValueType` is the
  15. // value type being stored.
  16. //
  17. // The value store builds a mapping so that either ID can be used later to find
  18. // a value. And the user can query if a related `RelatedStoreT::IdType` has been
  19. // used to add a value to the store or not.
  20. //
  21. // When adding to the store, the user provides the related
  22. // `RelatedStoreT::IdType` along with the value being stored, and gets back the
  23. // ID of the value in the store.
  24. //
  25. // This store requires more storage space than normal ValueStore does, as it
  26. // requires storing a bit for presence of each `RelatedStore::IdType`. And it
  27. // allocates memory for values for all IDs up largest ID present in the store,
  28. // even if they are not yet used.
  29. template <typename RelatedStoreT, typename IdT, typename ValueT>
  30. class RelationalValueStore {
  31. public:
  32. using RelatedIdType = RelatedStoreT::IdType;
  33. using RelatedIdTagType = RelatedStoreT::IdTagType;
  34. using RelatedTagIdType = RelatedIdTagType::TagIdType;
  35. using ValueType = ValueStoreTypes<ValueT>::ValueType;
  36. using ConstRefType = ValueStoreTypes<ValueT>::ConstRefType;
  37. explicit RelationalValueStore(const RelatedStoreT* related_store)
  38. : values_(related_store->GetIdTag()), related_store_(related_store) {}
  39. // Given the related ID and a value, stores the value and returns a mapped ID
  40. // to reference it in the store.
  41. auto Add(RelatedIdType related_id, ValueType value) -> IdT {
  42. auto related_index = related_store_->GetRawIndex(related_id);
  43. values_.Resize(related_index + 1, std::nullopt);
  44. auto& opt = values_.Get(related_id);
  45. CARBON_CHECK(!opt.has_value(),
  46. "Add with `related_id` that was already added to the store");
  47. opt.emplace(std::move(value));
  48. return IdT(related_store_->GetIdTag().Apply(related_index).index);
  49. }
  50. // Returns the ID of a value in the store if the `related_id` was previously
  51. // used to add a value to the store, or None.
  52. auto TryGetId(RelatedIdType related_id) const -> IdT {
  53. auto related_index = related_store_->GetRawIndex(related_id);
  54. if (static_cast<size_t>(related_index) >= values_.size()) {
  55. return IdT::None;
  56. }
  57. auto& opt = values_.Get(related_id);
  58. if (!opt.has_value()) {
  59. return IdT::None;
  60. }
  61. return IdT(related_store_->GetIdTag().Apply(related_index).index);
  62. }
  63. // Returns a value for an ID.
  64. auto Get(IdT id) const -> ConstRefType {
  65. return *values_.Get(RelatedIdType(id.index));
  66. }
  67. private:
  68. ValueStore<RelatedIdType, std::optional<ValueType>, Tag<RelatedTagIdType>>
  69. values_;
  70. const RelatedStoreT* related_store_;
  71. };
  72. } // namespace Carbon
  73. #endif // CARBON_TOOLCHAIN_BASE_RELATIONAL_VALUE_STORE_H_