Skip to content

Commit

Permalink
Added 'filter_item' enum in order to filter member items during retri…
Browse files Browse the repository at this point in the history
…eve from type

e.g.:
for (auto& prop : t.get_properties(filter_item::instance_item | filter_item::public_access | filter_item::declared_only))
    std::cout << prop.get_name() << std::endl;

This will print all property names from the current type t, which are public and need an instance for invoking.
  • Loading branch information
acki-m committed May 12, 2016
1 parent 7164770 commit e465b66
Show file tree
Hide file tree
Showing 9 changed files with 396 additions and 43 deletions.
12 changes: 12 additions & 0 deletions src/rttr/array_range.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,13 +286,23 @@ class array_range
/*!
* \brief Returns the number of elements in the range.
*
* \remark Every element will be checked against the condition of the used predicate.
* Only elements which fulfill the condition of predicate will be included in the counter.
* That means, in order to determine the size of the range, the underlying algorithm needs to iterate
* through the whole range. So don't call it to often. It's better to cache the result in a temporary variable.
*
* \return The number of elements in the range.
*/
size_t size() const;

/*!
* \brief Checks if the range has no elements, i.e. whether `begin() == end()`.
*
* \remark Every element will be checked against the condition of the used predicate.
* Only when every element doe not fulfill the condition of predicate, the range is declared empty.
* That means, in order to check for emptiness, the underlying algorithm needs to iterate
* through the whole range. So don't call it to often. It's better to cache the result in a temporary variable.
*
* \return `True` if this range is empty, otherwise `false`.
*/
bool empty() const;
Expand All @@ -304,6 +314,8 @@ class array_range
template<typename DataType>
void prev(array_reverse_iterator<DataType>& itr) const;

bool empty_() const;

