diff options
| -rw-r--r-- | source/core/core.natvis | 51 | ||||
| -rw-r--r-- | source/core/core.vcxproj | 1 | ||||
| -rw-r--r-- | source/core/core.vcxproj.filters | 3 | ||||
| -rw-r--r-- | source/core/slang-allocator.h | 70 | ||||
| -rw-r--r-- | source/core/slang-basic.h | 1 | ||||
| -rw-r--r-- | source/core/slang-dictionary.h | 2 | ||||
| -rw-r--r-- | source/core/slang-list.h | 73 | ||||
| -rw-r--r-- | source/core/slang-short-list.h | 488 | ||||
| -rw-r--r-- | tools/slang-test/slang-test.vcxproj | 1 | ||||
| -rw-r--r-- | tools/slang-test/slang-test.vcxproj.filters | 3 | ||||
| -rw-r--r-- | tools/slang-test/unit-test-short-list.cpp | 78 |
11 files changed, 699 insertions, 72 deletions
diff --git a/source/core/core.natvis b/source/core/core.natvis index 2b1e3ff7e..1087b4e6a 100644 --- a/source/core/core.natvis +++ b/source/core/core.natvis @@ -18,7 +18,7 @@ </Expand> </Type> -<Type Name="Slang::List<*>"> +<Type Name="Slang::List<*,*>"> <DisplayString>{{ size={m_count} }}</DisplayString> <Expand> <Item Name="[size]">m_count</Item> @@ -30,6 +30,18 @@ </Expand> </Type> +<Type Name="Slang::ShortList<*,*,*>"> + <DisplayString>{{ size={m_count} }}</DisplayString> + <Expand> + <Item Name="[size]">m_count</Item> + <Item Name="[capacity]">m_capacity</Item> + <IndexListItems> + <Size>m_count</Size> + <ValueNode Condition="$i<$T2">m_shortBuffer + $i</ValueNode> + <ValueNode Condition="$i>=$T2">m_buffer + $i - $T2</ValueNode> + </IndexListItems> + </Expand> +</Type> <Type Name="Slang::Array<*,*>"> <DisplayString>{{ size={m_count} }}</DisplayString> @@ -47,10 +59,33 @@ <Expand> <Item Name="[size]">_count</Item> <Item Name="[capacity]">bucketSizeMinusOne + 1</Item> - <ArrayItems> - <Size>bucketSizeMinusOne + 1</Size> - <ValuePointer>hashMap</ValuePointer> - </ArrayItems> + <CustomListItems MaxItemsPerView="5000" ExcludeView="Test"> + <Variable Name="iBucket" InitialValue="0" /> + <Variable Name="pBucket" InitialValue="hashMap" /> + <Variable Name="isDeleted" InitialValue="0" /> + <Variable Name="isEmpty" InitialValue="0" /> + <Size>_count</Size> + <Exec>pBucket = hashMap</Exec> + <Loop> + <If Condition="iBucket >= bucketSizeMinusOne + 1"> + <Break/> + </If> + <Exec> + isDeleted = marks.m_buffer.m_count > (iBucket*2+1)/32 + ? ((marks.m_buffer.m_buffer[(iBucket*2+1)/32]&(1<<(iBucket*2+1)%32)) != 0) + : 0 + </Exec> + <Exec> + isEmpty = marks.m_buffer.m_count > (iBucket*2)/32 + ? ((marks.m_buffer.m_buffer[(iBucket*2)/32]&(1<<(iBucket*2)%32)) == 0) + : 1 + </Exec> + <If Condition="isDeleted+isEmpty==0"> + <Item>*(hashMap + iBucket)</Item> + </If> + <Exec>iBucket++</Exec> + </Loop> + </CustomListItems> </Expand> </Type> @@ -103,4 +138,10 @@ <StringView>(m_sizeThenContents + 1),s</StringView> </Type> +<Type Name="Slang::UnownedStringSlice"> + <DisplayString>{m_begin,[m_end-m_begin]s}</DisplayString> + <StringView>m_begin,[m_end-m_begin]s</StringView> + +</Type> + </AutoVisualizer> diff --git a/source/core/core.vcxproj b/source/core/core.vcxproj index 8c4e7753c..9676bb989 100644 --- a/source/core/core.vcxproj +++ b/source/core/core.vcxproj @@ -198,6 +198,7 @@ <ClInclude Include="slang-secure-crt.h" /> <ClInclude Include="slang-semantic-version.h" /> <ClInclude Include="slang-shared-library.h" /> + <ClInclude Include="slang-short-list.h" /> <ClInclude Include="slang-smart-pointer.h" /> <ClInclude Include="slang-std-writers.h" /> <ClInclude Include="slang-stream.h" /> diff --git a/source/core/core.vcxproj.filters b/source/core/core.vcxproj.filters index 312c24b17..3cb5ec8ec 100644 --- a/source/core/core.vcxproj.filters +++ b/source/core/core.vcxproj.filters @@ -138,6 +138,9 @@ <ClInclude Include="windows\slang-win-visual-studio-util.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="slang-short-list.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="slang-blob.cpp"> diff --git a/source/core/slang-allocator.h b/source/core/slang-allocator.h index 481f8810f..f25fd92c9 100644 --- a/source/core/slang-allocator.h +++ b/source/core/slang-allocator.h @@ -1,11 +1,15 @@ #ifndef SLANG_CORE_ALLOCATOR_H #define SLANG_CORE_ALLOCATOR_H +#include "slang-common.h" + #include <stdlib.h> #ifdef _MSC_VER # include <malloc.h> #endif +#include <type_traits> + namespace Slang { inline void* alignedAllocate(size_t size, size_t alignment) @@ -59,6 +63,72 @@ namespace Slang return alignedDeallocate(ptr); } }; + + // Helper utilties for calling allocators. + 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> + { + public: + static void initialize(T* buffer, int size) + { + // It's pod so no initialization required + //for (int i = 0; i < size; i++) + // new (buffer + i) T; + } + }; + + 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; + } + }; } #endif diff --git a/source/core/slang-basic.h b/source/core/slang-basic.h index 7931749f4..5387af4aa 100644 --- a/source/core/slang-basic.h +++ b/source/core/slang-basic.h @@ -6,6 +6,7 @@ #include "slang-string.h" #include "slang-array.h" #include "slang-list.h" +#include "slang-short-list.h" #include "slang-smart-pointer.h" #include "slang-exception.h" #include "slang-dictionary.h" diff --git a/source/core/slang-dictionary.h b/source/core/slang-dictionary.h index 72b24f81c..10c5a9b7d 100644 --- a/source/core/slang-dictionary.h +++ b/source/core/slang-dictionary.h @@ -82,7 +82,7 @@ namespace Slang private: inline int GetProbeOffset(int /*probeId*/) const { - // quadratic probing + // linear probing return 1; } private: diff --git a/source/core/slang-list.h b/source/core/slang-list.h index 28180ce4f..5c1e3cbc7 100644 --- a/source/core/slang-list.h +++ b/source/core/slang-list.h @@ -14,72 +14,6 @@ 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> - class Initializer<T, 1> - { - public: - static void initialize(T* buffer, int size) - { - // It's pod so no initialization required - //for (int i = 0; i < size; i++) - // new (buffer + i) T; - } - }; - - 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] @@ -102,6 +36,7 @@ namespace Slang } template<typename... Args> List(const T& val, Args... args) + : m_buffer(nullptr), m_count(0), m_capacity(0) { _init(val, args...); } @@ -611,6 +546,10 @@ namespace Slang { return AllocateMethod<T, TAllocator>::allocateArray(count); } + static void _free(T* buffer, Index count) + { + return AllocateMethod<T, TAllocator>::deallocateArray(buffer, count); + } template<typename... Args> void _init(const T& val, Args... args) @@ -618,6 +557,8 @@ namespace Slang add(val); _init(args...); } + + void _init() {} }; template<typename T> diff --git a/source/core/slang-short-list.h b/source/core/slang-short-list.h new file mode 100644 index 000000000..82ad4fe1e --- /dev/null +++ b/source/core/slang-short-list.h @@ -0,0 +1,488 @@ +#ifndef SLANG_CORE_SHORT_LIST_H +#define SLANG_CORE_SHORT_LIST_H + +#include "../../slang.h" + +#include "slang-allocator.h" +#include "slang-math.h" +#include "slang-array-view.h" + +namespace Slang +{ + template<typename T, int shortListSize = 16, typename TAllocator = StandardAllocator> + class ShortList + { + private: + static const Index kInitialCount = 16; + typedef ShortList<T, shortListSize, TAllocator> ThisType; + public: + ShortList() + : m_buffer(nullptr), m_count(0), m_capacity(0) + { + } + template<typename... Args> + ShortList(const T& val, Args... args) + { + _init(val, args...); + } + ShortList(const ThisType& list) + : m_buffer(nullptr), m_count(0), m_capacity(0) + { + this->operator=(list); + } + ShortList(ThisType&& list) + : m_buffer(nullptr), m_count(0), m_capacity(0) + { + this->operator=(static_cast<ThisType&&>(list)); + } + ~ShortList() + { + _deallocateBuffer(); + } + template<int _otherShortListSize, typename TOtherAllocator> + ThisType& operator=(const ShortList<T, _otherShortListSize, TOtherAllocator>& list) + { + clearAndDeallocate(); + addRange(list); + return *this; + } + + ThisType& operator=(ThisType&& 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; + + for (Index i = 0; i < Math::Min((Index)shortListSize, m_count); i++) + m_shortBuffer[i] = _Move(list.m_shortBuffer[i]); + return *this; + } + + struct Iterator + { + ThisType* container = nullptr; + Index index = -1; + Iterator& operator++() + { + ++index; + return *this; + } + Iterator operator++(int) + { + Iterator rs = *this; + ++index; + return rs; + } + Iterator& operator--() + { + --index; + return *this; + } + Iterator operator--(int) + { + Iterator rs = *this; + --index; + return rs; + } + T* operator->() + { + SLANG_ASSERT(container); + return &(*container)[index]; + } + T& operator*() + { + SLANG_ASSERT(container); + return (*container)[index]; + } + bool operator==(Iterator other) + { + return container == other.container && index == other.index; + } + bool operator!=(Iterator other) + { + return index != other.index || container != other.container; + } + }; + + Iterator begin() + { + Iterator rs; + rs.container = this; + rs.index = 0; + return rs; + } + Iterator end() + { + Iterator rs; + rs.container = this; + rs.index = m_count; + return rs; + } + + const T& getFirst() const + { + SLANG_ASSERT(m_count > 0); + return m_shortBuffer[0]; + } + + T& getFirst() + { + SLANG_ASSERT(m_count > 0); + return m_shortBuffer[0]; + } + + const T& getLast() const + { + SLANG_ASSERT(m_count > 0); + if (m_count <= shortListSize) + return m_shortBuffer[m_count - 1]; + return m_buffer[m_count - shortListSize - 1]; + } + + T& getLast() + { + SLANG_ASSERT(m_count > 0); + if (m_count <= shortListSize) + return m_shortBuffer[m_count - 1]; + return m_buffer[m_count - shortListSize - 1]; + } + + void removeLast() + { + SLANG_ASSERT(m_count > 0); + m_count--; + } + + struct GetArrayViewResult + { + ArrayView<T> arrayView; + bool ownsStorage = false; + + GetArrayViewResult() = default; + GetArrayViewResult(const GetArrayViewResult&) = delete; + GetArrayViewResult(GetArrayViewResult&& other) + { + ownsStorage = other.ownsStorage; + arrayView = other.arrayView; + other.ownsStorage = false; + } + ~GetArrayViewResult() + { + if (ownsStorage) + { + ThisType::_free(arrayView.m_buffer, arrayView.m_count); + } + } + T* getBuffer() { return arrayView.getBuffer(); } + }; + inline GetArrayViewResult getArrayView() const + { + GetArrayViewResult result; + if (m_count > shortListSize) + { + result.arrayView.m_buffer = ThisType::_allocate(m_count); + result.arrayView.m_count = m_count; + for (Index i = 0; i < shortListSize; i++) + result.arrayView.m_buffer[i] = m_shortBuffer[i]; + for (Index i = shortListSize; i < m_count; i++) + result.arrayView.m_buffer[i] = m_buffer[i - shortListSize]; + result.ownsStorage = true; + } + else + { + result.arrayView.m_buffer = const_cast<T*>(&m_shortBuffer[0]); + result.arrayView.m_count = m_count; + } + return result; + } + + inline GetArrayViewResult getArrayView(Index start, Index count) const + { + SLANG_ASSERT(start >= 0 && count >= 0 && start + count <= m_count); + GetArrayViewResult result; + if (start < shortListSize && start + count > shortListSize) + { + result.ownsStorage = true; + result.arrayView.m_count = count; + result.arrayView.m_buffer = ThisType::_allocate(count); + for (Index i = start; i < shortListSize; i++) + result.arrayView.m_buffer[i - start] = m_shortBuffer[i]; + for (Index i = shortListSize; i < start + count; i++) + result.arrayView.m_buffer[i - start] = m_buffer[i - shortListSize]; + return result; + } + else if (start + count <= shortListSize) + { + result.ownsStorage = false; + result.arrayView.m_count = count; + result.arrayView.m_buffer = const_cast<T*>(m_shortBuffer) + start; + return result; + } + else + { + result.ownsStorage = false; + result.arrayView.m_count = count; + result.arrayView.m_buffer = m_buffer + start - shortListSize; + return result; + } + } + + void _maybeReserveForAdd() + { + if (m_capacity <= m_count - shortListSize) + { + Index newBufferSize = kInitialCount; + if (m_capacity) + newBufferSize = (m_capacity << 1); + + reserveOverflowBuffer(newBufferSize); + } + } + + void add(T&& obj) + { + if (m_count < shortListSize) + { + m_shortBuffer[m_count] = static_cast<T&&>(obj); + m_count++; + return; + } + _maybeReserveForAdd(); + m_buffer[m_count - shortListSize] = static_cast<T&&>(obj); + m_count++; + } + + void add(const T& obj) + { + if (m_count < shortListSize) + { + m_shortBuffer[m_count] = obj; + m_count++; + return; + } + _maybeReserveForAdd(); + m_buffer[m_count - shortListSize] = obj; + m_count++; + } + + Index getCount() const { return m_count; } + + void addRange(const T* vals, Index n) + { + for (Index i = 0; i < n; i++) + add(vals[i]); + } + + void addRange(ArrayView<T> list) { addRange(list.m_buffer, list.m_count); } + + template<int _otherShortListSize, typename TOtherAllocator> + void addRange(const ShortList<T, _otherShortListSize, TOtherAllocator>& list) + { + for (Index i = 0; i < list.getCount(); i++) + add(list[i]); + } + + void fastRemove(const T& val) + { + Index idx = indexOf(val); + if (idx >= 0) + { + fastRemoveAt(idx); + } + } + + void fastRemoveAt(Index idx) + { + SLANG_ASSERT(idx >= 0 && idx < m_count); + + if (idx != m_count - 1) + { + (*this)[idx] = _Move(getLast()); + } + m_count--; + } + + void clear() { m_count = 0; } + + void clearAndDeallocate() + { + _deallocateBuffer(); + m_count = m_capacity = 0; + } + + void reserveOverflowBuffer(Index size) + { + if (size > m_capacity) + { + T* newBuffer = _allocate(size); + if (m_capacity) + { + for (Index i = 0; i < m_count - shortListSize; i++) + newBuffer[i] = static_cast<T&&>(m_buffer[i]); + + // Default-initialize the remaining elements + for (Index i = m_count - shortListSize; i < size; i++) + { + new(newBuffer + i) T(); + } + _deallocateBuffer(); + } + m_buffer = newBuffer; + m_capacity = size; + } + } + + void setCount(Index count) + { + if (count > shortListSize) + reserveOverflowBuffer(count - shortListSize); + m_count = count; + } + + void unsafeShrinkToCount(Index count) { m_count = count; } + + void compress() + { + if (m_capacity > m_count - shortListSize && m_count > shortListSize) + { + T* newBuffer = nullptr; + if (m_count > shortListSize) + { + newBuffer = _allocate(m_count - shortListSize); + for (Index i = shortListSize; i < m_count; i++) + newBuffer[i - shortListSize] = static_cast<T&&>(m_buffer[i - shortListSize]); + } + _deallocateBuffer(); + m_buffer = newBuffer; + m_capacity = m_count - shortListSize; + } + } + + SLANG_FORCE_INLINE const T& operator [](Index idx) const + { + SLANG_ASSERT(idx >= 0 && idx < m_count); + return (idx < shortListSize) ? + m_shortBuffer[idx] : m_buffer[idx - shortListSize]; + } + + SLANG_FORCE_INLINE T& operator [](Index idx) + { + SLANG_ASSERT(idx >= 0 && idx < m_count); + return (idx < shortListSize) ? + m_shortBuffer[idx] : m_buffer[idx - shortListSize]; + } + + template<typename Func> + Index findFirstIndex(const Func& predicate) const + { + for (Index i = 0; i < Math::Min(m_count, (Index)shortListSize); i++) + { + if (predicate(m_shortBuffer[i])) + return i; + } + for (Index i = shortListSize; i < m_count; i++) + { + if (predicate(m_buffer[i - shortListSize])) + return i; + } + return -1; + } + + template<typename T2> + Index indexOf(const T2& val) const + { + for (Index i = 0; i < Math::Min(m_count, (Index)shortListSize); i++) + { + if (m_shortBuffer[i] == val) + return i; + } + for (Index i = shortListSize; i < m_count; i++) + { + if (m_buffer[i - shortListSize] == val) + return i; + } + return -1; + } + + template<typename Func> + Index findLastIndex(const Func& predicate) const + { + for (Index i = m_count - 1; i >= shortListSize; i--) + { + if (predicate(m_buffer[i - shortListSize])) + return i; + } + for (Index i = Math::Min((Index)shortListSize, m_count) - 1; i >= 0; i--) + { + if (predicate(m_shortBuffer[i])) + return i; + } + return -1; + } + + template<typename T2> + Index lastIndexOf(const T2& val) const + { + for (Index i = m_count - 1; i >= shortListSize; i--) + { + if (m_buffer[i - shortListSize] == val) + return i; + } + for (Index i = Math::Min((Index)shortListSize, m_count) - 1; i >= 0; i--) + { + if (m_shortBuffer[i] == val) + return i; + } + return -1; + } + + bool contains(const T& val) const { return indexOf(val) != Index(-1); } + + template <typename IterateFunc> + void forEach(IterateFunc f) const + { + for (Index i = 0; i < m_count; i++) + f(m_buffer[i]); + } + + private: + T* m_buffer = nullptr; ///< A new T[N] allocated buffer. NOTE! All elements up to capacity are in some valid form for T. + Index m_capacity = 0; ///< The total capacity of elements in m_buffer + Index m_count = 0; ///< The amount of elements + T m_shortBuffer[shortListSize]; + + void _deallocateBuffer() + { + if (m_buffer) + { + AllocateMethod<T, TAllocator>::deallocateArray(m_buffer, m_capacity); + m_buffer = nullptr; + } + } + static inline T* _allocate(Index count) + { + return AllocateMethod<T, TAllocator>::allocateArray(count); + } + static inline void _free(T* ptr, Index count) + { + return AllocateMethod<T, TAllocator>::deallocateArray(ptr, count); + } + + template<typename... Args> + void _init(const T& val, Args... args) + { + add(val); + _init(args...); + } + + void _init() {} + }; +} + +#endif diff --git a/tools/slang-test/slang-test.vcxproj b/tools/slang-test/slang-test.vcxproj index bf79af2f1..d3e049222 100644 --- a/tools/slang-test/slang-test.vcxproj +++ b/tools/slang-test/slang-test.vcxproj @@ -182,6 +182,7 @@ <ClCompile Include="unit-test-memory-arena.cpp" /> <ClCompile Include="unit-test-path.cpp" /> <ClCompile Include="unit-test-riff.cpp" /> + <ClCompile Include="unit-test-short-list.cpp" /> <ClCompile Include="unit-test-string.cpp" /> </ItemGroup> <ItemGroup> diff --git a/tools/slang-test/slang-test.vcxproj.filters b/tools/slang-test/slang-test.vcxproj.filters index 824d92d26..70125e44d 100644 --- a/tools/slang-test/slang-test.vcxproj.filters +++ b/tools/slang-test/slang-test.vcxproj.filters @@ -68,5 +68,8 @@ <ClCompile Include="unit-test-string.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="unit-test-short-list.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> </Project>
\ No newline at end of file diff --git a/tools/slang-test/unit-test-short-list.cpp b/tools/slang-test/unit-test-short-list.cpp new file mode 100644 index 000000000..0559419bb --- /dev/null +++ b/tools/slang-test/unit-test-short-list.cpp @@ -0,0 +1,78 @@ +// unit-test-path.cpp + +#include "test-context.h" + +using namespace Slang; + +template<typename T> +static bool _checkArrayView(ArrayView<T> v0, ArrayView<T> v1) +{ + if (v0.getCount() != v1.getCount()) + return false; + for (Index i = 0; i < v0.getCount(); i++) + if (v0[i] != v1[i]) + return false; + return true; +} + +static void shortListUnitTest() +{ + { + ShortList<String, 4> shortList = { "a", "b", "c" }; + shortList.add("d"); + auto arrayView = shortList.getArrayView(); + SLANG_CHECK(arrayView.ownsStorage == false); + SLANG_CHECK(_checkArrayView(arrayView.arrayView, + List<String>{"a", "b", "c", "d"}.getArrayView())); + shortList.add("e"); + auto arrayView2 = shortList.getArrayView(); + SLANG_CHECK(arrayView2.ownsStorage == true); + SLANG_CHECK(_checkArrayView(arrayView2.arrayView, + List<String>{"a", "b", "c", "d", "e"}.getArrayView())); + auto arrayView3 = shortList.getArrayView(0, 2); + SLANG_CHECK(arrayView3.ownsStorage == false); + SLANG_CHECK(_checkArrayView(arrayView3.arrayView, + List<String>{"a", "b"}.getArrayView())); + auto arrayView4 = shortList.getArrayView(4, 1); + SLANG_CHECK(arrayView4.ownsStorage == false); + SLANG_CHECK(_checkArrayView(arrayView4.arrayView, + List<String>{"e"}.getArrayView())); + auto arrayView5 = shortList.getArrayView(2, 3); + SLANG_CHECK(arrayView5.ownsStorage == true); + SLANG_CHECK(_checkArrayView(arrayView5.arrayView, + List<String>{"c", "d", "e"}.getArrayView())); + + ShortList<String, 1> copy2; + ShortList<String, 2> copy1; + copy1 = shortList; + for (auto item : copy1) + copy2.add(item); + SLANG_CHECK(_checkArrayView(copy2.getArrayView().arrayView, + List<String>{"a", "b", "c", "d", "e"}.getArrayView())); + + SLANG_CHECK(copy2.indexOf("a") == 0); + SLANG_CHECK(copy2.indexOf("e") == 4); + + SLANG_CHECK(copy2.lastIndexOf("a") == 0); + SLANG_CHECK(copy2.lastIndexOf("e") == 4); + + copy2.compress(); + copy2.add("f"); + copy2.fastRemove("c"); + copy2.compress(); + SLANG_CHECK(_checkArrayView(copy2.getArrayView().arrayView, + List<String>{"a", "b", "f", "d", "e"}.getArrayView())); + + shortList.removeLast(); + shortList.removeLast(); + shortList.compress(); + SLANG_CHECK(_checkArrayView(shortList.getArrayView().arrayView, + List<String>{"a", "b", "c"}.getArrayView())); + shortList.add("d"); + shortList.add("e"); + SLANG_CHECK(_checkArrayView(shortList.getArrayView().arrayView, + List<String>{"a", "b", "c", "d", "e"}.getArrayView())); + } +} + +SLANG_UNIT_TEST("ShortList", shortListUnitTest); |
