|
@@ -41,18 +41,15 @@ class PropertyIdSetIterator;
|
|
|
/*
|
|
/*
|
|
|
PropertyIdSet is a 'set'-like container for PropertyIds.
|
|
PropertyIdSet is a 'set'-like container for PropertyIds.
|
|
|
|
|
|
|
|
- It is quite cheap to construct and use, requiring no dynamic allocation for the library-defined IDs as they are based around a bitset.
|
|
|
|
|
- Custom IDs on the other hand need to use a more trafitional set, and are thus more expensive to insert.
|
|
|
|
|
|
|
+ Implemented as a wrapper around bitset. It is cheap to construct and use, requiring no dynamic allocation.
|
|
|
|
|
|
|
|
Supports union and intersection operations between two sets, as well as iteration through the IDs that are inserted.
|
|
Supports union and intersection operations between two sets, as well as iteration through the IDs that are inserted.
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
-
|
|
|
|
|
class RMLUICORE_API PropertyIdSet {
|
|
class RMLUICORE_API PropertyIdSet {
|
|
|
private:
|
|
private:
|
|
|
- static constexpr size_t N = (size_t)PropertyId::NumDefinedIds;
|
|
|
|
|
|
|
+ static constexpr size_t N = size_t(PropertyId::MaxNumIds);
|
|
|
std::bitset<N> defined_ids;
|
|
std::bitset<N> defined_ids;
|
|
|
- SmallOrderedSet<PropertyId> custom_ids;
|
|
|
|
|
|
|
|
|
|
public:
|
|
public:
|
|
|
PropertyIdSet() {
|
|
PropertyIdSet() {
|
|
@@ -60,92 +57,59 @@ public:
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Insert(PropertyId id) {
|
|
void Insert(PropertyId id) {
|
|
|
- if ((size_t)id < N)
|
|
|
|
|
- defined_ids.set((size_t)id);
|
|
|
|
|
- else
|
|
|
|
|
- custom_ids.insert(id);
|
|
|
|
|
|
|
+ RMLUI_ASSERT(size_t(id) < N);
|
|
|
|
|
+ defined_ids.set((size_t)id);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Clear() {
|
|
void Clear() {
|
|
|
defined_ids.reset();
|
|
defined_ids.reset();
|
|
|
- custom_ids.clear();
|
|
|
|
|
}
|
|
}
|
|
|
void Erase(PropertyId id) {
|
|
void Erase(PropertyId id) {
|
|
|
- if ((size_t)id < N)
|
|
|
|
|
- defined_ids.reset((size_t)id);
|
|
|
|
|
- else
|
|
|
|
|
- custom_ids.erase(id);
|
|
|
|
|
|
|
+ RMLUI_ASSERT(size_t(id) < N);
|
|
|
|
|
+ defined_ids.reset((size_t)id);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool Empty() const {
|
|
bool Empty() const {
|
|
|
- return defined_ids.none() && custom_ids.empty();
|
|
|
|
|
|
|
+ return defined_ids.none();
|
|
|
}
|
|
}
|
|
|
bool Contains(PropertyId id) const {
|
|
bool Contains(PropertyId id) const {
|
|
|
- if ((size_t)id < N)
|
|
|
|
|
- return defined_ids.test((size_t)id);
|
|
|
|
|
- else
|
|
|
|
|
- return custom_ids.count(id) == 1;
|
|
|
|
|
|
|
+ return defined_ids.test((size_t)id);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
size_t Size() const {
|
|
size_t Size() const {
|
|
|
- return defined_ids.count() + custom_ids.size();
|
|
|
|
|
|
|
+ return defined_ids.count();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Union with another set
|
|
// Union with another set
|
|
|
- PropertyIdSet& operator|=(const PropertyIdSet& other)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ PropertyIdSet& operator|=(const PropertyIdSet& other) {
|
|
|
defined_ids |= other.defined_ids;
|
|
defined_ids |= other.defined_ids;
|
|
|
- custom_ids.insert(other.custom_ids.begin(), other.custom_ids.end());
|
|
|
|
|
return *this;
|
|
return *this;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- PropertyIdSet operator|(const PropertyIdSet& other) const
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ PropertyIdSet operator|(const PropertyIdSet& other) const {
|
|
|
PropertyIdSet result = *this;
|
|
PropertyIdSet result = *this;
|
|
|
result |= other;
|
|
result |= other;
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Intersection with another set
|
|
// Intersection with another set
|
|
|
- PropertyIdSet& operator&=(const PropertyIdSet& other)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ PropertyIdSet& operator&=(const PropertyIdSet& other) {
|
|
|
defined_ids &= other.defined_ids;
|
|
defined_ids &= other.defined_ids;
|
|
|
- if (custom_ids.size() > 0 && other.custom_ids.size() > 0)
|
|
|
|
|
- {
|
|
|
|
|
- for (auto it = custom_ids.begin(); it != custom_ids.end();)
|
|
|
|
|
- if (other.custom_ids.count(*it) == 0)
|
|
|
|
|
- it = custom_ids.erase(it);
|
|
|
|
|
- else
|
|
|
|
|
- ++it;
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- custom_ids.clear();
|
|
|
|
|
- }
|
|
|
|
|
return *this;
|
|
return *this;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- PropertyIdSet operator&(const PropertyIdSet& other) const
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ PropertyIdSet operator&(const PropertyIdSet& other) const {
|
|
|
PropertyIdSet result;
|
|
PropertyIdSet result;
|
|
|
result.defined_ids = (defined_ids & other.defined_ids);
|
|
result.defined_ids = (defined_ids & other.defined_ids);
|
|
|
- if (custom_ids.size() > 0 && other.custom_ids.size() > 0)
|
|
|
|
|
- {
|
|
|
|
|
- for (PropertyId id : custom_ids)
|
|
|
|
|
- if (other.custom_ids.count(id) == 1)
|
|
|
|
|
- result.custom_ids.insert(id);
|
|
|
|
|
- }
|
|
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Iterator support. Iterates through all the PropertyIds that are set (contained).
|
|
// Iterator support. Iterates through all the PropertyIds that are set (contained).
|
|
|
- // @note: Modifying the container invalidates the iterators. Only const_iterators are provided.
|
|
|
|
|
|
|
+ // @note: Only const_iterators are provided.
|
|
|
inline PropertyIdSetIterator begin() const;
|
|
inline PropertyIdSetIterator begin() const;
|
|
|
inline PropertyIdSetIterator end() const;
|
|
inline PropertyIdSetIterator end() const;
|
|
|
|
|
|
|
|
- // Erases the property id represented by a valid iterator. Invalidates any previous iterators.
|
|
|
|
|
- // @return A new valid iterator pointing to the next element or end().
|
|
|
|
|
- inline PropertyIdSetIterator Erase(const PropertyIdSetIterator& it);
|
|
|
|
|
|
|
+ // Erases the property id represented by a valid iterator. Iterator must be in the range [begin, end).
|
|
|
|
|
+ // @return A new iterator pointing to the next element or end().
|
|
|
|
|
+ inline PropertyIdSetIterator Erase(PropertyIdSetIterator it);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
@@ -153,79 +117,61 @@ public:
|
|
|
class RMLUICORE_API PropertyIdSetIterator
|
|
class RMLUICORE_API PropertyIdSetIterator
|
|
|
{
|
|
{
|
|
|
public:
|
|
public:
|
|
|
- using CustomIdsIt = SmallOrderedSet<PropertyId>::const_iterator;
|
|
|
|
|
-
|
|
|
|
|
- PropertyIdSetIterator() : container(nullptr), defined_ids_index(0), custom_ids_iterator() {}
|
|
|
|
|
- PropertyIdSetIterator(const PropertyIdSet* container, size_t defined_ids_index, CustomIdsIt custom_ids_iterator)
|
|
|
|
|
- : container(container), defined_ids_index(defined_ids_index), custom_ids_iterator(custom_ids_iterator)
|
|
|
|
|
|
|
+ PropertyIdSetIterator() = default;
|
|
|
|
|
+ PropertyIdSetIterator(const PropertyIdSet* container, size_t id_index) : container(container), id_index(id_index)
|
|
|
{
|
|
{
|
|
|
ProceedToNextValid();
|
|
ProceedToNextValid();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
PropertyIdSetIterator& operator++() {
|
|
PropertyIdSetIterator& operator++() {
|
|
|
- if (defined_ids_index < N)
|
|
|
|
|
- ++defined_ids_index;
|
|
|
|
|
- else
|
|
|
|
|
- ++custom_ids_iterator;
|
|
|
|
|
|
|
+ ++id_index;
|
|
|
ProceedToNextValid();
|
|
ProceedToNextValid();
|
|
|
return *this;
|
|
return *this;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool operator==(const PropertyIdSetIterator& other) const {
|
|
bool operator==(const PropertyIdSetIterator& other) const {
|
|
|
- return container == other.container && defined_ids_index == other.defined_ids_index && custom_ids_iterator == other.custom_ids_iterator;
|
|
|
|
|
|
|
+ return container == other.container && id_index == other.id_index;
|
|
|
}
|
|
}
|
|
|
bool operator!=(const PropertyIdSetIterator& other) const {
|
|
bool operator!=(const PropertyIdSetIterator& other) const {
|
|
|
return !(*this == other);
|
|
return !(*this == other);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
PropertyId operator*() const {
|
|
PropertyId operator*() const {
|
|
|
- if (defined_ids_index < N)
|
|
|
|
|
- return static_cast<PropertyId>(defined_ids_index);
|
|
|
|
|
- else
|
|
|
|
|
- return *custom_ids_iterator;
|
|
|
|
|
|
|
+ return static_cast<PropertyId>(id_index);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
private:
|
|
|
|
|
|
|
|
inline void ProceedToNextValid()
|
|
inline void ProceedToNextValid()
|
|
|
{
|
|
{
|
|
|
- for (; defined_ids_index < N; ++defined_ids_index)
|
|
|
|
|
|
|
+ for (; id_index < size_t(PropertyId::MaxNumIds); ++id_index)
|
|
|
{
|
|
{
|
|
|
- if (container->Contains( static_cast<PropertyId>(defined_ids_index) ))
|
|
|
|
|
|
|
+ if (container->Contains( static_cast<PropertyId>(id_index) ))
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- static constexpr size_t N = (size_t)PropertyId::NumDefinedIds;
|
|
|
|
|
- const PropertyIdSet* container;
|
|
|
|
|
- size_t defined_ids_index;
|
|
|
|
|
- CustomIdsIt custom_ids_iterator;
|
|
|
|
|
|
|
+ const PropertyIdSet* container = nullptr;
|
|
|
|
|
+ size_t id_index = 0;
|
|
|
|
|
|
|
|
- friend PropertyIdSetIterator PropertyIdSet::Erase(const PropertyIdSetIterator&);
|
|
|
|
|
|
|
+ friend PropertyIdSetIterator PropertyIdSet::Erase(PropertyIdSetIterator);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PropertyIdSetIterator PropertyIdSet::begin() const {
|
|
PropertyIdSetIterator PropertyIdSet::begin() const {
|
|
|
- return PropertyIdSetIterator(this, 1, custom_ids.begin());
|
|
|
|
|
|
|
+ if (Empty())
|
|
|
|
|
+ return end();
|
|
|
|
|
+ return PropertyIdSetIterator(this, 1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
PropertyIdSetIterator PropertyIdSet::end() const {
|
|
PropertyIdSetIterator PropertyIdSet::end() const {
|
|
|
- return PropertyIdSetIterator(this, N, custom_ids.end());
|
|
|
|
|
|
|
+ return PropertyIdSetIterator(this, N);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-PropertyIdSetIterator PropertyIdSet::Erase(const PropertyIdSetIterator& it_in) {
|
|
|
|
|
- RMLUI_ASSERT(it_in.container == this);
|
|
|
|
|
- PropertyIdSetIterator it = it_in;
|
|
|
|
|
- if (it.defined_ids_index < N)
|
|
|
|
|
- {
|
|
|
|
|
- defined_ids.reset(it.defined_ids_index);
|
|
|
|
|
- ++it;
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- it.custom_ids_iterator = custom_ids.erase(it.custom_ids_iterator);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+PropertyIdSetIterator PropertyIdSet::Erase(PropertyIdSetIterator it) {
|
|
|
|
|
+ RMLUI_ASSERT(it.container == this && it.id_index < N);
|
|
|
|
|
+ defined_ids.reset(it.id_index);
|
|
|
|
|
+ ++it;
|
|
|
return it;
|
|
return it;
|
|
|
}
|
|
}
|
|
|
|
|
|