diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2020-02-11 16:16:43 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-02-11 16:16:43 -0500 |
| commit | 9b3e768bceae562deeb330067f3ef5febc2e5244 (patch) | |
| tree | 9282a68c9696f3bb0863b8e9a0474dd523edc788 /source/core | |
| parent | 30d0932add53a50a80f07ce28576bd779b82b4c1 (diff) | |
Small improvements around List (#1216)
* * Improved fastRemoveAt
* Fixed off by one bug
* Fixed const safeness with List<>
* Made List begin and end const safe.
* Revert to previous RefPtr usage.
* Fix bug with casting.
* Tabs -> spaces.
Small fixes/improvements to List.
* Improve comment on List.
* hasContent -> isNonEmpty
Diffstat (limited to 'source/core')
| -rw-r--r-- | source/core/slang-list.h | 1005 |
1 files changed, 509 insertions, 496 deletions
diff --git a/source/core/slang-list.h b/source/core/slang-list.h index 0affbfd66..28180ce4f 100644 --- a/source/core/slang-list.h +++ b/source/core/slang-list.h @@ -15,22 +15,22 @@ namespace Slang { - template<typename T, int isPOD> - class Initializer - { - - }; - - template<typename T> - class Initializer<T, 0> - { - public: - static void initialize(T* buffer, int size) - { - for (int i = 0; i<size; i++) - new (buffer + i) T(); - } - }; + template<typename T, int isPOD> + class Initializer + { + + }; + + template<typename T> + class Initializer<T, 0> + { + public: + static void initialize(T* buffer, int size) + { + for (int i = 0; i<size; i++) + new (buffer + i) T(); + } + }; template<typename T> class Initializer<T, 1> { @@ -43,126 +43,136 @@ namespace Slang } }; - template<typename T, typename TAllocator> - class AllocateMethod - { - public: - static inline T* allocateArray(Index count) - { - TAllocator allocator; - T * rs = (T*)allocator.allocate(count * sizeof(T)); - Initializer<T, std::is_pod<T>::value>::initialize(rs, count); - return rs; - } - static inline void deallocateArray(T* ptr, Index count) - { - TAllocator allocator; - if (!std::is_trivially_destructible<T>::value) - { - for (Index i = 0; i < count; i++) - ptr[i].~T(); - } - allocator.deallocate(ptr); - } - }; - - template<typename T> - class AllocateMethod<T, StandardAllocator> - { - public: - static inline T* allocateArray(Index count) - { - return new T[count]; - } - static inline void deallocateArray(T* ptr, Index /*bufferSize*/) - { - delete [] ptr; - } - }; - - - template<typename T, typename TAllocator = StandardAllocator> - class List - { + template<typename T, typename TAllocator> + class AllocateMethod + { + public: + static inline T* allocateArray(Index count) + { + TAllocator allocator; + T * rs = (T*)allocator.allocate(count * sizeof(T)); + Initializer<T, std::is_pod<T>::value>::initialize(rs, count); + return rs; + } + static inline void deallocateArray(T* ptr, Index count) + { + TAllocator allocator; + if (!std::is_trivially_destructible<T>::value) + { + for (Index i = 0; i < count; i++) + ptr[i].~T(); + } + allocator.deallocate(ptr); + } + }; + + template<typename T> + class AllocateMethod<T, StandardAllocator> + { + public: + static inline T* allocateArray(Index count) + { + return new T[count]; + } + static inline void deallocateArray(T* ptr, Index /*bufferSize*/) + { + delete [] ptr; + } + }; + + // List is container of values of a type held consecutively in memory (much like std::vector) + // + // Note that in this implementation, the underlying memory is backed via an allocation of T[capacity] + // This means that all values have to be in a valid state *even if they are not used* (ie indices >= m_count must be valid) + // + // Also note this implementation does not necessarily 'initialize' an element which is no longer used, + // and this may lead to surprising behavior. Say the list contains a single smart pointer, and the last element is removed (say with removeLast). + // The smart pointer will *not* be released. The smart pointer will be released if the that index is used (via say an add) or + // the List goes out of scope. + template<typename T, typename TAllocator = StandardAllocator> + class List + { private: static const Index kInitialCount = 16; - public: - List() - : m_buffer(nullptr), m_count(0), m_capacity(0) - { - } - template<typename... Args> - List(const T& val, Args... args) - { - _init(val, args...); - } - List(const List<T>& list) - : m_buffer(nullptr), m_count(0), m_capacity(0) - { - this->operator=(list); - } - List(List<T>&& list) - : m_buffer(nullptr), m_count(0), m_capacity(0) - { - this->operator=(static_cast<List<T>&&>(list)); - } - static List<T> makeRepeated(const T& val, Index count) - { - List<T> rs; - rs.setCount(count); - for (Index i = 0; i < count; i++) - rs[i] = val; - return rs; - } - ~List() - { + public: + List() + : m_buffer(nullptr), m_count(0), m_capacity(0) + { + } + template<typename... Args> + List(const T& val, Args... args) + { + _init(val, args...); + } + List(const List<T>& list) + : m_buffer(nullptr), m_count(0), m_capacity(0) + { + this->operator=(list); + } + List(List<T>&& list) + : m_buffer(nullptr), m_count(0), m_capacity(0) + { + this->operator=(static_cast<List<T>&&>(list)); + } + static List<T> makeRepeated(const T& val, Index count) + { + List<T> rs; + rs.setCount(count); + for (Index i = 0; i < count; i++) + rs[i] = val; + return rs; + } + ~List() + { _deallocateBuffer(); - } - List<T>& operator=(const List<T>& list) - { - clearAndDeallocate(); - addRange(list); - return *this; - } - - List<T>& operator=(List<T>&& list) - { + } + List<T>& operator=(const List<T>& list) + { + clearAndDeallocate(); + addRange(list); + return *this; + } + + List<T>& operator=(List<T>&& list) + { // Could just do a swap here, and memory would be freed on rhs dtor _deallocateBuffer(); - m_count = list.m_count; - m_capacity = list.m_capacity; - m_buffer = list.m_buffer; - - list.m_buffer = nullptr; - list.m_count = 0; - list.m_capacity = 0; - return *this; - } - - // TODO(JS): These should be made const safe but some other code depends on this behavior for now. - T* begin() const { return m_buffer; } - T* end() const { return m_buffer + m_count; } - - const T& getFirst() const - { - SLANG_ASSERT(m_count > 0); - return m_buffer[0]; - } + m_count = list.m_count; + m_capacity = list.m_capacity; + m_buffer = list.m_buffer; + + list.m_buffer = nullptr; + list.m_count = 0; + list.m_capacity = 0; + return *this; + } - const T& getLast() const - { - SLANG_ASSERT(m_count > 0); - return m_buffer[m_count-1]; - } + const T* begin() const { return m_buffer; } + const T* end() const { return m_buffer + m_count; } + + T* begin() { return m_buffer; } + T* end() { return m_buffer + m_count; } + const T& getFirst() const + { + SLANG_ASSERT(m_count > 0); + return m_buffer[0]; + } + T& getFirst() { SLANG_ASSERT(m_count > 0); return m_buffer[0]; } + const T& getLast() const + { + SLANG_ASSERT(m_count > 0); + return m_buffer[m_count - 1]; + } + T& getLast() { SLANG_ASSERT(m_count > 0); @@ -175,180 +185,177 @@ namespace Slang m_count--; } - inline void swapWith(List<T, TAllocator>& other) - { - T* buffer = m_buffer; - m_buffer = other.m_buffer; - other.m_buffer = buffer; - - auto bufferSize = m_capacity; - m_capacity = other.m_capacity; - other.m_capacity = bufferSize; - - auto count = m_count; - m_count = other.m_count; - other.m_count = count; - } - - T* detachBuffer() - { - T* rs = m_buffer; - m_buffer = nullptr; - m_count = 0; - m_capacity = 0; - return rs; - } - - inline ArrayView<T> getArrayView() const - { - return ArrayView<T>(m_buffer, m_count); - } - - inline ArrayView<T> getArrayView(Index start, Index count) const - { + inline void swapWith(List<T, TAllocator>& other) + { + T* buffer = m_buffer; + m_buffer = other.m_buffer; + other.m_buffer = buffer; + + auto bufferSize = m_capacity; + m_capacity = other.m_capacity; + other.m_capacity = bufferSize; + + auto count = m_count; + m_count = other.m_count; + other.m_count = count; + } + + T* detachBuffer() + { + T* rs = m_buffer; + m_buffer = nullptr; + m_count = 0; + m_capacity = 0; + return rs; + } + + inline ArrayView<T> getArrayView() const + { + return ArrayView<T>(m_buffer, m_count); + } + + inline ArrayView<T> getArrayView(Index start, Index count) const + { SLANG_ASSERT(start >= 0 && count >= 0 && start + count <= m_count); - return ArrayView<T>(m_buffer + start, count); - } - - void add(T&& obj) - { - if (m_capacity < m_count + 1) - { - Index newBufferSize = kInitialCount; - if (m_capacity) - newBufferSize = (m_capacity << 1); - - reserve(newBufferSize); - } - m_buffer[m_count++] = static_cast<T&&>(obj); - } - - void add(const T& obj) - { - if (m_capacity < m_count + 1) - { - Index newBufferSize = kInitialCount; - if (m_capacity) - newBufferSize = (m_capacity << 1); - - reserve(newBufferSize); - } - m_buffer[m_count++] = obj; - - } + return ArrayView<T>(m_buffer + start, count); + } + + void _maybeReserveForAdd() + { + if (m_capacity <= m_count) + { + Index newBufferSize = kInitialCount; + if (m_capacity) + newBufferSize = (m_capacity << 1); + + reserve(newBufferSize); + } + } + + void add(T&& obj) + { + _maybeReserveForAdd(); + m_buffer[m_count++] = static_cast<T&&>(obj); + } + + void add(const T& obj) + { + _maybeReserveForAdd(); + m_buffer[m_count++] = obj; + } Index getCount() const { return m_count; } Index getCapacity() const { return m_capacity; } - const T* getBuffer() const { return m_buffer; } + const T* getBuffer() const { return m_buffer; } T* getBuffer() { return m_buffer; } - void insert(Index idx, const T& val) { insertRange(idx, &val, 1); } + void insert(Index idx, const T& val) { insertRange(idx, &val, 1); } - void insertRange(Index idx, const T* vals, Index n) - { - if (m_capacity < m_count + n) - { + void insertRange(Index idx, const T* vals, Index n) + { + if (m_capacity < m_count + n) + { Index newBufferCount = kInitialCount; - while (newBufferCount < m_count + n) - newBufferCount = newBufferCount << 1; - - T* newBuffer = _allocate(newBufferCount); - if (m_capacity) - { - /*if (std::has_trivial_copy_assign<T>::value && std::has_trivial_destructor<T>::value) - { - memcpy(newBuffer, buffer, sizeof(T) * id); - memcpy(newBuffer + id + n, buffer + id, sizeof(T) * (_count - id)); - } - else*/ - { - for (Index i = 0; i < idx; i++) - newBuffer[i] = m_buffer[i]; - for (Index i = idx; i < m_count; i++) - newBuffer[i + n] = T(static_cast<T&&>(m_buffer[i])); - } - _deallocateBuffer(); - } - m_buffer = newBuffer; - m_capacity = newBufferCount; - } - else - { - /*if (std::has_trivial_copy_assign<T>::value && std::has_trivial_destructor<T>::value) - memmove(buffer + id + n, buffer + id, sizeof(T) * (_count - id)); - else*/ - { - for (Index i = m_count; i > idx; i--) - m_buffer[i + n - 1] = static_cast<T&&>(m_buffer[i - 1]); - } - } - /*if (std::has_trivial_copy_assign<T>::value && std::has_trivial_destructor<T>::value) - memcpy(buffer + id, vals, sizeof(T) * n); - else*/ - for (Index i = 0; i < n; i++) - m_buffer[idx + i] = vals[i]; - - m_count += n; - } - - //slower than original edition - //void Add(const T & val) - //{ - // InsertRange(_count, &val, 1); - //} - - void insertRange(Index id, const List<T>& list) { insertRange(id, list.m_buffer, list.m_count); } - - void addRange(ArrayView<T> list) { insertRange(m_count, list.getBuffer(), list.Count()); } + while (newBufferCount < m_count + n) + newBufferCount = newBufferCount << 1; + + T* newBuffer = _allocate(newBufferCount); + if (m_capacity) + { + /*if (std::has_trivial_copy_assign<T>::value && std::has_trivial_destructor<T>::value) + { + memcpy(newBuffer, buffer, sizeof(T) * id); + memcpy(newBuffer + id + n, buffer + id, sizeof(T) * (_count - id)); + } + else*/ + { + for (Index i = 0; i < idx; i++) + newBuffer[i] = m_buffer[i]; + for (Index i = idx; i < m_count; i++) + newBuffer[i + n] = T(static_cast<T&&>(m_buffer[i])); + } + _deallocateBuffer(); + } + m_buffer = newBuffer; + m_capacity = newBufferCount; + } + else + { + /*if (std::has_trivial_copy_assign<T>::value && std::has_trivial_destructor<T>::value) + memmove(buffer + id + n, buffer + id, sizeof(T) * (_count - id)); + else*/ + { + for (Index i = m_count; i > idx; i--) + m_buffer[i + n - 1] = static_cast<T&&>(m_buffer[i - 1]); + } + } + /*if (std::has_trivial_copy_assign<T>::value && std::has_trivial_destructor<T>::value) + memcpy(buffer + id, vals, sizeof(T) * n); + else*/ + for (Index i = 0; i < n; i++) + m_buffer[idx + i] = vals[i]; + + m_count += n; + } + + void insertRange(Index id, const List<T>& list) { insertRange(id, list.m_buffer, list.m_count); } + + void addRange(ArrayView<T> list) { insertRange(m_count, list.getBuffer(), list.Count()); } void addRange(const T* vals, Index n) { insertRange(m_count, vals, n); } - void addRange(const List<T>& list) { insertRange(m_count, list.m_buffer, list.m_count); } + void addRange(const List<T>& list) { insertRange(m_count, list.m_buffer, list.m_count); } - void removeRange(Index idx, Index count) - { + void removeRange(Index idx, Index count) + { SLANG_ASSERT(idx >= 0 && idx <= m_count); - const Index actualDeleteCount = ((idx + count) >= m_count)? (m_count - idx) : count; - for (Index i = idx + actualDeleteCount; i < m_count; i++) - m_buffer[i - actualDeleteCount] = static_cast<T&&>(m_buffer[i]); - m_count -= actualDeleteCount; - } + const Index actualDeleteCount = ((idx + count) >= m_count)? (m_count - idx) : count; + for (Index i = idx + actualDeleteCount; i < m_count; i++) + m_buffer[i - actualDeleteCount] = static_cast<T&&>(m_buffer[i]); + m_count -= actualDeleteCount; + } - void removeAt(Index id) { removeRange(id, 1); } + void removeAt(Index id) { removeRange(id, 1); } - void remove(const T& val) - { + void remove(const T& val) + { Index idx = indexOf(val); - if (idx != -1) - removeAt(idx); - } - - void reverse() - { - for (Index i = 0; i < (m_count >> 1); i++) - { - swapElements(m_buffer, i, m_count - i - 1); - } - } - - void fastRemove(const T& val) - { + if (idx != -1) + removeAt(idx); + } + + void reverse() + { + for (Index i = 0; i < (m_count >> 1); i++) + { + swapElements(m_buffer, i, m_count - i - 1); + } + } + + void fastRemove(const T& val) + { Index idx = indexOf(val); - fastRemoveAt(idx); - } + if (idx >= 0) + { + fastRemoveAt(idx); + } + } - void fastRemoveAt(Index idx) - { - if (idx != -1 && m_count - 1 != idx) - { - m_buffer[idx] = _Move(m_buffer[m_count - 1]); - } - m_count--; - } + void fastRemoveAt(Index idx) + { + SLANG_ASSERT(idx >= 0 && idx < m_count); + // We do not test for idx == m_count - 1 (ie the move is to current index). With the assumption that any reasonable move implementation + // tests and ignores this case + if (idx != m_count - 1) + { + m_buffer[idx] = _Move(m_buffer[m_count - 1]); + } + m_count--; + } - void clear() { m_count = 0; } + void clear() { m_count = 0; } void clearAndDeallocate() { @@ -356,233 +363,239 @@ namespace Slang m_count = m_capacity = 0; } - void reserve(Index size) - { - if(size > m_capacity) - { - T* newBuffer = _allocate(size); - if (m_capacity) - { - /*if (std::has_trivial_copy_assign<T>::value && std::has_trivial_destructor<T>::value) - memcpy(newBuffer, buffer, _count * sizeof(T)); - else*/ - { - for (Index i = 0; i < m_count; i++) - newBuffer[i] = static_cast<T&&>(m_buffer[i]); + void reserve(Index size) + { + if(size > m_capacity) + { + T* newBuffer = _allocate(size); + if (m_capacity) + { + /*if (std::has_trivial_copy_assign<T>::value && std::has_trivial_destructor<T>::value) + memcpy(newBuffer, buffer, _count * sizeof(T)); + else*/ + { + for (Index i = 0; i < m_count; i++) + newBuffer[i] = static_cast<T&&>(m_buffer[i]); // Default-initialize the remaining elements for(Index i = m_count; i < size; i++) { new(newBuffer + i) T(); } - } - _deallocateBuffer(); - } - m_buffer = newBuffer; - m_capacity = size; - } - } - - void growToCount(Index count) - { + } + _deallocateBuffer(); + } + m_buffer = newBuffer; + m_capacity = size; + } + } + + void growToCount(Index count) + { Index newBufferCount = Index(1) << Math::Log2Ceil(count); - if (m_capacity < newBufferCount) - { - reserve(newBufferCount); - } - m_count = count; - } - - void setCount(Index count) - { - reserve(count); - m_count = count; - } - - void unsafeShrinkToCount(Index count) { m_count = count; } - - void compress() - { - if (m_capacity > m_count && m_count > 0) - { - T* newBuffer = _allocate(m_count); - for (Index i = 0; i < m_count; i++) - newBuffer[i] = static_cast<T&&>(m_buffer[i]); - - _deallocateBuffer(); - m_buffer = newBuffer; - m_capacity = m_count; - } - } - - SLANG_FORCE_INLINE T& operator [](Index idx) const - { - SLANG_ASSERT(idx >= 0 && idx <= m_count); - return m_buffer[idx]; - } + if (m_capacity < newBufferCount) + { + reserve(newBufferCount); + } + m_count = count; + } + + void setCount(Index count) + { + reserve(count); + m_count = count; + } - template<typename Func> + void unsafeShrinkToCount(Index count) { m_count = count; } + + void compress() + { + if (m_capacity > m_count && m_count > 0) + { + T* newBuffer = _allocate(m_count); + for (Index i = 0; i < m_count; i++) + newBuffer[i] = static_cast<T&&>(m_buffer[i]); + + _deallocateBuffer(); + m_buffer = newBuffer; + m_capacity = m_count; + } + } + + SLANG_FORCE_INLINE const T& operator [](Index idx) const + { + SLANG_ASSERT(idx >= 0 && idx < m_count); + return m_buffer[idx]; + } + + SLANG_FORCE_INLINE T& operator [](Index idx) + { + SLANG_ASSERT(idx >= 0 && idx < m_count); + return m_buffer[idx]; + } + + template<typename Func> Index findFirstIndex(const Func& predicate) const - { - for (Index i = 0; i < m_count; i++) - { - if (predicate(m_buffer[i])) - return i; - } - return (Index)-1; - } - - template<typename Func> - Index findLastIndex(const Func& predicate) const - { - for (Index i = m_count; i > 0; i--) - { - if (predicate(m_buffer[i-1])) - return i-1; - } - return (Index)-1; - } - - template<typename T2> + { + for (Index i = 0; i < m_count; i++) + { + if (predicate(m_buffer[i])) + return i; + } + return -1; + } + + template<typename T2> Index indexOf(const T2& val) const - { - for (Index i = 0; i < m_count; i++) - { - if (m_buffer[i] == val) - return i; - } - return (Index)-1; - } - - template<typename T2> + { + for (Index i = 0; i < m_count; i++) + { + if (m_buffer[i] == val) + return i; + } + return -1; + } + + template<typename Func> + Index findLastIndex(const Func& predicate) const + { + for (Index i = m_count - 1; i >= 0; i--) + { + if (predicate(m_buffer[i])) + return i; + } + return -1; + } + + template<typename T2> Index lastIndexOf(const T2& val) const - { - for (Index i = m_count; i > 0; i--) - { - if(m_buffer[i-1] == val) - return i-1; - } - return (Index)-1; - } - - void sort() - { - sort([](const T& t1, const T& t2){return t1 < t2;}); - } + { + for (Index i = m_count - 1; i >= 0; i--) + { + if(m_buffer[i] == val) + return i; + } + return -1; + } + + void sort() + { + sort([](const T& t1, const T& t2){return t1 < t2;}); + } bool contains(const T& val) const { return indexOf(val) != Index(-1); } - template<typename Comparer> - void sort(Comparer compare) - { - //insertionSort(buffer, 0, _count - 1); - //quickSort(buffer, 0, _count - 1, compare); - std::sort(m_buffer, m_buffer + m_count, compare); - } - - template <typename IterateFunc> - void forEach(IterateFunc f) const - { - for (Index i = 0; i< m_count; i++) - f(m_buffer[i]); - } - - template<typename Comparer> - void quickSort(T* vals, Index startIndex, Index endIndex, Comparer comparer) - { + template<typename Comparer> + void sort(Comparer compare) + { + //insertionSort(buffer, 0, _count - 1); + //quickSort(buffer, 0, _count - 1, compare); + std::sort(m_buffer, m_buffer + m_count, compare); + } + + template <typename IterateFunc> + void forEach(IterateFunc f) const + { + for (Index i = 0; i < m_count; i++) + f(m_buffer[i]); + } + + template<typename Comparer> + void quickSort(T* vals, Index startIndex, Index endIndex, Comparer comparer) + { static const Index kMinQSortSize = 32; - if(startIndex < endIndex) - { - if (endIndex - startIndex < kMinQSortSize) - insertionSort(vals, startIndex, endIndex, comparer); - else - { + if(startIndex < endIndex) + { + if (endIndex - startIndex < kMinQSortSize) + insertionSort(vals, startIndex, endIndex, comparer); + else + { Index pivotIndex = (startIndex + endIndex) >> 1; Index pivotNewIndex = partition(vals, startIndex, endIndex, pivotIndex, comparer); - quickSort(vals, startIndex, pivotNewIndex - 1, comparer); - quickSort(vals, pivotNewIndex + 1, endIndex, comparer); - } - } + quickSort(vals, startIndex, pivotNewIndex - 1, comparer); + quickSort(vals, pivotNewIndex + 1, endIndex, comparer); + } + } - } - template<typename Comparer> + } + template<typename Comparer> Index partition(T* vals, Index left, Index right, Index pivotIndex, Comparer comparer) - { - T pivotValue = vals[pivotIndex]; - swapElements(vals, right, pivotIndex); + { + T pivotValue = vals[pivotIndex]; + swapElements(vals, right, pivotIndex); Index storeIndex = left; - for (Index i = left; i < right; i++) - { - if (comparer(vals[i], pivotValue)) - { - swapElements(vals, i, storeIndex); - storeIndex++; - } - } - swapElements(vals, storeIndex, right); - return storeIndex; - } - template<typename Comparer> - void insertionSort(T* vals, Index startIndex, Index endIndex, Comparer comparer) - { - for (Index i = startIndex + 1; i <= endIndex; i++) - { - T insertValue = static_cast<T&&>(vals[i]); + for (Index i = left; i < right; i++) + { + if (comparer(vals[i], pivotValue)) + { + swapElements(vals, i, storeIndex); + storeIndex++; + } + } + swapElements(vals, storeIndex, right); + return storeIndex; + } + template<typename Comparer> + void insertionSort(T* vals, Index startIndex, Index endIndex, Comparer comparer) + { + for (Index i = startIndex + 1; i <= endIndex; i++) + { + T insertValue = static_cast<T&&>(vals[i]); Index insertIndex = i - 1; - while (insertIndex >= startIndex && comparer(insertValue, vals[insertIndex])) - { - vals[insertIndex + 1] = static_cast<T&&>(vals[insertIndex]); - insertIndex--; - } - vals[insertIndex + 1] = static_cast<T&&>(insertValue); - } - } - - inline void swapElements(T* vals, Index index1, Index index2) - { - if (index1 != index2) - { - T tmp = static_cast<T&&>(vals[index1]); - vals[index1] = static_cast<T&&>(vals[index2]); - vals[index2] = static_cast<T&&>(tmp); - } - } - - template<typename T2, typename Comparer> + while (insertIndex >= startIndex && comparer(insertValue, vals[insertIndex])) + { + vals[insertIndex + 1] = static_cast<T&&>(vals[insertIndex]); + insertIndex--; + } + vals[insertIndex + 1] = static_cast<T&&>(insertValue); + } + } + + inline void swapElements(T* vals, Index index1, Index index2) + { + if (index1 != index2) + { + T tmp = static_cast<T&&>(vals[index1]); + vals[index1] = static_cast<T&&>(vals[index2]); + vals[index2] = static_cast<T&&>(tmp); + } + } + + template<typename T2, typename Comparer> Index binarySearch(const T2& obj, Comparer comparer) - { + { Index imin = 0, imax = m_count - 1; - while (imax >= imin) - { + while (imax >= imin) + { Index imid = (imin + imax) >> 1; - int compareResult = comparer(m_buffer[imid], obj); - if (compareResult == 0) - return imid; - else if (compareResult < 0) - imin = imid + 1; - else - imax = imid - 1; - } - return -1; - } - - template<typename T2> - int binarySearch(const T2& obj) - { - return binarySearch(obj, - [](T & curObj, const T2 & thatObj)->int - { - if (curObj < thatObj) - return -1; - else if (curObj == thatObj) - return 0; - else - return 1; - }); - } + int compareResult = comparer(m_buffer[imid], obj); + if (compareResult == 0) + return imid; + else if (compareResult < 0) + imin = imid + 1; + else + imax = imid - 1; + } + return -1; + } + + template<typename T2> + int binarySearch(const T2& obj) + { + return binarySearch(obj, + [](T & curObj, const T2 & thatObj)->int + { + if (curObj < thatObj) + return -1; + else if (curObj == thatObj) + return 0; + else + return 1; + }); + } private: - T* m_buffer; ///< A new T[N] allocated buffer. NOTE! All elements up to capacity are in some valid form for T. + T* m_buffer; ///< A new T[N] allocated buffer. NOTE! All elements up to capacity are in some valid form for T. Index m_capacity; ///< The total capacity of elements Index m_count; ///< The amount of elements @@ -605,27 +618,27 @@ namespace Slang add(val); _init(args...); } - }; - - template<typename T> - T calcMin(const List<T>& list) - { - T minVal = list.getFirst(); - for (Index i = 1; i < list.getCount(); i++) - if (list[i] < minVal) - minVal = list[i]; - return minVal; - } - - template<typename T> - T calcMax(const List<T>& list) - { - T maxVal = list.getFirst(); - for (Index i = 1; i< list.getCount(); i++) - if (list[i] > maxVal) - maxVal = list[i]; - return maxVal; - } + }; + + template<typename T> + T calcMin(const List<T>& list) + { + T minVal = list.getFirst(); + for (Index i = 1; i < list.getCount(); i++) + if (list[i] < minVal) + minVal = list[i]; + return minVal; + } + + template<typename T> + T calcMax(const List<T>& list) + { + T maxVal = list.getFirst(); + for (Index i = 1; i< list.getCount(); i++) + if (list[i] > maxVal) + maxVal = list[i]; + return maxVal; + } } #endif |
