2013-11-26 16:58:33 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2010 ForzeField Studios S.L. http://forzefield.com
|
|
|
|
Copyright (c) 2010 cocos2d-x.org
|
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
|
|
|
#ifndef __CCVECTOR_H__
|
|
|
|
#define __CCVECTOR_H__
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
#include <algorithm>
|
|
|
|
#include "ccMacros.h"
|
|
|
|
|
|
|
|
NS_CC_BEGIN
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
class CC_DLL Vector
|
|
|
|
{
|
|
|
|
public:
|
2013-11-28 17:57:13 +08:00
|
|
|
|
|
|
|
Vector<T>()
|
|
|
|
: _data()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
2013-11-28 16:02:03 +08:00
|
|
|
|
2013-11-26 16:58:33 +08:00
|
|
|
/** creates an emptry Vector */
|
2013-11-28 17:57:13 +08:00
|
|
|
explicit Vector<T>(long capacity)
|
2013-11-26 16:58:33 +08:00
|
|
|
: _data()
|
|
|
|
{
|
2013-11-28 17:57:13 +08:00
|
|
|
CCLOG("In the default constructor with capacity of Vector.");
|
|
|
|
setCapacity(capacity);
|
2013-11-26 16:58:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~Vector<T>() {
|
2013-11-28 11:04:39 +08:00
|
|
|
CCLOG("In the destructor of Vector.");
|
|
|
|
removeAllObjects();
|
2013-11-26 16:58:33 +08:00
|
|
|
}
|
|
|
|
|
2013-11-28 11:04:39 +08:00
|
|
|
Vector<T>(const Vector<T>& other)
|
|
|
|
{
|
|
|
|
CCLOG("In the copy constructor!");
|
|
|
|
copy(other);
|
|
|
|
}
|
|
|
|
|
2013-11-28 16:02:03 +08:00
|
|
|
/** Move constructor */
|
|
|
|
Vector<T>(Vector<T>&& other)
|
|
|
|
{
|
|
|
|
CCLOG("In the move constructor of Vector!");
|
|
|
|
_data = std::move(other._data);
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector<T>& operator=(const Vector<T>& other)
|
2013-11-28 11:04:39 +08:00
|
|
|
{
|
2013-11-28 16:02:03 +08:00
|
|
|
CCLOG("In the copy assignment operator!");
|
2013-11-28 11:04:39 +08:00
|
|
|
copy(other);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2013-11-28 16:02:03 +08:00
|
|
|
Vector<T>& operator=(Vector<T>&& other)
|
|
|
|
{
|
|
|
|
CCLOG("In the move assignment operator!");
|
|
|
|
_data = std::move(other._data);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2013-11-28 11:04:39 +08:00
|
|
|
T operator[](long index) const
|
|
|
|
{
|
|
|
|
return getObjectAtIndex(index);
|
|
|
|
}
|
|
|
|
|
2013-11-28 17:57:13 +08:00
|
|
|
/** Sets capacity of current array */
|
|
|
|
void setCapacity(long capacity)
|
2013-11-26 16:58:33 +08:00
|
|
|
{
|
|
|
|
_data.reserve(capacity);
|
2013-11-28 17:57:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns capacity of the array */
|
|
|
|
long getCapacity() const
|
|
|
|
{
|
|
|
|
return _data.capacity();
|
2013-11-26 16:58:33 +08:00
|
|
|
}
|
2013-11-28 11:04:39 +08:00
|
|
|
|
|
|
|
void copy(const Vector<T>& other)
|
|
|
|
{
|
|
|
|
if (this == &other)
|
|
|
|
return;
|
|
|
|
|
|
|
|
removeAllObjects();
|
2013-11-28 17:57:13 +08:00
|
|
|
setCapacity(other.count());
|
2013-11-28 11:04:39 +08:00
|
|
|
addObjectsFromArray(other);
|
|
|
|
}
|
|
|
|
|
2013-11-26 16:58:33 +08:00
|
|
|
// Querying an Array
|
|
|
|
|
|
|
|
/** Returns element count of the array */
|
2013-11-28 09:30:40 +08:00
|
|
|
long count() const
|
2013-11-26 16:58:33 +08:00
|
|
|
{
|
|
|
|
return _data.size();
|
|
|
|
}
|
|
|
|
|
2013-11-28 18:23:06 +08:00
|
|
|
bool empty() const
|
|
|
|
{
|
|
|
|
return _data.empty();
|
|
|
|
}
|
|
|
|
|
2013-11-26 16:58:33 +08:00
|
|
|
/** Returns index of a certain object, return UINT_MAX if doesn't contain the object */
|
2013-11-28 09:30:40 +08:00
|
|
|
long getIndexOfObject(T object) const
|
2013-11-26 16:58:33 +08:00
|
|
|
{
|
2013-11-28 09:30:40 +08:00
|
|
|
long i=0;
|
2013-11-26 16:58:33 +08:00
|
|
|
for (auto it = _data.begin(); it != _data.end(); ++it, ++i)
|
|
|
|
{
|
|
|
|
if (*it == object)
|
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns an element with a certain index */
|
2013-11-28 09:30:40 +08:00
|
|
|
T getObjectAtIndex(long index) const
|
2013-11-26 16:58:33 +08:00
|
|
|
{
|
|
|
|
CCASSERT(index>=0 && index < count(), "index out of range in getObjectAtIndex()");
|
|
|
|
return _data[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns the last element of the array */
|
|
|
|
T getLastObject() const
|
|
|
|
{
|
|
|
|
return _data.back();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns a random element */
|
|
|
|
T getRandomObject() const
|
|
|
|
{
|
|
|
|
return *_data.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns a Boolean value that indicates whether object is present in array. */
|
|
|
|
bool containsObject(T object) const
|
|
|
|
{
|
|
|
|
return( std::find(_data.begin(), _data.end(), object) != _data.end() );
|
|
|
|
}
|
|
|
|
|
|
|
|
/** returns true if the the arrays are equal */
|
|
|
|
bool isEqualToArray(const Vector<T> &otherArray)
|
|
|
|
{
|
2013-11-28 09:30:40 +08:00
|
|
|
for (long i = 0; i< this->count(); i++)
|
2013-11-26 16:58:33 +08:00
|
|
|
{
|
|
|
|
if (!this->getObjectAtIndex(i)->isEqual(otherArray.getObjectAtIndex(i)))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adding Objects
|
|
|
|
|
|
|
|
/** Add a certain object */
|
|
|
|
void addObject(T object)
|
|
|
|
{
|
|
|
|
_data.push_back( object );
|
|
|
|
object->retain();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Add all elements of an existing array */
|
2013-11-28 11:04:39 +08:00
|
|
|
void addObjectsFromArray(const Vector<T>& otherArray)
|
2013-11-26 16:58:33 +08:00
|
|
|
{
|
2013-11-28 11:04:39 +08:00
|
|
|
for( auto it = otherArray.begin(); it != otherArray.end(); ++it ) {
|
2013-11-26 16:58:33 +08:00
|
|
|
_data.push_back( *it );
|
|
|
|
(*it)->retain();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Insert a certain object at a certain index */
|
2013-11-28 09:30:40 +08:00
|
|
|
void insertObject(T object, long index)
|
2013-11-26 16:58:33 +08:00
|
|
|
{
|
2013-11-28 16:02:03 +08:00
|
|
|
CCASSERT(index >= 0 && index < count(), "Invalid index!");
|
|
|
|
_data.insert((std::begin(_data) + index), object);
|
2013-11-26 16:58:33 +08:00
|
|
|
object->retain();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** sets a certain object at a certain index */
|
2013-11-28 09:30:40 +08:00
|
|
|
void setObject(T object, long index)
|
2013-11-26 16:58:33 +08:00
|
|
|
{
|
|
|
|
_data[index] = object;
|
|
|
|
object->retain();
|
|
|
|
}
|
|
|
|
/** sets a certain object at a certain index without retaining. Use it with caution */
|
2013-11-28 09:30:40 +08:00
|
|
|
void fastSetObject(T object, long index)
|
2013-11-26 16:58:33 +08:00
|
|
|
{
|
|
|
|
_data[index] = object;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Removing Objects
|
|
|
|
|
|
|
|
/** Remove last object */
|
|
|
|
void removeLastObject()
|
|
|
|
{
|
|
|
|
CCASSERT(_data.size(), "no objects added");
|
|
|
|
auto last = _data.back();
|
|
|
|
_data.pop_back();
|
|
|
|
last->release();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Remove a certain object */
|
|
|
|
void removeObject(T object)
|
|
|
|
{
|
|
|
|
_data.erase( std::remove( _data.begin(), _data.end(), object ) );
|
|
|
|
object->release();
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Removes an element with a certain index */
|
2013-11-28 09:30:40 +08:00
|
|
|
void removeObjectAtIndex(long index)
|
2013-11-26 16:58:33 +08:00
|
|
|
{
|
|
|
|
auto it = std::next( begin(), index );
|
|
|
|
(*it)->release();
|
2013-11-28 11:04:39 +08:00
|
|
|
_data.erase(it);
|
2013-11-26 16:58:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Removes all objects */
|
|
|
|
void removeAllObjects()
|
|
|
|
{
|
|
|
|
for( auto it = std::begin(_data); it != std::end(_data); ++it ) {
|
|
|
|
(*it)->release();
|
|
|
|
}
|
2013-11-28 11:04:39 +08:00
|
|
|
_data.clear();
|
2013-11-26 16:58:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Fast way to remove a certain object */
|
|
|
|
void fastRemoveObject(T object) {
|
|
|
|
removeObjectAtIndex(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Fast way to remove an element with a certain index */
|
2013-11-28 09:30:40 +08:00
|
|
|
void fastRemoveObjectAtIndex(long index)
|
2013-11-26 16:58:33 +08:00
|
|
|
{
|
|
|
|
removeObjectAtIndex(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Rearranging Content
|
|
|
|
|
|
|
|
/** Swap two elements */
|
|
|
|
void swapObjects(T object1, T object2)
|
|
|
|
{
|
2013-11-28 09:30:40 +08:00
|
|
|
long idx1 = getIndexOfObject(object1);
|
|
|
|
long idx2 = getIndexOfObject(object2);
|
2013-11-26 16:58:33 +08:00
|
|
|
|
|
|
|
CCASSERT(idx1>=0 && idx2>=2, "invalid object index");
|
|
|
|
|
|
|
|
std::swap( _data[idx1], _data[idx2] );
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Swap two elements with certain indexes */
|
2013-11-28 09:30:40 +08:00
|
|
|
void swap(long index1, long index2)
|
2013-11-26 16:58:33 +08:00
|
|
|
{
|
|
|
|
CCASSERT(index1 >=0 && index1 < count() && index2 >= 0 && index2 < count(), "Invalid indices");
|
|
|
|
|
|
|
|
std::swap( _data[index1], _data[index2] );
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Replace object at index with another object. */
|
2013-11-28 09:30:40 +08:00
|
|
|
void replaceObjectAtIndex(long index, T object)
|
2013-11-26 16:58:33 +08:00
|
|
|
{
|
|
|
|
if( object != _data[index] ) {
|
|
|
|
object->retain();
|
|
|
|
_data[index]->release();
|
|
|
|
_data[index] = object;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** reverses the array */
|
|
|
|
void reverseObjects()
|
|
|
|
{
|
|
|
|
std::reverse( std::begin(_data), std::end(_data) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Shrinks the array so the memory footprint corresponds with the number of items */
|
|
|
|
void reduceMemoryFootprint()
|
|
|
|
{
|
|
|
|
_data.shrink_to_fit();
|
|
|
|
}
|
2013-11-28 16:02:03 +08:00
|
|
|
|
2013-11-28 18:23:06 +08:00
|
|
|
void forEach(std::function<void(T)> callback)
|
2013-11-28 16:02:03 +08:00
|
|
|
{
|
|
|
|
if (count() <= 0)
|
|
|
|
return;
|
|
|
|
|
2013-11-29 10:37:40 +08:00
|
|
|
std::for_each(_data.cbegin(), _data.cend(), [&callback](T obj){
|
2013-11-28 16:02:03 +08:00
|
|
|
callback(obj);
|
|
|
|
});
|
|
|
|
}
|
2013-11-26 16:58:33 +08:00
|
|
|
|
2013-11-29 10:37:40 +08:00
|
|
|
void forEachReverse(std::function<void(T)> callback)
|
|
|
|
{
|
|
|
|
if (count() <= 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
std::for_each(_data.crbegin(), _data.crend(), [&callback](T obj){
|
|
|
|
callback(obj);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-11-26 16:58:33 +08:00
|
|
|
// ------------------------------------------
|
|
|
|
// Iterators
|
|
|
|
// ------------------------------------------
|
|
|
|
typedef typename std::vector<T>::iterator iterator;
|
|
|
|
typedef typename std::vector<T>::const_iterator const_iterator;
|
|
|
|
|
2013-11-28 16:02:03 +08:00
|
|
|
typedef typename std::vector<T>::reverse_iterator reverse_iterator;
|
|
|
|
typedef typename std::vector<T>::const_reverse_iterator const_reverse_iterator;
|
|
|
|
|
2013-11-26 16:58:33 +08:00
|
|
|
iterator begin() { return _data.begin(); }
|
2013-11-28 11:04:39 +08:00
|
|
|
const_iterator begin() const { return _data.begin(); }
|
|
|
|
|
2013-11-26 16:58:33 +08:00
|
|
|
iterator end() { return _data.end(); }
|
2013-11-28 11:04:39 +08:00
|
|
|
const_iterator end() const { return _data.end(); }
|
|
|
|
|
|
|
|
const_iterator cbegin() const { return _data.cbegin(); }
|
|
|
|
const_iterator cend() const { return _data.cend(); }
|
2013-11-28 16:02:03 +08:00
|
|
|
|
|
|
|
reverse_iterator rbegin() { return _data.rbegin(); }
|
|
|
|
const_reverse_iterator rbegin() const { return _data.rbegin(); }
|
|
|
|
|
|
|
|
reverse_iterator rend() { return _data.rend(); }
|
|
|
|
const_reverse_iterator rend() const { return _data.rend(); }
|
|
|
|
|
2013-11-29 11:36:42 +08:00
|
|
|
const_reverse_iterator crbegin() const { return _data.crbegin(); }
|
|
|
|
const_reverse_iterator crend() const { return _data.crend(); }
|
2013-11-26 16:58:33 +08:00
|
|
|
protected:
|
|
|
|
std::vector<T> _data;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
// end of data_structure group
|
|
|
|
/// @}
|
|
|
|
|
|
|
|
NS_CC_END
|
|
|
|
|
|
|
|
#endif // __CCVECTOR_H__
|