Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR for Modernizing for C++11: replacing instances of SmallVector #6817

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
6447f50
Add: New adapter functions to help transition from SmallVector
M3Henry Dec 30, 2017
e397df9
Codechange: Make Window::scheduled_invalidation_data use std::vector …
M3Henry Dec 30, 2017
ec544d7
Codechange: Make SubtypeList use std::vector over SmallVector
M3Henry Dec 30, 2017
cd8d6cc
Codechange: Make GetBestFittingSubType()::subtypes use std::vector ov…
M3Henry Dec 30, 2017
ccf3c5c
Codechange: Make TextfileWindow::lines use std::vector over SmallVector
M3Henry Dec 30, 2017
fbc5e75
Codechange: Make CheckSubsidised()::towns_near use std::vector over S…
M3Henry Dec 30, 2017
e894abe
Codechange: Make StringFilter::word_index use std::vector over SmallV…
M3Henry Dec 30, 2017
daa7997
Codechange: Make IcuStringIterator sung std::vector over SmallVector
M3Henry Dec 30, 2017
2561105
Codechange: Make SmallIndustryList use std::vector over SmallVector
M3Henry Dec 30, 2017
c95b308
Codechange: Make FileList::files use std::vector over SmallVector
M3Henry Dec 30, 2017
bee3249
Codechange: Make VehicleGroupWindow::indents use std::vector over Sma…
M3Henry Dec 30, 2017
8897223
Codechange: Make _hotkey_lists use std::vector over SmallVector
M3Henry Dec 30, 2017
7845eed
Codechange: Make Hotkey::keycodes use std::vector over SmallVector
M3Henry Dec 30, 2017
573b1b2
Codechange: Make LanguageList use std::vector over SmallVector
M3Henry Dec 31, 2017
27c0082
Codechange: Make LinkGraph::NodeVector use std::vector over SmallVector
M3Henry Dec 31, 2017
72d73e3
Codechange: Make LinkGraphJob::NodeAnnotationVector use std::vector o…
M3Henry Dec 31, 2017
445bcdb
Codechange: Make NetworkAddressList use std::vector over SmallVector
M3Henry Dec 31, 2017
f748fcd
Codechange: Make _tcp_connectors use std::vector over SmallVector
M3Henry Dec 31, 2017
633629c
Codechange: Make _http_connections use std::vector over SmallVector
M3Henry Dec 31, 2017
40dd391
Codechange: Make IndustryCargoesWindow::Fields use std::vector over S…
M3Henry Dec 31, 2017
81b7b07
Codechange: Make ContentVector use std::vector over SmallVector
M3Henry Dec 31, 2017
d6fba11
Codechange: Make GetLinkGraphJobDesc()::saveloads use std::vector ove…
M3Henry Dec 31, 2017
054063e
Codechange: Make _old_waypoints use std::vector over SmallVector
M3Henry Dec 31, 2017
2f119f1
Codechange: Make StationList use std::vector over SmallVector
M3Henry Dec 30, 2017
43b6222
Codechange: Make _text_effects use std::vector over SmallVector
M3Henry Dec 30, 2017
e660300
Codechange: Make OutputStore::output_buffer use std::vector over Smal…
M3Henry Jan 2, 2018
9804906
Codechange: Make TrainList use std::vector over SmallVector
M3Henry Jan 2, 2018
d4d0b5d
Codechange: Make CmdSetTimetableStart()::vehs use std::vector over Sm…
M3Henry Jan 2, 2018
1f3845a
Codechange: Make AfterLoadGame()::skip_frames use std::vector over Sm…
M3Henry Jan 2, 2018
072d1b9
Codechange: Make station_gui.cpp SmallVectors use std::vector over Sm…
M3Henry Jan 2, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
119 changes: 118 additions & 1 deletion src/core/smallvec_type.hpp
Expand Up @@ -7,14 +7,131 @@
* 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. */
/** @file smallvec_type.hpp Simple vector class that allows allocating an item without the need to copy this->data needlessly.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

text should be on a separate line, to preserve alignment

(applies to lots of functions)

* @note The std::vector adapter functions are _temporary_ substitutions for methods of SmallVector
*/

#ifndef SMALLVEC_TYPE_HPP
#define SMALLVEC_TYPE_HPP

