relational_value_store.h 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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 "llvm/ADT/SmallVector.h"
  9. #include "toolchain/base/value_store.h"
  10. #include "toolchain/base/value_store_types.h"
  11. namespace Carbon {
  12. // A ValueStore that builds a 1:1 relationship between two IDs.
  13. // * `RelatedStoreT` represents a related ValueStore with ids that can be used
  14. // to find values in this store.
  15. // * `IdT` is the actual ID of values in this store, and `IdT::ValueType` is the
  16. // value type being stored.
  17. //
  18. // The value store builds a mapping so that either ID can be used later to find
  19. // a value. And the user can query if a related `RelatedStoreT::IdType` has been
  20. // used to add a value to the store or not.
  21. //
  22. // When adding to the store, the user provides the related
  23. // `RelatedStoreT::IdType` along with the value being stored, and gets back the
  24. // ID of the value in the store.
  25. //
  26. // This store requires more storage space than normal ValueStore does, as it
  27. // requires storing a bit for presence of each `RelatedStore::IdType`. And it
  28. // allocates memory for values for all IDs up largest ID present in the store,
  29. // even if they are not yet used.
  30. template <typename RelatedStoreT, typename IdT, typename ValueT>
  31. class RelationalValueStore {
  32. public:
  33. using RelatedIdType = RelatedStoreT::IdType;
  34. using ValueType = ValueStoreTypes<ValueT>::ValueType;
  35. using ConstRefType = ValueStoreTypes<ValueT>::ConstRefType;
  36. explicit RelationalValueStore(const RelatedStoreT* related_store)
  37. : related_store_(related_store) {}
  38. // Given the related ID and a value, stores the value and returns a mapped ID
  39. // to reference it in the store.
  40. auto Add(RelatedIdType related_id, ValueType value) -> IdT {
  41. auto related_index = related_store_->GetRawIndex(related_id);
  42. IdT id(related_index);
  43. if (static_cast<size_t>(id.index) >= values_.size()) {
  44. values_.resize(id.index + 1);
  45. }
  46. auto& opt = values_[id.index];
  47. CARBON_CHECK(!opt.has_value(),
  48. "Add with `related_id` that was already added to the store");
  49. opt.emplace(std::move(value));
  50. return id;
  51. }
  52. // Returns the ID of a value in the store if the `related_id` was previously
  53. // used to add a value to the store, or None.
  54. auto TryGetId(RelatedIdType related_id) const -> IdT {
  55. auto related_index = related_store_->GetRawIndex(related_id);
  56. if (static_cast<size_t>(related_index) >= values_.size()) {
  57. return IdT::None;
  58. }
  59. auto& opt = values_[related_index];
  60. if (!opt.has_value()) {
  61. return IdT::None;
  62. }
  63. return IdT(related_index);
  64. }
  65. // Returns a value for an ID.
  66. auto Get(IdT id) const -> ConstRefType {
  67. CARBON_DCHECK(id.index >= 0, "{0}", id);
  68. return *values_[id.index];
  69. }
  70. private:
  71. // Set inline size to 0 because these will typically be too large for the
  72. // stack, while this does make File smaller.
  73. llvm::SmallVector<std::optional<ValueType>, 0> values_;
  74. const RelatedStoreT* related_store_;
  75. };
  76. } // namespace Carbon
  77. #endif // CARBON_TOOLCHAIN_BASE_RELATIONAL_VALUE_STORE_H_