[cpp] Refactored hash map, it's really a linked list for simplicity

This commit is contained in:
badlogic 2018-02-22 13:27:37 +01:00
parent ed7dc4ea93
commit 2d41846b1f
6 changed files with 98 additions and 93 deletions

View File

@ -85,7 +85,7 @@ namespace Spine {
SkeletonData* _skeletonData; SkeletonData* _skeletonData;
float _defaultMix; float _defaultMix;
HashMap<AnimationPair, float, HashAnimationPair> _animationToMixTime; HashMap<AnimationPair, float> _animationToMixTime;
}; };
} }

View File

@ -36,53 +36,57 @@
#include <spine/SpineObject.h> #include <spine/SpineObject.h>
namespace Spine { namespace Spine {
template <typename K, typename V, typename H> template <typename K, typename V>
class HashMap : public SpineObject { class HashMap : public SpineObject {
private: private:
class Entry; class Entry;
public: public:
class Iterator : public SpineObject { class Pair {
public:
explicit Pair(K& k, V& v) : key(k), value(v) {}
K& key;
V& value;
};
class Entries {
public:
friend class HashMap; friend class HashMap;
public: explicit Entries(Entry *entry) : _entry(NULL), _hasChecked(false) {
explicit Iterator(Entry* entry = NULL) : _entry(entry) { _start.next = entry;
_entry = &_start;
} }
Iterator& operator++() { Pair next() {
_entry = _entry->next; assert(_entry);
return *this; assert(_hasChecked);
} _entry = _entry->next;
Pair pair(_entry->_key, _entry->_value);
bool operator==(const Iterator& p) const { _hasChecked = false;
return _entry == p._entry; return pair;
} }
bool operator!=(const Iterator& p) const { bool hasNext() {
return _entry != p._entry; _hasChecked = true;
} return _entry->next;
K& key() {
return _entry->_key;
}
V& value() {
return _entry->_value;
} }
private: private:
bool _hasChecked;
Entry _start;
Entry* _entry; Entry* _entry;
}; };
HashMap() : HashMap() :
_head(NULL), _head(NULL),
_hashFunction(),
_size(0) { _size(0) {
} }
~HashMap() { ~HashMap() {
for (Iterator it = begin(); it != end(); ++it) { for (Entry* entry = _head; entry != NULL; entry = entry->next) {
delete it._entry; delete entry;
} }
} }
@ -90,16 +94,8 @@ namespace Spine {
return _size; return _size;
} }
Iterator begin() { void put(const K& key, const V& value) {
return Iterator(_head); Entry* entry = find(key);
}
Iterator end() {
return Iterator(NULL);
}
void insert(const K& key, const V& value) {
Entry* entry = find(key)._entry;
if (entry) { if (entry) {
entry->_key = key; entry->_key = key;
entry->_value = value; entry->_value = value;
@ -117,19 +113,18 @@ namespace Spine {
} else { } else {
_head = entry; _head = entry;
} }
_size++;
} }
} }
Iterator find(const K& key) { bool containsKey(const K& key) {
for (Iterator it = begin(); it != end(); ++it) { return find(key) != NULL;
if (it._entry && it.key() == key)
return it;
}
return end();
} }
Iterator erase(Iterator pos) { bool remove(const K& key) {
Entry* entry = pos._entry; Entry* entry = find(key);
if (!entry) return false;
Entry* prev = entry->prev; Entry* prev = entry->prev;
Entry* next = entry->next; Entry* next = entry->next;
@ -138,15 +133,30 @@ namespace Spine {
if (next) next->prev = entry->prev; if (next) next->prev = entry->prev;
delete entry; delete entry;
return Iterator(next); _size--;
return true;
} }
V operator[](const K& key) { V operator[](const K& key) {
Iterator iter = find(key); Entry* entry = find(key);
return iter; if (entry) return entry->_value;
else assert(false);
}
Entries getEntries() {
return Entries(_head);
} }
private: private:
Entry* find(const K& key) {
for (Entry* entry = _head; entry != NULL; entry = entry->next) {
if (entry->_key == key)
return entry;
}
return NULL;
}
class Entry : public SpineObject { class Entry : public SpineObject {
public: public:
K _key; K _key;
@ -157,7 +167,6 @@ namespace Spine {
Entry () : next(NULL), prev(NULL) {} Entry () : next(NULL), prev(NULL) {}
}; };
const H _hashFunction;
Entry* _head; Entry* _head;
size_t _size; size_t _size;
}; };

View File

@ -86,11 +86,11 @@ namespace Spine {
void findAttachmentsForSlot(int slotIndex, Vector<Attachment*>& attachments); void findAttachmentsForSlot(int slotIndex, Vector<Attachment*>& attachments);
const String& getName(); const String& getName();
HashMap<AttachmentKey, Attachment*, HashAttachmentKey>& getAttachments(); HashMap<AttachmentKey, Attachment*>& getAttachments();
private: private:
const String _name; const String _name;
HashMap<AttachmentKey, Attachment*, HashAttachmentKey> _attachments; HashMap<AttachmentKey, Attachment*> _attachments;
/// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached. /// Attach all attachments from this skin if the corresponding attachment from the old skin is currently attached.
void attachAll(Skeleton& skeleton, Skin& oldSkin); void attachAll(Skeleton& skeleton, Skin& oldSkin);

View File

@ -49,9 +49,7 @@ namespace Spine {
assert(to != NULL); assert(to != NULL);
AnimationPair key(from, to); AnimationPair key(from, to);
HashMap<AnimationPair, float, HashAnimationPair>::Iterator i = _animationToMixTime.find(key); _animationToMixTime.put(key, duration);
_animationToMixTime.erase(i);
_animationToMixTime.insert(key, duration);
} }
float AnimationStateData::getMix(Animation* from, Animation* to) { float AnimationStateData::getMix(Animation* from, Animation* to) {
@ -60,12 +58,7 @@ namespace Spine {
AnimationPair key(from, to); AnimationPair key(from, to);
HashMap<AnimationPair, float, HashAnimationPair>::Iterator i = _animationToMixTime.find(key); if (_animationToMixTime.containsKey(key)) return _animationToMixTime[key];
if (i != _animationToMixTime.end()) {
return i.value();
}
return _defaultMix; return _defaultMix;
} }

View File

@ -625,12 +625,13 @@ namespace Spine {
} }
void Skeleton::sortPathConstraintAttachment(Skin* skin, int slotIndex, Bone& slotBone) { void Skeleton::sortPathConstraintAttachment(Skin* skin, int slotIndex, Bone& slotBone) {
HashMap<Skin::AttachmentKey, Attachment*, Skin::HashAttachmentKey>& attachments = skin->getAttachments(); HashMap<Skin::AttachmentKey, Attachment*>& attachments = skin->getAttachments();
for (HashMap<Skin::AttachmentKey, Attachment*, Skin::HashAttachmentKey>::Iterator i = attachments.begin(); i != attachments.end(); ++i) { for (HashMap<Skin::AttachmentKey, Attachment*>::Entries entries = attachments.getEntries(); entries.hasNext();) {
Skin::AttachmentKey key = i.key(); HashMap<Skin::AttachmentKey, Attachment*>::Pair pair = entries.next();
Skin::AttachmentKey& key = pair.key;
if (key._slotIndex == slotIndex) { if (key._slotIndex == slotIndex) {
Attachment* value = i.value(); Attachment* value = pair.value;
sortPathConstraintAttachment(value, slotBone); sortPathConstraintAttachment(value, slotBone);
} }
} }

View File

@ -58,42 +58,43 @@ namespace Spine {
} }
Skin::~Skin() { Skin::~Skin() {
HashMap<AttachmentKey, Attachment*, HashAttachmentKey>::Iterator i = _attachments.begin(); HashMap<AttachmentKey, Attachment*>::Entries entries = _attachments.getEntries();
for (; i != _attachments.end(); ++i) { while(entries.hasNext()) {
delete i.value(); HashMap<AttachmentKey, Attachment*>::Pair pair = entries.next();
delete pair.value;
} }
} }
void Skin::addAttachment(int slotIndex, const String& name, Attachment* attachment) { void Skin::addAttachment(int slotIndex, const String& name, Attachment* attachment) {
assert(attachment); assert(attachment);
_attachments.put(AttachmentKey(slotIndex, name), attachment);
_attachments.insert(AttachmentKey(slotIndex, name), attachment);
} }
Attachment* Skin::getAttachment(int slotIndex, const String& name) { Attachment* Skin::getAttachment(int slotIndex, const String& name) {
HashMap<AttachmentKey, Attachment*, HashAttachmentKey>::Iterator i = _attachments.find(AttachmentKey(slotIndex, name)); AttachmentKey key(slotIndex, name);
if (_attachments.containsKey(key)) {
Attachment* ret = NULL; return _attachments[key];
} else {
if (i != _attachments.end()) { return NULL;
ret = i.value();
} }
return ret;
} }
void Skin::findNamesForSlot(int slotIndex, Vector<String>& names) { void Skin::findNamesForSlot(int slotIndex, Vector<String>& names) {
for (HashMap<AttachmentKey, Attachment*, HashAttachmentKey>::Iterator i = _attachments.begin(); i != _attachments.end(); ++i) { HashMap<AttachmentKey, Attachment*>::Entries entries = _attachments.getEntries();
if (i.key()._slotIndex == slotIndex) { while(entries.hasNext()) {
names.add(i.key()._name); HashMap<AttachmentKey, Attachment*>::Pair pair = entries.next();
if (pair.key._slotIndex == slotIndex) {
names.add(pair.key._name);
} }
} }
} }
void Skin::findAttachmentsForSlot(int slotIndex, Vector<Attachment*>& attachments) { void Skin::findAttachmentsForSlot(int slotIndex, Vector<Attachment*>& attachments) {
for (HashMap<AttachmentKey, Attachment*, HashAttachmentKey>::Iterator i = _attachments.begin(); i != _attachments.end(); ++i) { HashMap<AttachmentKey, Attachment*>::Entries entries = _attachments.getEntries();
if (i.key()._slotIndex == slotIndex) { while(entries.hasNext()) {
attachments.add(i.value()); HashMap<AttachmentKey, Attachment*>::Pair pair = entries.next();
if (pair.key._slotIndex == slotIndex) {
attachments.add(pair.value);
} }
} }
} }
@ -102,20 +103,21 @@ namespace Spine {
return _name; return _name;
} }
HashMap<Skin::AttachmentKey, Attachment*, Skin::HashAttachmentKey>& Skin::getAttachments() { HashMap<Skin::AttachmentKey, Attachment*>& Skin::getAttachments() {
return _attachments; return _attachments;
} }
void Skin::attachAll(Skeleton& skeleton, Skin& oldSkin) { void Skin::attachAll(Skeleton& skeleton, Skin& oldSkin) {
Vector<Slot*>& slots = skeleton.getSlots(); Vector<Slot*>& slots = skeleton.getSlots();
HashMap<AttachmentKey, Attachment*>::Entries entries = oldSkin.getAttachments().getEntries();
for (HashMap<AttachmentKey, Attachment*, HashAttachmentKey>::Iterator i = oldSkin.getAttachments().begin(); i != oldSkin.getAttachments().end(); ++i) { while(entries.hasNext()) {
int slotIndex = i.key()._slotIndex; HashMap<AttachmentKey, Attachment*>::Pair pair = entries.next();
int slotIndex = pair.key._slotIndex;
Slot* slot = slots[slotIndex]; Slot* slot = slots[slotIndex];
if (slot->getAttachment() == i.value()) { if (slot->getAttachment() == pair.value) {
Attachment* attachment = NULL; Attachment* attachment = NULL;
if ((attachment = getAttachment(slotIndex, i.key()._name))) { if ((attachment = getAttachment(slotIndex, pair.key._name))) {
slot->setAttachment(attachment); slot->setAttachment(attachment);
} }
} }