blob: 05a6db8d2b58fdd0967812f999386d201998c3e2 [file] [log] [blame]
// Copyright 2017-2020 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef VERIBLE_COMMON_STRINGS_STRING_MEMORY_MAP_H_
#define VERIBLE_COMMON_STRINGS_STRING_MEMORY_MAP_H_
#include <utility>
#include "absl/strings/string_view.h"
#include "common/strings/range.h"
#include "common/util/interval_map.h"
#include "common/util/interval_set.h"
#include "common/util/logging.h"
namespace verible {
namespace internal {
inline std::pair<absl::string_view::const_iterator,
absl::string_view::const_iterator>
string_view_to_pair(absl::string_view sv) {
return std::make_pair(sv.begin(), sv.end());
}
} // namespace internal
// StringViewSuperRangeMap maps a string_view to a super-range to which it
// belongs. This can associate a string_view with the full text (file) from
// which it originated.
// Since this operates solely on string_views, it is not responsible for owning
// any of the referenced memory -- the user is responsible for maintaining
// proper string lifetime, owning strings must outlive these objects.
class StringViewSuperRangeMap {
typedef DisjointIntervalSet<absl::string_view::const_iterator> impl_type;
public:
// This iterator dereferences to a std::pair of
// absl::string_view::const_iterator, which can be constructed into a
// string_view.
typedef impl_type::const_iterator const_iterator;
StringViewSuperRangeMap() = default;
StringViewSuperRangeMap(const StringViewSuperRangeMap&) = default;
StringViewSuperRangeMap(StringViewSuperRangeMap&&) = default;
StringViewSuperRangeMap& operator=(const StringViewSuperRangeMap&) = default;
StringViewSuperRangeMap& operator=(StringViewSuperRangeMap&&) = default;
bool empty() const { return string_map_.empty(); }
const_iterator begin() const { return string_map_.begin(); }
const_iterator end() const { return string_map_.end(); }
// Given a substring, return an iterator pointing to the superstring that
// fully contains the substring, if it exists, else return end().
const_iterator find(absl::string_view substring) const {
return string_map_.find({substring.begin(), substring.end()});
}
// Similar to find(), but asserts that a superstring range is found,
// and converts the result directly to a string_view.
absl::string_view must_find(absl::string_view substring) const {
const const_iterator found(find(substring));
CHECK(found != string_map_.end());
return make_string_view_range(found->first, found->second); // superstring
}
// Insert a superstring (range) that does not overlap with any previously
// inserted string range. This is suitable for string ranges that correspond
// to allocated memory, because allocators only return non-overlapping memory
// blocks.
const_iterator must_emplace(absl::string_view superstring) {
return string_map_.must_emplace(superstring.begin(), superstring.end());
}
private:
// Internal representation of string range map.
impl_type string_map_;
};
// StringMemoryMap maps (non-owned) string_views to owned memory.
// This class provides a set-like interface to objects of type T.
// T is any type of object that *owns* some string memory, whose
// address range serves as a key. Since string addresses are the result of
// allocation, they are guaranteed to not overlap.
// T needs to be move-able, like a std::unique_ptr.
// Note: std::string is move-able, but *not* guaranteed to maintain the same
// address after std::move-ing.
// RangeOf is any functor that returns a string_view of memory owned by objects
// of type T.
//
// It is expected that the owned string memory address range never changes over
// the lifetime of objects stored in this map, in other words, RangeOf(obj) will
// always return the same range for the same object. One way to ensure this is
// to make the underlying storage a 'const std::string'.
//
template <class T, absl::string_view RangeOf(const T&)>
class StringMemoryMap {
typedef absl::string_view::const_iterator key_type;
typedef DisjointIntervalMap<key_type, T> map_type;
public:
typedef typename map_type::iterator iterator;
StringMemoryMap() = default;
StringMemoryMap(const StringMemoryMap&) = delete;
StringMemoryMap(StringMemoryMap&&) = delete;
StringMemoryMap& operator=(const StringMemoryMap&) = delete;
StringMemoryMap& operator=(StringMemoryMap&&) = delete;
// Returns reference to the object in the set that owns the memory range of
// string 's', or else nullptr if 's' does not fall entirely within one of the
// intervals in the map.
const T* find(absl::string_view sv) const {
const auto iter = memory_map_.find(internal::string_view_to_pair(sv));
if (iter == memory_map_.end()) return nullptr;
return &iter->second;
}
// Move-inserts an element into the set, keyed on the memory range owned
// by the object.
iterator insert(T&& t) {
const absl::string_view key = RangeOf(t);
return memory_map_.must_emplace(internal::string_view_to_pair(key),
std::move(t));
}
private:
map_type memory_map_;
};
} // namespace verible
#endif // VERIBLE_COMMON_STRINGS_STRING_MEMORY_MAP_H_