[Scummvm-git-logs] scummvm master -> f6a0dad8df46ade5e32be890bed77a6ea618db5a

grisenti noreply at scummvm.org
Thu Mar 2 10:31:46 UTC 2023


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
f6a0dad8df HPL1: implement set and multiset with Std::Tree


Commit: f6a0dad8df46ade5e32be890bed77a6ea618db5a
    https://github.com/scummvm/scummvm/commit/f6a0dad8df46ade5e32be890bed77a6ea618db5a
Author: grisenti (emanuele at grisenti.net)
Date: 2023-03-02T11:31:16+01:00

Commit Message:
HPL1: implement set and multiset with Std::Tree

this fixes current issues with multiple inserts in set and possible future issues of iterator invalidation.

Changed paths:
    engines/hpl1/std/multiset.h
    engines/hpl1/std/set.h


diff --git a/engines/hpl1/std/multiset.h b/engines/hpl1/std/multiset.h
index c414f6f1c9f..2a9addb2854 100644
--- a/engines/hpl1/std/multiset.h
+++ b/engines/hpl1/std/multiset.h
@@ -22,13 +22,94 @@
 #ifndef HPL1_STD_MULTISET_H
 #define HPL1_STD_MULTISET_H
 
-#include "hpl1/std/set.h"
+#include "hpl1/std/tree.h"
 
 namespace Hpl1 {
 namespace Std {
 
-template<typename T, typename Comp>
-using multiset = set<T, Comp>;
+template<class T, class CompFn = Common::Less<T>>
+class multiset {
+	using TreeT = Tree<T, T, Identity<T>, CompFn>;
+public:
+	using iterator = typename TreeT::BasicIterator;
+	using const_iterator = typename TreeT::ConstIterator;
+
+	iterator begin() {
+		return _items.begin();
+	}
+
+	iterator end() {
+		return _items.end();
+	}
+
+	const_iterator begin() const {
+		return _items.begin();
+	}
+
+	const_iterator end() const {
+		return _items.end();
+	}
+
+	void clear() {
+		_items.clear();
+	}
+
+	bool empty() {
+		return _items.size() == 0;
+	}
+
+	size_t size() {
+		return _items.size();
+	}
+
+	/**
+	 * Locate an item in the set
+	 */
+	iterator find(const T &item) {
+		const auto it = _items.lowerBound(item);
+		if (it != _items.end() && CompareEq(*it, item)) {
+			return it;
+		}
+		return _items.end();
+	}
+
+	iterator insert(const T &item) {
+		return _items.insert(item);
+	}
+
+	void erase(iterator item) {
+		_items.erase(item);
+	}
+
+	void erase(iterator first, iterator last) {
+		_items.erase(first, last);
+	}
+
+	size_t erase(const T &item) {
+		size_t total = 0;
+		for (auto it = _items.lowerBound(item); it != end() && CompareEq(*it, item);) {
+			_items.erase(it++);
+			++total;
+		}
+		return total;
+	}
+
+	/**
+	 * Returns the number of keys that match the specified key
+	 */
+	size_t count(const T &item) const {
+		size_t total = 0;
+		for (auto it = _items.lowerBound(item); it != end() && CompareEq(*it, item); ++it)
+			++total;
+		return total;
+	}
+private:
+	static bool CompareEq(const T &a, const T &b) {
+		return !CompFn()(a, b) && !CompFn()(b, a);
+	}
+
+	TreeT _items;
+};
 
 }
 
diff --git a/engines/hpl1/std/set.h b/engines/hpl1/std/set.h
index 5a02cd9a3cf..f1a3fae1ab5 100644
--- a/engines/hpl1/std/set.h
+++ b/engines/hpl1/std/set.h
@@ -22,102 +22,101 @@
 #ifndef HPL1_STD_SET_H
 #define HPL1_STD_SET_H
 
-#include "common/array.h"
+#include "tree.h"
 
 namespace Hpl1 {
 namespace Std {
 
-/**
- * Derives the ScummVM SortedArray to match the Std::set class
- */
-template<class T, class Comparitor = Common::Less<T> >
-class set : public Common::SortedArray<T, const T &> {
-private:
-	static int ComparatorFn(const T &a, const T &b) {
-		return Comparitor().operator()(a, b) ? -1 : 0;
+template<class T, class CompFn = Common::Less<T>>
+class set {
+	using TreeT = Tree<T, T, Identity<T>, CompFn>;
+public:
+	using iterator = typename TreeT::BasicIterator;
+	using const_iterator = typename TreeT::ConstIterator;
+
+	iterator begin() {
+		return _items.begin();
 	}
 
-	static bool CompareEq(const T &a, const T &b) {
-		return !ComparatorFn(a, b) && !ComparatorFn(b, a);
+	iterator end() {
+		return _items.end();
 	}
 
-public:
-	struct Entry {
-		const T &_value;
-		Entry(const T &item) : _value(item) {
-		}
-	};
-public:
-	using iterator = typename Common::SortedArray<T, const T &>::iterator;
-	using const_iterator = typename Common::SortedArray<T, const T &>::const_iterator;
+	const_iterator begin() const {
+		return _items.begin();
+	}
 
-	/**
-	 * Constructor
-	 */
-	set() : Common::SortedArray<T, const T & >(ComparatorFn) {}
+	const_iterator end() const {
+		return _items.end();
+	}
+
+	void clear() {
+		_items.clear();
+	}
+
+	bool empty() {
+		return _items.size() == 0;
+	}
+
+	size_t size() {
+		return _items.size();
+	}
 
 	/**
 	 * Locate an item in the set
 	 */
 	iterator find(const T &item) {
-		iterator begin = this->begin();
-		iterator end = this->end();
-		while (begin < end) {
-			iterator mid = begin + (Common::distance(begin, end) / 2);
-			if (ComparatorFn(item, *mid))
-				end = mid;
-			else if (ComparatorFn(*mid, item))
-			 	begin = mid + 1;
-			else
-				return mid;
+		const auto it = _items.lowerBound(item);
+		if (it != _items.end() && CompareEq(*it, item)) {
+			return it;
 		}
-		return this->end();
+		return _items.end();
 	}
 
 	/**
 	 * Insert an element at the sorted position.
 	 */
-	Entry insert(const T &item) {
-		Common::SortedArray<T, const T &>::insert(item);
-		return Entry(item);
+	pair<iterator, bool> insert(const T &item) {
+		const auto it = _items.lowerBound(item);
+		if (it == _items.end() || !CompareEq(*it, item)) {
+			const auto position = _items.insert(it, item);
+			return {position, true};
+		}
+		return {it, false};
 	}
 
 	void erase(iterator item) {
-		Common::SortedArray<T, const T &>::erase(item);
+		_items.erase(item);
 	}
 
 	void erase(iterator first, iterator last) {
-		Common::SortedArray<T, const T &>::erase(first, last);
+		_items.erase(first, last);
 	}
 
 	size_t erase(const T &item) {
-		iterator first = find(item);
-		if (first == this->end())
-			return 0;
-		iterator end = first + 1;
-		while (end != this->end() && CompareEq(*first, *end)) {
-			++end;
+		iterator it = find(item);
+		if (it != end()) {
+			_items.erase(it);
+			return 1;
 		}
-		size_t erased = Common::distance(first, end);
-		this->erase(first, end);
-		return erased;
+		return 0;
 	}
 
 	/**
 	 * Returns the number of keys that match the specified key
 	 */
-	size_t count(const T item) const {
+	size_t count(const T &item) const {
 		size_t total = 0;
-		for (const_iterator it = this->begin(); it != this->end(); ++it) {
-			if (CompareEq(*it, item))
-				++total;
-			else if (!ComparatorFn(item, *it))
-				// Passed beyond possibility of matches
-				break;
-		}
-
+		for (auto it = _items.lowerBound(item); it != end() && CompareEq(*it, item); ++it)
+			++total;
 		return total;
 	}
+private:
+	static bool CompareEq(const T &a, const T &b) {
+		return !CompFn()(a, b) && !CompFn()(b, a);
+	}
+
+	TreeT _items;
 };
 
 } // namespace Std




More information about the Scummvm-git-logs mailing list