New implementation of modification_queue...

...that preserves order when priorities are equal.

Fixes bug #20196.
This commit is contained in:
J. Tyne 2012-09-29 02:30:43 +00:00
parent 9c63d717cc
commit 52ae1ea735
3 changed files with 64 additions and 19 deletions

View file

@ -44,6 +44,7 @@ Version 1.11.0+svn:
* Added [terrain_type] max_light= and min_light=.
* Standardize weapon filters, supporting special=, [and], [or], and [not]
wherever weapons can be filtered.
* Image path functions again evaluated left-to-right. Fixes bug #20196.
* Miscellaneous and bug fixes:
* Fix invalid memory access crash resulting from deleting all saved games
in the Load Game dialog

View file

@ -35,6 +35,43 @@ static lg::log_domain log_display("display");
namespace image {
/** Adds @a mod to the queue (unless mod is NULL). */
void modification_queue::push(modification * mod)
{
// Null pointers do not get stored. (Shouldn't happen, but just in case.)
if ( mod != NULL )
priorities_[mod->priority()].push_back(mod);
}
/** Removes the top element from the queue */
void modification_queue::pop()
{
map_type::iterator top_pair = priorities_.begin();
std::vector<modification *> & top_vector = top_pair->second;
// Erase the top element.
top_vector.erase(top_vector.begin());
if ( top_vector.empty() )
// We need to keep the map clean.
priorities_.erase(top_pair);
}
/** Returns the number of elements in the queue. */
size_t modification_queue::size() const
{
size_t count = 0;
BOOST_FOREACH ( const map_type::value_type & pair, priorities_ )
count += pair.second.size();
return count;
}
/** Returns the top element in the queue . */
modification * modification_queue::top() const
{
return priorities_.begin()->second.front();
}
namespace {
/// A function used to parse modification arguments
@ -113,13 +150,6 @@ modification_queue modification::decode(const std::string& encoded_mods)
return mods;
}
/// Compares two modification pointers, providing descending priority order
bool mod_ptr_comparator_::operator()(const modification* a,
const modification* b) const
{
return a->priority() < b->priority();
}
surface rc_modification::operator()(const surface& src) const
{
// unchecked

View file

@ -24,11 +24,32 @@
namespace image {
class modification;
struct mod_ptr_comparator_;
/// A priority queue used to enforce using the rc modifications first
typedef std::priority_queue<modification*,
std::vector<modification*>,
mod_ptr_comparator_> modification_queue;
/// A modified priority queue used to order image modifications.
/// The priorities for this queue are to order modifications by priority(),
/// then by the order they are added to the queue.
class modification_queue {
// Invariant for this class:
// At the beginning and end of each member function call, there
// are no empty vectors in priorities_.
public:
modification_queue() {}
~modification_queue() {}
bool empty() const { return priorities_.empty(); }
void push(modification * mod);
void pop();
size_t size() const;
modification * top() const;
private: // data
/// Map from a mod's priority() to the mods having that priority.
typedef std::map<int, std::vector<modification *>, std::greater<int> > map_type;
/// Map from a mod's priority() to the mods having that priority.
map_type priorities_;
};
/// Base abstract class for an image-path modification
class modification
@ -81,13 +102,6 @@ public:
virtual int priority() const { return 0; }
};
/// A functor for comparing modification pointers
struct mod_ptr_comparator_
{
/// Provides a descending priority ordering
bool operator()(const modification* a, const modification* b) const;
};
/**
* Recolor (RC/TC/PAL) modification.
* It is used not only for color-range-based recoloring ("~RC(magenta>teal)")