#include "alloc_func.hpp"
#include "mem_func.hpp"

#include <vector>
#include <algorithm>

/** Get a const iterator to a matching element in the vector.
* @param vec the vector to be searched
* @param elem the element to search fo
* @tparam T the contained type of the vector
*/
template <typename T>
typename std::vector<T>::const_iterator Find(const std::vector<T>& vec, const T& elem) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opening brace of a function should be on a newline

(applies to various functions)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
typename std::vector<T>::const_iterator Find(const std::vector<T>& vec, const T& elem) {
typename std::vector<T>::const_iterator Find(const std::vector<T>& vec, const T& elem)
{

return std::find(vec.begin(), vec.end(), elem);
}

/** Get a non-const iterator to a matching element in the vector.
* @param vec the vector to be searched
* @param elem the element to search for
* @tparam T the contained type of the vector
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing @return doxygen command

(applies to various functions)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
*/
* @return an iterator to the position of the element if it was found. vec.end() otherwise.
*/

template <typename T>
typename std::vector<T>::iterator Find(std::vector<T>& vec, const T& elem) {
return std::find(vec.begin(), vec.end(), elem);
}

/** Get the index of the first matching element.
* @param vec the vector to be searched
* @param elem the element to search for
* @tparam T the contained type of the vector
*/
template <typename T>
int FindIndex(const std::vector<T>& vec, const T& elem) {
auto it = Find(vec, elem);
if (vec.end() == it) return -1;
return std::distance(vec.begin(), it);
}

/** Check whether an element exists.
* @param vec the vector to be searched
* @param elem the element to search for
* @tparam T the contained type of the vector
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
*/
* @return true if vec contains elem. false otherwise.
*/

template <typename T>
bool Contains(const std::vector<T>& vec, const T& elem) {
return Find(vec, elem) != vec.end();
}

/** Count instances of an element.
* @param vec the vector to be searched
* @param elem the element to count instances of
* @tparam T the contained type of the vector
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
*/
* @return the number of occurrences.
*/

template <typename T>
size_t Count(const std::vector<T>& vec, const T& elem) {
return std::count(vec.begin(), vec.end(), elem);
}

/** Append an element if it does not already exist in the vector.
* @param vec the vector to be modified
* @param elem the element to add for and remove if missing
* @tparam T the contained type of the vector
* @tparam U the universal reference type for perfect forwarding
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
*/
* @return true if the element had to be added.
*/

template <typename T, typename U>
bool Include(std::vector<T>& vec, U&& elem) {
auto missing = not Contains(vec, elem);
if (missing) vec.push_back(std::forward<U>(elem));
return missing;
}

/** Remove an element referenced in the vector and move the last element to take its place.
* @param vec the vector to be modified
* @param it the element to remove
* @tparam T the contained type of the vector
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @tparam T the contained type of the vector
* @tparam T the contained type of the vector
* @return the iterator it

*/
template <typename T>
typename std::vector<T>::iterator Erase(std::vector<T>& vec, typename std::vector<T>::iterator it) {
assert(vec.begin() <= it and vec.end() > it);
if (std::prev(vec.end()) != it) std::swap(vec.back(), *it);
vec.pop_back();
return it;
}

/** Remove an element if it exists in the vector and move the last element to take its place.
* @param vec the vector to be modified
* @param elem the element to search for and remove if found
* @tparam T the contained type of the vector
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
*/
* @return true if the element was removed, false if it was not found.
*/

template <typename T>
bool Exclude(std::vector<T>& vec, const T& elem) {
auto it = Find(vec, elem);
if (vec.end() == it) return false;
Erase(vec, it);
return true;
}

/** Clear a vector and then force it to reduce its capacity.
* @param vec the vector to be modified
* @tparam T the contained type of the vector
*/
template <typename T>
void Reset(std::vector<T>& vec) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pretty sure this function isn't necessary - can be replaced with a clear() - the capacity reduction was just due to how the allocations worked

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be a good idea to keep the capacity reduction where it is used in case that behavior is desired.
According to cppreference: "Leaves the capacity() of the vector unchanged"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shrink_to_fit is only a request which may be ignored.
The guaranteed implementation looks like this:

template <typename T>
void Reset(std::vector<T>& vec) {
  std::vector<T>{}.swap(vec);
}

vec.clear();
vec.shrink_to_fit();
}

