├── .gitignore ├── LICENSE ├── README.md ├── ntl.sln ├── ntl ├── algorithm ├── allocator ├── exception ├── iterator ├── memory ├── ntl ├── ntl.vcxproj ├── ntl.vcxproj.filters ├── ntl.vcxproj.user ├── system ├── type_traits ├── utility └── vector └── ntl_test ├── algorithm.cpp ├── ntl_test.vcxproj ├── ntl_test.vcxproj.filters ├── ntl_test.vcxproj.user ├── pch.cpp ├── pch.h └── vector.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | /.vs 2 | 3 | Win32 4 | x64 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Richard Dzenis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Abandoned 2 | 3 | Abandoned in favor of directly using [STL](https://github.com/microsoft/STL) in WDM drivers. 4 | 5 | See [wdmcpp](https://github.com/RIscRIpt/wdmcpp) Visual Studio project example. 6 | 7 | # ntl 8 | 9 | **ntl** is very tiny and selective implementation of C++ Standard Library (which is sometimes mistakenly called STL) for Windows NT kernel mode drivers. 10 | 11 | The name comes from combining **NT** and S**TL**. 12 | 13 | ## Tests 14 | 15 | Tests are done in user-mode using Microsoft's VisualStudio C++ Unit Test Framework. 16 | 17 | ## Implemented functionality 18 | 19 | ### [<algorithm>](https://en.cppreference.com/w/cpp/header/algorithm) 20 | 21 | #### Comparison operations 22 | 23 | - `equal`; 24 | - `lexicographical_compare`; 25 | 26 | ### [<type_traits>](https://en.cppreference.com/w/cpp/header/type_traits) 27 | 28 | #### Classes 29 | 30 | ##### Helper classes 31 | 32 | - `integral_constant`; 33 | - `bool_constant`; 34 | - `true_type`; 35 | - `false_type`; 36 | 37 | ##### Primary type categories 38 | 39 | - `is_class` (as `is_union` is not implemented, it doesn't detect unions); 40 | - `is_pointer`; 41 | - `is_lvalue_reference`(`_v`); 42 | 43 | ##### Const-volatility specifiers 44 | 45 | - `remove_const`(`_t`); 46 | - `remove_volatile`(`_t`); 47 | - `remove_cv`(`_t`); 48 | 49 | ##### Type relationships 50 | 51 | - `is_same`(`_v`); 52 | - `is_base_of`(`_v`); 53 | 54 | ##### References 55 | 56 | - `remove_reference`(`_t`); 57 | - `add_lvalue_reference`(`_t`); 58 | - `add_rvalue_reference`(`_t`); 59 | 60 | ##### Miscellaneous transformations 61 | 62 | - `enable_if`(`_t`); 63 | - `conditional`(`_t`); 64 | - `void_t`; 65 | 66 | ### [<utility>](https://en.cppreference.com/w/cpp/header/utility) 67 | 68 | #### Functions 69 | 70 | - `swap`; 71 | - `forward`; 72 | - `move`; 73 | 74 | ### [<vector>](https://en.cppreference.com/w/cpp/container/vector) 75 | 76 | #### Member functions 77 | 78 | - `(constructor)`; 79 | - `(destructor)`; 80 | - `operator=`; 81 | - `assign`; 82 | 83 | ##### Element access 84 | 85 | - `at`; 86 | - `operator[]`; 87 | - `front`; 88 | - `back`; 89 | - `data`; 90 | 91 | ##### Iterators 92 | 93 | - `begin` / `cbegin`; 94 | - `end` / `cend`; 95 | - `rbegin` / `crbegin`; 96 | - `rend` / `crend`; 97 | 98 | ##### Capacity 99 | 100 | - `empty`; 101 | - `size`; 102 | - `reserve`; 103 | - `capacity`; 104 | - `shrink_to_fit`; 105 | 106 | ##### Modifiers 107 | 108 | - `clear`; 109 | - `insert`; 110 | - `emplace`; 111 | - `erase`; 112 | - `push_back`; 113 | - `emplace_back`; 114 | - `pop_back`; 115 | - `resize`; 116 | - `swap`; 117 | 118 | #### Non-member functions 119 | 120 | - `operator==`; 121 | - `operator!=`; 122 | - `operator<`; 123 | - `operator<=`; 124 | - `operator>`; 125 | - `operator>=`; 126 | -------------------------------------------------------------------------------- /ntl.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29025.244 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ntl", "ntl\ntl.vcxproj", "{7AEB2784-2AB5-41D2-9846-689F139C813A}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7F07A320-68E3-45F8-9DA1-AB27F4483BEC}" 9 | ProjectSection(SolutionItems) = preProject 10 | .gitignore = .gitignore 11 | EndProjectSection 12 | EndProject 13 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ntl_test", "ntl_test\ntl_test.vcxproj", "{31883F18-1B08-4889-B0AB-B7DB1863F0D1}" 14 | ProjectSection(ProjectDependencies) = postProject 15 | {7AEB2784-2AB5-41D2-9846-689F139C813A} = {7AEB2784-2AB5-41D2-9846-689F139C813A} 16 | EndProjectSection 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|x64 = Debug|x64 21 | Debug|x86 = Debug|x86 22 | DebugInUserMode|x64 = DebugInUserMode|x64 23 | DebugInUserMode|x86 = DebugInUserMode|x86 24 | Release|x64 = Release|x64 25 | Release|x86 = Release|x86 26 | EndGlobalSection 27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 28 | {7AEB2784-2AB5-41D2-9846-689F139C813A}.Debug|x64.ActiveCfg = Debug|x64 29 | {7AEB2784-2AB5-41D2-9846-689F139C813A}.Debug|x64.Build.0 = Debug|x64 30 | {7AEB2784-2AB5-41D2-9846-689F139C813A}.Debug|x86.ActiveCfg = Debug|Win32 31 | {7AEB2784-2AB5-41D2-9846-689F139C813A}.Debug|x86.Build.0 = Debug|Win32 32 | {7AEB2784-2AB5-41D2-9846-689F139C813A}.DebugInUserMode|x64.ActiveCfg = DebugInUserMode|x64 33 | {7AEB2784-2AB5-41D2-9846-689F139C813A}.DebugInUserMode|x64.Build.0 = DebugInUserMode|x64 34 | {7AEB2784-2AB5-41D2-9846-689F139C813A}.DebugInUserMode|x86.ActiveCfg = Debug|Win32 35 | {7AEB2784-2AB5-41D2-9846-689F139C813A}.DebugInUserMode|x86.Build.0 = Debug|Win32 36 | {7AEB2784-2AB5-41D2-9846-689F139C813A}.Release|x64.ActiveCfg = Release|x64 37 | {7AEB2784-2AB5-41D2-9846-689F139C813A}.Release|x64.Build.0 = Release|x64 38 | {7AEB2784-2AB5-41D2-9846-689F139C813A}.Release|x86.ActiveCfg = Release|Win32 39 | {7AEB2784-2AB5-41D2-9846-689F139C813A}.Release|x86.Build.0 = Release|Win32 40 | {31883F18-1B08-4889-B0AB-B7DB1863F0D1}.Debug|x64.ActiveCfg = Debug|x64 41 | {31883F18-1B08-4889-B0AB-B7DB1863F0D1}.Debug|x86.ActiveCfg = Debug|Win32 42 | {31883F18-1B08-4889-B0AB-B7DB1863F0D1}.DebugInUserMode|x64.ActiveCfg = Debug|x64 43 | {31883F18-1B08-4889-B0AB-B7DB1863F0D1}.DebugInUserMode|x64.Build.0 = Debug|x64 44 | {31883F18-1B08-4889-B0AB-B7DB1863F0D1}.DebugInUserMode|x86.ActiveCfg = Debug|Win32 45 | {31883F18-1B08-4889-B0AB-B7DB1863F0D1}.DebugInUserMode|x86.Build.0 = Debug|Win32 46 | {31883F18-1B08-4889-B0AB-B7DB1863F0D1}.Release|x64.ActiveCfg = Release|x64 47 | {31883F18-1B08-4889-B0AB-B7DB1863F0D1}.Release|x86.ActiveCfg = Release|Win32 48 | EndGlobalSection 49 | GlobalSection(SolutionProperties) = preSolution 50 | HideSolutionNode = FALSE 51 | EndGlobalSection 52 | GlobalSection(ExtensibilityGlobals) = postSolution 53 | SolutionGuid = {20A80C83-01B1-44B6-8884-8FBE6E8549BF} 54 | EndGlobalSection 55 | EndGlobal 56 | -------------------------------------------------------------------------------- /ntl/algorithm: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "iterator" 4 | 5 | namespace ntl { 6 | 7 | #pragma region lower_bound 8 | 9 | template 10 | I lower_bound(I first, I last, const T& value) { 11 | I it; 12 | typename iterator_traits::difference_type count, step; 13 | count = distance(first, last); 14 | while (count > 0) { 15 | it = first; 16 | step = count / 2; 17 | advance(it, step); 18 | if (*it < value) { 19 | first = ++it; 20 | count -= step + 1; 21 | } 22 | else { 23 | count = step; 24 | } 25 | } 26 | return first; 27 | } 28 | 29 | template 30 | I lower_bound(I first, I last, const T& value, BinaryPredicate p) { 31 | I it; 32 | typename iterator_traits::difference_type count, step; 33 | count = distance(first, last); 34 | while (count > 0) { 35 | it = first; 36 | step = count / 2; 37 | advance(it, step); 38 | if (p(*it, value)) { 39 | first = ++it; 40 | count -= step + 1; 41 | } 42 | else { 43 | count = step; 44 | } 45 | } 46 | return first; 47 | } 48 | 49 | #pragma endregion 50 | #pragma region upper_bound 51 | 52 | template 53 | I upper_bound(I first, I last, const T& value) { 54 | I it; 55 | typename iterator_traits::difference_type count, step; 56 | count = distance(first, last); 57 | while (count > 0) { 58 | it = first; 59 | step = count / 2; 60 | advance(it, step); 61 | if (!(value < *it)) { 62 | first = ++it; 63 | count -= step + 1; 64 | } 65 | else { 66 | count = step; 67 | } 68 | } 69 | return first; 70 | } 71 | 72 | template 73 | I upper_bound(I first, I last, const T& value, BinaryPredicate p) { 74 | I it; 75 | typename iterator_traits::difference_type count, step; 76 | count = distance(first, last); 77 | while (count > 0) { 78 | it = first; 79 | step = count / 2; 80 | advance(it, step); 81 | if (!p(value, *it)) { 82 | first = ++it; 83 | count -= step + 1; 84 | } 85 | else { 86 | count = step; 87 | } 88 | } 89 | return first; 90 | } 91 | 92 | #pragma endregion 93 | #pragma region equal 94 | 95 | template 96 | constexpr bool equal(II1 first1, II1 last1, II2 first2) noexcept { 97 | for (auto i = first1, j = first2; i != last1; ++i, ++j) { 98 | if (*i != *j) { 99 | return false; 100 | } 101 | } 102 | return true; 103 | } 104 | 105 | template 106 | constexpr bool equal(II1 first1, II1 last1, II2 first2, BinaryPredicate p) noexcept { 107 | for (auto i = first1, j = first2; i != last1; ++i, ++j) { 108 | if (!p(*i, *j)) { 109 | return false; 110 | } 111 | } 112 | return true; 113 | } 114 | 115 | template 116 | constexpr bool equal(II1 first1, II1 last1, II2 first2, II2 last2) noexcept { 117 | for (auto i = first1, j = first2; i != last1 && j != last2; ++i, ++j) { 118 | if (*i != *j) { 119 | return false; 120 | } 121 | } 122 | return true; 123 | } 124 | 125 | template 126 | constexpr bool equal(II1 first1, II1 last1, II2 first2, II2 last2, BinaryPredicate p) noexcept { 127 | for (auto i = first1, j = first2; i != last1 && j != last2; ++i, ++j) { 128 | if (p(*i, *j)) { 129 | return false; 130 | } 131 | } 132 | return true; 133 | } 134 | 135 | #pragma endregion 136 | #pragma region lexicographical_compare 137 | 138 | template 139 | constexpr bool lexicographical_compare(II1 first1, II1 last1, II2 first2, II2 last2) noexcept { 140 | for (; first1 != last1 && first2 != last2; ++first1, ++first2) { 141 | if (*first1 < *first2) 142 | return true; 143 | if (*first2 < *first1) 144 | return false; 145 | } 146 | return first1 == last1 && first2 != last2; 147 | } 148 | 149 | template 150 | constexpr bool lexicographical_compare(II1 first1, II1 last1, II2 first2, II2 last2, Compare compare) noexcept { 151 | for (; first1 != last1 && first2 != last2; ++first1, ++first2) { 152 | if (compare(*first1, *first2)) 153 | return true; 154 | if (compare(*first2, *first1)) 155 | return false; 156 | } 157 | return first1 == last1 && first2 != last2; 158 | } 159 | 160 | #pragma endregion 161 | 162 | } 163 | -------------------------------------------------------------------------------- /ntl/allocator: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "system" 4 | 5 | #ifdef NTL_USER_MODE 6 | 7 | // Copy-paste from 8 | typedef enum _POOL_TYPE { 9 | NonPagedPool, 10 | NonPagedPoolExecute = NonPagedPool, 11 | PagedPool, 12 | NonPagedPoolMustSucceed = NonPagedPool + 2, 13 | DontUseThisType, 14 | NonPagedPoolCacheAligned = NonPagedPool + 4, 15 | PagedPoolCacheAligned, 16 | NonPagedPoolCacheAlignedMustS = NonPagedPool + 6, 17 | MaxPoolType, 18 | 19 | NonPagedPoolBase = 0, 20 | NonPagedPoolBaseMustSucceed = NonPagedPoolBase + 2, 21 | NonPagedPoolBaseCacheAligned = NonPagedPoolBase + 4, 22 | NonPagedPoolBaseCacheAlignedMustS = NonPagedPoolBase + 6, 23 | 24 | NonPagedPoolSession = 32, 25 | PagedPoolSession = NonPagedPoolSession + 1, 26 | NonPagedPoolMustSucceedSession = PagedPoolSession + 1, 27 | DontUseThisTypeSession = NonPagedPoolMustSucceedSession + 1, 28 | NonPagedPoolCacheAlignedSession = DontUseThisTypeSession + 1, 29 | PagedPoolCacheAlignedSession = NonPagedPoolCacheAlignedSession + 1, 30 | NonPagedPoolCacheAlignedMustSSession = PagedPoolCacheAlignedSession + 1, 31 | 32 | NonPagedPoolNx = 512, 33 | NonPagedPoolNxCacheAligned = NonPagedPoolNx + 4, 34 | NonPagedPoolSessionNx = NonPagedPoolNx + 32, 35 | } POOL_TYPE; 36 | 37 | #endif 38 | 39 | namespace ntl { 40 | 41 | template 42 | class allocator final { 43 | public: 44 | using value_type = T; 45 | using size_type = ntl::size_t; 46 | using difference_type = ntl::ptrdiff_t; 47 | 48 | constexpr explicit allocator(POOL_TYPE pool_type = NonPagedPoolNx, ULONG tag = NTL_TAG, bool zero_initialize = true) noexcept 49 | : pool_type_(pool_type) 50 | , tag_(tag) 51 | , zero_initialize_(zero_initialize) 52 | {} 53 | 54 | constexpr allocator(allocator const &other) noexcept 55 | : pool_type_(other.pool_type_) 56 | , tag_(other.tag_) 57 | {} 58 | 59 | template 60 | constexpr allocator(allocator const &other) noexcept 61 | : pool_type_(other.pool_type_) 62 | , tag_(other.tag_) 63 | {} 64 | 65 | ~allocator() noexcept {} 66 | 67 | T* allocate(size_type n) noexcept { 68 | #ifndef NTL_USER_MODE 69 | T *result = static_cast(ExAllocatePoolWithTag(pool_type_, sizeof(T) * n, tag_)); 70 | if (!result) { 71 | ExRaiseStatus(STATUS_FATAL_MEMORY_EXHAUSTION); 72 | } 73 | if (zero_initialize_) { 74 | RtlZeroMemory(result, sizeof(T) * n); 75 | } 76 | #else 77 | T *result = static_cast(calloc(n, sizeof(T))); 78 | if (!result) { 79 | SetLastError(ERROR_OUTOFMEMORY); 80 | } 81 | #endif 82 | return result; 83 | } 84 | 85 | void deallocate(T *p, size_type n) noexcept { 86 | #ifndef NTL_USER_MODE 87 | ExFreePoolWithTag(p, tag_); 88 | #else 89 | free(p); 90 | #endif 91 | } 92 | 93 | private: 94 | POOL_TYPE pool_type_; 95 | ULONG tag_; 96 | bool zero_initialize_; 97 | }; 98 | 99 | template 100 | bool operator==(allocator const &lhs, allocator const &rhs) noexcept { 101 | return false; 102 | } 103 | 104 | template 105 | bool operator==(allocator const &lhs, allocator const &rhs) noexcept { 106 | return lhs.pool_type_ == rhs.pool_type_ 107 | && lhs.tag_ == rhs.tag_ 108 | && lhs.zero_initialize_ == rhs.zero_initialize_; 109 | } 110 | 111 | template 112 | bool operator!=(allocator const &lhs, allocator const &rhs) noexcept { 113 | return true; 114 | } 115 | 116 | template 117 | bool operator!=(allocator const &lhs, allocator const &rhs) noexcept { 118 | return lhs.pool_type_ != rhs.pool_type_ 119 | || lhs.tag_ != rhs.tag_ 120 | || lhs.zero_initialize_ != rhs.zero_initialize_; 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ntl/exception: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifdef NTL_USER_MODE 3 | 4 | #include "system" 5 | 6 | namespace ntl { 7 | 8 | class exception { 9 | }; 10 | 11 | class logic_error : public exception { 12 | }; 13 | 14 | class out_of_range : public logic_error { 15 | public: 16 | out_of_range(ssize_t lower_bound, ssize_t upper_bound, ssize_t value) noexcept 17 | : lower_bound(lower_bound) 18 | , upper_bound(upper_bound) 19 | , value(value) 20 | {} 21 | 22 | ssize_t const lower_bound; 23 | ssize_t const upper_bound; 24 | ssize_t const value; 25 | }; 26 | 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /ntl/iterator: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "system" 4 | #include "memory" 5 | #include "type_traits" 6 | 7 | namespace ntl { 8 | 9 | #pragma region iterator_tag 10 | 11 | struct input_iterator_tag {}; 12 | struct output_iterator_tag {}; 13 | struct forward_iterator_tag : public input_iterator_tag {}; 14 | struct bidirectional_iterator_tag : public forward_iterator_tag {}; 15 | struct random_access_iterator_tag : public bidirectional_iterator_tag {}; 16 | struct contiguous_iterator_tag : public random_access_iterator_tag {}; 17 | 18 | #pragma endregion 19 | #pragma region iterator_traits 20 | 21 | template 22 | struct iterator_traits { 23 | using difference_type = typename T::difference_type; 24 | using value_type = typename T::value_type; 25 | using pointer = typename T::pointer; 26 | using reference = typename T::reference; 27 | using iterator_category = typename T::iterator_category; 28 | }; 29 | 30 | template 31 | struct iterator_traits { 32 | using difference_type = ptrdiff_t; 33 | using value_type = T; 34 | using pointer = T*; 35 | using reference = T&; 36 | using iterator_category = random_access_iterator_tag; 37 | }; 38 | 39 | template 40 | struct is_iterator { 41 | static constexpr bool value = false; 42 | }; 43 | 44 | template 45 | struct is_iterator::value_type, void>::value>::type> { 46 | static constexpr bool value = true; 47 | }; 48 | 49 | template 50 | inline constexpr bool is_iterator_v = is_iterator::value; 51 | 52 | template 53 | using enable_if_is_iterator_t = enable_if_t, T>; 54 | 55 | #pragma endregion 56 | #pragma region iterator 57 | 58 | template< 59 | typename Category, 60 | typename T, 61 | typename Distance = ntl::ptrdiff_t, 62 | typename Pointer = T*, 63 | typename Reference = T& 64 | > 65 | class iterator { 66 | public: 67 | using value_type = T; 68 | using difference_type = Distance; 69 | using pointer = Pointer; 70 | using reference = Reference; 71 | using iterator_category = Category; 72 | 73 | iterator(pointer p) noexcept 74 | : p_(p) 75 | {} 76 | 77 | constexpr operator pointer() const noexcept { 78 | return p_; 79 | } 80 | 81 | constexpr bool operator==(iterator const &rhs) noexcept { 82 | return p_ == rhs.p_; 83 | } 84 | 85 | constexpr bool operator!=(iterator const &rhs) noexcept { 86 | return p_ != rhs.p_; 87 | } 88 | 89 | constexpr bool operator<(iterator const &rhs) noexcept { 90 | return p_ < rhs.p_; 91 | } 92 | 93 | constexpr bool operator<=(iterator const &rhs) noexcept { 94 | return p_ <= rhs.p_; 95 | } 96 | 97 | constexpr bool operator>(iterator const &rhs) noexcept { 98 | return p_ > rhs.p_; 99 | } 100 | 101 | constexpr bool operator>=(iterator const &rhs) noexcept { 102 | return p_ >= rhs.p_; 103 | } 104 | 105 | protected: 106 | pointer p_; 107 | }; 108 | 109 | #pragma endregion 110 | #pragma region random_access_iterator 111 | 112 | template< 113 | typename T, 114 | typename Distance = ntl::ptrdiff_t, 115 | typename Pointer = T*, 116 | typename Reference = T& 117 | > 118 | class random_access_iterator 119 | : public iterator< 120 | random_access_iterator_tag, 121 | T, 122 | Distance, 123 | Pointer, 124 | Reference 125 | > 126 | { 127 | public: 128 | constexpr random_access_iterator() noexcept 129 | : iterator(nullptr) 130 | {} 131 | 132 | constexpr random_access_iterator(Pointer x) noexcept 133 | : iterator(x) 134 | {} 135 | 136 | constexpr random_access_iterator(random_access_iterator const &other) noexcept 137 | : iterator(other.p_) 138 | {} 139 | 140 | constexpr random_access_iterator& operator=(random_access_iterator const &other) noexcept { 141 | p_ = other.p_; 142 | return *this; 143 | } 144 | 145 | constexpr operator random_access_iterator() const noexcept { 146 | return p_; 147 | } 148 | 149 | constexpr T& operator*() const noexcept { 150 | return *p_; 151 | } 152 | 153 | constexpr Pointer operator->() const noexcept { 154 | return p_; 155 | } 156 | 157 | constexpr T& operator[](Distance n) const noexcept { 158 | return p_[n]; 159 | } 160 | 161 | constexpr random_access_iterator& operator++() noexcept { 162 | ++p_; 163 | return *this; 164 | } 165 | 166 | constexpr random_access_iterator& operator--() noexcept { 167 | --p_; 168 | return *this; 169 | } 170 | 171 | constexpr random_access_iterator operator++(int) noexcept { 172 | auto t = p_; 173 | ++p_; 174 | return t; 175 | } 176 | 177 | constexpr random_access_iterator operator--(int) noexcept { 178 | auto t = p_; 179 | --p_; 180 | return t; 181 | } 182 | 183 | constexpr random_access_iterator operator+(Distance n) const noexcept { 184 | return p_ + n; 185 | } 186 | 187 | constexpr random_access_iterator operator-(Distance n) const noexcept { 188 | return p_ - n; 189 | } 190 | 191 | constexpr random_access_iterator& operator+=(Distance n) noexcept { 192 | p_ += n; 193 | return *this; 194 | } 195 | 196 | constexpr random_access_iterator& operator-=(Distance n) noexcept { 197 | p_ -= n; 198 | return *this; 199 | } 200 | }; 201 | 202 | #pragma endregion 203 | #pragma region reverse_iterator 204 | 205 | template 206 | class reverse_iterator { 207 | public: 208 | using iterator_type = I; 209 | using iterator_category = typename ntl::iterator_traits::iterator_category; 210 | using value_type = typename ntl::iterator_traits::value_type; 211 | using difference_type = typename ntl::iterator_traits::difference_type; 212 | using pointer = typename ntl::iterator_traits::pointer; 213 | using reference = typename ntl::iterator_traits::reference; 214 | 215 | constexpr reverse_iterator() noexcept {} 216 | constexpr reverse_iterator(iterator_type x) noexcept { 217 | base_ = x; 218 | } 219 | 220 | constexpr reverse_iterator(reverse_iterator const &other) noexcept 221 | : base_(other.base_) 222 | {} 223 | 224 | constexpr reverse_iterator& operator=(reverse_iterator const &other) noexcept { 225 | base_ = other.base_; 226 | } 227 | 228 | constexpr iterator_type base() const noexcept { 229 | return base_; 230 | } 231 | 232 | constexpr reference operator*() const noexcept { 233 | return *(base_ - 1); 234 | } 235 | 236 | constexpr pointer operator->() const noexcept { 237 | return ntl::addressof(operator*()); 238 | } 239 | 240 | constexpr value_type& operator[](difference_type n) const noexcept { 241 | return base_[-n - 1]; 242 | } 243 | 244 | 245 | constexpr reverse_iterator& operator++() noexcept { 246 | --base_; 247 | return *this; 248 | } 249 | 250 | constexpr reverse_iterator& operator--() noexcept { 251 | ++base_; 252 | return *this; 253 | } 254 | 255 | constexpr reverse_iterator operator++(int) noexcept { 256 | auto t = base_; 257 | --base_; 258 | return t; 259 | } 260 | 261 | constexpr reverse_iterator operator--(int) noexcept { 262 | auto t = base_; 263 | ++base_; 264 | return t; 265 | } 266 | 267 | constexpr reverse_iterator operator+(difference_type n) const noexcept { 268 | return base() - n; 269 | } 270 | 271 | constexpr reverse_iterator operator-(difference_type n) const noexcept { 272 | return base() + n; 273 | } 274 | 275 | constexpr reverse_iterator& operator+=(difference_type n) noexcept { 276 | base_ -= n; 277 | return *this; 278 | } 279 | 280 | constexpr reverse_iterator& operator-=(difference_type n) noexcept { 281 | base_ += n; 282 | return *this; 283 | } 284 | 285 | protected: 286 | iterator_type base_; 287 | }; 288 | 289 | 290 | template 291 | constexpr bool operator==(reverse_iterator const &lhs, reverse_iterator const &rhs) noexcept { 292 | return lhs.base() == rhs.base(); 293 | } 294 | 295 | template 296 | constexpr bool operator!=(reverse_iterator const &lhs, reverse_iterator const &rhs) noexcept { 297 | return lhs.base() != rhs.base(); 298 | } 299 | 300 | template 301 | constexpr bool operator<(reverse_iterator const &lhs, reverse_iterator const &rhs) noexcept { 302 | return lhs.base() < rhs.base(); 303 | } 304 | 305 | template 306 | constexpr bool operator<=(reverse_iterator const &lhs, reverse_iterator const &rhs) noexcept { 307 | return lhs.base() <= rhs.base(); 308 | } 309 | 310 | template 311 | constexpr bool operator>(reverse_iterator const &lhs, reverse_iterator const &rhs) noexcept { 312 | return lhs.base() > rhs.base(); 313 | } 314 | 315 | template 316 | constexpr bool operator>=(reverse_iterator const &lhs, reverse_iterator const &rhs) noexcept { 317 | return lhs.base() >= rhs.base(); 318 | } 319 | 320 | #pragma endregion 321 | #pragma region operations 322 | 323 | namespace detail { 324 | template 325 | constexpr void do_advance(I& it, typename iterator_traits::difference_type n, input_iterator_tag) { 326 | while (n > 0) { 327 | --n; 328 | ++it; 329 | } 330 | } 331 | 332 | template 333 | constexpr void do_advance(I& it, typename iterator_traits::difference_type n, bidirectional_iterator_tag) { 334 | while (n > 0) { 335 | --n; 336 | ++it; 337 | } 338 | while (n < 0) { 339 | ++n; 340 | --it; 341 | } 342 | } 343 | 344 | template 345 | constexpr void do_advance(I& it, typename iterator_traits::difference_type n, random_access_iterator_tag) { 346 | it += n; 347 | } 348 | 349 | } 350 | 351 | template 352 | constexpr void advance(I& it, D n) { 353 | detail::do_advance(it, 354 | typename iterator_traits::difference_type(n), 355 | typename iterator_traits::iterator_category()); 356 | } 357 | 358 | template 359 | constexpr typename iterator_traits::difference_type distance(II first, II last) noexcept { 360 | if constexpr (is_same_v::iterator_category>) { 361 | return last - first; 362 | } 363 | else { 364 | static_assert( 365 | is_same_v::iterator_category>, 366 | "TODO: support more types in ntl::distance" 367 | ); 368 | } 369 | } 370 | 371 | #pragma endregion 372 | 373 | } 374 | -------------------------------------------------------------------------------- /ntl/memory: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace ntl { 4 | 5 | template 6 | constexpr T* addressof(T& arg) noexcept { 7 | static_assert(false && "not implemented"); 8 | return nullptr; 9 | } 10 | 11 | template 12 | const T* addressof(const T&&) noexcept = delete; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /ntl/ntl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define NTL_TAG 'LTN ' 4 | 5 | #ifndef NTL_USER_MODE 6 | 7 | void* __cdecl operator new(size_t); 8 | void* __cdecl operator new(size_t, void*); 9 | void __cdecl operator delete(void*); 10 | void __cdecl operator delete(void*, void*); 11 | void __cdecl operator delete(void*, size_t); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /ntl/ntl.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | DebugInUserMode 22 | Win32 23 | 24 | 25 | DebugInUserMode 26 | x64 27 | 28 | 29 | 30 | 16.0 31 | {7AEB2784-2AB5-41D2-9846-689F139C813A} 32 | ntl 33 | $(LatestTargetPlatformVersion) 34 | 35 | 36 | 37 | StaticLibrary 38 | true 39 | WindowsKernelModeDriver10.0 40 | Unicode 41 | 42 | 43 | StaticLibrary 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | StaticLibrary 50 | false 51 | WindowsKernelModeDriver10.0 52 | true 53 | Unicode 54 | 55 | 56 | StaticLibrary 57 | true 58 | WindowsKernelModeDriver10.0 59 | Unicode 60 | 61 | 62 | StaticLibrary 63 | true 64 | v142 65 | Unicode 66 | 67 | 68 | StaticLibrary 69 | false 70 | WindowsKernelModeDriver10.0 71 | true 72 | Unicode 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | $(SolutionDir)$(Platform)\$(ConfigurationName)\ 100 | $(Platform)\$(ConfigurationName)\ 101 | $(CRT_IncludePath);$(KM_IncludePath);$(KIT_SHARED_IncludePath) 102 | $(DDK_LibraryPath_DDKPlatform);$(LibraryPath) 103 | 104 | 105 | $(SolutionDir)$(Platform)\$(ConfigurationName)\ 106 | $(Platform)\$(ConfigurationName)\ 107 | 108 | 109 | $(SolutionDir)$(Platform)\$(ConfigurationName)\ 110 | $(Platform)\$(ConfigurationName)\ 111 | $(CRT_IncludePath);$(KM_IncludePath);$(KIT_SHARED_IncludePath) 112 | $(DDK_LibraryPath_DDKPlatform);$(LibraryPath) 113 | 114 | 115 | $(CRT_IncludePath);$(KM_IncludePath);$(KIT_SHARED_IncludePath) 116 | $(DDK_LibraryPath_DDKPlatform);$(LibraryPath) 117 | 118 | 119 | 120 | $(CRT_IncludePath);$(KM_IncludePath);$(KIT_SHARED_IncludePath) 121 | $(DDK_LibraryPath_DDKPlatform);$(LibraryPath) 122 | 123 | 124 | 125 | EnableAllWarnings 126 | Disabled 127 | true 128 | true 129 | stdcpplatest 130 | 4514;4748;%(DisableSpecificWarnings) 131 | 132 | 133 | Console 134 | 135 | 136 | 137 | 138 | EnableAllWarnings 139 | Disabled 140 | false 141 | true 142 | stdcpplatest 143 | 4514;4748;%(DisableSpecificWarnings) 144 | true 145 | NTL_USER_MODE;%(PreprocessorDefinitions) 146 | 147 | 148 | Console 149 | 150 | 151 | 152 | 153 | EnableAllWarnings 154 | Disabled 155 | true 156 | true 157 | stdcpplatest 158 | 4514;4748;%(DisableSpecificWarnings) 159 | 160 | 161 | Console 162 | 163 | 164 | 165 | 166 | EnableAllWarnings 167 | Disabled 168 | false 169 | true 170 | stdcpplatest 171 | 4514;4748;%(DisableSpecificWarnings) 172 | true 173 | NTL_USER_MODE;%(PreprocessorDefinitions) 174 | 175 | 176 | Console 177 | 178 | 179 | 180 | 181 | EnableAllWarnings 182 | MaxSpeed 183 | true 184 | true 185 | true 186 | true 187 | stdcpplatest 188 | 4514;4603;4627;4986;4987;4996;%(DisableSpecificWarnings) 189 | 190 | 191 | Console 192 | true 193 | true 194 | false 195 | 196 | 197 | 198 | 199 | EnableAllWarnings 200 | MaxSpeed 201 | true 202 | true 203 | true 204 | true 205 | stdcpplatest 206 | 4514;4603;4627;4986;4987;4996;%(DisableSpecificWarnings) 207 | 208 | 209 | Console 210 | true 211 | true 212 | false 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | -------------------------------------------------------------------------------- /ntl/ntl.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ntl/ntl.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /ntl/system: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef NTL_USER_MODE 4 | extern "C" { 5 | #pragma warning(push) 6 | #pragma warning(disable : 5026 5027) 7 | #include 8 | #pragma warning(pop) 9 | } 10 | #else 11 | #pragma warning(push) 12 | #pragma warning(disable : 4668 5039) 13 | #include 14 | #pragma warning(pop) 15 | 16 | #include 17 | #endif 18 | 19 | namespace ntl { 20 | 21 | using size_t = SIZE_T; 22 | using ssize_t = SSIZE_T; 23 | using ptrdiff_t = SSIZE_T; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /ntl/type_traits: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "system" 4 | 5 | namespace ntl { 6 | 7 | namespace detail { 8 | 9 | template 10 | struct type_identity { using type = T; }; 11 | 12 | template 13 | auto try_add_lvalue_reference(int) noexcept -> type_identity; 14 | template 15 | auto try_add_lvalue_reference(...) noexcept -> type_identity; 16 | 17 | template 18 | auto try_add_rvalue_reference(int) noexcept -> type_identity; 19 | template 20 | auto try_add_rvalue_reference(...) noexcept -> type_identity; 21 | 22 | } 23 | 24 | template 25 | struct integral_constant { 26 | static constexpr T value = v; 27 | using value_type = T; 28 | using type = integral_constant; 29 | constexpr operator value_type() const noexcept { return value; } 30 | constexpr value_type operator()() const noexcept { return value; } 31 | }; 32 | 33 | template 34 | using bool_constant = integral_constant; 35 | 36 | using true_type = bool_constant; 37 | using false_type = bool_constant; 38 | 39 | template 40 | using void_t = void; 41 | 42 | template struct remove_const { typedef T type; }; 43 | template struct remove_const { typedef T type; }; 44 | 45 | template struct remove_volatile { typedef T type; }; 46 | template struct remove_volatile { typedef T type; }; 47 | 48 | template 49 | using remove_const_t = typename remove_const::type; 50 | 51 | template 52 | using remove_volatile_t = typename remove_volatile::type; 53 | 54 | template 55 | struct remove_cv { 56 | using type = remove_volatile_t>; 57 | }; 58 | 59 | template 60 | using remove_cv_t = typename remove_cv::type; 61 | 62 | template struct is_pointer_helper : false_type {}; 63 | template struct is_pointer_helper : true_type {}; 64 | template struct is_pointer : is_pointer_helper> {}; 65 | 66 | template 67 | struct add_lvalue_reference : decltype(detail::try_add_lvalue_reference(0)) {}; 68 | 69 | template 70 | using add_lvalue_reference_t = typename add_lvalue_reference::type; 71 | 72 | template 73 | struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference(0)) {}; 74 | 75 | template 76 | using add_rvalue_reference_t = typename add_rvalue_reference::type; 77 | 78 | template 79 | typename add_rvalue_reference_t declval() noexcept; 80 | 81 | namespace detail { 82 | 83 | struct one_t { char c[1]; }; 84 | struct two_t { char c[2]; }; 85 | template one_t is_class_test(int T::*) noexcept; 86 | template two_t is_class_test(...) noexcept; 87 | 88 | template true_type is_base_of_test(volatile const Base*) noexcept; 89 | template false_type is_base_of_test(volatile const void*) noexcept; 90 | template 91 | using pre_is_base_of = decltype(is_base_of_test(declval())); 92 | template 93 | struct pre_is_base_of2 : public true_type { }; 94 | template 95 | struct pre_is_base_of2>> : public pre_is_base_of { }; 96 | 97 | } 98 | 99 | template 100 | struct is_class 101 | : bool_constant< 102 | sizeof(detail::is_class_test(0)) == sizeof(detail::one_t) 103 | /* && !is_union_v */ // TODO 104 | > 105 | {}; 106 | 107 | template 108 | inline constexpr bool is_class_v = is_class::value; 109 | 110 | template struct is_lvalue_reference : false_type {}; 111 | template struct is_lvalue_reference : true_type {}; 112 | template 113 | inline constexpr bool is_lvalue_reference_v = is_lvalue_reference::value; 114 | 115 | template 116 | struct conditional { using type = T; }; 117 | 118 | template 119 | struct conditional { using type = F; }; 120 | 121 | template 122 | using conditional_t = typename conditional::type; 123 | 124 | template struct conjunction : true_type {}; 125 | template struct conjunction : B1 {}; 126 | template 127 | struct conjunction 128 | : conditional_t, B1> 129 | {}; 130 | 131 | template 132 | inline constexpr bool conjunction_v = conjunction::value; 133 | 134 | template struct disjunction : false_type {}; 135 | template struct disjunction : B1 {}; 136 | template 137 | struct disjunction 138 | : conditional_t> 139 | {}; 140 | 141 | template 142 | inline constexpr bool disjunction_v = disjunction::value; 143 | 144 | template 145 | struct is_same : false_type {}; 146 | 147 | template 148 | struct is_same : true_type {}; 149 | 150 | template 151 | inline constexpr bool is_same_v = is_same::value; 152 | 153 | template 154 | struct is_base_of 155 | : public conditional_t< 156 | is_class_v&& is_class_v, 157 | detail::pre_is_base_of2, 158 | false_type 159 | > 160 | {}; 161 | 162 | template 163 | inline constexpr bool is_base_of_v = is_base_of::value; 164 | 165 | template 166 | struct remove_reference { using type = T; }; 167 | 168 | template 169 | struct remove_reference { using type = T; }; 170 | 171 | template 172 | struct remove_reference { using type = T; }; 173 | 174 | template 175 | using remove_reference_t = typename remove_reference::type; 176 | 177 | template 178 | struct enable_if {}; 179 | 180 | template 181 | struct enable_if { using type = T; }; 182 | 183 | template 184 | using enable_if_t = typename enable_if::type; 185 | 186 | template 187 | struct is_any_of : public disjunction...> {}; 188 | 189 | template 190 | inline constexpr bool is_any_of_v = is_any_of::value; 191 | 192 | template 193 | struct is_integral : public is_any_of< 194 | remove_cv_t, 195 | bool, char, signed char, unsigned char, 196 | wchar_t, char16_t, char32_t, 197 | short, unsigned short, 198 | int, unsigned int, long, unsigned long, 199 | long long, unsigned long long 200 | > 201 | {}; 202 | 203 | template 204 | inline constexpr bool is_integral_v = is_integral::value; 205 | 206 | template 207 | struct is_floating_point : public is_any_of< 208 | remove_cv_t, 209 | float, double, long double 210 | > 211 | {}; 212 | 213 | template 214 | inline constexpr bool is_floating_point_v = is_floating_point::value; 215 | } 216 | -------------------------------------------------------------------------------- /ntl/utility: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "type_traits" 4 | 5 | namespace ntl { 6 | 7 | template 8 | void swap(T &a, T &b) noexcept { 9 | T t = move(a); 10 | a = move(b); 11 | b = move(t); 12 | } 13 | 14 | template 15 | constexpr T&& forward(typename remove_reference_t &t) noexcept { 16 | return static_cast(t); 17 | } 18 | 19 | template 20 | constexpr T&& forward(typename remove_reference_t &&t) noexcept { 21 | static_assert(!is_lvalue_reference_v, "cannot forward an rvalue as an lvalue."); 22 | return static_cast(t); 23 | } 24 | 25 | template 26 | typename remove_reference_t&& move(T &&t) noexcept { 27 | return static_cast&&>(t); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /ntl/vector: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "system" 4 | #include "ntl" 5 | #include "algorithm" 6 | #include "allocator" 7 | #include "utility" 8 | #include "iterator" 9 | #include "exception" 10 | 11 | namespace ntl { 12 | 13 | template> 14 | class vector final { 15 | public: 16 | using value_type = T; 17 | using allocator_type = Allocator; 18 | using size_type = size_t; 19 | using difference_type = ptrdiff_t; 20 | using reference = value_type&; 21 | using const_reference = value_type const&; 22 | using pointer = T*; 23 | using const_pointer = T const*; 24 | using iterator = random_access_iterator; 25 | using const_iterator = random_access_iterator; 26 | using reverse_iterator = ntl::reverse_iterator; 27 | using const_reverse_iterator = ntl::reverse_iterator; 28 | 29 | vector() noexcept 30 | : begin_(nullptr) 31 | , end_(nullptr) 32 | , capacity_(0) 33 | , allocator_() 34 | {} 35 | 36 | explicit vector(allocator_type const &allocator) noexcept 37 | : begin_(nullptr) 38 | , end_(nullptr) 39 | , capacity_(0) 40 | , allocator_(allocator) 41 | {} 42 | 43 | vector(size_type count, value_type const &value, allocator_type const &allocator = allocator_type()) noexcept 44 | : vector(allocator) 45 | { 46 | reserve(count); 47 | for (size_t i = 0; i != capacity_; i++) { 48 | push_back(value); 49 | } 50 | } 51 | 52 | explicit vector(size_type count, allocator_type const &allocator = allocator_type()) noexcept 53 | : vector(allocator) 54 | { 55 | reserve(count); 56 | for (size_t i = 0; i != capacity_; i++) { 57 | push_back(value_type()); 58 | } 59 | } 60 | 61 | template 62 | vector(II first, II last, allocator_type const &allocator = allocator_type()) noexcept 63 | : vector(allocator) 64 | { 65 | reserve(distance(first, last)); 66 | for (; first != last; ++first) { 67 | push_back(*first); 68 | } 69 | } 70 | 71 | vector(vector const &other) noexcept { 72 | reserve(other.size()); 73 | for (auto const &e : other) { 74 | push_back(e); 75 | } 76 | } 77 | 78 | vector(vector const &other, allocator_type const &allocator) noexcept 79 | : vector(allocator) 80 | { 81 | reserve(other.size()); 82 | for (auto const &e : other) { 83 | push_back(e); 84 | } 85 | } 86 | 87 | vector(vector &&other) noexcept 88 | : begin_(other.begin_) 89 | , end_(other.end_) 90 | , capacity_(other.capacity_) 91 | , allocator_(other.allocator_) 92 | { 93 | other.begin_ = nullptr; 94 | other.end_ = nullptr; 95 | other.capacity_ = 0; 96 | } 97 | 98 | vector(vector &&other, allocator_type const &allocator) noexcept 99 | : begin_(other.begin_) 100 | , end_(other.end_) 101 | , capacity_(other.capacity_) 102 | , allocator_(allocator) 103 | { 104 | other.begin_ = nullptr; 105 | other.end_ = nullptr; 106 | other.capacity_ = 0; 107 | } 108 | 109 | ~vector() noexcept { 110 | clear(); 111 | } 112 | 113 | vector& operator=(vector const &other) noexcept { 114 | clear(); 115 | reserve(other.size()); 116 | for (auto const &e : other) { 117 | push_back(e); 118 | } 119 | return *this; 120 | } 121 | 122 | vector& operator=(vector &&other) noexcept { 123 | clear(); 124 | swap(other); 125 | return *this; 126 | } 127 | 128 | void assign(size_type count, value_type const &value) noexcept { 129 | clear(); 130 | reserve(count); 131 | while (count--) { 132 | push_back(value); 133 | } 134 | } 135 | 136 | template 137 | void assign(II first, II last) noexcept { 138 | clear(); 139 | reserve(ntl::distance(first, last)); 140 | for (; first != last; ++first) { 141 | push_back(*first); 142 | } 143 | } 144 | 145 | reference at(size_type position) noexcept { 146 | validate_offset(position); 147 | return begin_[position]; 148 | } 149 | 150 | const_reference at(size_type position) const noexcept { 151 | validate_offset(position); 152 | return begin_[position]; 153 | } 154 | 155 | reference operator[](size_type position) noexcept { 156 | return begin_[position]; 157 | } 158 | 159 | const_reference operator[](size_type position) const noexcept { 160 | return begin_[position]; 161 | } 162 | 163 | reference front() noexcept { 164 | return *begin_; 165 | } 166 | 167 | const_reference front() const noexcept { 168 | return *begin_; 169 | } 170 | 171 | reference back() noexcept { 172 | return *(end_ - 1); 173 | } 174 | 175 | const_reference back() const noexcept { 176 | return *(end_ - 1); 177 | } 178 | 179 | pointer data() noexcept { 180 | return begin_; 181 | } 182 | 183 | const_pointer data() const noexcept { 184 | return begin_; 185 | } 186 | 187 | iterator begin() noexcept { 188 | return begin_; 189 | } 190 | 191 | const_iterator begin() const noexcept { 192 | return begin_; 193 | } 194 | 195 | const_iterator cbegin() const noexcept { 196 | return begin_; 197 | } 198 | 199 | iterator end() noexcept { 200 | return end_; 201 | } 202 | 203 | const_iterator end() const noexcept { 204 | return end_; 205 | } 206 | 207 | const_iterator cend() const noexcept { 208 | return end_; 209 | } 210 | 211 | reverse_iterator rbegin() noexcept { 212 | return end_; 213 | } 214 | 215 | const_reverse_iterator rbegin() const noexcept { 216 | return end_; 217 | } 218 | 219 | const_reverse_iterator crbegin() const noexcept { 220 | return end_; 221 | } 222 | 223 | reverse_iterator rend() noexcept { 224 | return begin_; 225 | } 226 | 227 | const_reverse_iterator rend() const noexcept { 228 | return begin_; 229 | } 230 | 231 | const_reverse_iterator crend() const noexcept { 232 | return begin_; 233 | } 234 | 235 | bool empty() const noexcept { 236 | return begin() == end(); 237 | } 238 | 239 | size_type size() const noexcept { 240 | return end_ - begin_; 241 | } 242 | 243 | void reserve(size_type new_capacity) noexcept { 244 | if (new_capacity <= capacity_) { 245 | return; 246 | } 247 | vector new_vector(allocator_); 248 | new_vector.capacity_ = new_capacity; 249 | new_vector.begin_ = allocator_.allocate(new_capacity); 250 | new_vector.end_ = new_vector.begin_; 251 | for (auto &&e : *this) { 252 | new_vector.push_back(ntl::move(e)); 253 | } 254 | swap(new_vector); 255 | } 256 | 257 | size_type capacity() const noexcept { 258 | return capacity_; 259 | } 260 | 261 | void shrink_to_fit() noexcept { 262 | if (size() == capacity_) { 263 | return; 264 | } 265 | vector new_vector(allocator_); 266 | new_vector.reserve(size()); 267 | for (auto &&e : *this) { 268 | new_vector.push_back(ntl::move(e)); 269 | } 270 | swap(new_vector); 271 | } 272 | 273 | void clear() noexcept { 274 | for (auto i = rbegin(); i != rend(); ++i) { 275 | (*i).~value_type(); 276 | } 277 | if (begin_) { 278 | allocator_.deallocate(begin_, capacity_); 279 | } 280 | begin_ = nullptr; 281 | end_ = nullptr; 282 | capacity_ = 0; 283 | } 284 | 285 | iterator insert(const_iterator position, value_type const &value) noexcept { 286 | insert(position, static_cast(1), value); 287 | } 288 | 289 | iterator insert(const_iterator position, value_type &&value) noexcept { 290 | size_type offset = position - begin_; 291 | reserve(capacity() + 1); 292 | for (auto p = end_; p > begin_ + offset; --p) { 293 | *p = move(*(p - 1)); 294 | } 295 | ++end_; 296 | *(begin_ + offset) = move(value); 297 | return begin_ + offset; 298 | } 299 | 300 | iterator insert(const_iterator position, size_type count, value_type const &value) noexcept { 301 | size_type offset = position - begin_; 302 | reserve(capacity() + count); 303 | for (auto p = end_ - 1; p >= begin_ + offset; --p) { 304 | *(p + count) = move(*p); 305 | } 306 | end_ += count; 307 | for (auto p = begin_ + offset; count--; ++p) { 308 | *p = value; 309 | } 310 | return begin_ + offset; 311 | } 312 | 313 | template 314 | iterator insert(const_iterator position, II first, II last) noexcept { 315 | size_type count = distance(first, last); 316 | size_type offset = position - begin_; 317 | reserve(capacity() + count); 318 | for (auto p = end_ - 1; p >= begin_ + offset; --p) { 319 | *(p + count) = move(*p); 320 | } 321 | end_ += count; 322 | for (auto p = begin_ + offset; count--; ++p, ++first) { 323 | *p = *first; 324 | } 325 | return begin_ + offset; 326 | } 327 | 328 | template 329 | iterator emplace(const_iterator position, Args &&...args) noexcept { 330 | size_type offset = position - begin_; 331 | reserve(capacity() + 1); 332 | for (auto p = end_; p > begin_ + offset; --p) { 333 | *p = move(*(p - 1)); 334 | } 335 | ++end_; 336 | *(begin_ + offset) = move(value_type(forward(args)...)); 337 | return begin_ + offset; 338 | } 339 | 340 | iterator erase(const_iterator position) noexcept { 341 | size_type offset = position - begin_; 342 | validate_offset(offset); 343 | for (auto p = begin_ + offset + 1; p != end_; ++p) { 344 | *(p - 1) = move(*p); 345 | } 346 | --end_; 347 | return begin_ + offset; 348 | } 349 | 350 | iterator erase(const_iterator first, const_iterator last) noexcept { 351 | size_type offset_first = first - begin_; 352 | size_type offset_last = last - begin_; 353 | if (offset_first >= offset_last) { 354 | return begin_ + offset_last; 355 | } 356 | validate_offset(offset_first); 357 | validate_offset(offset_last - 1); 358 | for (auto p = begin_ + offset_last, q = begin_ + offset_first; p != end_; ++p, ++q) { 359 | *q = move(*p); 360 | } 361 | for (auto p = end_ - 1; p != end_ - (offset_last - offset_first); --p) { 362 | p->~value_type(); 363 | } 364 | end_ -= offset_last - offset_first; 365 | return begin_ + offset_last; 366 | } 367 | 368 | void push_back(value_type const &value) noexcept { 369 | if (size() >= capacity()) { 370 | size_type new_size = capacity() * 2; 371 | if (!new_size) { 372 | new_size++; 373 | } 374 | reserve(new_size); 375 | } 376 | new (end_++) value_type(value); 377 | } 378 | 379 | void push_back(value_type &&value) noexcept { 380 | if (size() >= capacity()) { 381 | size_type new_size = capacity() * 2; 382 | if (!new_size) { 383 | new_size++; 384 | } 385 | reserve(new_size); 386 | } 387 | new (end_++) value_type(move(value)); 388 | } 389 | 390 | template 391 | reference emplace_back(Args &&...args) noexcept { 392 | if (size() >= capacity()) { 393 | size_type new_size = capacity() * 2; 394 | if (!new_size) { 395 | new_size++; 396 | } 397 | reserve(new_size); 398 | } 399 | new (end_) value_type(forward(args)...); 400 | return *(end_++); 401 | } 402 | 403 | void pop_back() noexcept { 404 | if (!empty()) { 405 | (--end_)->~value_type(); 406 | } 407 | } 408 | 409 | void resize(size_type count) noexcept { 410 | resize(count, value_type()); 411 | } 412 | 413 | void resize(size_type count, value_type const &value) noexcept { 414 | if (count <= size()) { 415 | while (size() > count) { 416 | pop_back(); 417 | } 418 | } else { 419 | vector new_vector(allocator_); 420 | new_vector.reserve(count); 421 | for (auto &&e : *this) { 422 | new_vector.push_back(move(e)); 423 | } 424 | while (new_vector.size() < count) { 425 | new_vector.push_back(value); 426 | } 427 | swap(new_vector); 428 | } 429 | } 430 | 431 | void swap(vector &other) noexcept { 432 | ntl::swap(begin_, other.begin_); 433 | ntl::swap(end_, other.end_); 434 | ntl::swap(capacity_, other.capacity_); 435 | ntl::swap(allocator_, other.allocator_); 436 | } 437 | 438 | private: 439 | void validate_offset(size_type offset) { 440 | if (offset >= size()) { 441 | #ifndef NTL_USER_MODE 442 | ExRaiseStatus(STATUS_ARRAY_BOUNDS_EXCEEDED); 443 | #else 444 | throw out_of_range(0, size(), offset); 445 | #endif 446 | } 447 | } 448 | 449 | pointer begin_, end_; 450 | size_type capacity_; 451 | allocator_type allocator_; 452 | }; 453 | 454 | template 455 | bool operator==(vector const &lhs, vector const &rhs) noexcept { 456 | if (lhs.size() != rhs.size()) { 457 | return false; 458 | } 459 | return equals(lhs.begin(), lhs.end(), rhs.begin()); 460 | } 461 | 462 | template 463 | bool operator!=(vector const &lhs, vector const &rhs) noexcept { 464 | if (lhs.size() != rhs.size()) { 465 | return true; 466 | } 467 | return !equals(lhs.begin(), lhs.end(), rhs.begin()); 468 | } 469 | 470 | template 471 | bool operator<(vector const &lhs, vector const &rhs) noexcept { 472 | return lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); 473 | } 474 | 475 | template 476 | bool operator<=(vector const &lhs, vector const &rhs) noexcept { 477 | return !(lhs > rhs); 478 | } 479 | 480 | template 481 | bool operator>(vector const &lhs, vector const &rhs) noexcept { 482 | return lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), 483 | [](vector::const_iterator a, vector::const_iterator b) { 484 | if (*a > *b) 485 | return true; 486 | if (*b > *a) 487 | return false; 488 | } 489 | ); 490 | } 491 | 492 | template 493 | bool operator>=(vector const &lhs, vector const &rhs) noexcept { 494 | return !(lhs < rhs); 495 | } 496 | 497 | } 498 | -------------------------------------------------------------------------------- /ntl_test/algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "CppUnitTest.h" 3 | 4 | #include "../ntl/algorithm" 5 | 6 | using namespace Microsoft::VisualStudio::CppUnitTestFramework; 7 | 8 | namespace ntltest { 9 | TEST_CLASS(algorithm) { 10 | public: 11 | TEST_METHOD(lower_bound) { 12 | int a[] = { 1, 3, 5, 7, 9 }; 13 | for (int i = 0; i < 10; i++) { 14 | auto it = ntl::lower_bound(a, a + 5, i); 15 | Assert::IsTrue(*it - i <= 1); 16 | } 17 | auto it = ntl::lower_bound(a, a + 5, 10); 18 | Assert::AreEqual(it, a + 5); 19 | } 20 | 21 | TEST_METHOD(lower_bound_predicate) { 22 | int a[] = { 1, 3, 5, 7, 9 }; 23 | for (int i = 0; i < 10; i++) { 24 | auto it = ntl::lower_bound(a, a + 5, i, [](int a, int b) { return a < b; }); 25 | Assert::IsTrue(*it - i <= 1); 26 | } 27 | auto it = ntl::lower_bound(a, a + 5, 10, [](int a, int b) { return a < b; }); 28 | Assert::AreEqual(it, a + 5); 29 | } 30 | 31 | TEST_METHOD(upper_bound) { 32 | int a[] = { 1, 3, 5, 7, 9 }; 33 | for (int i = 0; i < 9; i++) { 34 | auto it = ntl::upper_bound(a, a + 5, i); 35 | Assert::IsTrue(*it - i == 1 || *it - i == 2); 36 | } 37 | auto it = ntl::upper_bound(a, a + 5, 9); 38 | Assert::AreEqual(it, a + 5); 39 | } 40 | 41 | TEST_METHOD(upper_bound_predicate) { 42 | int a[] = { 1, 3, 5, 7, 9 }; 43 | for (int i = 0; i < 9; i++) { 44 | auto it = ntl::upper_bound(a, a + 5, i, [](int a, int b) { return a < b; }); 45 | Assert::IsTrue(*it - i == 1 || *it - i == 2); 46 | } 47 | auto it = ntl::upper_bound(a, a + 5, 9, [](int a, int b) { return a < b; }); 48 | Assert::AreEqual(it, a + 5); 49 | } 50 | }; 51 | } 52 | -------------------------------------------------------------------------------- /ntl_test/ntl_test.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {31883F18-1B08-4889-B0AB-B7DB1863F0D1} 24 | Win32Proj 25 | ntltest 26 | 10.0 27 | NativeUnitTestProject 28 | 29 | 30 | 31 | DynamicLibrary 32 | true 33 | v142 34 | Unicode 35 | false 36 | 37 | 38 | DynamicLibrary 39 | false 40 | v142 41 | true 42 | Unicode 43 | false 44 | 45 | 46 | DynamicLibrary 47 | true 48 | v142 49 | Unicode 50 | false 51 | 52 | 53 | DynamicLibrary 54 | false 55 | v142 56 | true 57 | Unicode 58 | false 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | true 80 | 81 | 82 | true 83 | 84 | 85 | false 86 | 87 | 88 | false 89 | 90 | 91 | 92 | Use 93 | Level3 94 | Disabled 95 | true 96 | $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) 97 | NTL_USER_MODE;_DEBUG;%(PreprocessorDefinitions) 98 | true 99 | pch.h 100 | stdcpp17 101 | stdc17 102 | 103 | 104 | Windows 105 | $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) 106 | 107 | 108 | 109 | 110 | Use 111 | Level3 112 | Disabled 113 | true 114 | $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) 115 | NTL_USER_MODE;_DEBUG;%(PreprocessorDefinitions) 116 | true 117 | pch.h 118 | stdcpp17 119 | stdc17 120 | 121 | 122 | Windows 123 | $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) 124 | 125 | 126 | 127 | 128 | Use 129 | Level3 130 | MaxSpeed 131 | true 132 | true 133 | true 134 | $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) 135 | NTL_USER_MODE;WIN32;NDEBUG;%(PreprocessorDefinitions) 136 | true 137 | pch.h 138 | stdcpp17 139 | stdc17 140 | 141 | 142 | Windows 143 | true 144 | true 145 | $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) 146 | 147 | 148 | 149 | 150 | Use 151 | Level3 152 | MaxSpeed 153 | true 154 | true 155 | true 156 | $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) 157 | NTL_USER_MODE;NDEBUG;%(PreprocessorDefinitions) 158 | true 159 | pch.h 160 | stdcpp17 161 | stdc17 162 | 163 | 164 | Windows 165 | true 166 | true 167 | $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) 168 | 169 | 170 | 171 | 172 | 173 | 174 | Create 175 | Create 176 | Create 177 | Create 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /ntl_test/ntl_test.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {ad7ea8e7-7e6e-4356-a617-b288fc844311} 6 | 7 | 8 | 9 | 10 | pch 11 | 12 | 13 | 14 | 15 | 16 | 17 | pch 18 | 19 | 20 | -------------------------------------------------------------------------------- /ntl_test/ntl_test.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /ntl_test/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to the pre-compiled header 2 | 3 | #include "pch.h" 4 | 5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. 6 | -------------------------------------------------------------------------------- /ntl_test/pch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | -------------------------------------------------------------------------------- /ntl_test/vector.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "CppUnitTest.h" 3 | 4 | #include "../ntl/vector" 5 | 6 | using namespace Microsoft::VisualStudio::CppUnitTestFramework; 7 | 8 | namespace ntltest { 9 | TEST_CLASS(vector) { 10 | public: 11 | TEST_METHOD(empty_constructor) { 12 | ntl::vector v; 13 | } 14 | TEST_METHOD(count_constructor) { 15 | size_t size = 16; 16 | ntl::vector v(size); 17 | Assert::AreEqual(v.size(), size); 18 | Assert::AreEqual(v.capacity(), size); 19 | for (auto e : v) { 20 | Assert::AreEqual(0, e); 21 | } 22 | } 23 | TEST_METHOD(count_value_constructor) { 24 | int value = 2; 25 | size_t size = 16; 26 | ntl::vector v(size, value); 27 | Assert::AreEqual(v.size(), size); 28 | Assert::AreEqual(v.capacity(), size); 29 | for (auto e : v) { 30 | Assert::AreEqual(value, e); 31 | } 32 | } 33 | TEST_METHOD(range_constructor) { 34 | int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; 35 | ntl::vector w(a, a + 8); 36 | for (int i = 0; i != 8; i++) { 37 | Assert::AreEqual(i, w[i]); 38 | } 39 | } 40 | TEST_METHOD(copy_constructor) { 41 | int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; 42 | ntl::vector w(a, a + 8); 43 | ntl::vector v(w); 44 | for (int i = 0; i != 8; i++) { 45 | Assert::AreEqual(i, w[i]); 46 | } 47 | } 48 | TEST_METHOD(move_constructor) { 49 | size_t size = 16; 50 | ntl::vector v(size); 51 | ntl::vector w(ntl::move(v)); 52 | Assert::AreEqual(size, w.size()); 53 | Assert::AreEqual((size_t)0, v.size()); 54 | } 55 | TEST_METHOD(assignment_copy) { 56 | int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; 57 | ntl::vector v(a, a + 8); 58 | ntl::vector w; 59 | w = v; 60 | Assert::AreEqual(v.size(), w.size()); 61 | for (size_t i = 0; i != v.size(); i++) { 62 | Assert::AreEqual(v[i], w[i]); 63 | } 64 | } 65 | TEST_METHOD(assignment_move) { 66 | int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; 67 | ntl::vector v(a, a + 8); 68 | ntl::vector w; 69 | w = ntl::move(v); 70 | Assert::AreEqual((size_t)0, v.size()); 71 | for (size_t i = 0; i != 8; i++) { 72 | Assert::AreEqual(a[i], w[i]); 73 | } 74 | } 75 | TEST_METHOD(assign_count_value) { 76 | size_t size = 16; 77 | int value = 1; 78 | ntl::vector v; 79 | v.assign(size, value); 80 | for (size_t i = 0; i != size; i++) { 81 | Assert::AreEqual(value, v[i]); 82 | } 83 | } 84 | TEST_METHOD(assign_range) { 85 | int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; 86 | ntl::vector v; 87 | v.assign(a, a + 8); 88 | for (int i = 0; i != 8; i++) { 89 | Assert::AreEqual(a[i], v[i]); 90 | } 91 | } 92 | TEST_METHOD(at) { 93 | int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; 94 | ntl::vector v(a, a + 8); 95 | for (int i = 0; i != 8; i++) { 96 | Assert::AreEqual(a[i], v.at(i)); 97 | } 98 | try { 99 | v.at(8); 100 | Assert::Fail(L"exception was expected"); 101 | } catch (ntl::out_of_range const&) { 102 | } 103 | } 104 | TEST_METHOD(empty_and_clear) { 105 | ntl::vector v((size_t)1, 1); 106 | Assert::IsFalse(v.empty()); 107 | v.clear(); 108 | Assert::IsTrue(v.empty()); 109 | } 110 | TEST_METHOD(size) { 111 | size_t size = 16; 112 | ntl::vector v(size, 1); 113 | Assert::AreEqual(size, v.size()); 114 | } 115 | TEST_METHOD(reserve) { 116 | size_t initial_size = 5; 117 | size_t new_capacity = 16; 118 | ntl::vector v(initial_size, 1); 119 | Assert::AreEqual(initial_size, v.size()); 120 | Assert::AreEqual(initial_size, v.capacity()); 121 | v.reserve(new_capacity); 122 | Assert::AreEqual(initial_size, v.size()); 123 | Assert::AreEqual(new_capacity, v.capacity()); 124 | for (size_t i = 0; i != initial_size; i++) { 125 | Assert::AreEqual(1, v[i]); 126 | } 127 | } 128 | TEST_METHOD(shrink_to_fit) { 129 | size_t size = 16; 130 | ntl::vector v; 131 | v.reserve(size); 132 | Assert::AreEqual(size, v.capacity()); 133 | v.shrink_to_fit(); 134 | Assert::AreEqual((size_t)0, v.capacity()); 135 | } 136 | TEST_METHOD(clear) { 137 | size_t size = 16; 138 | ntl::vector v(size, 1); 139 | Assert::AreEqual(size, v.size()); 140 | v.clear(); 141 | Assert::IsTrue(v.empty()); 142 | } 143 | TEST_METHOD(resize) { 144 | int value = 1; 145 | size_t initial_size = 5; 146 | size_t new_size = 16; 147 | ntl::vector v(initial_size, value); 148 | Assert::AreEqual(initial_size, v.size()); 149 | for (size_t i = 0; i != v.size(); i++) { 150 | Assert::AreEqual(value, v[i]); 151 | } 152 | v.resize(new_size); 153 | Assert::AreEqual(new_size, v.size()); 154 | for (size_t i = 0; i != initial_size; i++) { 155 | Assert::AreEqual(value, v[i]); 156 | } 157 | for (size_t i = initial_size; i != new_size; i++) { 158 | Assert::AreEqual(0, v[i]); 159 | } 160 | v.resize(initial_size); 161 | for (size_t i = 0; i != initial_size; i++) { 162 | Assert::AreEqual(value, v[i]); 163 | } 164 | } 165 | TEST_METHOD(swap) { 166 | int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; 167 | int b[] = { 7, 6, 5, 4, 3, 2, 1, 0 }; 168 | ntl::vector v(a, a + 8); 169 | ntl::vector w(b, b + 8); 170 | for (size_t i = 0; i != 8; i++) { 171 | Assert::AreEqual(a[i], v[i]); 172 | Assert::AreEqual(b[i], w[i]); 173 | } 174 | v.swap(w); 175 | for (size_t i = 0; i != 8; i++) { 176 | Assert::AreEqual(b[i], v[i]); 177 | Assert::AreEqual(a[i], w[i]); 178 | } 179 | } 180 | TEST_METHOD(insert) { 181 | int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; 182 | ntl::vector v(a, a + 8); 183 | for (size_t i = 0; i != 8; i++) { 184 | Assert::AreEqual(a[i], v[i]); 185 | } 186 | v.insert(v.begin() + 4, 8); 187 | for (size_t i = 0; i != 9; i++) { 188 | if (i < 4) { 189 | Assert::AreEqual(a[i], v[i]); 190 | } else if (i == 4) { 191 | Assert::AreEqual(8, v[i]); 192 | } else /*if (i > 4)*/ { 193 | Assert::AreEqual(a[i - 1], v[i]); 194 | } 195 | } 196 | } 197 | TEST_METHOD(insert_move) { 198 | size_t count = 16; 199 | size_t value = 3; 200 | ntl::vector> v; 201 | ntl::vector w(count, value); 202 | v.resize(2); 203 | for (size_t i = 0; i != v.size(); i++) { 204 | v[i].assign(count, i + 1); 205 | } 206 | for (size_t i = 0; i != v.size(); i++) { 207 | for (size_t j = 0; j != count; j++) { 208 | Assert::AreEqual(i + 1, v[i][j]); 209 | } 210 | } 211 | for (size_t i = 0; i != w.size(); i++) { 212 | Assert::AreEqual(value, w[i]); 213 | } 214 | v.insert(v.begin() + 1, ntl::move(w)); 215 | Assert::AreEqual((size_t)3, v.size()); 216 | for (size_t i = 0; i != count; i++) { 217 | Assert::AreEqual((size_t)1, v[0][i]); 218 | Assert::AreEqual((size_t)3, v[1][i]); 219 | Assert::AreEqual((size_t)2, v[2][i]); 220 | } 221 | Assert::IsTrue(w.empty()); 222 | } 223 | TEST_METHOD(insert_count) { 224 | int a[] = { 0, 1, 2, 3, 12, 13, 14, 15 }; 225 | ntl::vector v(a, a + 8); 226 | for (size_t i = 0; i != 8; i++) { 227 | Assert::AreEqual(a[i], v[i]); 228 | } 229 | v.insert(v.begin() + 4, (size_t)8, 8); 230 | Assert::AreEqual((size_t)16, v.size()); 231 | for (size_t i = 0; i != v.size(); i++) { 232 | if (i < 4) { 233 | Assert::AreEqual(a[i], v[i]); 234 | } else if (i < 12) { 235 | Assert::AreEqual(8, v[i]); 236 | } else /*if (i < 16)*/ { 237 | Assert::AreEqual(a[i - 8], v[i]); 238 | } 239 | } 240 | } 241 | TEST_METHOD(insert_range) { 242 | int a[] = { 0, 1, 2, 3, 3, 2, 1, 0 }; 243 | ntl::vector v(a, a + 8); 244 | v.insert(v.begin() + 4, a, a + 4); 245 | v.insert(v.begin() + 8, a + 4, a + 8); 246 | Assert::AreEqual((size_t)16, v.size()); 247 | for (size_t i = 0; i != 8; i++) { 248 | if (i < 4) { 249 | Assert::AreEqual(a[i], v[i]); 250 | } else /*if (i < 8)*/ { 251 | Assert::AreEqual(a[i - 4], v[i]); 252 | } 253 | } 254 | for (size_t i = 8; i != 16; i++) { 255 | if (i < 12) { 256 | Assert::AreEqual(a[i - 4], v[i]); 257 | } else /*if (i < 8)*/ { 258 | Assert::AreEqual(a[i - 8], v[i]); 259 | } 260 | } 261 | } 262 | TEST_METHOD(emplace) { 263 | size_t count = 16; 264 | ntl::vector> v; 265 | v.resize(2); 266 | v[0].assign(count, (size_t)1); 267 | v[1].assign(count, (size_t)3); 268 | for (size_t i = 0; i != count; i++) { 269 | Assert::AreEqual((size_t)1, v[0][i]); 270 | Assert::AreEqual((size_t)3, v[1][i]); 271 | } 272 | v.emplace(v.begin() + 1, count, (size_t)2); 273 | Assert::AreEqual((size_t)3, v.size()); 274 | for (size_t i = 0; i != v.size(); i++) { 275 | for (size_t j = 0; j != count; j++) { 276 | Assert::AreEqual(i + 1, v[i][j]); 277 | } 278 | } 279 | } 280 | TEST_METHOD(erase) { 281 | int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; 282 | ntl::vector v(a, a + 8); 283 | for (size_t i = 0; i != 8; i++) { 284 | Assert::AreEqual(a[i], v[i]); 285 | } 286 | v.erase(v.begin() + 4); 287 | Assert::AreEqual((size_t)7, v.size()); 288 | for (size_t i = 0; i != v.size(); i++) { 289 | if (i < 4) { 290 | Assert::AreEqual(a[i], v[i]); 291 | } else /*if (i >= 4)*/ { 292 | Assert::AreEqual(a[i + 1], v[i]); 293 | } 294 | } 295 | } 296 | TEST_METHOD(erase_range) { 297 | int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; 298 | ntl::vector v(a, a + 8); 299 | for (size_t i = 0; i != 8; i++) { 300 | Assert::AreEqual(a[i], v[i]); 301 | } 302 | v.erase(v.begin() + 3, v.begin() + 5); 303 | Assert::AreEqual((size_t)6, v.size()); 304 | for (size_t i = 0; i != v.size(); i++) { 305 | if (i < 3) { 306 | Assert::AreEqual(a[i], v[i]); 307 | } else /*if (i >= 4)*/ { 308 | Assert::AreEqual(a[i + 2], v[i]); 309 | } 310 | } 311 | v.erase(v.begin() + 3, v.end()); 312 | Assert::AreEqual((size_t)3, v.size()); 313 | for (size_t i = 0; i != v.size(); i++) { 314 | Assert::AreEqual(a[i], v[i]); 315 | } 316 | } 317 | }; 318 | } 319 | --------------------------------------------------------------------------------