relational_value_store.h 3.0 KB

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