[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;
float _defaultMix;
HashMap<AnimationPair, float, HashAnimationPair> _animationToMixTime;
HashMap<AnimationPair, float> _animationToMixTime;
};
}

View File

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

View File

@ -86,11 +86,11 @@ namespace Spine {
void findAttachmentsForSlot(int slotIndex, Vector<Attachment*>& attachments);
const String& getName();
HashMap<AttachmentKey, Attachment*, HashAttachmentKey>& getAttachments();
HashMap<AttachmentKey, Attachment*>& getAttachments();
private:
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.
void attachAll(Skeleton& skeleton, Skin& oldSkin);

View File

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

View File

@ -625,12 +625,13 @@ namespace Spine {
}
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) {
Skin::AttachmentKey key = i.key();
for (HashMap<Skin::AttachmentKey, Attachment*>::Entries entries = attachments.getEntries(); entries.hasNext();) {
HashMap<Skin::AttachmentKey, Attachment*>::Pair pair = entries.next();
Skin::AttachmentKey& key = pair.key;
if (key._slotIndex == slotIndex) {
Attachment* value = i.value();
Attachment* value = pair.value;
sortPathConstraintAttachment(value, slotBone);
}
}

View File

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