summaryrefslogtreecommitdiff
path: root/src/core/smallvec_type.hpp
blob: f43265ebe82fbcf18a32b70b356505d1c54189f7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* $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 smallvec_type.hpp Simple vector class that allows allocating an item without the need to copy this->data needlessly. */

#ifndef SMALLVEC_TYPE_HPP
#define SMALLVEC_TYPE_HPP

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

/**
 * Helper function to append an item to a vector if it is not already contained
 * Consider using std::set, std::unordered_set or std::flat_set in new code
 *
 * @param vec A reference to the vector to be extended
 * @param item Reference to the item to be copy-constructed if not found
 *
 * @return Whether the item was already present
 */
template <typename T>
inline bool include(std::vector<T>& vec, const T &item)
{
	const bool is_member = std::find(vec.begin(), vec.end(), item) != vec.end();
	if (!is_member) vec.emplace_back(item);
	return is_member;
}

/**
 * Helper function to get the index of an item
 * Consider using std::set, std::unordered_set or std::flat_set in new code
 *
 * @param vec A reference to the vector to be extended
 * @param item Reference to the item to be search for
 *
 * @return Index of element if found, otherwise -1
 */
template <typename T>
int find_index(std::vector<T> const& vec, T const& item)
{
	auto const it = std::find(vec.begin(), vec.end(), item);
	if (it != vec.end()) return it - vec.begin();

	return -1;
}

/**
 * Helper function to append N default-constructed elements and get a pointer to the first new element
 * Consider using std::back_inserter in new code
 *
 * @param vec A reference to the vector to be extended
 * @param num Number of elements to be default-constructed
 *
 * @return Pointer to the first new element
 */
template <typename T>
T* grow(std::vector<T>& vec, std::size_t num)
{
	std::size_t const pos = vec.size();
	vec.resize(pos + num);
	return vec.data() + pos;
}

/**
 * Simple vector template class, with automatic free.
 *
 * @note There are no asserts in the class so you have
 *       to care about that you grab an item which is
 *       inside the list.
 *
 * @param T The type of the items stored, must be a pointer
 */
template <typename T>
class AutoFreeSmallVector : public std::vector<T> {
public:
	~AutoFreeSmallVector()
	{
		this->Clear();
	}

	/**
	 * Remove all items from the list.
	 */
	inline void Clear()
	{
		for (T p : *this) {
			free(p);
		}

		std::vector<T>::clear();
	}
};

/**
 * Simple vector template class, with automatic delete.
 *
 * @note There are no asserts in the class so you have
 *       to care about that you grab an item which is
 *       inside the list.
 *
 * @param T The type of the items stored, must be a pointer
 */
template <typename T>
class AutoDeleteSmallVector : public std::vector<T> {
public:
	~AutoDeleteSmallVector()
	{
		this->Clear();
	}

	/**
	 * Remove all items from the list.
	 */
	inline void Clear()
	{
		for (T p : *this) {
			delete p;
		}

		std::vector<T>::clear();
	}
};

typedef AutoFreeSmallVector<char*> StringList; ///< Type for a list of strings.

#endif /* SMALLVEC_TYPE_HPP */