mirror of
https://github.com/godotengine/godot.git
synced 2024-11-10 14:12:51 +00:00
Implement Range Iterators
This PR implements range iterators in the base containers (Vector, Map, List, Pair Set). Given several of these data structures will be replaced by more efficient versions, having a common iterator API will make this simpler. Iterating can be done as follows (examples): ```C++ //Vector<String> for(const String& I: vector) { } //List<String> for(const String& I: list) { } //Map<String,int> for(const KeyValue<String,int>&I : map) { print_line("key: "+I.key+" value: "+itos(I.value)); } //if intending to write the elements, reference can be used //Map<String,int> for(KeyValue<String,int>& I: map) { I.value = 25; //this will fail because key is always const //I.key = "hello" } ``` The containers are (for now) not STL compatible, since this would mean changing how they work internally (STL uses a special head/tail allocation for end(), while Godot Map/Set/List do not). The idea is to change the Godot versions to be more compatible with STL, but this will happen after conversion to new iterators have taken place.
This commit is contained in:
parent
5db1f8b1ab
commit
a9c943bef9
@ -135,6 +135,83 @@ public:
|
||||
_FORCE_INLINE_ Element() {}
|
||||
};
|
||||
|
||||
typedef T ValueType;
|
||||
|
||||
struct Iterator {
|
||||
_FORCE_INLINE_ T &operator*() const {
|
||||
return E->get();
|
||||
}
|
||||
_FORCE_INLINE_ T *operator->() const { return &E->get(); }
|
||||
_FORCE_INLINE_ Iterator &operator++() {
|
||||
E = E->next();
|
||||
return *this;
|
||||
}
|
||||
_FORCE_INLINE_ Iterator &operator--() {
|
||||
E = E->prev();
|
||||
return *this;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
|
||||
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
|
||||
|
||||
Iterator(Element *p_E) { E = p_E; }
|
||||
Iterator() {}
|
||||
Iterator(const Iterator &p_it) { E = p_it.E; }
|
||||
|
||||
private:
|
||||
Element *E = nullptr;
|
||||
};
|
||||
|
||||
struct ConstIterator {
|
||||
_FORCE_INLINE_ const T &operator*() const {
|
||||
return E->get();
|
||||
}
|
||||
_FORCE_INLINE_ const T *operator->() const { return &E->get(); }
|
||||
_FORCE_INLINE_ ConstIterator &operator++() {
|
||||
E = E->next();
|
||||
return *this;
|
||||
}
|
||||
_FORCE_INLINE_ ConstIterator &operator--() {
|
||||
E = E->prev();
|
||||
return *this;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
|
||||
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
|
||||
|
||||
_FORCE_INLINE_ ConstIterator(const Element *p_E) { E = p_E; }
|
||||
_FORCE_INLINE_ ConstIterator() {}
|
||||
_FORCE_INLINE_ ConstIterator(const ConstIterator &p_it) { E = p_it.E; }
|
||||
|
||||
private:
|
||||
const Element *E = nullptr;
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ Iterator begin() {
|
||||
return Iterator(front());
|
||||
}
|
||||
_FORCE_INLINE_ Iterator end() {
|
||||
return Iterator(nullptr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
//to use when replacing find()
|
||||
_FORCE_INLINE_ Iterator find(const K &p_key) {
|
||||
return Iterator(find(p_key));
|
||||
}
|
||||
#endif
|
||||
_FORCE_INLINE_ ConstIterator begin() const {
|
||||
return ConstIterator(front());
|
||||
}
|
||||
_FORCE_INLINE_ ConstIterator end() const {
|
||||
return ConstIterator(nullptr);
|
||||
}
|
||||
#if 0
|
||||
//to use when replacing find()
|
||||
_FORCE_INLINE_ ConstIterator find(const K &p_key) const {
|
||||
return ConstIterator(find(p_key));
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
struct _Data {
|
||||
Element *first = nullptr;
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include "core/error/error_macros.h"
|
||||
#include "core/os/memory.h"
|
||||
#include "core/templates/pair.h"
|
||||
|
||||
// based on the very nice implementation of rb-trees by:
|
||||
// https://web.archive.org/web/20120507164830/http://web.mit.edu/~emin/www/source_code/red_black_tree/index.html
|
||||
@ -55,11 +56,12 @@ public:
|
||||
Element *parent = nullptr;
|
||||
Element *_next = nullptr;
|
||||
Element *_prev = nullptr;
|
||||
K _key;
|
||||
V _value;
|
||||
//_Data *data;
|
||||
KeyValue<K, V> _data;
|
||||
|
||||
public:
|
||||
KeyValue<K, V> &key_value() { return _data; }
|
||||
const KeyValue<K, V> &key_value() const { return _data; }
|
||||
|
||||
const Element *next() const {
|
||||
return _next;
|
||||
}
|
||||
@ -73,23 +75,106 @@ public:
|
||||
return _prev;
|
||||
}
|
||||
const K &key() const {
|
||||
return _key;
|
||||
return _data.key;
|
||||
}
|
||||
V &value() {
|
||||
return _value;
|
||||
return _data.value;
|
||||
}
|
||||
const V &value() const {
|
||||
return _value;
|
||||
return _data.value;
|
||||
}
|
||||
V &get() {
|
||||
return _value;
|
||||
return _data.value;
|
||||
}
|
||||
const V &get() const {
|
||||
return _value;
|
||||
return _data.value;
|
||||
}
|
||||
Element() {}
|
||||
Element(const KeyValue<K, V> &p_data) :
|
||||
_data(p_data) {}
|
||||
};
|
||||
|
||||
typedef KeyValue<K, V> ValueType;
|
||||
|
||||
struct Iterator {
|
||||
_FORCE_INLINE_ KeyValue<K, V> &operator*() const {
|
||||
return E->key_value();
|
||||
}
|
||||
_FORCE_INLINE_ KeyValue<K, V> *operator->() const { return &E->key_value(); }
|
||||
_FORCE_INLINE_ Iterator &operator++() {
|
||||
E = E->next();
|
||||
return *this;
|
||||
}
|
||||
_FORCE_INLINE_ Iterator &operator--() {
|
||||
E = E->prev();
|
||||
return *this;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
|
||||
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
|
||||
|
||||
Iterator(Element *p_E) { E = p_E; }
|
||||
Iterator() {}
|
||||
Iterator(const Iterator &p_it) { E = p_it.E; }
|
||||
|
||||
private:
|
||||
Element *E = nullptr;
|
||||
};
|
||||
|
||||
struct ConstIterator {
|
||||
_FORCE_INLINE_ const KeyValue<K, V> &operator*() const {
|
||||
return E->key_value();
|
||||
}
|
||||
_FORCE_INLINE_ const KeyValue<K, V> *operator->() const { return &E->key_value(); }
|
||||
_FORCE_INLINE_ ConstIterator &operator++() {
|
||||
E = E->next();
|
||||
return *this;
|
||||
}
|
||||
_FORCE_INLINE_ ConstIterator &operator--() {
|
||||
E = E->prev();
|
||||
return *this;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return E == b.E; }
|
||||
_FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return E != b.E; }
|
||||
|
||||
ConstIterator(const Element *p_E) { E = p_E; }
|
||||
ConstIterator() {}
|
||||
ConstIterator(const ConstIterator &p_it) { E = p_it.E; }
|
||||
|
||||
private:
|
||||
const Element *E = nullptr;
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ Iterator begin() {
|
||||
return Iterator(front());
|
||||
}
|
||||
_FORCE_INLINE_ Iterator end() {
|
||||
return Iterator(nullptr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
//to use when replacing find()
|
||||
_FORCE_INLINE_ Iterator find(const K &p_key) {
|
||||
return Iterator(find(p_key));
|
||||
}
|
||||
#endif
|
||||
_FORCE_INLINE_ void remove(const Iterator &p_iter) {
|
||||
return erase(p_iter.E);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ ConstIterator begin() const {
|
||||
return ConstIterator(front());
|
||||
}
|
||||
_FORCE_INLINE_ ConstIterator end() const {
|
||||
return ConstIterator(nullptr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
//to use when replacing find()
|
||||
_FORCE_INLINE_ ConstIterator find(const K &p_key) const {
|
||||
return ConstIterator(find(p_key));
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
struct _Data {
|
||||
Element *_root = nullptr;
|
||||
@ -107,7 +192,7 @@ private:
|
||||
}
|
||||
|
||||
void _create_root() {
|
||||
_root = memnew_allocator(Element, A);
|
||||
_root = memnew_allocator(Element(KeyValue<K, V>(K(), V())), A);
|
||||
_root->parent = _root->left = _root->right = _nil;
|
||||
_root->color = BLACK;
|
||||
}
|
||||
@ -216,9 +301,9 @@ private:
|
||||
C less;
|
||||
|
||||
while (node != _data._nil) {
|
||||
if (less(p_key, node->_key)) {
|
||||
if (less(p_key, node->_data.key)) {
|
||||
node = node->left;
|
||||
} else if (less(node->_key, p_key)) {
|
||||
} else if (less(node->_data.key, p_key)) {
|
||||
node = node->right;
|
||||
} else {
|
||||
return node; // found
|
||||
@ -236,9 +321,9 @@ private:
|
||||
while (node != _data._nil) {
|
||||
prev = node;
|
||||
|
||||
if (less(p_key, node->_key)) {
|
||||
if (less(p_key, node->_data.key)) {
|
||||
node = node->left;
|
||||
} else if (less(node->_key, p_key)) {
|
||||
} else if (less(node->_data.key, p_key)) {
|
||||
node = node->right;
|
||||
} else {
|
||||
return node; // found
|
||||
@ -249,7 +334,7 @@ private:
|
||||
return nullptr; // tree empty
|
||||
}
|
||||
|
||||
if (less(p_key, prev->_key)) {
|
||||
if (less(p_key, prev->_data.key)) {
|
||||
prev = prev->_prev;
|
||||
}
|
||||
|
||||
@ -312,25 +397,25 @@ private:
|
||||
while (node != _data._nil) {
|
||||
new_parent = node;
|
||||
|
||||
if (less(p_key, node->_key)) {
|
||||
if (less(p_key, node->_data.key)) {
|
||||
node = node->left;
|
||||
} else if (less(node->_key, p_key)) {
|
||||
} else if (less(node->_data.key, p_key)) {
|
||||
node = node->right;
|
||||
} else {
|
||||
node->_value = p_value;
|
||||
node->_data.value = p_value;
|
||||
return node; // Return existing node with new value
|
||||
}
|
||||
}
|
||||
|
||||
Element *new_node = memnew_allocator(Element, A);
|
||||
typedef KeyValue<K, V> KV;
|
||||
Element *new_node = memnew_allocator(Element(KV(p_key, p_value)), A);
|
||||
new_node->parent = new_parent;
|
||||
new_node->right = _data._nil;
|
||||
new_node->left = _data._nil;
|
||||
new_node->_key = p_key;
|
||||
new_node->_value = p_value;
|
||||
|
||||
//new_node->data=_data;
|
||||
|
||||
if (new_parent == _data._root || less(p_key, new_parent->_key)) {
|
||||
if (new_parent == _data._root || less(p_key, new_parent->_data.key)) {
|
||||
new_parent->left = new_node;
|
||||
} else {
|
||||
new_parent->right = new_node;
|
||||
@ -575,7 +660,7 @@ public:
|
||||
CRASH_COND(!_data._root);
|
||||
const Element *e = find(p_key);
|
||||
CRASH_COND(!e);
|
||||
return e->_value;
|
||||
return e->_data.value;
|
||||
}
|
||||
|
||||
V &operator[](const K &p_key) {
|
||||
@ -588,7 +673,7 @@ public:
|
||||
e = insert(p_key, V());
|
||||
}
|
||||
|
||||
return e->_value;
|
||||
return e->_data.value;
|
||||
}
|
||||
|
||||
Element *front() const {
|
||||
|
@ -31,6 +31,8 @@
|
||||
#ifndef PAIR_H
|
||||
#define PAIR_H
|
||||
|
||||
#include "core/typedefs.h"
|
||||
|
||||
template <class F, class S>
|
||||
struct Pair {
|
||||
F first;
|
||||
@ -64,4 +66,37 @@ struct PairSort {
|
||||
}
|
||||
};
|
||||
|
||||
template <class K, class V>
|
||||
struct KeyValue {
|
||||
const K key;
|
||||
V value;
|
||||
|
||||
void operator=(const KeyValue &p_kv) = delete;
|
||||
_FORCE_INLINE_ KeyValue(const KeyValue &p_kv) :
|
||||
key(p_kv.key),
|
||||
value(p_kv.value) {
|
||||
}
|
||||
_FORCE_INLINE_ KeyValue(const K &p_key, const V &p_value) :
|
||||
key(p_key),
|
||||
value(p_value) {
|
||||
}
|
||||
};
|
||||
|
||||
template <class K, class V>
|
||||
bool operator==(const KeyValue<K, V> &pair, const KeyValue<K, V> &other) {
|
||||
return (pair.key == other.key) && (pair.value == other.value);
|
||||
}
|
||||
|
||||
template <class K, class V>
|
||||
bool operator!=(const KeyValue<K, V> &pair, const KeyValue<K, V> &other) {
|
||||
return (pair.key != other.key) || (pair.value != other.value);
|
||||
}
|
||||
|
||||
template <class K, class V>
|
||||
struct KeyValueSort {
|
||||
bool operator()(const KeyValue<K, V> &A, const KeyValue<K, V> &B) const {
|
||||
return A.key < B.key;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // PAIR_H
|
||||
|
@ -77,6 +77,85 @@ public:
|
||||
Element() {}
|
||||
};
|
||||
|
||||
typedef T ValueType;
|
||||
|
||||
struct Iterator {
|
||||
_FORCE_INLINE_ T &operator*() const {
|
||||
return E->get();
|
||||
}
|
||||
_FORCE_INLINE_ T *operator->() const { return &E->get(); }
|
||||
_FORCE_INLINE_ Iterator &operator++() {
|
||||
E = E->next();
|
||||
return *this;
|
||||
}
|
||||
_FORCE_INLINE_ Iterator &operator--() {
|
||||
E = E->prev();
|
||||
return *this;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
|
||||
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
|
||||
|
||||
Iterator(Element *p_E) { E = p_E; }
|
||||
Iterator() {}
|
||||
Iterator(const Iterator &p_it) { E = p_it.E; }
|
||||
|
||||
private:
|
||||
Element *E = nullptr;
|
||||
};
|
||||
|
||||
struct ConstIterator {
|
||||
_FORCE_INLINE_ const T &operator*() const {
|
||||
return E->get();
|
||||
}
|
||||
_FORCE_INLINE_ const T *operator->() const { return &E->get(); }
|
||||
_FORCE_INLINE_ ConstIterator &operator++() {
|
||||
E = E->next();
|
||||
return *this;
|
||||
}
|
||||
_FORCE_INLINE_ ConstIterator &operator--() {
|
||||
E = E->prev();
|
||||
return *this;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return E == b.E; }
|
||||
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return E != b.E; }
|
||||
|
||||
_FORCE_INLINE_ ConstIterator(const Element *p_E) { E = p_E; }
|
||||
_FORCE_INLINE_ ConstIterator() {}
|
||||
_FORCE_INLINE_ ConstIterator(const ConstIterator &p_it) { E = p_it.E; }
|
||||
|
||||
private:
|
||||
const Element *E = nullptr;
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ Iterator begin() {
|
||||
return Iterator(front());
|
||||
}
|
||||
_FORCE_INLINE_ Iterator end() {
|
||||
return Iterator(nullptr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
//to use when replacing find()
|
||||
_FORCE_INLINE_ Iterator find(const K &p_key) {
|
||||
return Iterator(find(p_key));
|
||||
}
|
||||
#endif
|
||||
|
||||
_FORCE_INLINE_ ConstIterator begin() const {
|
||||
return ConstIterator(front());
|
||||
}
|
||||
_FORCE_INLINE_ ConstIterator end() const {
|
||||
return ConstIterator(nullptr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
//to use when replacing find()
|
||||
_FORCE_INLINE_ ConstIterator find(const K &p_key) const {
|
||||
return ConstIterator(find(p_key));
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
struct _Data {
|
||||
Element *_root = nullptr;
|
||||
|
@ -187,6 +187,70 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
struct Iterator {
|
||||
_FORCE_INLINE_ T &operator*() const {
|
||||
return *elem_ptr;
|
||||
}
|
||||
_FORCE_INLINE_ T *operator->() const { return elem_ptr; }
|
||||
_FORCE_INLINE_ Iterator &operator++() {
|
||||
elem_ptr++;
|
||||
return *this;
|
||||
}
|
||||
_FORCE_INLINE_ Iterator &operator--() {
|
||||
elem_ptr--;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const Iterator &b) const { return elem_ptr == b.elem_ptr; }
|
||||
_FORCE_INLINE_ bool operator!=(const Iterator &b) const { return elem_ptr != b.elem_ptr; }
|
||||
|
||||
Iterator(T *p_ptr) { elem_ptr = p_ptr; }
|
||||
Iterator() {}
|
||||
Iterator(const Iterator &p_it) { elem_ptr = p_it.elem_ptr; }
|
||||
|
||||
private:
|
||||
T *elem_ptr = nullptr;
|
||||
};
|
||||
|
||||
struct ConstIterator {
|
||||
_FORCE_INLINE_ const T &operator*() const {
|
||||
return *elem_ptr;
|
||||
}
|
||||
_FORCE_INLINE_ const T *operator->() const { return elem_ptr; }
|
||||
_FORCE_INLINE_ ConstIterator &operator++() {
|
||||
elem_ptr++;
|
||||
return *this;
|
||||
}
|
||||
_FORCE_INLINE_ ConstIterator &operator--() {
|
||||
elem_ptr--;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool operator==(const ConstIterator &b) const { return elem_ptr == b.elem_ptr; }
|
||||
_FORCE_INLINE_ bool operator!=(const ConstIterator &b) const { return elem_ptr != b.elem_ptr; }
|
||||
|
||||
ConstIterator(T *p_ptr) { elem_ptr = p_ptr; }
|
||||
ConstIterator() {}
|
||||
ConstIterator(const ConstIterator &p_it) { elem_ptr = p_it.elem_ptr; }
|
||||
|
||||
private:
|
||||
const T *elem_ptr = nullptr;
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ Iterator begin() {
|
||||
return Iterator(ptrw());
|
||||
}
|
||||
_FORCE_INLINE_ Iterator end() {
|
||||
return Iterator(ptrw() + size());
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ ConstIterator begin() const {
|
||||
return ConstIterator(ptr());
|
||||
}
|
||||
_FORCE_INLINE_ ConstIterator end() const {
|
||||
return ConstIterator(ptr() + size());
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ Vector() {}
|
||||
_FORCE_INLINE_ Vector(const Vector &p_from) { _cowdata._ref(p_from._cowdata); }
|
||||
|
||||
|
@ -75,6 +75,15 @@ class AudioStreamPreviewGenerator : public Node {
|
||||
thread = p_rhs.thread;
|
||||
return *this;
|
||||
}
|
||||
Preview(const Preview &p_rhs) {
|
||||
preview = p_rhs.preview;
|
||||
base_stream = p_rhs.base_stream;
|
||||
playback = p_rhs.playback;
|
||||
generating.set_to(generating.is_set());
|
||||
id = p_rhs.id;
|
||||
thread = p_rhs.thread;
|
||||
}
|
||||
Preview() {}
|
||||
};
|
||||
|
||||
Map<ObjectID, Preview> previews;
|
||||
|
Loading…
Reference in New Issue
Block a user