Merge branch 'save_ext' into cargo_type_order

# Conflicts:
#	src/core/smallstack_type.hpp
This commit is contained in:
Jonathan G Rennison
2018-07-02 18:52:22 +01:00
534 changed files with 24037 additions and 9447 deletions

View File

@@ -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;
}

View File

@@ -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();
}
}

View File

@@ -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

View 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 */

View 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 */

View File

@@ -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)

View File

@@ -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 */

View File

@@ -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

View File

@@ -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.

View File

@@ -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
}

View File

@@ -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:

View File

@@ -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);
}
}
};

View File

@@ -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);
}
/**