123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474 |
- /****************************************************************************
- Copyright (c) 2007 Scott Lembcke
- Copyright (c) 2010-2012 cocos2d-x.org
- Copyright (c) 2013-2016 Chukong Technologies Inc.
- Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
- 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.
- ****************************************************************************/
- #include "base/ccCArray.h"
- #include "base/ccTypes.h"
- NS_CC_BEGIN
- /** Allocates and initializes a new array with specified capacity */
- ccArray* ccArrayNew(ssize_t capacity)
- {
- if (capacity == 0)
- capacity = 7;
-
- ccArray *arr = (ccArray*)malloc( sizeof(ccArray) );
- arr->num = 0;
- arr->arr = (Ref**)calloc(capacity, sizeof(Ref*));
- arr->max = capacity;
-
- return arr;
- }
- /** Frees array after removing all remaining objects. Silently ignores nullptr arr. */
- void ccArrayFree(ccArray*& arr)
- {
- if( arr == nullptr )
- {
- return;
- }
- ccArrayRemoveAllObjects(arr);
-
- free(arr->arr);
- free(arr);
- arr = nullptr;
- }
- void ccArrayDoubleCapacity(ccArray *arr)
- {
- arr->max *= 2;
- Ref** newArr = (Ref**)realloc( arr->arr, arr->max * sizeof(Ref*) );
- // will fail when there's not enough memory
- CCASSERT(newArr != 0, "ccArrayDoubleCapacity failed. Not enough memory");
- arr->arr = newArr;
- }
- void ccArrayEnsureExtraCapacity(ccArray *arr, ssize_t extra)
- {
- while (arr->max < arr->num + extra)
- {
- CCLOGINFO("cocos2d: ccCArray: resizing ccArray capacity from [%d] to [%d].",
- static_cast<int>(arr->max),
- static_cast<int>(arr->max*2));
- ccArrayDoubleCapacity(arr);
- }
- }
- void ccArrayShrink(ccArray *arr)
- {
- ssize_t newSize = 0;
-
- //only resize when necessary
- if (arr->max > arr->num && !(arr->num==0 && arr->max==1))
- {
- if (arr->num!=0)
- {
- newSize=arr->num;
- arr->max=arr->num;
- }
- else
- {//minimum capacity of 1, with 0 elements the array would be free'd by realloc
- newSize=1;
- arr->max=1;
- }
-
- arr->arr = (Ref**)realloc(arr->arr,newSize * sizeof(Ref*) );
- CCASSERT(arr->arr!=nullptr,"could not reallocate the memory");
- }
- }
- /** Returns index of first occurrence of object, CC_INVALID_INDEX if object not found. */
- ssize_t ccArrayGetIndexOfObject(ccArray *arr, Ref* object)
- {
- const auto arrNum = arr->num;
- Ref** ptr = arr->arr;
- for (ssize_t i = 0; i < arrNum; ++i, ++ptr)
- {
- if (*ptr == object)
- return i;
- }
-
- return CC_INVALID_INDEX;
- }
- /** Returns a Boolean value that indicates whether object is present in array. */
- bool ccArrayContainsObject(ccArray *arr, Ref* object)
- {
- return ccArrayGetIndexOfObject(arr, object) != CC_INVALID_INDEX;
- }
- /** Appends an object. Behavior undefined if array doesn't have enough capacity. */
- void ccArrayAppendObject(ccArray *arr, Ref* object)
- {
- CCASSERT(object != nullptr, "Invalid parameter!");
- object->retain();
- arr->arr[arr->num] = object;
- arr->num++;
- }
- /** Appends an object. Capacity of arr is increased if needed. */
- void ccArrayAppendObjectWithResize(ccArray *arr, Ref* object)
- {
- ccArrayEnsureExtraCapacity(arr, 1);
- ccArrayAppendObject(arr, object);
- }
- /** Appends objects from plusArr to arr. Behavior undefined if arr doesn't have
- enough capacity. */
- void ccArrayAppendArray(ccArray *arr, ccArray *plusArr)
- {
- for (ssize_t i = 0; i < plusArr->num; i++)
- {
- ccArrayAppendObject(arr, plusArr->arr[i]);
- }
- }
- /** Appends objects from plusArr to arr. Capacity of arr is increased if needed. */
- void ccArrayAppendArrayWithResize(ccArray *arr, ccArray *plusArr)
- {
- ccArrayEnsureExtraCapacity(arr, plusArr->num);
- ccArrayAppendArray(arr, plusArr);
- }
- /** Inserts an object at index */
- void ccArrayInsertObjectAtIndex(ccArray *arr, Ref* object, ssize_t index)
- {
- CCASSERT(index<=arr->num, "Invalid index. Out of bounds");
- CCASSERT(object != nullptr, "Invalid parameter!");
- ccArrayEnsureExtraCapacity(arr, 1);
-
- ssize_t remaining = arr->num - index;
- if (remaining > 0)
- {
- memmove((void *)&arr->arr[index+1], (void *)&arr->arr[index], sizeof(Ref*) * remaining );
- }
- object->retain();
- arr->arr[index] = object;
- arr->num++;
- }
- /** Swaps two objects */
- void ccArraySwapObjectsAtIndexes(ccArray *arr, ssize_t index1, ssize_t index2)
- {
- CCASSERT(index1>=0 && index1 < arr->num, "(1) Invalid index. Out of bounds");
- CCASSERT(index2>=0 && index2 < arr->num, "(2) Invalid index. Out of bounds");
-
- Ref* object1 = arr->arr[index1];
-
- arr->arr[index1] = arr->arr[index2];
- arr->arr[index2] = object1;
- }
- /** Removes all objects from arr */
- void ccArrayRemoveAllObjects(ccArray *arr)
- {
- while (arr->num > 0)
- {
- (arr->arr[--arr->num])->release();
- }
- }
- /** Removes object at specified index and pushes back all subsequent objects.
- Behavior undefined if index outside [0, num-1]. */
- void ccArrayRemoveObjectAtIndex(ccArray *arr, ssize_t index, bool releaseObj/* = true*/)
- {
- CCASSERT(arr && arr->num > 0 && index>=0 && index < arr->num, "Invalid index. Out of bounds");
- if (releaseObj)
- {
- CC_SAFE_RELEASE(arr->arr[index]);
- }
-
- arr->num--;
-
- ssize_t remaining = arr->num - index;
- if(remaining>0)
- {
- memmove((void *)&arr->arr[index], (void *)&arr->arr[index+1], remaining * sizeof(Ref*));
- }
- }
- /** Removes object at specified index and fills the gap with the last object,
- thereby avoiding the need to push back subsequent objects.
- Behavior undefined if index outside [0, num-1]. */
- void ccArrayFastRemoveObjectAtIndex(ccArray *arr, ssize_t index)
- {
- CC_SAFE_RELEASE(arr->arr[index]);
- auto last = --arr->num;
- arr->arr[index] = arr->arr[last];
- }
- void ccArrayFastRemoveObject(ccArray *arr, Ref* object)
- {
- auto index = ccArrayGetIndexOfObject(arr, object);
- if (index != CC_INVALID_INDEX)
- {
- ccArrayFastRemoveObjectAtIndex(arr, index);
- }
- }
- /** Searches for the first occurrence of object and removes it. If object is not
- found the function has no effect. */
- void ccArrayRemoveObject(ccArray *arr, Ref* object, bool releaseObj/* = true*/)
- {
- auto index = ccArrayGetIndexOfObject(arr, object);
- if (index != CC_INVALID_INDEX)
- {
- ccArrayRemoveObjectAtIndex(arr, index, releaseObj);
- }
- }
- /** Removes from arr all objects in minusArr. For each object in minusArr, the
- first matching instance in arr will be removed. */
- void ccArrayRemoveArray(ccArray *arr, ccArray *minusArr)
- {
- for (ssize_t i = 0; i < minusArr->num; i++)
- {
- ccArrayRemoveObject(arr, minusArr->arr[i]);
- }
- }
- /** Removes from arr all objects in minusArr. For each object in minusArr, all
- matching instances in arr will be removed. */
- void ccArrayFullRemoveArray(ccArray *arr, ccArray *minusArr)
- {
- ssize_t back = 0;
-
- for (ssize_t i = 0; i < arr->num; i++)
- {
- if (ccArrayContainsObject(minusArr, arr->arr[i]))
- {
- CC_SAFE_RELEASE(arr->arr[i]);
- back++;
- }
- else
- {
- arr->arr[i - back] = arr->arr[i];
- }
- }
-
- arr->num -= back;
- }
- //
- // // ccCArray for Values (c structures)
- /** Allocates and initializes a new C array with specified capacity */
- ccCArray* ccCArrayNew(ssize_t capacity)
- {
- if (capacity == 0)
- {
- capacity = 7;
- }
- ccCArray *arr = (ccCArray*)malloc(sizeof(ccCArray));
- arr->num = 0;
- arr->arr = (void**)malloc(capacity * sizeof(void*));
- arr->max = capacity;
-
- return arr;
- }
- /** Frees C array after removing all remaining values. Silently ignores nullptr arr. */
- void ccCArrayFree(ccCArray *arr)
- {
- if (arr == nullptr)
- {
- return;
- }
- ccCArrayRemoveAllValues(arr);
-
- free(arr->arr);
- free(arr);
- }
- /** Doubles C array capacity */
- void ccCArrayDoubleCapacity(ccCArray *arr)
- {
- ccArrayDoubleCapacity((ccArray*)arr);
- }
- /** Increases array capacity such that max >= num + extra. */
- void ccCArrayEnsureExtraCapacity(ccCArray *arr, ssize_t extra)
- {
- ccArrayEnsureExtraCapacity((ccArray*)arr,extra);
- }
- /** Returns index of first occurrence of value, CC_INVALID_INDEX if value not found. */
- ssize_t ccCArrayGetIndexOfValue(ccCArray *arr, void* value)
- {
- for(ssize_t i = 0; i < arr->num; i++)
- {
- if( arr->arr[i] == value )
- return i;
- }
- return CC_INVALID_INDEX;
- }
- /** Returns a Boolean value that indicates whether value is present in the C array. */
- bool ccCArrayContainsValue(ccCArray *arr, void* value)
- {
- return ccCArrayGetIndexOfValue(arr, value) != CC_INVALID_INDEX;
- }
- /** Inserts a value at a certain position. Behavior undefined if array doesn't have enough capacity */
- void ccCArrayInsertValueAtIndex( ccCArray *arr, void* value, ssize_t index)
- {
- CCASSERT( index < arr->max, "ccCArrayInsertValueAtIndex: invalid index");
-
- auto remaining = arr->num - index;
- // make sure it has enough capacity
- if (arr->num + 1 == arr->max)
- {
- ccCArrayDoubleCapacity(arr);
- }
- // last Value doesn't need to be moved
- if( remaining > 0) {
- // tex coordinates
- memmove((void *)&arr->arr[index+1], (void *)&arr->arr[index], sizeof(void*) * remaining );
- }
-
- arr->num++;
- arr->arr[index] = value;
- }
- /** Appends an value. Behavior undefined if array doesn't have enough capacity. */
- void ccCArrayAppendValue(ccCArray *arr, void* value)
- {
- arr->arr[arr->num] = value;
- arr->num++;
- // double the capacity for the next append action
- // if the num >= max
- if (arr->num >= arr->max)
- {
- ccCArrayDoubleCapacity(arr);
- }
- }
- /** Appends an value. Capacity of arr is increased if needed. */
- void ccCArrayAppendValueWithResize(ccCArray *arr, void* value)
- {
- ccCArrayEnsureExtraCapacity(arr, 1);
- ccCArrayAppendValue(arr, value);
- }
- /** Appends values from plusArr to arr. Behavior undefined if arr doesn't have
- enough capacity. */
- void ccCArrayAppendArray(ccCArray *arr, ccCArray *plusArr)
- {
- for( ssize_t i = 0; i < plusArr->num; i++)
- {
- ccCArrayAppendValue(arr, plusArr->arr[i]);
- }
- }
- /** Appends values from plusArr to arr. Capacity of arr is increased if needed. */
- void ccCArrayAppendArrayWithResize(ccCArray *arr, ccCArray *plusArr)
- {
- ccCArrayEnsureExtraCapacity(arr, plusArr->num);
- ccCArrayAppendArray(arr, plusArr);
- }
- /** Removes all values from arr */
- void ccCArrayRemoveAllValues(ccCArray *arr)
- {
- arr->num = 0;
- }
- /** Removes value at specified index and pushes back all subsequent values.
- Behavior undefined if index outside [0, num-1].
- @since v0.99.4
- */
- void ccCArrayRemoveValueAtIndex(ccCArray *arr, ssize_t index)
- {
- for( ssize_t last = --arr->num; index < last; index++)
- {
- arr->arr[index] = arr->arr[index + 1];
- }
- }
- /** Removes value at specified index and fills the gap with the last value,
- thereby avoiding the need to push back subsequent values.
- Behavior undefined if index outside [0, num-1].
- @since v0.99.4
- */
- void ccCArrayFastRemoveValueAtIndex(ccCArray *arr, ssize_t index)
- {
- ssize_t last = --arr->num;
- arr->arr[index] = arr->arr[last];
- }
- /** Searches for the first occurrence of value and removes it. If value is not found the function has no effect.
- @since v0.99.4
- */
- void ccCArrayRemoveValue(ccCArray *arr, void* value)
- {
- auto index = ccCArrayGetIndexOfValue(arr, value);
- if (index != CC_INVALID_INDEX)
- {
- ccCArrayRemoveValueAtIndex(arr, index);
- }
- }
- /** Removes from arr all values in minusArr. For each Value in minusArr, the first matching instance in arr will be removed.
- @since v0.99.4
- */
- void ccCArrayRemoveArray(ccCArray *arr, ccCArray *minusArr)
- {
- for(ssize_t i = 0; i < minusArr->num; i++)
- {
- ccCArrayRemoveValue(arr, minusArr->arr[i]);
- }
- }
- /** Removes from arr all values in minusArr. For each value in minusArr, all matching instances in arr will be removed.
- @since v0.99.4
- */
- void ccCArrayFullRemoveArray(ccCArray *arr, ccCArray *minusArr)
- {
- ssize_t back = 0;
-
- for(ssize_t i = 0; i < arr->num; i++)
- {
- if( ccCArrayContainsValue(minusArr, arr->arr[i]) )
- {
- back++;
- }
- else
- {
- arr->arr[i - back] = arr->arr[i];
- }
- }
-
- arr->num -= back;
- }
- NS_CC_END
|