Changeset - r21606:c4d9fa63836a
[Not reviewed]
master
0 1 0
rubidium - 10 years ago 2014-08-16 10:20:15
rubidium@openttd.org
(svn r26736) -Fix [Script]: infinite loop (by scripts; always returning the same item) when sorted by item in descending order by oddly constructed FindNext that uses forward iterators. Simply use the same code as the ascending item sort but use the reverse iterator instead of the forward. Also do this same trick for the descending value sort even though I couldn't trigger the problem there
1 file changed with 15 insertions and 21 deletions:
0 comments (0 inline, 0 general)
src/script/api/script_list.cpp
Show inline comments
 
@@ -148,15 +148,15 @@ public:
 

	
 
/**
 
 * Sort by value, descending.
 
 */
 
class ScriptListSorterValueDescending : public ScriptListSorter {
 
private:
 
	ScriptList::ScriptListBucket::iterator bucket_iter;    ///< The iterator over the list to find the buckets.
 
	ScriptList::ScriptItemList *bucket_list;               ///< The current bucket list we're iterator over.
 
	ScriptList::ScriptItemList::iterator bucket_list_iter; ///< The iterator over the bucket list.
 
	ScriptList::ScriptListBucket::reverse_iterator bucket_iter;    ///< The iterator over the list to find the buckets.
 
	ScriptList::ScriptItemList *bucket_list;                       ///< The current bucket list we're iterator over.
 
	ScriptList::ScriptItemList::reverse_iterator bucket_list_iter; ///< The iterator over the bucket list.
 

	
 
public:
 
	/**
 
	 * Create a new sorter.
 
	 * @param list The list to sort.
 
	 */
 
@@ -169,19 +169,17 @@ public:
 
	int32 Begin()
 
	{
 
		if (this->list->buckets.empty()) return 0;
 
		this->has_no_more_items = false;
 

	
 
		/* Go to the end of the bucket-list */
 
		this->bucket_iter = this->list->buckets.begin();
 
		for (size_t i = this->list->buckets.size(); i > 1; i--) this->bucket_iter++;
 
		this->bucket_iter = this->list->buckets.rbegin();
 
		this->bucket_list = &(*this->bucket_iter).second;
 

	
 
		/* Go to the end of the items in the bucket */
 
		this->bucket_list_iter = this->bucket_list->begin();
 
		for (size_t i = this->bucket_list->size(); i > 1; i--) this->bucket_list_iter++;
 
		this->bucket_list_iter = this->bucket_list->rbegin();
 
		this->item_next = *this->bucket_list_iter;
 

	
 
		int32 item_current = this->item_next;
 
		FindNext();
 
		return item_current;
 
	}
 
@@ -200,24 +198,21 @@ public:
 
	{
 
		if (this->bucket_list == NULL) {
 
			this->has_no_more_items = true;
 
			return;
 
		}
 

	
 
		if (this->bucket_list_iter == this->bucket_list->begin()) {
 
			if (this->bucket_iter == this->list->buckets.begin()) {
 
		this->bucket_list_iter++;
 
		if (this->bucket_list_iter == this->bucket_list->rend()) {
 
			this->bucket_iter++;
 
			if (this->bucket_iter == this->list->buckets.rend()) {
 
				this->bucket_list = NULL;
 
				return;
 
			}
 
			this->bucket_iter--;
 
			this->bucket_list = &(*this->bucket_iter).second;
 
			/* Go to the end of the items in the bucket */
 
			this->bucket_list_iter = this->bucket_list->begin();
 
			for (size_t i = this->bucket_list->size(); i > 1; i--) this->bucket_list_iter++;
 
		} else {
 
			this->bucket_list_iter--;
 
			this->bucket_list_iter = this->bucket_list->rbegin();
 
		}
 
		this->item_next = *this->bucket_list_iter;
 
	}
 

	
 
	int32 Next()
 
	{
 
@@ -312,13 +307,13 @@ public:
 

	
 
/**
 
 * Sort by item, descending.
 
 */
 
class ScriptListSorterItemDescending : public ScriptListSorter {
 
private:
 
	ScriptList::ScriptListMap::iterator item_iter; ///< The iterator over the items in the map.
 
	ScriptList::ScriptListMap::reverse_iterator item_iter; ///< The iterator over the items in the map.
 

	
 
public:
 
	/**
 
	 * Create a new sorter.
 
	 * @param list The list to sort.
 
	 */
 
@@ -330,14 +325,13 @@ public:
 

	
 
	int32 Begin()
 
	{
 
		if (this->list->items.empty()) return 0;
 
		this->has_no_more_items = false;
 

	
 
		this->item_iter = this->list->items.begin();
 
		for (size_t i = this->list->items.size(); i > 1; i--) this->item_iter++;
 
		this->item_iter = this->list->items.rbegin();
 
		this->item_next = (*this->item_iter).first;
 

	
 
		int32 item_current = this->item_next;
 
		FindNext();
 
		return item_current;
 
	}
 
@@ -349,18 +343,18 @@ public:
 

	
 
	/**
 
	 * Find the next item, and store that information.
 
	 */
 
	void FindNext()
 
	{
 
		if (this->item_iter == this->list->items.end()) {
 
		if (this->item_iter == this->list->items.rend()) {
 
			this->has_no_more_items = true;
 
			return;
 
		}
 
		this->item_iter--;
 
		if (this->item_iter != this->list->items.end()) item_next = (*this->item_iter).first;
 
		this->item_iter++;
 
		if (this->item_iter != this->list->items.rend()) item_next = (*this->item_iter).first;
 
	}
 

	
 
	int32 Next()
 
	{
 
		if (this->IsEnd()) return 0;
 

	
0 comments (0 inline, 0 general)