Merge branch 'save_ext' into cargo_type_order
# Conflicts: # src/core/smallstack_type.hpp
This commit is contained in:
@@ -125,7 +125,7 @@ static inline T *ReallocT(T *t_ptr, size_t num_elements)
|
||||
/* Ensure the size does not overflow. */
|
||||
CheckAllocationConstraints<T>(num_elements);
|
||||
|
||||
t_ptr = (T*)realloc(t_ptr, num_elements * sizeof(T));
|
||||
t_ptr = (T*)realloc(static_cast<void *>(t_ptr), num_elements * sizeof(T));
|
||||
if (t_ptr == NULL) ReallocError(num_elements * sizeof(T));
|
||||
return t_ptr;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ struct Backup {
|
||||
{
|
||||
/* We cannot assert here, as missing restoration is 'normal' when exceptions are thrown.
|
||||
* Exceptions are especially used to abort world generation. */
|
||||
DEBUG(misc, 0, "%s:%d: Backupped value was not restored!", this->file, this->line);
|
||||
DEBUG(misc, 0, "%s:%d: Backed-up value was not restored!", this->file, this->line);
|
||||
this->Restore();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,13 +365,32 @@ static inline T ROR(const T x, const uint8 n)
|
||||
* (since it will use hardware swapping if available).
|
||||
* Even though they should return uint16 and uint32, we get
|
||||
* warnings if we don't cast those (why?) */
|
||||
#define BSWAP64(x) ((uint64)CFSwapInt64(x))
|
||||
#define BSWAP32(x) ((uint32)CFSwapInt32(x))
|
||||
#define BSWAP16(x) ((uint16)CFSwapInt16(x))
|
||||
#elif defined(_MSC_VER)
|
||||
/* MSVC has intrinsics for swapping, resulting in faster code */
|
||||
#define BSWAP64(x) (_byteswap_uint64(x))
|
||||
#define BSWAP32(x) (_byteswap_ulong(x))
|
||||
#define BSWAP16(x) (_byteswap_ushort(x))
|
||||
#else
|
||||
/**
|
||||
* Perform a 64 bits endianness bitswap on x.
|
||||
* @param x the variable to bitswap
|
||||
* @return the bitswapped value.
|
||||
*/
|
||||
static inline uint64 BSWAP64(uint64 x)
|
||||
{
|
||||
#if !defined(__ICC) && (defined(__GNUC__) || defined(__clang__))
|
||||
/* GCC >= 4.3 provides a builtin, resulting in faster code */
|
||||
return (uint64)__builtin_bswap64((uint64)x);
|
||||
#else
|
||||
return ((x >> 56) & 0xFFULL) | ((x >> 40) & 0xFF00ULL) | ((x >> 24) & 0xFF0000ULL) | ((x >> 8) & 0xFF000000ULL) |
|
||||
((x << 8) & 0xFF00000000ULL) | ((x << 24) & 0xFF0000000000ULL) | ((x << 40) & 0xFF000000000000ULL) | ((x << 56) & 0xFF000000000000ULL);
|
||||
;
|
||||
#endif /* __GNUC__ || __clang__ */
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a 32 bits endianness bitswap on x.
|
||||
* @param x the variable to bitswap
|
||||
|
||||
42
src/core/container_func.hpp
Normal file
42
src/core/container_func.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD 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, version 2.
|
||||
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file container_func.hpp Functions related to use of containers. */
|
||||
|
||||
#ifndef CONTAINER_FUNC_HPP
|
||||
#define CONTAINER_FUNC_HPP
|
||||
|
||||
#include <iterator>
|
||||
|
||||
template <typename C, typename UP> unsigned int container_unordered_remove_if (C &container, UP predicate) {
|
||||
unsigned int removecount = 0;
|
||||
for (auto it = container.begin(); it != container.end();) {
|
||||
if (predicate(*it)) {
|
||||
removecount++;
|
||||
if (std::next(it) != container.end()) {
|
||||
*it = std::move(container.back());
|
||||
container.pop_back();
|
||||
} else {
|
||||
container.pop_back();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
return removecount;
|
||||
}
|
||||
|
||||
template <typename C, typename V> unsigned int container_unordered_remove(C &container, const V &value) {
|
||||
return container_unordered_remove_if (container, [&](const typename C::value_type &v) {
|
||||
return v == value;
|
||||
});
|
||||
}
|
||||
|
||||
#endif /* CONTAINER_FUNC_HPP */
|
||||
102
src/core/dyn_arena_alloc.hpp
Normal file
102
src/core/dyn_arena_alloc.hpp
Normal file
@@ -0,0 +1,102 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD 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, version 2.
|
||||
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file dyn_arena_alloc.hpp Dynamic chunk-size arena allocator. */
|
||||
|
||||
#ifndef DYN_ARENA_ALLOC_HPP
|
||||
#define DYN_ARENA_ALLOC_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Custom arena allocator for uniform-size allocations of a variable size.
|
||||
* The allocation and chunk sizes may only be changed when the arena is empty.
|
||||
*/
|
||||
class DynUniformArenaAllocator {
|
||||
std::vector<void *> used_blocks;
|
||||
|
||||
void *current_block = nullptr;
|
||||
void *last_freed = nullptr;
|
||||
size_t next_position = 0;
|
||||
|
||||
size_t item_size = 0;
|
||||
size_t items_per_chunk = 0;
|
||||
|
||||
void NewBlock()
|
||||
{
|
||||
current_block = malloc(item_size * items_per_chunk);
|
||||
assert(current_block != nullptr);
|
||||
next_position = 0;
|
||||
used_blocks.push_back(current_block);
|
||||
}
|
||||
|
||||
public:
|
||||
DynUniformArenaAllocator() = default;
|
||||
DynUniformArenaAllocator(const DynUniformArenaAllocator &other) = delete;
|
||||
DynUniformArenaAllocator& operator=(const DynUniformArenaAllocator &other) = delete;
|
||||
|
||||
~DynUniformArenaAllocator()
|
||||
{
|
||||
EmptyArena();
|
||||
}
|
||||
|
||||
void EmptyArena()
|
||||
{
|
||||
current_block = nullptr;
|
||||
last_freed = nullptr;
|
||||
next_position = 0;
|
||||
for (void *block : used_blocks) {
|
||||
free(block);
|
||||
}
|
||||
used_blocks.clear();
|
||||
}
|
||||
|
||||
void ResetArena()
|
||||
{
|
||||
EmptyArena();
|
||||
item_size = 0;
|
||||
items_per_chunk = 0;
|
||||
}
|
||||
|
||||
void *Allocate() {
|
||||
assert(item_size != 0);
|
||||
if (last_freed) {
|
||||
void *ptr = last_freed;
|
||||
last_freed = *reinterpret_cast<void**>(ptr);
|
||||
return ptr;
|
||||
} else {
|
||||
if (current_block == nullptr || next_position == items_per_chunk) {
|
||||
NewBlock();
|
||||
}
|
||||
void *out = reinterpret_cast<char *>(current_block) + (item_size * next_position);
|
||||
next_position++;
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
void Free(void *ptr) {
|
||||
if (!ptr) return;
|
||||
assert(current_block != nullptr);
|
||||
|
||||
*reinterpret_cast<void**>(ptr) = last_freed;
|
||||
last_freed = ptr;
|
||||
}
|
||||
|
||||
void SetParameters(size_t item_size, size_t items_per_chunk)
|
||||
{
|
||||
if (item_size < sizeof(void *)) item_size = sizeof(void *);
|
||||
if (this->item_size == item_size && this->items_per_chunk == items_per_chunk) return;
|
||||
|
||||
assert(current_block == nullptr);
|
||||
this->item_size = item_size;
|
||||
this->items_per_chunk = items_per_chunk;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* DYN_ARENA_ALLOC_HPP */
|
||||
@@ -19,25 +19,33 @@
|
||||
#if TTD_ENDIAN == TTD_BIG_ENDIAN
|
||||
#define FROM_BE16(x) (x)
|
||||
#define FROM_BE32(x) (x)
|
||||
#define FROM_BE64(x) (x)
|
||||
#define TO_BE16(x) (x)
|
||||
#define TO_BE32(x) (x)
|
||||
#define TO_BE32X(x) (x)
|
||||
#define TO_BE64(x) (x)
|
||||
#define FROM_LE16(x) BSWAP16(x)
|
||||
#define FROM_LE32(x) BSWAP32(x)
|
||||
#define FROM_LE64(x) BSWAP64(x)
|
||||
#define TO_LE16(x) BSWAP16(x)
|
||||
#define TO_LE32(x) BSWAP32(x)
|
||||
#define TO_LE32X(x) BSWAP32(x)
|
||||
#define TO_LE64(x) BSWAP64(x)
|
||||
#else
|
||||
#define FROM_BE16(x) BSWAP16(x)
|
||||
#define FROM_BE32(x) BSWAP32(x)
|
||||
#define FROM_BE64(x) BSWAP64(x)
|
||||
#define TO_BE16(x) BSWAP16(x)
|
||||
#define TO_BE32(x) BSWAP32(x)
|
||||
#define TO_BE32X(x) BSWAP32(x)
|
||||
#define TO_BE64(x) BSWAP64(x)
|
||||
#define FROM_LE16(x) (x)
|
||||
#define FROM_LE32(x) (x)
|
||||
#define FROM_LE64(x) (x)
|
||||
#define TO_LE16(x) (x)
|
||||
#define TO_LE32(x) (x)
|
||||
#define TO_LE32X(x) (x)
|
||||
#define TO_LE64(x) (x)
|
||||
#endif /* TTD_ENDIAN == TTD_BIG_ENDIAN */
|
||||
|
||||
static inline uint16 ReadLE16Aligned(const void *x)
|
||||
|
||||
@@ -27,14 +27,21 @@
|
||||
|
||||
/* Windows has always LITTLE_ENDIAN */
|
||||
#if defined(WIN32) || defined(__OS2__) || defined(WIN64)
|
||||
#define TTD_ENDIAN TTD_LITTLE_ENDIAN
|
||||
# define TTD_ENDIAN TTD_LITTLE_ENDIAN
|
||||
#elif defined(OSX)
|
||||
# include <sys/types.h>
|
||||
# if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN
|
||||
# define TTD_ENDIAN TTD_LITTLE_ENDIAN
|
||||
# else
|
||||
# define TTD_ENDIAN TTD_BIG_ENDIAN
|
||||
# endif
|
||||
#elif !defined(TESTING)
|
||||
/* Else include endian[target/host].h, which has the endian-type, autodetected by the Makefile */
|
||||
#if defined(STRGEN) || defined(SETTINGSGEN)
|
||||
#include "endian_host.h"
|
||||
#else
|
||||
#include "endian_target.h"
|
||||
#endif
|
||||
# include <sys/param.h>
|
||||
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# define TTD_ENDIAN TTD_LITTLE_ENDIAN
|
||||
# else
|
||||
# define TTD_ENDIAN TTD_BIG_ENDIAN
|
||||
# endif
|
||||
#endif /* WIN32 || __OS2__ || WIN64 */
|
||||
|
||||
#endif /* ENDIAN_TYPE_HPP */
|
||||
|
||||
@@ -318,6 +318,18 @@ static inline uint CeilDiv(uint a, uint b)
|
||||
return (a + b - 1) / b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes ceil(a / b) for non-negative a and b (templated).
|
||||
* @param a Numerator
|
||||
* @param b Denominator
|
||||
* @return Quotient, rounded up
|
||||
*/
|
||||
template <typename T>
|
||||
static inline T CeilDivT(T a, T b)
|
||||
{
|
||||
return (a + b - 1) / b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes ceil(a / b) * b for non-negative a and b.
|
||||
* @param a Numerator
|
||||
@@ -329,6 +341,18 @@ static inline uint Ceil(uint a, uint b)
|
||||
return CeilDiv(a, b) * b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes ceil(a / b) * b for non-negative a and b (templated).
|
||||
* @param a Numerator
|
||||
* @param b Denominator
|
||||
* @return a rounded up to the nearest multiple of b.
|
||||
*/
|
||||
template <typename T>
|
||||
static inline T CeilT(T a, T b)
|
||||
{
|
||||
return CeilDivT<T>(a, b) * b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes round(a / b) for signed a and unsigned b.
|
||||
* @param a Numerator
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
template<typename Tkey, typename Tvalue, typename Tcompare>
|
||||
template<typename Tkey, typename Tvalue, typename Tcontainer, typename Tcompare>
|
||||
class MultiMap;
|
||||
|
||||
/**
|
||||
@@ -23,14 +23,15 @@ class MultiMap;
|
||||
* @tparam Tmap_iter Iterator type for the map in the MultiMap.
|
||||
* @tparam Tlist_iter Iterator type for the lists in the MultiMap.
|
||||
* @tparam Tkey Key type of the MultiMap.
|
||||
* @tparam Tvalue Value type of the MultMap.
|
||||
* @tparam Tvalue Value type of the MultiMap.
|
||||
* @tparam Tcontainer Container type for the values of the MultiMap.
|
||||
* @tparam Tcompare Comparator type for keys of the MultiMap.
|
||||
*/
|
||||
template<class Tmap_iter, class Tlist_iter, class Tkey, class Tvalue, class Tcompare>
|
||||
template<class Tmap_iter, class Tlist_iter, class Tkey, class Tvalue, class Tcontainer, class Tcompare>
|
||||
class MultiMapIterator {
|
||||
protected:
|
||||
friend class MultiMap<Tkey, Tvalue, Tcompare>;
|
||||
typedef MultiMapIterator<Tmap_iter, Tlist_iter, Tkey, Tvalue, Tcompare> Self;
|
||||
friend class MultiMap<Tkey, Tvalue, Tcontainer, Tcompare>;
|
||||
typedef MultiMapIterator<Tmap_iter, Tlist_iter, Tkey, Tvalue, Tcontainer, Tcompare> Self;
|
||||
|
||||
Tlist_iter list_iter; ///< Iterator pointing to current position in the current list of items with equal keys.
|
||||
Tmap_iter map_iter; ///< Iterator pointing to the position of the current list of items with equal keys in the map.
|
||||
@@ -201,8 +202,8 @@ public:
|
||||
* @param iter2 Second iterator to compare.
|
||||
* @return If iter1 and iter2 are equal.
|
||||
*/
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcompare>
|
||||
bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare> &iter2)
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcontainer1, class Tcontainer2, class Tcompare>
|
||||
bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcontainer1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcontainer2, Tcompare> &iter2)
|
||||
{
|
||||
if (iter1.GetMapIter() != iter2.GetMapIter()) return false;
|
||||
if (!iter1.ListValid()) return !iter2.ListValid();
|
||||
@@ -218,8 +219,8 @@ bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, T
|
||||
* @param iter2 Second iterator to compare.
|
||||
* @return If iter1 and iter2 are not equal.
|
||||
*/
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcompare>
|
||||
bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare> &iter2)
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcontainer1, class Tcontainer2, class Tcompare>
|
||||
bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcontainer1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcontainer2, Tcompare> &iter2)
|
||||
{
|
||||
return !(iter1 == iter2);
|
||||
}
|
||||
@@ -232,8 +233,8 @@ bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, T
|
||||
* @param iter2 Map iterator.
|
||||
* @return If iter1 points to the begin of the list pointed to by iter2.
|
||||
*/
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
|
||||
bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1, const Tmap_iter2 &iter2)
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcontainer, class Tcompare >
|
||||
bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcontainer, Tcompare> &iter1, const Tmap_iter2 &iter2)
|
||||
{
|
||||
return !iter1.ListValid() && iter1.GetMapIter() == iter2;
|
||||
}
|
||||
@@ -244,8 +245,8 @@ bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tc
|
||||
* @param iter2 Map iterator.
|
||||
* @return If iter1 doesn't point to the begin of the list pointed to by iter2.
|
||||
*/
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
|
||||
bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1, const Tmap_iter2 &iter2)
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcontainer, class Tcompare >
|
||||
bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcontainer, Tcompare> &iter1, const Tmap_iter2 &iter2)
|
||||
{
|
||||
return iter1.ListValid() || iter1.GetMapIter() != iter2;
|
||||
}
|
||||
@@ -256,8 +257,8 @@ bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tc
|
||||
* @param iter1 MultiMap iterator.
|
||||
* @return If iter1 points to the begin of the list pointed to by iter2.
|
||||
*/
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
|
||||
bool operator==(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1)
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcontainer, class Tcompare >
|
||||
bool operator==(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcontainer, Tcompare> &iter1)
|
||||
{
|
||||
return !iter1.ListValid() && iter1.GetMapIter() == iter2;
|
||||
}
|
||||
@@ -268,8 +269,8 @@ bool operator==(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlis
|
||||
* @param iter1 MultiMap iterator.
|
||||
* @return If iter1 doesn't point to the begin of the list pointed to by iter2.
|
||||
*/
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
|
||||
bool operator!=(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1)
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcontainer, class Tcompare >
|
||||
bool operator!=(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcontainer, Tcompare> &iter1)
|
||||
{
|
||||
return iter1.ListValid() || iter1.GetMapIter() != iter2;
|
||||
}
|
||||
@@ -282,10 +283,10 @@ bool operator!=(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlis
|
||||
* STL-compatible members are named in STL style, all others are named in OpenTTD
|
||||
* style.
|
||||
*/
|
||||
template<typename Tkey, typename Tvalue, typename Tcompare = std::less<Tkey> >
|
||||
class MultiMap : public std::map<Tkey, std::list<Tvalue>, Tcompare > {
|
||||
template<typename Tkey, typename Tvalue, typename Tcontainer = std::list<Tvalue>, typename Tcompare = std::less<Tkey> >
|
||||
class MultiMap : public std::map<Tkey, Tcontainer, Tcompare > {
|
||||
public:
|
||||
typedef typename std::list<Tvalue> List;
|
||||
typedef Tcontainer List;
|
||||
typedef typename List::iterator ListIterator;
|
||||
typedef typename List::const_iterator ConstListIterator;
|
||||
|
||||
@@ -293,8 +294,8 @@ public:
|
||||
typedef typename Map::iterator MapIterator;
|
||||
typedef typename Map::const_iterator ConstMapIterator;
|
||||
|
||||
typedef MultiMapIterator<MapIterator, ListIterator, Tkey, Tvalue, Tcompare> iterator;
|
||||
typedef MultiMapIterator<ConstMapIterator, ConstListIterator, Tkey, const Tvalue, Tcompare> const_iterator;
|
||||
typedef MultiMapIterator<MapIterator, ListIterator, Tkey, Tvalue, Tcontainer, Tcompare> iterator;
|
||||
typedef MultiMapIterator<ConstMapIterator, ConstListIterator, Tkey, const Tvalue, Tcontainer, Tcompare> const_iterator;
|
||||
|
||||
/**
|
||||
* Erase the value pointed to by an iterator. The iterator may be invalid afterwards.
|
||||
|
||||
@@ -196,6 +196,7 @@ DEFINE_POOL_METHOD(void)::FreeItem(size_t index)
|
||||
DEFINE_POOL_METHOD(void)::CleanPool()
|
||||
{
|
||||
this->cleaning = true;
|
||||
Titem::PreCleanPool();
|
||||
for (size_t i = 0; i < this->first_unused; i++) {
|
||||
delete this->Get(i); // 'delete NULL;' is very valid
|
||||
}
|
||||
|
||||
@@ -286,6 +286,13 @@ struct Pool : PoolBase {
|
||||
* @note it's called only when !CleaningPool()
|
||||
*/
|
||||
static inline void PostDestructor(size_t index) { }
|
||||
|
||||
/**
|
||||
* Dummy function called before a pool is about to be cleaned.
|
||||
* If you want to use it, override it in PoolItem's subclass.
|
||||
* @note it's called only when CleaningPool()
|
||||
*/
|
||||
static inline void PreCleanPool() { }
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
@@ -183,9 +183,9 @@ public:
|
||||
inline void Push(const Titem &item)
|
||||
{
|
||||
if (this->value != Tinvalid) {
|
||||
Tindex new_item = _pool.Create();
|
||||
Tindex new_item = SmallStack::GetPool().Create();
|
||||
if (new_item != Tmax_size) {
|
||||
PooledSmallStack &pushed = _pool.Get(new_item);
|
||||
PooledSmallStack &pushed = SmallStack::GetPool().Get(new_item);
|
||||
pushed.value = this->value;
|
||||
pushed.next = this->next;
|
||||
pushed.branch_count = 0;
|
||||
@@ -205,13 +205,15 @@ public:
|
||||
if (this->next == Tmax_size) {
|
||||
this->value = Tinvalid;
|
||||
} else {
|
||||
PooledSmallStack &popped = _pool.Get(this->next);
|
||||
PooledSmallStack &popped = SmallStack::GetPool().Get(this->next);
|
||||
this->value = popped.value;
|
||||
if (popped.branch_count == 0) {
|
||||
_pool.Destroy(this->next);
|
||||
SmallStack::GetPool().Destroy(this->next);
|
||||
} else {
|
||||
--popped.branch_count;
|
||||
this->Branch();
|
||||
if (popped.next != Tmax_size) {
|
||||
++(SmallStack::GetPool().Get(popped.next).branch_count);
|
||||
}
|
||||
}
|
||||
/* Accessing popped here is no problem as the pool will only set
|
||||
* the validity flag, not actually delete the item, on Destroy().
|
||||
@@ -243,7 +245,7 @@ public:
|
||||
const SmallStack *in_list = this;
|
||||
do {
|
||||
in_list = static_cast<const SmallStack *>(
|
||||
static_cast<const Item *>(&_pool.Get(in_list->next)));
|
||||
static_cast<const Item *>(&SmallStack::GetPool().Get(in_list->next)));
|
||||
if (in_list->value == item) return true;
|
||||
} while (in_list->next != Tmax_size);
|
||||
}
|
||||
@@ -251,7 +253,11 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
static SmallStackPool _pool;
|
||||
static SmallStackPool &GetPool()
|
||||
{
|
||||
static SmallStackPool pool;
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a branch in the pool if necessary.
|
||||
@@ -259,7 +265,7 @@ protected:
|
||||
inline void Branch()
|
||||
{
|
||||
if (this->next != Tmax_size) {
|
||||
++(_pool.Get(this->next).branch_count);
|
||||
++(SmallStack::GetPool().Get(this->next).branch_count);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -158,6 +158,23 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new item at a specific position into the vector, moving all following items.
|
||||
* @param item Position at which the new item should be inserted
|
||||
* @return pointer to the new item
|
||||
*/
|
||||
inline T *Insert(T *item)
|
||||
{
|
||||
assert(item >= this->Begin() && item <= this->End());
|
||||
|
||||
size_t to_move = this->End() - item;
|
||||
size_t start = item - this->Begin();
|
||||
|
||||
this->Append();
|
||||
if (to_move > 0) MemMoveT(this->Begin() + start + 1, this->Begin() + start, to_move);
|
||||
return this->Begin() + start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for the first occurrence of an item.
|
||||
* The '!=' operator of T is used for comparison.
|
||||
@@ -232,13 +249,24 @@ public:
|
||||
* @param count Number of consecutive items to remove.
|
||||
*/
|
||||
void ErasePreservingOrder(uint pos, uint count = 1)
|
||||
{
|
||||
ErasePreservingOrder(this->data + pos, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove items from the vector while preserving the order of other items.
|
||||
* @param item First item to remove.
|
||||
* @param count Number of consecutive items to remove.
|
||||
*/
|
||||
inline void ErasePreservingOrder(T *item, uint count = 1)
|
||||
{
|
||||
if (count == 0) return;
|
||||
assert(pos < this->items);
|
||||
assert(pos + count <= this->items);
|
||||
assert(item >= this->Begin());
|
||||
assert(item + count <= this->End());
|
||||
|
||||
this->items -= count;
|
||||
uint to_move = this->items - pos;
|
||||
if (to_move > 0) MemMoveT(this->data + pos, this->data + pos + count, to_move);
|
||||
ptrdiff_t to_move = this->End() - item;
|
||||
if (to_move > 0) MemMoveT(item, item + count, to_move);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user