CCArray.h 17 KB

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