This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/blenlib/BLI_vector_set_slots.hh

172 lines
5.0 KiB
C++
Raw Normal View History

/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __BLI_VECTOR_SET_SLOTS_HH__
#define __BLI_VECTOR_SET_SLOTS_HH__
/** \file
* \ingroup bli
*
* This file contains slot types that are supposed to be used with BLI::VectorSet.
*
* Every slot type has to be able to hold an integer index and state information.
* A vector set slot has three possible states: empty, occupied and removed.
*
* A vector slot type has to implement a couple of methods that are explained in
* SimpleVectorSetSlot.
* A vector slot type is assumed to be trivially destructible, when it is in empty or removed
* state.
*
* Possible Improvements:
* - Implement a slot type that stores the hash.
* - Implement a slot type that stores the key. That means that the key would be stored in two
* places: the key vector and the slot itself. Maybe storing the key in the slot as well, can
* result in better performance, due to better cache utilization.
*/
#include "BLI_sys_types.h"
namespace BLI {
/**
* The simplest possible vector set slot. It stores the index and state in a signed integer. If the
* value is negative, it represents empty or occupied state. Otherwise it represents the index.
*/
template<typename Key> class SimpleVectorSetSlot {
private:
#define s_is_empty -1
#define s_is_removed -2
/**
* After the default constructor has run, the slot has to be in the empty state.
*/
int32_t m_state = s_is_empty;
public:
/**
* Return true if this slot contains an index to a key.
*/
bool is_occupied() const
{
return m_state >= 0;
}
/**
* Return true if the slot is empty, i.e. it does not contain an index.
*/
bool is_empty() const
{
return m_state == s_is_empty;
}
/**
* Return the stored index. It is assumed that the slot is occupied.
*/
uint32_t index() const
{
BLI_assert(this->is_occupied());
return (uint32_t)m_state;
}
/**
* Return true if the slot contains the given key, i.e. its index points to a key that compares
* equal to it. The hash can be used by other implementations to determine inequality faster.
*/
template<typename ForwardKey, typename IsEqual>
bool contains(const ForwardKey &key,
const IsEqual &is_equal,
uint32_t UNUSED(hash),
const Key *keys) const
{
if (m_state >= 0) {
return is_equal(key, keys[m_state]);
}
return false;
}
/**
* Move the other slot into this slot and destruct it. We do destruction here, because this way
* we can avoid a comparison with the state, since we know the slot is occupied. For this
* specific slot implementation, this does not make a difference.
*/
void relocate_occupied_here(SimpleVectorSetSlot &other, uint32_t UNUSED(hash))
{
BLI_assert(!this->is_occupied());
BLI_assert(other.is_occupied());
m_state = other.m_state;
}
/**
* Change the state of this slot from empty/removed to occupied. The hash can be used by other
* slot implementations.
*/
void occupy(uint32_t index, uint32_t UNUSED(hash))
{
BLI_assert(!this->is_occupied());
m_state = (int32_t)index;
}
/**
* The key has changed its position in the vector, so the index has to be updated. This method
* can assume that the slot is currently occupied.
*/
void update_index(uint32_t index)
{
BLI_assert(this->is_occupied());
m_state = (int32_t)index;
}
/**
* Change the state of this slot from occupied to removed.
*/
void remove()
{
BLI_assert(this->is_occupied());
m_state = s_is_removed;
}
/**
* Return true if this slot is currently occupied and its corresponding key has the given index.
*/
bool has_index(uint32_t index) const
{
return (uint32_t)m_state == index;
}
/**
* Return the hash of the currently stored key. In this simple set slot implementation, we just
* compute the hash here. Other implementations might store the hash in the slot instead.
*/
template<typename Hash> uint32_t get_hash(const Key &key, const Hash &hash) const
{
BLI_assert(this->is_occupied());
return hash(key);
}
#undef s_is_empty
#undef s_is_removed
};
template<typename Key> struct DefaultVectorSetSlot;
template<typename Key> struct DefaultVectorSetSlot {
using type = SimpleVectorSetSlot<Key>;
};
} // namespace BLI
#endif /* __BLI_VECTOR_SET_SLOTS_HH__ */