/** Extend a vector by an amount and return an iterator to the new elements.
* @param vec the vector to be modified
* @param num the number of elements to add
* @tparam T the contained type of the vector
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @tparam T the contained type of the vector
* @tparam T the contained type of the vector
* @return an iterator to the first of the added elements.

*/
template <typename T>
typename std::vector<T>::iterator Extend(std::vector<T>& vec, size_t num) {
vec.resize(vec.size() + num);
return vec.end() - num;
}

/**
* Simple vector template class.
*
Expand Down
11 changes: 4 additions & 7 deletions src/economy.cpp
Expand Up @@ -77,7 +77,7 @@ static inline int32 BigMulS(const int32 a, const int32 b, const uint8 shift)
return (int32)((int64)a * (int64)b >> shift);
}

typedef SmallVector<Industry *, 16> SmallIndustryList;
using SmallIndustryList = std::vector<Industry *> ;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra space before ;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
using SmallIndustryList = std::vector<Industry *> ;
using SmallIndustryList = std::vector<Industry *>;


/**
* Score info, values used for computing the detailed performance rating.
Expand Down Expand Up @@ -1057,7 +1057,7 @@ static uint DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, uint n
if (IndustryTemporarilyRefusesCargo(ind, cargo_type)) continue;

/* Insert the industry into _cargo_delivery_destinations, if not yet contained */
_cargo_delivery_destinations.Include(ind);
Include(_cargo_delivery_destinations, ind);

uint amount = min(num_pieces, 0xFFFFU - ind->incoming_cargo_waiting[cargo_index]);
ind->incoming_cargo_waiting[cargo_index] += amount;
Expand Down Expand Up @@ -1930,11 +1930,8 @@ void LoadUnloadStation(Station *st)
}

