Files
blender/source/blender/blenlib/BLI_stack_cxx.h
Jacques Lucke 68cc982dcb BLI: improve various C++ data structures
The changes come from the `functions` branch, where I'm using
these structures a lot.

This also includes a new `BLI::Optional<T>` type, which is similar
to `std::Optional<T>` which can be used when Blender starts using
C++17.
2020-02-10 14:09:01 +01:00

151 lines
2.9 KiB
C++

/*
* 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_STACK_CXX_H__
#define __BLI_STACK_CXX_H__
/** \file
* \ingroup bli
*
* Basic stack implementation with support for small object optimization.
*/
#include "BLI_vector.h"
namespace BLI {
template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Stack {
private:
Vector<T, N, Allocator> m_elements;
public:
Stack() = default;
/**
* Construct a stack from an array ref. The elements will be pushed in the same order they are in
* the array.
*/
Stack(ArrayRef<T> values) : m_elements(values)
{
}
operator ArrayRef<T>()
{
return m_elements;
}
/**
* Return the number of elements in the stack.
*/
uint size() const
{
return m_elements.size();
}
/**
* Return true when the stack is empty, otherwise false.
*/
bool is_empty() const
{
return this->size() == 0;
}
/**
* Add a new element to the top of the stack.
*/
void push(const T &value)
{
m_elements.append(value);
}
void push(T &&value)
{
m_elements.append(std::move(value));
}
void push_multiple(ArrayRef<T> values)
{
m_elements.extend(values);
}
/**
* Remove the element from the top of the stack and return it.
* This will assert when the stack is empty.
*/
T pop()
{
return m_elements.pop_last();
}
/**
* Return a reference to the value a the top of the stack.
* This will assert when the stack is empty.
*/
T &peek()
{
BLI_assert(!this->is_empty());
return m_elements[this->size() - 1];
}
T *begin()
{
return m_elements.begin();
}
T *end()
{
return m_elements.end();
}
const T *begin() const
{
return m_elements.begin();
}
const T *end() const
{
return m_elements.end();
}
/**
* Remove all elements from the stack but keep the memory.
*/
void clear()
{
m_elements.clear();
}
/**
* Remove all elements and free any allocated memory.
*/
void clear_and_make_small()
{
m_elements.clear_and_make_small();
}
/**
* Does a linear search to check if the value is in the stack.
*/
bool contains(const T &value)
{
return m_elements.contains(value);
}
};
} /* namespace BLI */
#endif /* __BLI_STACK_CXX_H__ */