Changeset - r23516:763b689dacfc
[Not reviewed]
master
0 7 0
Henry Wilson - 6 years ago 2018-09-20 21:41:43
m3henry@googlemail.com
Codechange: [core] Implement SmallVector using std::vector

The public and protected interface to SmallVector are unchanged
SmallVector now requires that items be default constructible
This isn't an issue since some contained items were previously created
uninitialized.

Temporary default constructors are added to the following structs
- SmallPair
- SmallStackItem
- GRFPresence

Where vector<bool> is required, transition immediately to std::vector
to avoid returning proxy object references.
7 files changed with 90 insertions and 116 deletions:
0 comments (0 inline, 0 general)
src/core/smallmap_type.hpp
Show inline comments
 
@@ -27,6 +27,7 @@ struct SmallPair {
 

	
 
	/** Initializes this Pair with data */
 
	inline SmallPair(const T &first, const U &second) : first(first), second(second) { }
 
	SmallPair() = default;
 
};
 

	
 
/**
 
@@ -56,8 +57,8 @@ struct SmallMap : SmallVector<SmallPair<
 
	 */
 
	inline const Pair *Find(const T &key) const
 
	{
 
		for (uint i = 0; i < this->items; i++) {
 
			if (key == this->data[i].first) return &this->data[i];
 
		for (uint i = 0; i < std::vector<Pair>::size(); i++) {
 
			if (key == std::vector<Pair>::operator[](i).first) return &std::vector<Pair>::operator[](i);
 
		}
 
		return this->End();
 
	}
 
@@ -69,12 +70,23 @@ struct SmallMap : SmallVector<SmallPair<
 
	 */
 
	inline Pair *Find(const T &key)
 
	{
 
		for (uint i = 0; i < this->items; i++) {
 
			if (key == this->data[i].first) return &this->data[i];
 
		for (uint i = 0; i < std::vector<Pair>::size(); i++) {
 
			if (key == std::vector<Pair>::operator[](i).first) return &std::vector<Pair>::operator[](i);
 
		}
 
		return this->End();
 
	}
 

	
 
	inline const Pair *End() const
 
	{
 
		return &*std::vector<Pair>::end();
 
	}
 

	
 
	inline Pair *End()
 
	{
 
		return &*std::vector<Pair>::end();
 
	}
 

	
 

	
 
	/**
 
	 * Tests whether a key is assigned in this map.
 
	 * @param key key to test
 
@@ -86,6 +98,16 @@ struct SmallMap : SmallVector<SmallPair<
 
	}
 

	
 
	/**
 
	 * Tests whether a key is assigned in this map.
 
	 * @param key key to test
 
	 * @return true iff the item is present
 
	 */
 
	inline bool Contains(const T &key)
 
	{
 
		return this->Find(key) != this->End();
 
	}
 

	
 
	/**
 
	 * Removes given pair from this map
 
	 * @param pair pair to remove
 
	 * @note it has to be pointer to pair in this map. It is overwritten by the last item.
 
@@ -93,7 +115,7 @@ struct SmallMap : SmallVector<SmallPair<
 
	inline void Erase(Pair *pair)
 
	{
 
		assert(pair >= this->Begin() && pair < this->End());
 
		*pair = this->data[--this->items];
 
		SmallVector<Pair, S>::Erase(pair);
 
	}
 

	
 
	/**
 
@@ -104,13 +126,12 @@ struct SmallMap : SmallVector<SmallPair<
 
	 */
 
	inline bool Erase(const T &key)
 
	{
 
		for (uint i = 0; i < this->items; i++) {
 
			if (key == this->data[i].first) {
 
				this->data[i] = this->data[--this->items];
 
				return true;
 
			}
 
		}
 
		return false;
 
		Pair *pair = this->Find(key);
 
		if (pair == this->End())
 
			return false;
 

	
 
		SmallVector<Pair, S>::Erase(pair);
 
		return true;
 
	}
 

	
 
	/**
 
@@ -136,8 +157,8 @@ struct SmallMap : SmallVector<SmallPair<
 
	 */
 
	inline U &operator[](const T &key)
 
	{
 
		for (uint i = 0; i < this->items; i++) {
 
			if (key == this->data[i].first) return this->data[i].second;
 
		for (uint i = 0; i < std::vector<Pair>::size(); i++) {
 
			if (key == std::vector<Pair>::operator[](i).first) return std::vector<Pair>::operator[](i).second;
 
		}
 
		Pair *n = this->Append();
 
		n->first = key;
 
@@ -146,7 +167,7 @@ struct SmallMap : SmallVector<SmallPair<
 

	
 
	inline void SortByKey()
 
	{
 
		QSortT(this->Begin(), this->items, KeySorter);
 
		QSortT(this->Begin(), std::vector<Pair>::size(), KeySorter);
 
	}
 

	
 
	static int CDECL KeySorter(const Pair *a, const Pair *b)
src/core/smallstack_type.hpp
Show inline comments
 
@@ -106,6 +106,7 @@ struct SmallStackItem {
 
	 */
 
	inline SmallStackItem(const Titem &value, Tindex next) :
 
		next(next), value(value) {}
 
	SmallStackItem() = default;
 
};
 

	
 
/**
src/core/smallvec_type.hpp
Show inline comments
 
@@ -14,6 +14,8 @@
 

	
 
#include "alloc_func.hpp"
 
#include "mem_func.hpp"
 
#include <vector>
 
#include <algorithm>
 

	
 
/**
 
 * Simple vector template class.
 
@@ -26,43 +28,30 @@
 
 * @tparam S The steps of allocation
 
 */
 
template <typename T, uint S>
 
class SmallVector {
 
protected:
 
	T *data;       ///< The pointer to the first item
 
	uint items;    ///< The number of items stored
 
	uint capacity; ///< The available space for storing items
 

	
 
class SmallVector : public std::vector<T> {
 
public:
 
	SmallVector() : data(NULL), items(0), capacity(0) { }
 
	SmallVector() = default;
 

	
 
	/**
 
	 * Copy constructor.
 
	 * @param other The other vector to copy.
 
	 */
 
	SmallVector(const SmallVector &other) : data(NULL), items(0), capacity(0)
 
	{
 
		this->Assign(other);
 
	}
 
	SmallVector(const SmallVector &other) = default;
 

	
 
	/**
 
	 * Generic copy constructor.
 
	 * @param other The other vector to copy.
 
	 */
 
	template <uint X>
 
	SmallVector(const SmallVector<T, X> &other) : data(NULL), items(0), capacity(0)
 
	SmallVector(const SmallVector<T, X> &other) : std::vector<T>(other)
 
	{
 
		this->Assign(other);
 
	}
 

	
 
	/**
 
	 * Assignment.
 
	 * @param other The other vector to assign.
 
	 */
 
	SmallVector &operator=(const SmallVector &other)
 
	{
 
		this->Assign(other);
 
		return *this;
 
	}
 
	SmallVector &operator=(const SmallVector &other) = default;
 

	
 
	/**
 
	 * Generic assignment.
 
@@ -75,10 +64,7 @@ public:
 
		return *this;
 
	}
 

	
 
	~SmallVector()
 
	{
 
		free(this->data);
 
	}
 
	~SmallVector() = default;
 

	
 
	/**
 
	 * Assign items from other vector.
 
@@ -88,8 +74,7 @@ public:
 
	{
 
		if ((const void *)&other == (void *)this) return;
 

	
 
		this->Clear();
 
		if (other.Length() > 0) MemCpyT<T>(this->Append(other.Length()), other.Begin(), other.Length());
 
		std::vector<T>::operator=(other);
 
	}
 

	
 
	/**
 
@@ -97,10 +82,7 @@ public:
 
	 */
 
	inline void Clear()
 
	{
 
		/* In fact we just reset the item counter avoiding the need to
 
		 * probably reallocate the same amount of memory the list was
 
		 * previously using. */
 
		this->items = 0;
 
		std::vector<T>::clear();
 
	}
 

	
 
	/**
 
@@ -108,10 +90,8 @@ public:
 
	 */
 
	inline void Reset()
 
	{
 
		this->items = 0;
 
		this->capacity = 0;
 
		free(data);
 
		data = NULL;
 
		std::vector<T>::clear();
 
		std::vector<T>::shrink_to_fit();
 
	}
 

	
 
	/**
 
@@ -119,11 +99,7 @@ public:
 
	 */
 
	inline void Compact()
 
	{
 
		uint capacity = Align(this->items, S);
 
		if (capacity >= this->capacity) return;
 

	
 
		this->capacity = capacity;
 
		this->data = ReallocT(this->data, this->capacity);
 
		std::vector<T>::shrink_to_fit();
 
	}
 

	
 
	/**
 
@@ -133,15 +109,8 @@ public:
 
	 */
 
	inline T *Append(uint to_add = 1)
 
	{
 
		uint begin = this->items;
 
		this->items += to_add;
 

	
 
		if (this->items > this->capacity) {
 
			this->capacity = Align(this->items, S);
 
			this->data = ReallocT(this->data, this->capacity);
 
		}
 

	
 
		return &this->data[begin];
 
		std::vector<T>::resize(std::vector<T>::size() + to_add);
 
		return this->End() - to_add;
 
	}
 

	
 
	/**
 
@@ -150,12 +119,7 @@ public:
 
	 */
 
	inline void Resize(uint num_items)
 
	{
 
		this->items = num_items;
 

	
 
		if (this->items > this->capacity) {
 
			this->capacity = Align(this->items, S);
 
			this->data = ReallocT(this->data, this->capacity);
 
		}
 
		std::vector<T>::resize(num_items);
 
	}
 

	
 
	/**
 
@@ -167,11 +131,8 @@ public:
 
	{
 
		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);
 
		std::vector<T>::insert(std::vector<T>::begin() + start);
 
		return this->Begin() + start;
 
	}
 

	
 
@@ -211,14 +172,8 @@ public:
 
	 */
 
	inline int FindIndex(const T &item) const
 
	{
 
		int index = 0;
 
		const T *pos = this->Begin();
 
		const T *end = this->End();
 
		while (pos != end && *pos != item) {
 
			pos++;
 
			index++;
 
		}
 
		return pos == end ? -1 : index;
 
		auto const it = this->Find(item);
 
		return it == this->End() ? -1 : it - this->Begin();
 
	}
 

	
 
	/**
 
@@ -240,7 +195,8 @@ public:
 
	inline void Erase(T *item)
 
	{
 
		assert(item >= this->Begin() && item < this->End());
 
		*item = this->data[--this->items];
 
		*item = std::vector<T>::back();
 
		std::vector<T>::pop_back();
 
	}
 

	
 
	/**
 
@@ -250,7 +206,8 @@ public:
 
	 */
 
	void ErasePreservingOrder(uint pos, uint count = 1)
 
	{
 
		ErasePreservingOrder(this->data + pos, count);
 
		auto const it = std::vector<T>::begin() + pos;
 
		std::vector<T>::erase(it, it + count);
 
	}
 

	
 
	/**
 
@@ -260,13 +217,7 @@ public:
 
	 */
 
	inline void ErasePreservingOrder(T *item, uint count = 1)
 
	{
 
		if (count == 0) return;
 
		assert(item >= this->Begin());
 
		assert(item + count <= this->End());
 

	
 
		this->items -= count;
 
		ptrdiff_t to_move = this->End() - item;
 
		if (to_move > 0) MemMoveT(item, item + count, to_move);
 
		this->ErasePreservingOrder(item - this->Begin(), count);
 
	}
 

	
 
	/**
 
@@ -289,7 +240,7 @@ public:
 
	 */
 
	inline uint Length() const
 
	{
 
		return this->items;
 
		return std::vector<T>::size();
 
	}
 

	
 
	/**
 
@@ -299,7 +250,7 @@ public:
 
	 */
 
	inline const T *Begin() const
 
	{
 
		return this->data;
 
		return std::vector<T>::data();
 
	}
 

	
 
	/**
 
@@ -309,7 +260,7 @@ public:
 
	 */
 
	inline T *Begin()
 
	{
 
		return this->data;
 
		return std::vector<T>::data();
 
	}
 

	
 
	/**
 
@@ -319,7 +270,7 @@ public:
 
	 */
 
	inline const T *End() const
 
	{
 
		return &this->data[this->items];
 
		return std::vector<T>::data() + std::vector<T>::size();
 
	}
 

	
 
	/**
 
@@ -329,7 +280,7 @@ public:
 
	 */
 
	inline T *End()
 
	{
 
		return &this->data[this->items];
 
		return std::vector<T>::data() + std::vector<T>::size();
 
	}
 

	
 
	/**
 
@@ -341,8 +292,8 @@ public:
 
	inline const T *Get(uint index) const
 
	{
 
		/* Allow access to the 'first invalid' item */
 
		assert(index <= this->items);
 
		return &this->data[index];
 
		assert(index <= std::vector<T>::size());
 
		return this->Begin() + index;
 
	}
 

	
 
	/**
 
@@ -354,8 +305,8 @@ public:
 
	inline T *Get(uint index)
 
	{
 
		/* Allow access to the 'first invalid' item */
 
		assert(index <= this->items);
 
		return &this->data[index];
 
		assert(index <= std::vector<T>::size());
 
		return this->Begin() + index;
 
	}
 

	
 
	/**
 
@@ -366,8 +317,8 @@ public:
 
	 */
 
	inline const T &operator[](uint index) const
 
	{
 
		assert(index < this->items);
 
		return this->data[index];
 
		assert(index < std::vector<T>::size());
 
		return std::vector<T>::operator[](index);
 
	}
 

	
 
	/**
 
@@ -378,8 +329,8 @@ public:
 
	 */
 
	inline T &operator[](uint index)
 
	{
 
		assert(index < this->items);
 
		return this->data[index];
 
		assert(index < std::vector<T>::size());
 
		return std::vector<T>::operator[](index);
 
	}
 
};
 

	
 
@@ -407,11 +358,11 @@ public:
 
	 */
 
	inline void Clear()
 
	{
 
		for (uint i = 0; i < this->items; i++) {
 
			free(this->data[i]);
 
		for (uint i = 0; i < std::vector<T>::size(); i++) {
 
			free(std::vector<T>::operator[](i));
 
		}
 

	
 
		this->items = 0;
 
		std::vector<T>::clear();
 
	}
 
};
 

	
 
@@ -438,11 +389,11 @@ public:
 
	 */
 
	inline void Clear()
 
	{
 
		for (uint i = 0; i < this->items; i++) {
 
			delete this->data[i];
 
		for (uint i = 0; i < std::vector<T>::size(); i++) {
 
			delete std::vector<T>::operator[](i);
 
		}
 

	
 
		this->items = 0;
 
		std::vector<T>::clear();
 
	}
 
};
 

	
src/fios_gui.cpp
Show inline comments
 
@@ -279,7 +279,7 @@ private:
 

	
 
	StringFilter string_filter; ///< Filter for available games.
 
	QueryString filter_editbox; ///< Filter editbox;
 
	SmallVector<bool, 32> fios_items_shown; ///< Map of the filtered out fios items
 
	std::vector<bool> fios_items_shown; ///< Map of the filtered out fios items
 

	
 
	static void SaveGameConfirmationCallback(Window *w, bool confirmed)
 
	{
 
@@ -824,7 +824,7 @@ public:
 

	
 
			case SLIWD_FILTER_CHANGES:
 
				/* Filter changes */
 
				this->fios_items_shown.Resize(this->fios_items.Length());
 
				this->fios_items_shown.resize(this->fios_items.Length());
 
				uint items_shown_count = 0; ///< The number of items shown in the list
 
				/* We pass through every fios item */
 
				for (uint i = 0; i < this->fios_items.Length(); i++) {
src/gamelog.cpp
Show inline comments
 
@@ -178,6 +178,7 @@ struct GRFPresence{
 
	bool was_missing;     ///< Grf was missing during some gameload in the past
 

	
 
	GRFPresence(const GRFConfig *gc) : gc(gc), was_missing(false) {}
 
	GRFPresence() = default;
 
};
 
typedef SmallMap<uint32, GRFPresence> GrfIDMapping;
 

	
src/script/squirrel_helper.hpp
Show inline comments
 
@@ -32,7 +32,7 @@ namespace SQConvert {
 
	struct SQAutoFreePointers : SmallVector<void *, 1> {
 
		~SQAutoFreePointers()
 
		{
 
			for (uint i = 0; i < this->items; i++) free(this->data[i]);
 
			for (uint i = 0; i < std::vector<void *>::size(); i++) free(std::vector<void *>::operator[](i));
 
		}
 
	};
 

	
src/sortlist_type.h
Show inline comments
 
@@ -67,7 +67,7 @@ protected:
 
	 */
 
	bool IsSortable() const
 
	{
 
		return (this->data != NULL && this->items >= 2);
 
		return std::vector<T>::size() >= 2;
 
	}
 

	
 
	/**
 
@@ -240,7 +240,7 @@ public:
 
	{
 
		this->flags ^= VL_DESC;
 

	
 
		if (this->IsSortable()) MemReverseT(this->data, this->items);
 
		if (this->IsSortable()) MemReverseT(std::vector<T>::data(), std::vector<T>::size());
 
	}
 

	
 
	/**
 
@@ -270,11 +270,11 @@ public:
 
		if (this->flags & VL_FIRST_SORT) {
 
			CLRBITS(this->flags, VL_FIRST_SORT);
 

	
 
			QSortT(this->data, this->items, compare, desc);
 
			QSortT(std::vector<T>::data(), std::vector<T>::size(), compare, desc);
 
			return true;
 
		}
 

	
 
		GSortT(this->data, this->items, compare, desc);
 
		GSortT(std::vector<T>::data(), std::vector<T>::size(), compare, desc);
 
		return true;
 
	}
 

	
 
@@ -337,8 +337,8 @@ public:
 
		if (!(this->flags & VL_FILTER)) return false;
 

	
 
		bool changed = false;
 
		for (uint iter = 0; iter < this->items;) {
 
			T *item = &this->data[iter];
 
		for (uint iter = 0; iter < std::vector<T>::size();) {
 
			T *item = &std::vector<T>::operator[](iter);
 
			if (!decide(item, filter_data)) {
 
				this->Erase(item);
 
				changed = true;
0 comments (0 inline, 0 general)