1
0

CCArray.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. /****************************************************************************
  2. Copyright (c) 2010 ForzeField Studios S.L. http://forzefield.com
  3. Copyright (c) 2010-2012 cocos2d-x.org
  4. Copyright (c) 2013-2017 Chukong Technologies Inc.
  5. http://www.cocos2d-x.org
  6. Permission is hereby granted, free of charge, to any person obtaining a copy
  7. of this software and associated documentation files (the "Software"), to deal
  8. in the Software without restriction, including without limitation the rights
  9. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. copies of the Software, and to permit persons to whom the Software is
  11. furnished to do so, subject to the following conditions:
  12. The above copyright notice and this permission notice shall be included in
  13. all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. THE SOFTWARE.
  21. ****************************************************************************/
  22. #ifndef __CCARRAY_H__
  23. #define __CCARRAY_H__
  24. /// @cond DO_NOT_SHOW
  25. #define CC_USE_ARRAY_VECTOR 0
  26. #if CC_USE_ARRAY_VECTOR
  27. #include <vector>
  28. #include <algorithm>
  29. #include "base/CCRef.h"
  30. #include "base/ccMacros.h"
  31. #else
  32. #include "base/ccCArray.h"
  33. #endif
  34. #include "base/CCDataVisitor.h"
  35. #if CC_USE_ARRAY_VECTOR
  36. /**
  37. * A reference counting-managed pointer for classes derived from RCBase which can
  38. * be used as C pointer
  39. * Original code: http://www.codeproject.com/Articles/64111/Building-a-Quick-and-Handy-Reference-Counting-Clas
  40. * License: http://www.codeproject.com/info/cpol10.aspx
  41. */
  42. template < class T >
  43. class RCPtr
  44. {
  45. public:
  46. //Construct using a C pointer
  47. //e.g. RCPtr< T > x = new (std::nothrow) T();
  48. RCPtr(T* ptr = nullptr)
  49. : _ptr(ptr)
  50. {
  51. if(ptr != nullptr) {ptr->retain();}
  52. }
  53. //Copy constructor
  54. RCPtr(const RCPtr &ptr)
  55. : _ptr(ptr._ptr)
  56. {
  57. // printf("Array: copy constructor: %p\n", this);
  58. if(_ptr != NULL) {_ptr->retain();}
  59. }
  60. //Move constructor
  61. RCPtr(RCPtr &&ptr)
  62. : _ptr(ptr._ptr)
  63. {
  64. // printf("Array: Move Constructor: %p\n", this);
  65. ptr._ptr = nullptr;
  66. }
  67. ~RCPtr()
  68. {
  69. // printf("Array: Destructor: %p\n", this);
  70. if(_ptr != nullptr) {_ptr->release();}
  71. }
  72. //Assign a pointer
  73. //e.g. x = new (std::nothrow) T();
  74. RCPtr &operator=(T* ptr)
  75. {
  76. // printf("Array: operator= T*: %p\n", this);
  77. //The following grab and release operations have to be performed
  78. //in that order to handle the case where ptr == _ptr
  79. //(See comment below by David Garlisch)
  80. if(ptr != nullptr) {ptr->retain();}
  81. if(_ptr != nullptr) {_ptr->release();}
  82. _ptr = ptr;
  83. return (*this);
  84. }
  85. //Assign another RCPtr
  86. RCPtr &operator=(const RCPtr &ptr)
  87. {
  88. // printf("Array: operator= const&: %p\n", this);
  89. return (*this) = ptr._ptr;
  90. }
  91. //Retrieve actual pointer
  92. T* get() const
  93. {
  94. return _ptr;
  95. }
  96. //Some overloaded operators to facilitate dealing with an RCPtr
  97. //as a conventional C pointer.
  98. //Without these operators, one can still use the less transparent
  99. //get() method to access the pointer.
  100. T* operator->() const {return _ptr;} //x->member
  101. T &operator*() const {return *_ptr;} //*x, (*x).member
  102. explicit operator T*() const {return _ptr;} //T* y = x;
  103. explicit operator bool() const {return _ptr != nullptr;} //if(x) {/*x is not NULL*/}
  104. bool operator==(const RCPtr &ptr) {return _ptr == ptr._ptr;}
  105. bool operator==(const T *ptr) {return _ptr == ptr;}
  106. private:
  107. T *_ptr; //Actual pointer
  108. };
  109. #endif // CC_USE_ARRAY_VECTOR
  110. /**
  111. * @addtogroup data_structures
  112. * @{
  113. */
  114. /** @def CCARRAY_FOREACH
  115. A convenience macro to iterate over a Array using. It is faster than the "fast enumeration" interface.
  116. @since v0.99.4
  117. */
  118. /*
  119. In cocos2d-iphone 1.0.0, This macro have been update to like this:
  120. #define CCARRAY_FOREACH(__array__, __object__) \
  121. if (__array__ && __array__->data->num > 0) \
  122. for(id *__arr__ = __array__->data->arr, *end = __array__->data->arr + __array__->data->num-1; \
  123. __arr__ <= end && ((__object__ = *__arr__) != nil || true); \
  124. __arr__++)
  125. I found that it's not work in C++. So it keep what it's look like in version 1.0.0-rc3. ---By Bin
  126. */
  127. #if CC_USE_ARRAY_VECTOR
  128. #define CCARRAY_FOREACH(__array__, __object__) \
  129. if (__array__) \
  130. for( auto __it__ = (__array__)->data.begin(); \
  131. __it__ != (__array__)->data.end() && ((__object__) = __it__->get()) != nullptr; \
  132. ++__it__)
  133. #define CCARRAY_FOREACH_REVERSE(__array__, __object__) \
  134. if (__array__) \
  135. for( auto __it__ = (__array__)->data.rbegin(); \
  136. __it__ != (__array__)->data.rend() && ((__object__) = __it__->get()) != nullptr; \
  137. ++__it__ )
  138. #define CCARRAY_VERIFY_TYPE(__array__, __type__) void(0)
  139. #else // ! CC_USE_ARRAY_VECTOR --------------------------
  140. #define CCARRAY_FOREACH(__array__, __object__) \
  141. if ((__array__) && (__array__)->data->num > 0) \
  142. for(Ref** __arr__ = (__array__)->data->arr, **__end__ = (__array__)->data->arr + (__array__)->data->num-1; \
  143. __arr__ <= __end__ && (((__object__) = *__arr__) != NULL/* || true*/); \
  144. __arr__++)
  145. #define CCARRAY_FOREACH_REVERSE(__array__, __object__) \
  146. if ((__array__) && (__array__)->data->num > 0) \
  147. for(Ref** __arr__ = (__array__)->data->arr + (__array__)->data->num-1, **__end__ = (__array__)->data->arr; \
  148. __arr__ >= __end__ && (((__object__) = *__arr__) != NULL/* || true*/); \
  149. __arr__--)
  150. #if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
  151. #define CCARRAY_VERIFY_TYPE(__array__, __type__) \
  152. do { \
  153. if ((__array__) && (__array__)->data->num > 0) \
  154. for(Ref** __arr__ = (__array__)->data->arr, \
  155. **__end__ = (__array__)->data->arr + (__array__)->data->num-1; __arr__ <= __end__; __arr__++) \
  156. CCASSERT(dynamic_cast<__type__>(*__arr__), "element type is wrong!"); \
  157. } while(false)
  158. #else
  159. #define CCARRAY_VERIFY_TYPE(__array__, __type__) void(0)
  160. #endif
  161. #endif // ! CC_USE_ARRAY_VECTOR
  162. // Common defines -----------------------------------------------------------------------------------------------
  163. #define arrayMakeObjectsPerformSelector(pArray, func, elementType) \
  164. do { \
  165. if(pArray && pArray->count() > 0) \
  166. { \
  167. Ref* child; \
  168. CCARRAY_FOREACH(pArray, child) \
  169. { \
  170. elementType pNode = static_cast<elementType>(child); \
  171. if(pNode) \
  172. { \
  173. pNode->func(); \
  174. } \
  175. } \
  176. } \
  177. } \
  178. while(false)
  179. #define arrayMakeObjectsPerformSelectorWithObject(pArray, func, object, elementType) \
  180. do { \
  181. if(pArray && pArray->count() > 0) \
  182. { \
  183. Ref* child; \
  184. CCARRAY_FOREACH(pArray, child) \
  185. { \
  186. elementType pNode = static_cast<elementType>(child); \
  187. if(pNode) \
  188. { \
  189. pNode->func(object); \
  190. } \
  191. } \
  192. } \
  193. } \
  194. while(false)
  195. NS_CC_BEGIN
  196. class CC_DLL __Array : public Ref, public Clonable
  197. {
  198. public:
  199. /** Creates an empty array. Default capacity is 10
  200. * @js NA
  201. * @lua NA
  202. */
  203. static __Array* create();
  204. /** Create an array with objects
  205. * @js NA
  206. */
  207. static __Array* create(Ref* object, ...) CC_REQUIRES_NULL_TERMINATION;
  208. /** Create an array with one object
  209. * @js NA
  210. */
  211. static __Array* createWithObject(Ref* object);
  212. /** Create an array with a default capacity
  213. * @js NA
  214. */
  215. static __Array* createWithCapacity(ssize_t capacity);
  216. /** Create an array with from an existing array
  217. * @js NA
  218. */
  219. static __Array* createWithArray(__Array* otherArray);
  220. /**
  221. @brief Generate a Array pointer by file
  222. @param pFileName The file name of *.plist file
  223. @return The Array pointer generated from the file
  224. * @js NA
  225. */
  226. static __Array* createWithContentsOfFile(const std::string& pFileName);
  227. /*
  228. @brief The same meaning as arrayWithContentsOfFile(), but it doesn't call autorelease, so the
  229. invoker should call release().
  230. * @js NA
  231. * @lua NA
  232. */
  233. static __Array* createWithContentsOfFileThreadSafe(const std::string& pFileName);
  234. /**
  235. * @js NA
  236. * @lua NA
  237. */
  238. ~__Array();
  239. /** Initializes an array
  240. * @js NA
  241. * @lua NA
  242. */
  243. bool init();
  244. /** Initializes an array with one object
  245. * @js NA
  246. * @lua NA
  247. */
  248. bool initWithObject(Ref* object);
  249. /** Initializes an array with some objects
  250. * @js NA
  251. * @lua NA
  252. */
  253. bool initWithObjects(Ref* object, ...) CC_REQUIRES_NULL_TERMINATION;
  254. /** Initializes an array with capacity
  255. * @js NA
  256. * @lua NA
  257. */
  258. bool initWithCapacity(ssize_t capacity);
  259. /** Initializes an array with an existing array
  260. * @js NA
  261. * @lua NA
  262. */
  263. bool initWithArray(__Array* otherArray);
  264. // Querying an Array
  265. /** Returns element count of the array
  266. * @js NA
  267. */
  268. ssize_t count() const
  269. {
  270. #if CC_USE_ARRAY_VECTOR
  271. return data.size();
  272. #else
  273. return data->num;
  274. #endif
  275. }
  276. /** Returns capacity of the array
  277. * @js NA
  278. */
  279. ssize_t capacity() const
  280. {
  281. #if CC_USE_ARRAY_VECTOR
  282. return data.capacity();
  283. #else
  284. return data->max;
  285. #endif
  286. }
  287. /** Returns index of a certain object, return UINT_MAX if doesn't contain the object
  288. * @js NA
  289. * @lua NA
  290. */
  291. ssize_t getIndexOfObject(Ref* object) const;
  292. /**
  293. * @js NA
  294. */
  295. CC_DEPRECATED_ATTRIBUTE ssize_t indexOfObject(Ref* object) const { return getIndexOfObject(object); }
  296. /** Returns an element with a certain index
  297. * @js NA
  298. * @lua NA
  299. */
  300. Ref* getObjectAtIndex(ssize_t index)
  301. {
  302. CCASSERT(index>=0 && index < count(), "index out of range in getObjectAtIndex()");
  303. #if CC_USE_ARRAY_VECTOR
  304. return data[index].get();
  305. #else
  306. return data->arr[index];
  307. #endif
  308. }
  309. CC_DEPRECATED_ATTRIBUTE Ref* objectAtIndex(ssize_t index) { return getObjectAtIndex(index); }
  310. /** Returns the last element of the array
  311. * @js NA
  312. */
  313. Ref* getLastObject()
  314. {
  315. #if CC_USE_ARRAY_VECTOR
  316. return data.back().get();
  317. #else
  318. if(data->num > 0)
  319. return data->arr[data->num-1];
  320. return nullptr;
  321. #endif
  322. }
  323. /**
  324. * @js NA
  325. */
  326. CC_DEPRECATED_ATTRIBUTE Ref* lastObject() { return getLastObject(); }
  327. /** Returns a random element
  328. * @js NA
  329. * @lua NA
  330. */
  331. Ref* getRandomObject();
  332. /**
  333. * @js NA
  334. */
  335. CC_DEPRECATED_ATTRIBUTE Ref* randomObject() { return getRandomObject(); }
  336. /** Returns a Boolean value that indicates whether object is present in array.
  337. * @js NA
  338. */
  339. bool containsObject(Ref* object) const;
  340. /** @since 1.1
  341. * @js NA
  342. */
  343. bool isEqualToArray(__Array* otherArray);
  344. // Adding Objects
  345. /** Add a certain object
  346. * @js NA
  347. */
  348. void addObject(Ref* object);
  349. /**
  350. * @js NA
  351. */
  352. /** Add all elements of an existing array
  353. * @js NA
  354. */
  355. void addObjectsFromArray(__Array* otherArray);
  356. /** Insert a certain object at a certain index
  357. * @js NA
  358. */
  359. void insertObject(Ref* object, ssize_t index);
  360. /** sets a certain object at a certain index
  361. * @js NA
  362. * @lua NA
  363. */
  364. void setObject(Ref* object, ssize_t index);
  365. /** sets a certain object at a certain index without retaining. Use it with caution
  366. * @js NA
  367. * @lua NA
  368. */
  369. void fastSetObject(Ref* object, ssize_t index)
  370. {
  371. #if CC_USE_ARRAY_VECTOR
  372. setObject(object, index);
  373. #else
  374. // no retain
  375. data->arr[index] = object;
  376. #endif
  377. }
  378. /**
  379. * @js NA
  380. * @lua NA
  381. */
  382. void swap( ssize_t indexOne, ssize_t indexTwo )
  383. {
  384. CCASSERT(indexOne >=0 && indexOne < count() && indexTwo >= 0 && indexTwo < count(), "Invalid indices");
  385. #if CC_USE_ARRAY_VECTOR
  386. std::swap(data[indexOne], data[indexTwo]);
  387. #else
  388. std::swap(data->arr[indexOne], data->arr[indexTwo]);
  389. #endif
  390. }
  391. // Removing Objects
  392. /** Remove last object
  393. * @js NA
  394. */
  395. void removeLastObject(bool releaseObj = true);
  396. /** Remove a certain object
  397. * @js NA
  398. */
  399. void removeObject(Ref* object, bool releaseObj = true);
  400. /** Remove an element with a certain index
  401. * @js NA
  402. */
  403. void removeObjectAtIndex(ssize_t index, bool releaseObj = true);
  404. /** Remove all elements
  405. * @js NA
  406. */
  407. void removeObjectsInArray(__Array* otherArray);
  408. /** Remove all objects
  409. * @js NA
  410. */
  411. void removeAllObjects();
  412. /** Fast way to remove a certain object
  413. * @js NA
  414. */
  415. void fastRemoveObject(Ref* object);
  416. /** Fast way to remove an element with a certain index
  417. * @js NA
  418. */
  419. void fastRemoveObjectAtIndex(ssize_t index);
  420. // Rearranging Content
  421. /** Swap two elements
  422. * @js NA
  423. */
  424. void exchangeObject(Ref* object1, Ref* object2);
  425. /** Swap two elements with certain indexes
  426. * @js NA
  427. */
  428. void exchangeObjectAtIndex(ssize_t index1, ssize_t index2);
  429. /** Replace object at index with another object.
  430. * @js NA
  431. */
  432. void replaceObjectAtIndex(ssize_t index, Ref* object, bool releaseObject = true);
  433. /** Revers the array
  434. * @js NA
  435. */
  436. void reverseObjects();
  437. /* Shrinks the array so the memory footprint corresponds with the number of items
  438. * @js NA
  439. */
  440. void reduceMemoryFootprint();
  441. /* override functions
  442. * @js NA
  443. */
  444. virtual void acceptVisitor(DataVisitor &visitor);
  445. /**
  446. * @js NA
  447. * @lua NA
  448. */
  449. virtual __Array* clone() const override;
  450. // ------------------------------------------
  451. // Iterators
  452. // ------------------------------------------
  453. #if CC_USE_ARRAY_VECTOR
  454. typedef std::vector<RCPtr<Object>>::iterator iterator;
  455. typedef std::vector<RCPtr<Object>>::const_iterator const_iterator;
  456. /**
  457. * @js NA
  458. * @lua NA
  459. */
  460. iterator begin() { return data.begin(); }
  461. /**
  462. * @js NA
  463. * @lua NA
  464. */
  465. iterator end() { return data.end(); }
  466. const_iterator cbegin() { return data.cbegin(); }
  467. /**
  468. * @js NA
  469. * @lua NA
  470. */
  471. const_iterator cend() { return data.cend(); }
  472. std::vector<RCPtr<Object>> data;
  473. #else
  474. /**
  475. * @js NA
  476. * @lua NA
  477. */
  478. Ref** begin() { return &data->arr[0]; }
  479. /**
  480. * @js NA
  481. * @lua NA
  482. */
  483. Ref** end() { return &data->arr[data->num]; }
  484. ccArray* data;
  485. #endif
  486. //protected:
  487. /**
  488. * @js NA
  489. * @lua NA
  490. */
  491. __Array();
  492. };
  493. // end of data_structure group
  494. /// @}
  495. NS_CC_END
  496. /// @endcond
  497. #endif // __CCARRAY_H__