+ /// the element's group id
+ size_t group_id;
+private:
+ /// Protect construction
+ UndoElement();
+};
+
+
+class UndoElementStack
+{
+public:
+ /// limit is the maximum size of the stack
+ UndoElementStack(size_t limit = 100) { limit_ = limit; }
+ /// limit is the maximum size of the stack
+ ~UndoElementStack() { clear(); }
+
+ /// Return the top element.
+ UndoElement & top() { return c_.front(); }
+
+ /// Pop and throw away the top element.
+ void pop() { c_.pop_front(); }
+
+ /// Return true if the stack is empty.
+ bool empty() const { return c_.empty(); }
+
+ /// Clear all elements, deleting them.
+ void clear() {
+ for (size_t i = 0; i != c_.size(); ++i) {
+ delete c_[i].array;
+ delete c_[i].pars;
+ }
+ c_.clear();
+ }
+
+ /// Push an item on to the stack, deleting the bottom group on
+ /// overflow.
+ void push(UndoElement const & v) {
+ c_.push_front(v);
+ if (c_.size() > limit_) {
+ // remove a whole group at once.
+ const size_t gid = c_.back().group_id;
+ while (!c_.empty() && c_.back().group_id == gid)
+ c_.pop_back();
+ }
+ }
+
+private:
+ /// Internal contents.
+ std::deque<UndoElement> c_;
+ /// The maximum number elements stored.
+ size_t limit_;