[cpp] Fixed up memory issues & crashes. HashMap is a linked list atm, need a better replacement.

This commit is contained in:
badlogic 2018-02-15 18:45:24 +01:00
parent e7e240d109
commit 11d0a47360
49 changed files with 181 additions and 258 deletions

View File

@ -2,7 +2,7 @@ include_directories(include)
file(GLOB INCLUDES "spine-cpp/include/**/*.h") file(GLOB INCLUDES "spine-cpp/include/**/*.h")
file(GLOB SOURCES "spine-cpp/src/**/*.cpp") file(GLOB SOURCES "spine-cpp/src/**/*.cpp")
set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -Wall -std=c++03 -pedantic -fno-exceptions -fno-rtti") set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -Wall -Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic -std=c++03 -fno-exceptions -fno-rtti")
add_library(spine-cpp STATIC ${SOURCES} ${INCLUDES}) add_library(spine-cpp STATIC ${SOURCES} ${INCLUDES})
target_include_directories(spine-cpp PUBLIC spine-cpp/include) target_include_directories(spine-cpp PUBLIC spine-cpp/include)
install(TARGETS spine-cpp DESTINATION dist/lib) install(TARGETS spine-cpp DESTINATION dist/lib)

View File

@ -3,7 +3,8 @@ project(spine_cpp_unit_test)
set(CMAKE_INSTALL_PREFIX "./") set(CMAKE_INSTALL_PREFIX "./")
set(CMAKE_VERBOSE_MAKEFILE ON) set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ ") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic -std=c++03 -fno-exceptions -fno-rtti")
set(CMAKE_CPP_FLAGS "${CMAKE_CPP_FLAGS} -Wall -Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic -std=c++03 -fno-exceptions -fno-rtti")
include_directories(../spine-cpp/include teamcity minicppunit tests memory) include_directories(../spine-cpp/include teamcity minicppunit tests memory)

View File

