diff --git a/include/cppast/cpp_entity_index.hpp b/include/cppast/cpp_entity_index.hpp new file mode 100644 index 0000000..0cd3311 --- /dev/null +++ b/include/cppast/cpp_entity_index.hpp @@ -0,0 +1,76 @@ +// Copyright (C) 2017 Jonathan Müller +// 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 +#include +#include + +#include +#include +#include + +#include + +namespace cppast +{ + class cpp_entity; + + /// A [ts::strong_typedef]() representing the unique id of a [cppast::cpp_entity](). + /// + /// It is fully comparable. + struct cpp_entity_id : type_safe::strong_typedef, + type_safe::strong_typedef_op::equality_comparison, + type_safe::strong_typedef_op::relational_comparison + { + using strong_typedef::strong_typedef; + }; + + 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 size) + { + return cpp_entity_id(std::string(str, size)); + } + } + + /// 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: + /// \effects Registers a new [cppast::cpp_entity]() also giving its [cppast::cpp_entity_id](). + /// \requires The entity must not have been registered before, + /// and it must live as long as the index lives. + /// \notes This operation is thread safe. + void register_entity(cpp_entity_id id, type_safe::object_ref entity) const + { + std::lock_guard lock(mutex_); + auto result = map_.emplace(std::move(id), std::move(entity)); + DEBUG_ASSERT(result.second, detail::precondition_error_handler{}, + "duplicate index registration"); + } + + /// \returns A [ts::optional_ref]() corresponding to the entity of the given [cppast::cpp_entity_id](). + /// \notes This operation is thread safe. + type_safe::optional_ref lookup(const cpp_entity_id& id) const noexcept + { + std::lock_guard lock(mutex_); + auto iter = map_.find(id); + if (iter == map_.end()) + return {}; + return iter->second.get(); + } + + private: + mutable std::mutex mutex_; + mutable std::map> map_; + }; +} // namespace cppast + +#endif // CPPAST_CPP_ENTITY_INDEX_HPP_INCLUDED diff --git a/include/cppast/cpp_file.hpp b/include/cppast/cpp_file.hpp index a78ab4c..34d0a71 100644 --- a/include/cppast/cpp_file.hpp +++ b/include/cppast/cpp_file.hpp @@ -5,7 +5,7 @@ #ifndef CPPAST_CPP_FILE_HPP_INCLUDED #define CPPAST_CPP_FILE_HPP_INCLUDED -#include +#include #include namespace cppast @@ -28,12 +28,15 @@ namespace cppast /// \effects Adds an entity. void add_child(std::unique_ptr child) noexcept { - file_->children_.push_back(*file_, std::move(child)); + file_->add_child(std::move(child)); } + /// \effects Registers the file in the [cppast::cpp_entity_index](). + /// It will use the file name as identifier. /// \returns The finished file. - std::unique_ptr finish() noexcept + std::unique_ptr finish(const cpp_entity_index& idx) noexcept { + idx.register_entity(cpp_entity_id(file_->name()), type_safe::ref(*file_)); return std::move(file_); } @@ -48,8 +51,6 @@ namespace cppast /// \returns [cpp_entity_type::file_t](). cpp_entity_type do_get_entity_type() const noexcept override; - - detail::intrusive_list children_; }; } // namespace cppast diff --git a/include/cppast/cpp_namespace.hpp b/include/cppast/cpp_namespace.hpp index d5dc486..b6e4ba5 100644 --- a/include/cppast/cpp_namespace.hpp +++ b/include/cppast/cpp_namespace.hpp @@ -5,6 +5,7 @@ #ifndef CPPAST_CPP_NAMESPACE_HPP_INCLUDED #define CPPAST_CPP_NAMESPACE_HPP_INCLUDED +#include #include namespace cppast @@ -29,9 +30,13 @@ namespace cppast namespace_->add_child(std::move(child)); } + /// \effects Registers the file in the [cppast::cpp_entity_index](), + /// using the given [cppast::cpp_entity_id](). /// \returns The finished namespace. - std::unique_ptr finish() noexcept + std::unique_ptr finish(const cpp_entity_index& idx, + cpp_entity_id id) noexcept { + idx.register_entity(std::move(id), type_safe::ref(*namespace_)); return std::move(namespace_); }