/****************************************************************************** * Spine Runtimes License Agreement * Last updated January 1, 2020. Replaces all prior versions. * * Copyright (c) 2013-2020, Esoteric Software LLC * * Integration of the Spine Runtimes into software or otherwise creating * derivative works of the Spine Runtimes is permitted under the terms and * conditions of Section 2 of the Spine Editor License Agreement: * http://esotericsoftware.com/spine-editor-license * * Otherwise, it is permitted to integrate the Spine Runtimes into software * or otherwise create derivative works of the Spine Runtimes (collectively, * "Products"), provided that each user of the Products must obtain their own * Spine Editor license and redistribution of the Products in any form must * include this license and copyright notice. * * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ #ifndef Spine_Vector_h #define Spine_Vector_h #include #include #include #include namespace spine { template class SP_API Vector : public SpineObject { public: Vector() : _size(0), _capacity(0), _buffer(NULL) { } Vector(const Vector &inVector) : _size(inVector._size), _capacity(inVector._capacity), _buffer(NULL) { if (_capacity > 0) { _buffer = allocate(_capacity); for (size_t i = 0; i < _size; ++i) { construct(_buffer + i, inVector._buffer[i]); } } } ~Vector() { clear(); deallocate(_buffer); } inline void clear() { for (size_t i = 0; i < _size; ++i) { destroy(_buffer + (_size - 1 - i)); } _size = 0; } inline size_t getCapacity() const { return _capacity; } inline size_t size() const { return _size; } inline void setSize(size_t newSize, const T &defaultValue) { assert(newSize >= 0); size_t oldSize = _size; _size = newSize; if (_capacity < newSize) { _capacity = (int)(_size * 1.75f); if (_capacity < 8) _capacity = 8; _buffer = spine::SpineExtension::realloc(_buffer, _capacity, __FILE__, __LINE__); } if (oldSize < _size) { for (size_t i = oldSize; i < _size; i++) { construct(_buffer + i, defaultValue); } } } inline void ensureCapacity(size_t newCapacity = 0) { if (_capacity >= newCapacity) return; _capacity = newCapacity; _buffer = SpineExtension::realloc(_buffer, newCapacity, __FILE__, __LINE__); } inline void add(const T &inValue) { if (_size == _capacity) { // inValue might reference an element in this buffer // When we reallocate, the reference becomes invalid. // We thus need to create a defensive copy before // reallocating. T valueCopy = inValue; _capacity = (int)(_size * 1.75f); if (_capacity < 8) _capacity = 8; _buffer = spine::SpineExtension::realloc(_buffer, _capacity, __FILE__, __LINE__); construct(_buffer + _size++, valueCopy); } else { construct(_buffer + _size++, inValue); } } inline void addAll(Vector &inValue) { ensureCapacity(this->size() + inValue.size()); for (size_t i = 0; i < inValue.size(); i++) { add(inValue[i]); } } inline void clearAndAddAll(Vector &inValue) { this->clear(); this->addAll(inValue); } inline void removeAt(size_t inIndex) { assert(inIndex < _size); --_size; if (inIndex != _size) { for (size_t i = inIndex; i < _size; ++i) { T tmp(_buffer[i]); _buffer[i] = _buffer[i + 1]; _buffer[i + 1] = tmp; } } destroy(_buffer + _size); } inline bool contains(const T &inValue) { for (size_t i = 0; i < _size; ++i) { if (_buffer[i] == inValue) { return true; } } return false; } inline int indexOf(const T &inValue) { for (size_t i = 0; i < _size; ++i) { if (_buffer[i] == inValue) { return (int)i; } } return -1; } inline T &operator[](size_t inIndex) { assert(inIndex < _size); return _buffer[inIndex]; } inline friend bool operator==(Vector &lhs, Vector &rhs) { if (lhs.size() != rhs.size()) { return false; } for (size_t i = 0, n = lhs.size(); i < n; ++i) { if (lhs[i] != rhs[i]) { return false; } } return true; } inline friend bool operator!=(Vector &lhs, Vector &rhs) { return !(lhs == rhs); } inline T *buffer() { return _buffer; } private: size_t _size; size_t _capacity; T *_buffer; inline T *allocate(size_t n) { assert(n > 0); T *ptr = SpineExtension::calloc(n, __FILE__, __LINE__); assert(ptr); return ptr; } inline void deallocate(T *buffer) { if (_buffer) { SpineExtension::free(buffer, __FILE__, __LINE__); } } inline void construct(T *buffer, const T &val) { new (buffer) T(val); } inline void destroy(T *buffer) { buffer->~T(); } // Vector &operator=(const Vector &inVector) {}; }; } // namespace spine #endif /* Spine_Vector_h */