forked from standardese/cppast
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcpp_entity_index.hpp
More file actions
143 lines (121 loc) · 5.6 KB
/
Copy pathcpp_entity_index.hpp
File metadata and controls
143 lines (121 loc) · 5.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright (C) 2017-2018 Jonathan Müller <[email protected]>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.
#ifndef CPPAST_CPP_ENTITY_INDEX_HPP_INCLUDED
#define CPPAST_CPP_ENTITY_INDEX_HPP_INCLUDED
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
#include <type_safe/optional_ref.hpp>
#include <type_safe/reference.hpp>
#include <type_safe/strong_typedef.hpp>
namespace cppast
{
class cpp_entity;
class cpp_file;
class cpp_namespace;
/// \exclude
namespace detail
{
constexpr std::size_t fnv_basis = 14695981039346656037ull;
constexpr std::size_t fnv_prime = 1099511628211ull;
// FNV-1a 64 bit hash
constexpr std::size_t id_hash(const char* str, std::size_t hash = fnv_basis)
{
return *str ? id_hash(str + 1, (hash ^ std::size_t(*str)) * fnv_prime) : hash;
}
} // namespace detail
/// A [ts::strong_typedef]() representing the unique id of a [cppast::cpp_entity]().
///
/// It is comparable for equality.
struct cpp_entity_id : type_safe::strong_typedef<cpp_entity_id, std::size_t>,
type_safe::strong_typedef_op::equality_comparison<cpp_entity_id>
{
explicit cpp_entity_id(const std::string& str) : cpp_entity_id(str.c_str()) {}
explicit cpp_entity_id(const char* str) : strong_typedef(detail::id_hash(str)) {}
};
inline namespace literals
{
/// \returns A new [cppast::cpp_entity_id]() created from the given string.
inline cpp_entity_id operator"" _id(const char* str, std::size_t)
{
return cpp_entity_id(str);
}
} // namespace literals
/// An index of all [cppast::cpp_entity]() objects created.
///
/// It maps [cppast::cpp_entity_id]() to references to the [cppast::cpp_entity]() objects.
class cpp_entity_index
{
public:
/// Exception thrown on duplicate entity definition.
class duplicate_definition_error : public std::logic_error
{
public:
duplicate_definition_error();
};
/// \effects Registers a new [cppast::cpp_entity]() which is a definition.
/// It will override any previously registered declarations of the same entity.
/// \throws duplicate_defintion_error if the entity has been registered as definition before.
/// \requires The entity must live as long as the index lives,
/// and it must not be a namespace.
/// \notes This operation is thread safe.
void register_definition(cpp_entity_id id,
type_safe::object_ref<const cpp_entity> entity) const;
/// \effects Registers a new [cppast::cpp_file]().
/// \returns `true` if the file was not registered before.
/// If it returns `false`, the file was registered before and nothing was changed.
/// \requires The entity must live as long as the index lives.
/// \notes This operation is thread safe.
bool register_file(cpp_entity_id id, type_safe::object_ref<const cpp_file> file) const;
/// \effects Registers a new [cppast::cpp_entity]() which is a declaration.
/// Only the first declaration will be registered.
/// \requires The entity must live as long as the index lives.
/// \requires The entity must be forward declarable.
/// \notes This operation is thread safe.
void register_forward_declaration(cpp_entity_id id,
type_safe::object_ref<const cpp_entity> entity) const;
/// \effects Registers a new [cppast::cpp_namespace]().
/// \notes The namespace object must live as long as the index lives.
/// \notes This operation is thread safe.
void register_namespace(cpp_entity_id id, type_safe::object_ref<const cpp_namespace> ns) const;
/// \returns A [ts::optional_ref]() corresponding to the entity(/ies) of the given
/// [cppast::cpp_entity_id](). If no definition has been registered, it return the first
/// declaration that was registered. If the id resolves to a namespaces, returns an empty
/// optional. \notes This operation is thread safe.
type_safe::optional_ref<const cpp_entity> lookup(const cpp_entity_id& id) const noexcept;
/// \returns A [ts::optional_ref]() corresponding to the entity of the given
/// [cppast::cpp_entity_id](). If no definition has been registered, it returns an empty
/// optional. \notes This operation is thread safe.
type_safe::optional_ref<const cpp_entity> lookup_definition(const cpp_entity_id& id) const
noexcept;
/// \returns A [ts::array_ref]() of references to all namespaces matching the given
/// [cppast::cpp_entity_id](). If no namespace is found, it returns an empty array reference.
/// \notes This operation is thread safe.
auto lookup_namespace(const cpp_entity_id& id) const noexcept
-> type_safe::array_ref<type_safe::object_ref<const cpp_namespace>>;
private:
struct hash
{
std::size_t operator()(const cpp_entity_id& id) const noexcept
{
return static_cast<std::size_t>(id);
}
};
struct value
{
type_safe::object_ref<const cpp_entity> entity;
bool is_definition;
value(type_safe::object_ref<const cpp_entity> e, bool def)
: entity(std::move(e)), is_definition(def)
{}
};
mutable std::mutex mutex_;
mutable std::unordered_map<cpp_entity_id, value, hash> map_;
mutable std::unordered_map<cpp_entity_id,
std::vector<type_safe::object_ref<const cpp_namespace>>, hash>
ns_;
};
} // namespace cppast
#endif // CPPAST_CPP_ENTITY_INDEX_HPP_INCLUDED