/* Call the production machinery of industries */
const Industry * const *isend = _cargo_delivery_destinations.End();
for (Industry **iid = _cargo_delivery_destinations.Begin(); iid != isend; iid++) {
TriggerIndustryProduction(*iid);
}
_cargo_delivery_destinations.Clear();
for (const auto &iid : _cargo_delivery_destinations) TriggerIndustryProduction(iid);
_cargo_delivery_destinations.clear();
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/fios.cpp
Expand Up @@ -397,7 +397,7 @@ static void FiosGetFileList(SaveLoadOperation fop, fios_getlist_callback_proc *c
{
SortingBits order = _savegame_sort_order;
_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
QSortT(file_list.files.Begin(), file_list.files.Length(), CompareFiosItems);
QSortT(file_list.files.data(), file_list.Length(), CompareFiosItems);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit more work involved, but since you're converting some stuff in this PR other than just converting SmallVector, perhaps converting to use std::sort would be a good idea as well

Alternatively, it should be a separate PR (along with the various other changes in this PR) :)

Copy link
Contributor Author

@M3Henry M3Henry Sep 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that the standard algorithms would be ideal where applicable, a seperate PR would make most sense.

Copy link
Contributor

@fsimonis fsimonis Jan 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here an untested suggestion: (at least #include<algorithm> is missing)

Suggested change
QSortT(file_list.files.data(), file_list.Length(), CompareFiosItems);
std::sort(file_list.files.data(), file_list.files.data() + file_list.Length(), CompareFiosItems);

_savegame_sort_order = order;
}

Expand Down
18 changes: 9 additions & 9 deletions src/fios.h
Expand Up @@ -113,7 +113,7 @@ class FileList {
*/
inline FiosItem *Append()
{
return this->files.Append();
return &*Extend(this->files, 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ew. Looks like FileList is itself a pseudo-SmallVector - should be "converted" ?

}

/**
Expand All @@ -122,7 +122,7 @@ class FileList {
*/
inline uint Length() const
{
return this->files.Length();
return this->files.size();
}

/**
Expand All @@ -131,7 +131,7 @@ class FileList {
*/
inline const FiosItem *Begin() const
{
return this->files.Begin();
return this->files.data();
Copy link
Contributor

@fsimonis fsimonis Jan 23, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure the vector contains files.

Suggested change
return this->files.data();
return &(this->files->at(0));

}

/**
Expand All @@ -140,7 +140,7 @@ class FileList {
*/
inline const FiosItem *End() const
{
return this->files.End();
return this->Begin() + this->Length();
}

/**
Expand All @@ -149,7 +149,7 @@ class FileList {
*/
inline const FiosItem *Get(uint index) const
{
return this->files.Get(index);
return this->files.data() + index;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return this->files.data() + index;
return &(this->files.at(index));

}

/**
Expand All @@ -158,7 +158,7 @@ class FileList {
*/
inline FiosItem *Get(uint index)
{
return this->files.Get(index);
return this->files.data() + index;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return this->files.data() + index;
return &(this->files.at(index));

}

inline const FiosItem &operator[](uint index) const
Expand All @@ -178,19 +178,19 @@ class FileList {
/** Remove all items from the list. */
inline void Clear()
{
this->files.Clear();
this->files.clear();
}

/** Compact the list down to the smallest block size boundary. */
inline void Compact()
{
this->files.Compact();
this->files.shrink_to_fit();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the "swap-trick" to force the shrink.

Suggested change
this->files.shrink_to_fit();
decltype(files)(this->files).swap(this->files);

}

void BuildFileList(AbstractFileType abstract_filetype, SaveLoadOperation fop);
const FiosItem *FindItem(const char *file);

SmallVector<FiosItem, 32> files; ///< The list of files.
std::vector<FiosItem> files; ///< The list of files.
};

enum SortingBits {
Expand Down
6 changes: 3 additions & 3 deletions src/group_gui.cpp
Expand Up @@ -118,7 +118,7 @@ class VehicleGroupWindow : public BaseVehicleListWindow {
uint tiny_step_height; ///< Step height for the group list
Scrollbar *group_sb;

SmallVector<int, 16> indents; ///< Indentation levels
std::vector<int> indents; ///< Indentation levels

Dimension column_size[VGC_END]; ///< Size of the columns in the group list.

Expand All @@ -127,7 +127,7 @@ class VehicleGroupWindow : public BaseVehicleListWindow {
for (const Group **g = source->Begin(); g != source->End(); g++) {
if ((*g)->parent == parent) {
*this->groups.Append() = *g;
*this->indents.Append() = indent;
this->indents.push_back(indent);
AddParents(source, (*g)->index, indent + 1);
}
}
Expand Down Expand Up @@ -166,7 +166,7 @@ class VehicleGroupWindow : public BaseVehicleListWindow {
if (!this->groups.NeedRebuild()) return;

this->groups.Clear();
this->indents.Clear();
this->indents.clear();

GUIGroupList list;

Expand Down
30 changes: 15 additions & 15 deletions src/hotkeys.cpp
Expand Up @@ -24,7 +24,7 @@ char *_hotkeys_file;
* List of all HotkeyLists.
* This is a pointer to ensure initialisation order with the various static HotkeyList instances.
*/
static SmallVector<HotkeyList*, 16> *_hotkey_lists = NULL;
static std::vector<HotkeyList*> *_hotkey_lists = NULL;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pointer to a vector of pointers... lovely. I see from the comment that it was for initialisation order reasons, but is that still necessary?


/** String representation of a keycode */
struct KeycodeNames {
Expand Down Expand Up @@ -202,7 +202,7 @@ const char *SaveKeycodes(const Hotkey *hotkey)
{
static char buf[128];
buf[0] = '\0';
for (uint i = 0; i < hotkey->keycodes.Length(); i++) {
for (uint i = 0; i < hotkey->keycodes.size(); i++) {
const char *str = KeycodeToString(hotkey->keycodes[i]);
if (i > 0) strecat(buf, ",", lastof(buf));
strecat(buf, str, lastof(buf));
Expand Down Expand Up @@ -247,19 +247,19 @@ Hotkey::Hotkey(const uint16 *default_keycodes, const char *name, int num) :
*/
void Hotkey::AddKeycode(uint16 keycode)
{
this->keycodes.Include(keycode);
Include(this->keycodes, keycode);
}

HotkeyList::HotkeyList(const char *ini_group, Hotkey *items, GlobalHotkeyHandlerFunc global_hotkey_handler) :
global_hotkey_handler(global_hotkey_handler), ini_group(ini_group), items(items)
{
if (_hotkey_lists == NULL) _hotkey_lists = new SmallVector<HotkeyList*, 16>();
*_hotkey_lists->Append() = this;
if (_hotkey_lists == NULL) _hotkey_lists = new std::vector<HotkeyList*>();
_hotkey_lists->push_back(this);
}

HotkeyList::~HotkeyList()
{
_hotkey_lists->Erase(_hotkey_lists->Find(this));
Exclude(*_hotkey_lists, this);
}

/**
Expand All @@ -272,7 +272,7 @@ void HotkeyList::Load(IniFile *ini)
for (Hotkey *hotkey = this->items; hotkey->name != NULL; ++hotkey) {
IniItem *item = group->GetItem(hotkey->name, false);
if (item != NULL) {
hotkey->keycodes.Clear();
hotkey->keycodes.clear();
if (item->value != NULL) ParseHotkeys(hotkey, item->value);
}
}
Expand Down Expand Up @@ -300,7 +300,7 @@ void HotkeyList::Save(IniFile *ini) const
int HotkeyList::CheckMatch(uint16 keycode, bool global_only) const
{
for (const Hotkey *list = this->items; list->name != NULL; ++list) {
if (list->keycodes.Contains(keycode | WKC_GLOBAL_HOTKEY) || (!global_only && list->keycodes.Contains(keycode))) {
if (Contains(list->keycodes, static_cast<uint16>(keycode | WKC_GLOBAL_HOTKEY)) || (!global_only && Contains(list->keycodes, keycode))) {
return list->num;
}
}
Expand All @@ -313,11 +313,11 @@ static void SaveLoadHotkeys(bool save)
IniFile *ini = new IniFile();
ini->LoadFromDisk(_hotkeys_file, NO_DIRECTORY);

for (HotkeyList **list = _hotkey_lists->Begin(); list != _hotkey_lists->End(); ++list) {
for (auto &list : *_hotkey_lists) {
if (save) {
(*list)->Save(ini);
list->Save(ini);
} else {
(*list)->Load(ini);
list->Load(ini);
}
}

Expand All @@ -340,11 +340,11 @@ void SaveHotkeysToConfig()

void HandleGlobalHotkeys(WChar key, uint16 keycode)
{
for (HotkeyList **list = _hotkey_lists->Begin(); list != _hotkey_lists->End(); ++list) {
if ((*list)->global_hotkey_handler == NULL) continue;
for (auto &list : *_hotkey_lists) {
if (list->global_hotkey_handler == NULL) continue;

int hotkey = (*list)->CheckMatch(keycode, true);
if (hotkey >= 0 && ((*list)->global_hotkey_handler(hotkey) == ES_HANDLED)) return;
int hotkey = list->CheckMatch(keycode, true);
if (hotkey >= 0 && (list->global_hotkey_handler(hotkey) == ES_HANDLED)) return;
}
}

2 changes: 1 addition & 1 deletion src/hotkeys.h
Expand Up @@ -29,7 +29,7 @@ struct Hotkey {

const char *name;
int num;
SmallVector<uint16, 1> keycodes;
std::vector<uint16> keycodes;
};

#define HOTKEY_LIST_END Hotkey((uint16)0, NULL, -1)
Expand Down
4 changes: 2 additions & 2 deletions src/industry_cmd.cpp
Expand Up @@ -2391,7 +2391,7 @@ static int WhoCanServiceIndustry(Industry *ind)
StationList stations;
FindStationsAroundTiles(ind->location, &stations);

if (stations.Length() == 0) return 0; // No stations found at all => nobody services
if (stations.empty()) return 0; // No stations found at all => nobody services

const Vehicle *v;
int result = 0;
Expand Down Expand Up @@ -2427,7 +2427,7 @@ static int WhoCanServiceIndustry(Industry *ind)
/* Same cargo produced by industry is dropped here => not serviced by vehicle v */
if ((o->GetUnloadType() & OUFB_UNLOAD) && !c_accepts) break;

if (stations.Contains(st)) {
if (Contains(stations, st)) {
if (v->owner == _local_company) return 2; // Company services industry
result = 1; // Competitor services industry
}
Expand Down