private:
const T* const m_begin;
const T* const m_end;
Expand Down
45 changes: 34 additions & 11 deletions src/rttr/detail/impl/array_range_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ RTTR_INLINE array_range<T, Predicate>::array_range()
template<typename T, typename Predicate>
RTTR_INLINE typename array_range<T, Predicate>::const_iterator array_range<T, Predicate>::begin()
{
if (empty())
if (empty_())
{
return {m_end, this};
}
Expand Down Expand Up @@ -89,7 +89,7 @@ RTTR_INLINE typename array_range<T, Predicate>::const_iterator array_range<T, Pr
template<typename T, typename Predicate>
RTTR_INLINE typename array_range<T, Predicate>::const_iterator array_range<T, Predicate>::begin() const
{
if (empty())
if (empty_())
{
return {m_end, this};
}
Expand Down Expand Up @@ -118,7 +118,7 @@ RTTR_INLINE typename array_range<T, Predicate>::const_iterator array_range<T, Pr
template<typename T, typename Predicate>
RTTR_INLINE typename array_range<T, Predicate>::const_iterator array_range<T, Predicate>::cbegin() const
{
if (empty())
if (empty_())
{
return {m_end, this};
}
Expand Down Expand Up @@ -147,7 +147,7 @@ RTTR_INLINE typename array_range<T, Predicate>::const_iterator array_range<T, Pr
template<typename T, typename Predicate>
RTTR_INLINE typename array_range<T, Predicate>::const_reverse_iterator array_range<T, Predicate>::rbegin()
{
if (empty())
if (empty_())
{
return {m_end, this};
}
Expand All @@ -168,15 +168,15 @@ RTTR_INLINE typename array_range<T, Predicate>::const_reverse_iterator array_ran
template<typename T, typename Predicate>
RTTR_INLINE typename array_range<T, Predicate>::const_reverse_iterator array_range<T, Predicate>::rend()
{
return (empty() ? const_reverse_iterator{m_begin, this} : const_reverse_iterator{m_begin - 1, this});
return (empty_() ? const_reverse_iterator{m_begin, this} : const_reverse_iterator{m_begin - 1, this});
}

/////////////////////////////////////////////////////////////////////////////////////////

template<typename T, typename Predicate>
RTTR_INLINE typename array_range<T, Predicate>::const_reverse_iterator array_range<T, Predicate>::rbegin() const
{
if (empty())
if (empty_())
{
return {m_end, this};
}
Expand All @@ -197,15 +197,15 @@ RTTR_INLINE typename array_range<T, Predicate>::const_reverse_iterator array_ran
template<typename T, typename Predicate>
RTTR_INLINE typename array_range<T, Predicate>::const_reverse_iterator array_range<T, Predicate>::rend() const
{
return (empty() ? const_reverse_iterator{m_begin, this} : const_reverse_iterator{m_begin - 1, this});
return (empty_() ? const_reverse_iterator{m_begin, this} : const_reverse_iterator{m_begin - 1, this});
}

/////////////////////////////////////////////////////////////////////////////////////////

template<typename T, typename Predicate>
RTTR_INLINE typename array_range<T, Predicate>::const_reverse_iterator array_range<T, Predicate>::crbegin() const
{
if (empty())
if (empty_())
{
return {m_end, this};
}
Expand All @@ -226,7 +226,7 @@ RTTR_INLINE typename array_range<T, Predicate>::const_reverse_iterator array_ran
template<typename T, typename Predicate>
RTTR_INLINE typename array_range<T, Predicate>::const_reverse_iterator array_range<T, Predicate>::crend() const
{
return (empty() ? const_reverse_iterator{m_end, this} : const_reverse_iterator{m_begin - 1, this});
return (empty_() ? const_reverse_iterator{m_end, this} : const_reverse_iterator{m_begin - 1, this});
}

/////////////////////////////////////////////////////////////////////////////////////////
Expand All @@ -238,8 +238,10 @@ RTTR_INLINE size_t array_range<T, Predicate>::size() const
const_iterator itr{m_begin, this};
while(itr != cend())
{
++itr;
++result;
if (m_pred(*itr.m_ptr))
++result;

++itr.m_ptr;
}

return result;
Expand All @@ -249,6 +251,27 @@ RTTR_INLINE size_t array_range<T, Predicate>::size() const

template<typename T, typename Predicate>
RTTR_INLINE bool array_range<T, Predicate>::empty() const
{
if (m_begin == m_end)
return true;

const_iterator itr{m_begin, this};
if (m_pred(*itr))
return false;

++itr.m_ptr;
while(itr.m_ptr != m_end && !m_pred(*itr.m_ptr))
{
++itr.m_ptr;
}

return (itr == cend());
}

/////////////////////////////////////////////////////////////////////////////////////////

template<typename T, typename Predicate>
RTTR_INLINE bool array_range<T, Predicate>::empty_() const
{
return (m_begin == m_end);
}
Expand Down
65 changes: 64 additions & 1 deletion src/rttr/detail/type/type_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,70 @@ array_range<property> type_database::get_class_properties(const type& t) const
{
auto& vec = ret->second;
if (!vec.empty())
return array_range<property>(vec.data(), vec.size());
return array_range<property>(vec.data(), vec.size(),
default_predicate<property>([](const property& prop)
{
return (prop.get_access_level() == access_levels::public_access);
}) );
}

return array_range<property>();
}

/////////////////////////////////////////////////////////////////////////////////////////

static bool is_valid_filter_item(filter_items filter)
{
if ((filter.test_flag(filter_item::public_access) ||
filter.test_flag(filter_item::non_public_access)) &&
(filter.test_flag(filter_item::instance_item) ||
filter.test_flag(filter_item::static_item)))
{
return true;
}

return false;
}

/////////////////////////////////////////////////////////////////////////////////////////

array_range<property> type_database::get_class_properties(const type& t, filter_items filter) const
{
const auto ret = m_class_property_map.find(t);
if (ret != m_class_property_map.end())
{
auto& vec = ret->second;
if (!vec.empty())
{
return array_range<property>(vec.data(), vec.size(),
!is_valid_filter_item(filter) ?
default_predicate<property>([](const property& prop){ return false; }) :
default_predicate<property>([filter, t](const property& prop)
{
bool result = true;

if (filter.test_flag(filter_item::public_access))
result &= (prop.get_access_level() == access_levels::public_access);

if (filter.test_flag(filter_item::non_public_access))
{
const auto access_level = prop.get_access_level();
result &= (access_level == access_levels::private_access || access_level == access_levels::protected_access);
}

if (filter.test_flag(filter_item::instance_item) && filter.test_flag(filter_item::static_item))
result &= true;
else if (filter.test_flag(filter_item::instance_item) && !filter.test_flag(filter_item::static_item))
result &= !prop.is_static();
else if (!filter.test_flag(filter_item::instance_item) && filter.test_flag(filter_item::static_item))
result &= prop.is_static();

if (filter.test_flag(filter_item::declared_only))
result &= (prop.get_declaring_type() == t);

return result;
}));
}
}

return array_range<property>();
Expand Down
2 changes: 2 additions & 0 deletions src/rttr/detail/type/type_database_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "rttr/enumeration.h"
#include "rttr/array_range.h"
#include "rttr/string_view.h"
#include "rttr/filter_item.h"

#include "rttr/detail/misc/flat_map.h"
#include "rttr/detail/misc/flat_multimap.h"
Expand Down Expand Up @@ -107,6 +108,7 @@ class RTTR_LOCAL type_database
property get_type_property(const type& t, string_view name) const;
property get_class_property(const type& t, string_view name) const;
array_range<property> get_class_properties(const type& t) const;
array_range<property> get_class_properties(const type& t, filter_items filter) const;

property get_global_property(string_view name) const;
array_range<property> get_global_properties();
Expand Down
75 changes: 75 additions & 0 deletions src/rttr/filter_item.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/************************************************************************************
* *
* Copyright (c) 2014, 2015 - 2016 Axel Menzel <info@rttr.org> *
* *
* This file is part of RTTR (Run Time Type Reflection) *
* License: MIT License *
* *
* Permission is hereby granted, free of charge, to any person obtaining *
* a copy of this software and associated documentation files (the "Software"), *
* to deal in the Software without restriction, including without limitation *
* the rights to use, copy, modify, merge, publish, distribute, sublicense, *
* and/or sell copies of the Software, and to permit persons to whom the *
* Software is furnished to do so, subject to the following conditions: *
* *
* The above copyright notice and this permission notice shall be included in *
* all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
* SOFTWARE. *
* *
*************************************************************************************/

#ifndef RTTR_FILTER_ITEM_H_
#define RTTR_FILTER_ITEM_H_

#include "rttr/detail/base/core_prerequisites.h"
#include "rttr/enum_flags.h"

namespace rttr
{

/*!
* The \ref filter_item enum is used to search for members in \ref type "types".
*/
enum class filter_item
{
/*!
* \brief Includes all members which needs an instance to be invoked in the search.
*/
instance_item = 1,

/*!
* \brief Includes all static members in the search.
* Static members doesn't need any instance for invoking.
*/
static_item = 2,

/*!
* \brief Includes all public declared members in the search.
*/
public_access = 4,

/*!
* \brief Includes all non public (private or protected) members in the search.
*/
non_public_access = 8,

/*!
* \brief Returns all members declared for the current type;
* inherited members are not returned.
*/
declared_only = 16
};

RTTR_DECLARE_FLAGS(filter_items, filter_item)
RTTR_DECLARE_ENUM_FLAGS_OPERATORS(filter_items)

} // end namespace rttr

#endif // RTTR_FILTER_ITEM_H_
1 change: 1 addition & 0 deletions src/rttr/rttr.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ set(HEADER_FILES access_levels.h
destructor.h
enumeration.h
enum_flags.h
filter_item.h
instance.h
method.h
policy.h
Expand Down
7 changes: 7 additions & 0 deletions src/rttr/type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,13 @@ array_range<property> type::get_properties() const

/////////////////////////////////////////////////////////////////////////////////////////

array_range<property> type::get_properties(filter_items filter) const
{
return detail::type_database::instance().get_class_properties(get_raw_type(), filter);
}

/////////////////////////////////////////////////////////////////////////////////////////

method type::get_method(string_view name) const
{
return detail::type_database::instance().get_class_method(get_raw_type(), name);
Expand Down
13 changes: 12 additions & 1 deletion src/rttr/type.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "rttr/detail/base/core_prerequisites.h"
#include "rttr/string_view.h"
#include "rttr/array_range.h"
#include "rttr/filter_item.h"

#include <type_traits>
#include <vector>
Expand Down Expand Up @@ -541,7 +542,7 @@ class RTTR_API type
property get_property(string_view name) const;

/*!
* \brief Returns a range of all registered properties for this type and
* \brief Returns a range of all registered *public* properties for this type and
* all its base classes.
*
* \remark The properties are sorted after its order of registration.
Expand All @@ -550,6 +551,16 @@ class RTTR_API type
*/
array_range<property> get_properties() const;

/*!
* \brief Returns a range of all registered properties for this type,
* based on the given \p filter.
*
* \remark The properties are sorted after its order of registration.
*
* \return A range of properties.
*/
array_range<property> get_properties(filter_items filter) const;

/*!
* \brief Returns a global property with the name \p name.
*
Expand Down

0 comments on commit e465b66

Please sign in to comment.