@ -71,12 +71,14 @@ void Spine::TestSpineExtension::_free(void *mem, const char *file, int line) {
} }
printf("%s:%i (address %p): Double free or not allocated through SpineExtension\n", file, line, mem); printf("%s:%i (address %p): Double free or not allocated through SpineExtension\n", file, line, mem);
DefaultSpineExtension::_free(mem, file, line);
} }
void Spine::TestSpineExtension::reportLeaks() { void Spine::TestSpineExtension::reportLeaks() {
for (std::vector<Allocation>::iterator it = allocated.begin(); it != allocated.end(); it++) { for (std::vector<Allocation>::iterator it = allocated.begin(); it != allocated.end(); it++) {
printf("\"%s:%i (%zu bytes at %p)\n", it->fileName, it->line, it->size, it->address); printf("\"%s:%i (%zu bytes at %p)\n", it->fileName, it->line, it->size, it->address);
} }
if (allocated.size() == 0) printf("No leaks detected");
} }
void Spine::TestSpineExtension::clearAllocations() { void Spine::TestSpineExtension::clearAllocations() {

View File

@ -42,7 +42,7 @@ namespace Spine {
const char* fileName; const char* fileName;
int line; int line;
Allocation() : Allocation (0, 0, 0, 0) { Allocation() : address(0), size(0), fileName(0), line(0) {
} }
Allocation(void* a, size_t s, const char* f, int l) : address(a), size(s), fileName(f), line(l) { Allocation(void* a, size_t s, const char* f, int l) : address(a), size(s), fileName(f), line(l) {

View File

@ -79,7 +79,7 @@ int main (int argc, char** argv) {
TestSpineExtension* ext = new TestSpineExtension(); TestSpineExtension* ext = new TestSpineExtension();
SpineExtension::setInstance(ext); SpineExtension::setInstance(ext);
reproduceIssue_776(); reproduceIssue_776();
ext->reportLeaks(); ext->reportLeaks();
} }

View File

@ -44,7 +44,7 @@ namespace Spine {
/// See http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data about Loading Skeleton Data in the Spine Runtimes Guide. /// See http://esotericsoftware.com/spine-loading-skeleton-data#JSON-and-binary-data about Loading Skeleton Data in the Spine Runtimes Guide.
/// ///
class AtlasAttachmentLoader : public AttachmentLoader { class AtlasAttachmentLoader : public AttachmentLoader {
RTTI_DECL; RTTI_DECL
public: public:
AtlasAttachmentLoader(Atlas* atlas); AtlasAttachmentLoader(Atlas* atlas);

View File

@ -37,7 +37,7 @@
namespace Spine { namespace Spine {
class Attachment : public SpineObject { class Attachment : public SpineObject {
RTTI_DECL; RTTI_DECL
public: public:
Attachment(std::string name); Attachment(std::string name);

View File

@ -45,7 +45,7 @@ namespace Spine {
class ClippingAttachment; class ClippingAttachment;
class AttachmentLoader : public SpineObject { class AttachmentLoader : public SpineObject {
RTTI_DECL; RTTI_DECL
AttachmentLoader(); AttachmentLoader();

View File

@ -47,7 +47,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
AttachmentTimeline(int frameCount); AttachmentTimeline(int frameCount);

View File

@ -59,7 +59,7 @@ namespace Spine {
friend class ShearTimeline; friend class ShearTimeline;
friend class TranslateTimeline; friend class TranslateTimeline;
RTTI_DECL; RTTI_DECL
public: public:
static void setYDown(bool inValue); static void setYDown(bool inValue);

View File

@ -52,7 +52,7 @@ namespace Spine {
/// The index of the bone in Skeleton.Bones /// The index of the bone in Skeleton.Bones
const int getIndex(); const int getIndex();
/// The name of the bone, which is unique within the skeleton. /// The name of the bone, which is unique within the skeleton.
const std::string& getName(); const std::string& getName();

View File

@ -37,7 +37,7 @@
namespace Spine { namespace Spine {
/// Attachment that has a polygon for bounds checking. /// Attachment that has a polygon for bounds checking.
class BoundingBoxAttachment : public VertexAttachment { class BoundingBoxAttachment : public VertexAttachment {
RTTI_DECL; RTTI_DECL
BoundingBoxAttachment(std::string name); BoundingBoxAttachment(std::string name);
}; };

View File

@ -42,7 +42,7 @@ namespace Spine {
friend class SkeletonClipping; friend class SkeletonClipping;
RTTI_DECL; RTTI_DECL
public: public:
ClippingAttachment(std::string name); ClippingAttachment(std::string name);

View File

@ -38,7 +38,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
static const int ENTRIES; static const int ENTRIES;

View File

@ -36,7 +36,7 @@
namespace Spine { namespace Spine {
/// The interface for all constraints. /// The interface for all constraints.
class Constraint : public Updatable { class Constraint : public Updatable {
RTTI_DECL; RTTI_DECL
public: public:
Constraint(); Constraint();

View File

@ -39,7 +39,7 @@
namespace Spine { namespace Spine {
/// Base class for frames that use an interpolation bezier curve. /// Base class for frames that use an interpolation bezier curve.
class CurveTimeline : public Timeline { class CurveTimeline : public Timeline {
RTTI_DECL; RTTI_DECL
public: public:
CurveTimeline(int frameCount); CurveTimeline(int frameCount);

View File

@ -40,7 +40,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
DeformTimeline(int frameCount); DeformTimeline(int frameCount);

View File

@ -38,7 +38,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
DrawOrderTimeline(int frameCount); DrawOrderTimeline(int frameCount);

View File

@ -38,7 +38,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
EventTimeline(int frameCount); EventTimeline(int frameCount);

View File

@ -75,194 +75,77 @@ namespace Spine {
Entry* _entry; Entry* _entry;
}; };
HashMap(size_t capacity = 65535) : HashMap() :
_head(NULL),
_hashFunction(), _hashFunction(),
_capacity(capacity), _size(0) {
_header(),
_trailer(),
_hashSize(0) {
_hashTable.reserve(capacity);
for (int i = 0; i < _capacity; ++i) {
_hashTable.push_back(Entry());
}
_header.prev = &_header;
_header.next = &_trailer;
_trailer.prev = &_header;
_trailer.next = &_trailer;
} }
~HashMap() { ~HashMap() {
for (Iterator it = begin(); it != end(); ++it) { for (Iterator it = begin(); it != end(); ++it) {
delete it._entry; delete it._entry;
} }
_hashSize = 0;
} }
size_t size() { size_t size() {
return _hashSize; return _size;
} }
Iterator begin() { Iterator begin() {
return Iterator(_header.next); return Iterator(_head);
} }
Iterator end() { Iterator end() {
return Iterator(&_trailer); return Iterator(NULL);
} }
std::pair<Iterator, bool> insert(const K& key, const V& value) { void insert(const K& key, const V& value) {
Iterator iter = find(key); Entry* entry = find(key)._entry;
if (entry) {
if (iter._entry != &_trailer) { entry->_key = key;
return std::make_pair(iter, false); entry->_value = value;
} } else {
entry = new (__FILE__, __LINE__) Entry();
size_t index = hash(key); entry->_key = key;
entry->_value = value;
Entry* entry = new (__FILE__, __LINE__) Entry();
entry->_key = key; Entry* oldHead = _head;
entry->_value = value;
if (oldHead) {
_hashSize++; _head = entry;
oldHead->prev = entry;
if (_header.next == (&_trailer)) { entry->next = oldHead;
_hashTable[index].next = entry; } else {
_hashTable[index].prev = entry; _head = entry;
_header.next = entry;
entry->prev = &_header;
entry->next = &_trailer;
_trailer.prev = entry;
return std::make_pair(Iterator(entry), true);
}
if (_hashTable[index].next == NULL) {
_hashTable[index].next = entry;
_hashTable[index].prev = entry;
if (index < hash(_header.next->_key)) {
entry->next = _header.next;
entry->prev = &_header;
_header.next->prev = entry;
_header.next = entry;
} }
else {
entry->next = &_trailer;
entry->prev = _trailer.prev;
_trailer.prev = entry;
entry->prev->next = entry;
}
return std::make_pair(Iterator(entry), true);
} }
if (index == hash(_header.next->_key)) {
_header.next = entry;
entry->next = _hashTable[index].next;
entry->prev = &_header;
_hashTable[index].next->prev = entry;
_hashTable[index].next = entry;
}
else {
entry->next = _hashTable[index].next;
entry->prev = _hashTable[index].next->prev;
entry->next->prev = entry;
entry->prev->next = entry;
_hashTable[index].next = entry;
}
return std::make_pair(Iterator(entry), true);
} }
Iterator find(const K& key) { Iterator find(const K& key) {
const size_t index = hash(key); for (Iterator it = begin(); it != end(); ++it) {
Iterator iter(_hashTable[index].next); if (it._entry && it.key() == key)
return it;
if (iter._entry != NULL) {
for ( ; hash(iter._entry->_key) == index ; ++iter) {
if (iter._entry->_key == key) {
return iter;
}
}
} }
return end();
return Iterator(&_trailer);
} }
Iterator erase(Iterator pos) { Iterator erase(Iterator pos) {
if (pos._entry != &_header && pos._entry != &_trailer) { Entry* entry = pos._entry;
Entry* next = pos._entry->next; Entry* prev = entry->prev;
Entry* next = entry->next;
size_t index = hash(pos._entry->_key);
if (prev) prev->next = next;
if (_hashTable[index].next == pos._entry && _hashTable[index].prev == pos._entry) { else _head = next;
_hashTable[index].next = NULL; if (next) next->prev = entry->prev;
_hashTable[index].prev = NULL;
delete entry;
if (_header.next == pos._entry) { return Iterator(next);
_header.next = pos._entry->next;
pos._entry->next->prev = &_header;
}
else if (_trailer.prev == pos._entry) {
_trailer.prev = pos._entry->prev;
pos._entry->prev->next = &_trailer;
}
else {
pos._entry->prev->next = pos._entry->next;
pos._entry->next->prev = pos._entry->prev;
}
delete pos._entry;
}
else if (_hashTable[index].next == pos._entry) {
_hashTable[index].next = pos._entry->next;
if (_header.next == pos._entry) {
_header.next = pos._entry->next;
pos._entry->next->prev = &_header;
}
else {
pos._entry->prev->next = pos._entry->next;
pos._entry->next->prev = pos._entry->prev;
}
delete pos._entry;
}
else if (_hashTable[index].prev == pos._entry) {
_hashTable[index].prev = pos._entry->prev;
if (_trailer.prev == pos._entry) {
_trailer.prev = pos._entry->prev;
pos._entry->prev->next = &_trailer;
}
else {
pos._entry->prev->next = pos._entry->next;
pos._entry->next->prev = pos._entry->prev;
}
delete pos._entry;
}
else {
pos._entry->prev->next = pos._entry->next;
pos._entry->next->prev = pos._entry->prev;
delete pos._entry;
}
_hashSize--;
return Iterator(next);
}
return Iterator(&_trailer);
} }
V operator[](const K& key) { V operator[](const K& key) {
Iterator iter = find(key); Iterator iter = find(key);
return iter;
if (iter._entry != _trailer) {
return iter._entry->_value;
}
return V();
} }
private: private:
@ -272,18 +155,13 @@ namespace Spine {
V _value; V _value;
Entry* next; Entry* next;
Entry* prev; Entry* prev;
Entry () : next(NULL), prev(NULL) {}
}; };
const H _hashFunction; const H _hashFunction;
const size_t _capacity; Entry* _head;
Vector<Entry> _hashTable; size_t _size;
Entry _header;
Entry _trailer;
size_t _hashSize;
size_t hash(const K& key) {
return _hashFunction(key) % _capacity;
}
}; };
} }

View File

@ -44,7 +44,7 @@ namespace Spine {
friend class Skeleton; friend class Skeleton;
friend class IkConstraintTimeline; friend class IkConstraintTimeline;
RTTI_DECL; RTTI_DECL
public: public:
/// Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified /// Adjusts the bone rotation so the tip is as close to the target position as possible. The target is specified

View File

@ -38,7 +38,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
static const int ENTRIES; static const int ENTRIES;

View File

@ -44,7 +44,7 @@ namespace Spine {
friend class SkeletonJson; friend class SkeletonJson;
friend class AtlasAttachmentLoader; friend class AtlasAttachmentLoader;
RTTI_DECL; RTTI_DECL
public: public:
MeshAttachment(std::string name); MeshAttachment(std::string name);

View File

@ -38,7 +38,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
PathAttachment(std::string name); PathAttachment(std::string name);

View File

@ -48,7 +48,7 @@ namespace Spine {
friend class PathConstraintPositionTimeline; friend class PathConstraintPositionTimeline;
friend class PathConstraintSpacingTimeline; friend class PathConstraintSpacingTimeline;
RTTI_DECL; RTTI_DECL
public: public:
PathConstraint(PathConstraintData& data, Skeleton& skeleton); PathConstraint(PathConstraintData& data, Skeleton& skeleton);

View File

@ -38,7 +38,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
static const int ENTRIES; static const int ENTRIES;

View File

@ -38,7 +38,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
static const int ENTRIES; static const int ENTRIES;

View File

@ -38,7 +38,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
PathConstraintSpacingTimeline(int frameCount); PathConstraintSpacingTimeline(int frameCount);

View File

@ -47,7 +47,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
PointAttachment(std::string name); PointAttachment(std::string name);

View File

@ -48,7 +48,7 @@ namespace Spine {
friend class SkeletonJson; friend class SkeletonJson;
friend class AtlasAttachmentLoader; friend class AtlasAttachmentLoader;
RTTI_DECL; RTTI_DECL
public: public:
RegionAttachment(std::string name); RegionAttachment(std::string name);

View File

@ -39,7 +39,7 @@ namespace Spine {
friend class SkeletonJson; friend class SkeletonJson;
friend class AnimationState; friend class AnimationState;
RTTI_DECL; RTTI_DECL
public: public:
static const int ENTRIES = 2; static const int ENTRIES = 2;

View File

@ -38,7 +38,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
ScaleTimeline(int frameCount); ScaleTimeline(int frameCount);

View File

@ -38,7 +38,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
ShearTimeline(int frameCount); ShearTimeline(int frameCount);

View File

@ -46,12 +46,17 @@ namespace Spine {
friend class Skeleton; friend class Skeleton;
public: public:
class AttachmentKey : public SpineObject { class AttachmentKey {
public: public:
int _slotIndex; int _slotIndex;
std::string _name; std::string _name;
AttachmentKey(int slotIndex = 0, std::string name = ""); AttachmentKey(int slotIndex = 0, std::string name = "");
AttachmentKey(const AttachmentKey &other) {
this->_slotIndex = other._slotIndex;
this->_name = other._name;
}
bool operator==(const AttachmentKey &other) const; bool operator==(const AttachmentKey &other) const;
}; };

View File

@ -37,9 +37,10 @@ namespace Spine {
class SpineObject { class SpineObject {
public: public:
void* operator new(size_t sz, const char* file, int line); void* operator new(size_t sz, const char* file, int line);
void* operator new(size_t sz, void* ptr);
void operator delete(void* p); void operator delete(void* p);
virtual ~SpineObject(); virtual ~SpineObject();
}; };
} }
#endif #endif

View File

@ -42,7 +42,7 @@ namespace Spine {
class Event; class Event;
class Timeline : public SpineObject { class Timeline : public SpineObject {
RTTI_DECL; RTTI_DECL
public: public:
Timeline(); Timeline();

View File

@ -44,7 +44,7 @@ namespace Spine {
friend class Skeleton; friend class Skeleton;
friend class TransformConstraintTimeline; friend class TransformConstraintTimeline;
RTTI_DECL; RTTI_DECL
public: public:
TransformConstraint(TransformConstraintData& data, Skeleton& skeleton); TransformConstraint(TransformConstraintData& data, Skeleton& skeleton);

View File

@ -38,7 +38,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
static const int ENTRIES; static const int ENTRIES;

View File

@ -38,7 +38,7 @@ namespace Spine {
TransformMode_OnlyTranslation = 7, // 0111 TransformMode_OnlyTranslation = 7, // 0111
TransformMode_NoRotationOrReflection = 1, // 0001 TransformMode_NoRotationOrReflection = 1, // 0001
TransformMode_NoScale = 2, // 0010 TransformMode_NoScale = 2, // 0010
TransformMode_NoScaleOrReflection = 6, // 0110 TransformMode_NoScaleOrReflection = 6 // 0110
}; };
} }

View File

@ -41,7 +41,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
static const int ENTRIES; static const int ENTRIES;

View File

@ -38,7 +38,7 @@ namespace Spine {
friend class SkeletonBinary; friend class SkeletonBinary;
friend class SkeletonJson; friend class SkeletonJson;
RTTI_DECL; RTTI_DECL
public: public:
static const int ENTRIES; static const int ENTRIES;

View File

@ -36,7 +36,7 @@
namespace Spine { namespace Spine {
class Updatable : public SpineObject { class Updatable : public SpineObject {
RTTI_DECL; RTTI_DECL
public: public:
Updatable(); Updatable();

View File

@ -32,11 +32,12 @@
#define Spine_Vector_h #define Spine_Vector_h
#include <spine/Extension.h> #include <spine/Extension.h>
#include <spine/SpineObject.h>
#include <stdlib.h> #include <stdlib.h>
#include <memory> #include <memory>
#include <assert.h> #include <assert.h>
#include <spine/SpineObject.h>
#include <spine/Extension.h>
namespace Spine { namespace Spine {
template <typename T> template <typename T>
@ -45,106 +46,134 @@ namespace Spine {
Vector() : _size(0), _capacity(0), _buffer(NULL) { Vector() : _size(0), _capacity(0), _buffer(NULL) {
// Empty // Empty
} }
Vector(const Vector& inVector) : _size(inVector._size), _capacity(inVector._capacity), _buffer(NULL) { Vector(const Vector& inVector) : _size(inVector._size), _capacity(inVector._capacity), _buffer(NULL) {
if (_capacity > 0) { if (_capacity > 0) {
_buffer = allocate(_capacity); _buffer = allocate(_capacity);
for (size_t i = 0; i < _size; ++i) { for (size_t i = 0; i < _size; ++i) {
_buffer[i] = inVector._buffer[i]; construct(_buffer + i, inVector._buffer[i]);
} }
} }
} }
Vector& operator=(Vector& inVector) {
if (this != &inVector) {
clear();
deallocate(_buffer);
_buffer = NULL;
_size = inVector._size;
_capacity = inVector._capacity;
if (_capacity > 0) {
_buffer = allocate(_capacity);
for (size_t i = 0; i < _size; ++i) {
construct(_buffer + i, inVector._buffer[i]);
}
}
}
return *this;
}
~Vector() { ~Vector() {
clear();
deallocate(_buffer); deallocate(_buffer);
} }
bool contains(const T& inValue) { bool contains(const T& inValue) {
for (size_t i = 0; i < _size; ++i) { for (size_t i = 0; i < _size; ++i) {
if (_buffer[i] == inValue) { if (_buffer[i] == inValue) {
return true; return true;
} }
} }
return false; return false;
} }
int indexOf(const T& inValue) { int indexOf(const T& inValue) {
for (size_t i = 0; i < _size; ++i) { for (size_t i = 0; i < _size; ++i) {
if (_buffer[i] == inValue) { if (_buffer[i] == inValue) {
return static_cast<int>(i); return static_cast<int>(i);
} }
} }
return -1; return -1;
} }
void push_back(const T& inValue) { void push_back(const T& inValue) {
if (_size == _capacity) { if (_size == _capacity) {
reserve(); reserve();
} }
_buffer[_size++] = inValue; construct(_buffer + _size++, inValue);
} }
void insert(size_t inIndex, const T& inValue) { void insert(size_t inIndex, const T& inValue) {
assert(inIndex < _size); assert(inIndex < _size);
if (_size == _capacity) { if (_size == _capacity) {
reserve(); reserve();
} }
for (size_t i = ++_size - 1; i > inIndex; --i) { for (size_t i = ++_size - 1; i > inIndex; --i) {
_buffer[i] = _buffer[i - 1]; construct(_buffer + i, _buffer[i - 1]);
destroy(_buffer + (i - 1));
} }
_buffer[inIndex] = inValue; construct(_buffer + inIndex, inValue);
} }
void erase(size_t inIndex) { void erase(size_t inIndex) {
assert(inIndex < _size); assert(inIndex < _size);
--_size; --_size;
if (inIndex != _size) { if (inIndex != _size) {
for (size_t i = inIndex; i < _size; ++i) { for (size_t i = inIndex; i < _size; ++i) {
std::swap(_buffer[i], _buffer[i + 1]); std::swap(_buffer[i], _buffer[i + 1]);
} }
} }
destroy(_buffer + _size);
} }
void clear() { void clear() {
for (size_t i = 0; i < _size; ++i) {
destroy(_buffer + (_size - 1 - i));
}
_size = 0; _size = 0;
} }
size_t size() const { size_t size() const {
return _size; return _size;
} }
T& operator[](size_t inIndex) { T& operator[](size_t inIndex) {
assert(inIndex < _size); assert(inIndex < _size);
return _buffer[inIndex]; return _buffer[inIndex];
} }
void reserve(size_t inCapacity = 0) { void reserve(size_t inCapacity = 0) {
size_t newCapacity = inCapacity > 0 ? inCapacity : _capacity > 0 ? _capacity * 2 : 1; size_t newCapacity = inCapacity > 0 ? inCapacity : _capacity > 0 ? _capacity * 2 : 1;
if (newCapacity > _capacity) { if (newCapacity > _capacity) {
_buffer = (T*)SpineExtension::realloc<T>(_buffer, newCapacity, __FILE__, __LINE__); _buffer = SpineExtension::realloc<T>(_buffer, newCapacity, __FILE__, __LINE__);
_capacity = newCapacity; _capacity = newCapacity;
} }
} }
void setSize(size_t inValue) { void setSize(size_t inValue) {
assert(inValue <= _capacity); assert(inValue <= _capacity);
_size = inValue; _size = inValue;
} }
T* begin() { T* begin() {
return &_buffer[0]; return &_buffer[0];
} }
T* end() { T* end() {
return &_buffer[_size]; return &_buffer[_size];
} }
@ -166,28 +195,38 @@ namespace Spine {
friend bool operator!=(Vector<T>& lhs, Vector<T>& rhs) { friend bool operator!=(Vector<T>& lhs, Vector<T>& rhs) {
return !(lhs == rhs); return !(lhs == rhs);
} }
private: private:
size_t _size; size_t _size;
size_t _capacity; size_t _capacity;
T* _buffer; T* _buffer;
T* allocate(size_t n) { T* allocate(size_t n) {
assert(n > 0); assert(n > 0);
T* ptr = (T*)SpineExtension::alloc<T>(n, __FILE__, __LINE__); T* ptr = SpineExtension::alloc<T>(n, __FILE__, __LINE__);
assert(ptr); assert(ptr);
return ptr; return ptr;
} }
void deallocate(T* buffer) { void deallocate(T* buffer) {
if (_buffer) { if (_buffer) {
SpineExtension::free<T>(buffer, __FILE__, __LINE__); SpineExtension::free(buffer, __FILE__, __LINE__);
// _buffer = 0;
} }
} }
void construct(T* buffer, const T& val) {
/// This is a placement new operator
/// which basically means we are contructing a new object
/// using pre-allocated memory
new (buffer) T(val);
}
void destroy(T* buffer) {
buffer->~T();
}
}; };
} }

View File

@ -44,7 +44,7 @@ namespace Spine {
friend class SkeletonJson; friend class SkeletonJson;
friend class DeformTimeline; friend class DeformTimeline;
RTTI_DECL; RTTI_DECL
public: public:
VertexAttachment(std::string name); VertexAttachment(std::string name);

View File

@ -64,7 +64,6 @@ namespace Spine {
attachment._regionHeight = region.height; attachment._regionHeight = region.height;
attachment._regionOriginalWidth = region.originalWidth; attachment._regionOriginalWidth = region.originalWidth;
attachment._regionOriginalHeight = region.originalHeight; attachment._regionOriginalHeight = region.originalHeight;
printf("New region attachment, %p %p\n", &attachmentP->getUVs(), &attachmentP->getOffset());
return attachmentP; return attachmentP;
} }

View File

@ -35,10 +35,11 @@
#include <cstring> #include <cstring>
namespace Spine { namespace Spine {
SpineExtension* SpineExtension::_instance = NULL; DefaultSpineExtension _defaultExtension;
SpineExtension* SpineExtension::_instance = &_defaultExtension;
void SpineExtension::setInstance(SpineExtension* inValue) { void SpineExtension::setInstance(SpineExtension* inValue) {
assert(!_instance); assert(inValue);
_instance = inValue; _instance = inValue;
} }
@ -81,7 +82,6 @@ namespace Spine {
if (size == 0) if (size == 0)
return 0; return 0;
void* ptr = ::malloc(size); void* ptr = ::malloc(size);
printf("alloc %lu bytes at %p\n", size, ptr);
return ptr; return ptr;
} }
@ -93,7 +93,6 @@ namespace Spine {
if (ptr) { if (ptr) {
memset(ptr, 0, size); memset(ptr, 0, size);
} }
printf("calloc %lu bytes at %p\n", size, ptr);
return ptr; return ptr;
} }
@ -105,12 +104,10 @@ namespace Spine {
mem = ::malloc(size); mem = ::malloc(size);
else else
mem = ::realloc(ptr, size); mem = ::realloc(ptr, size);
printf("realloc %lu bytes from %p to %p\n", size, ptr, mem);
return mem; return mem;
} }
void DefaultSpineExtension::_free(void* mem, const char* file, int line) { void DefaultSpineExtension::_free(void* mem, const char* file, int line) {
printf("free %p\n", mem);
::free(mem); ::free(mem);
} }

View File

@ -656,7 +656,7 @@ 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*, Skin::HashAttachmentKey>& attachments = skin->getAttachments();
for (typename HashMap<Skin::AttachmentKey, Attachment*, Skin::HashAttachmentKey>::Iterator i = attachments.begin(); i != attachments.end(); ++i) { for (HashMap<Skin::AttachmentKey, Attachment*, Skin::HashAttachmentKey>::Iterator i = attachments.begin(); i != attachments.end(); ++i) {
Skin::AttachmentKey key = i.key(); Skin::AttachmentKey key = i.key();
if (key._slotIndex == slotIndex) { if (key._slotIndex == slotIndex) {
Attachment* value = i.value(); Attachment* value = i.value();

View File

@ -60,12 +60,9 @@ namespace Spine {
Skin::~Skin() { Skin::~Skin() {
HashMap<AttachmentKey, Attachment*, HashAttachmentKey>::Iterator i = _attachments.begin(); HashMap<AttachmentKey, Attachment*, HashAttachmentKey>::Iterator i = _attachments.begin();
printf("Disposing skin\n");
for (; i != _attachments.end(); ++i) { for (; i != _attachments.end(); ++i) {
printf("%p %s\n", i.value(), i.value()->getName().c_str());
delete i.value(); delete i.value();
} }
printf("Disposing skin done\n");
} }
void Skin::addAttachment(int slotIndex, std::string name, Attachment* attachment) { void Skin::addAttachment(int slotIndex, std::string name, Attachment* attachment) {

View File

@ -37,6 +37,10 @@ namespace Spine {
return SpineExtension::calloc<SpineObject>(sz, file, line); return SpineExtension::calloc<SpineObject>(sz, file, line);
} }
void *SpineObject::operator new(size_t sz, void* ptr) {
return ptr;
}
void SpineObject::operator delete(void *p) { void SpineObject::operator delete(void *p) {
SpineExtension::free(p, __FILE__, __LINE__); SpineExtension::free(p, __FILE__, __LINE__);
} }