From a66fc586fd679aab7a7f9ffd683af450f30e7c82 Mon Sep 17 00:00:00 2001
From: Brett Laptop <tri11paragon@tpgc.me>
Date: Mon, 30 Sep 2024 18:03:44 -0400
Subject: [PATCH] skip doesnt work

---
 CMakeLists.txt                |  12 +--
 include/blt/iterator/common.h | 198 ++++++++++++++++++++++++++++++++--
 include/blt/iterator/zip.h    | 173 ++---------------------------
 libraries/parallel-hashmap    |   2 +-
 tests/iterator_tests.cpp      |   7 +-
 5 files changed, 211 insertions(+), 181 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9da53f2..d0ebaf1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.20)
 include(cmake/color.cmake)
-set(BLT_VERSION 1.1.2)
+set(BLT_VERSION 1.1.3)
 
 set(BLT_TARGET BLT)
 
@@ -140,7 +140,7 @@ install(FILES ${CMAKE_BINARY_DIR}/config/blt/config.h DESTINATION ${CMAKE_INSTAL
 set_target_properties(${BLT_TARGET} PROPERTIES VERSION ${BLT_VERSION})
 set_target_properties(${BLT_TARGET} PROPERTIES SOVERSION ${PROJECT_VERSION_MAJOR})
 if (NOT ${MOLD} STREQUAL MOLD-NOTFOUND)
-    target_compile_options(${BLT_TARGET} PUBLIC -fuse-ld=mold)
+    target_link_options(${BLT_TARGET} PUBLIC -fuse-ld=mold)
 endif ()
 
 install(TARGETS ${BLT_TARGET}
@@ -154,16 +154,16 @@ macro(blt_add_project name source type)
 
     add_executable(${name}-${type} ${source})
 
+    if (NOT ${MOLD} STREQUAL MOLD-NOTFOUND)
+        add_link_options(-fuse-ld=mold)
+    endif ()
+
     target_link_libraries(${name}-${type} PRIVATE BLT)
 
     target_compile_options(${name}-${type} PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
     target_link_options(${name}-${type} PRIVATE -Wall -Wextra -Wpedantic -Wno-comment)
     target_compile_definitions(${name}-${type} PRIVATE BLT_DEBUG_LEVEL=${DEBUG_LEVEL})
 
-    if (NOT ${MOLD} STREQUAL MOLD-NOTFOUND)
-        target_compile_options(${name}-${type} PUBLIC -fuse-ld=mold)
-    endif ()
-
     if (${TRACK_ALLOCATIONS})
         target_compile_definitions(${name}-${type} PRIVATE BLT_TRACK_ALLOCATIONS=1)
     endif ()
diff --git a/include/blt/iterator/common.h b/include/blt/iterator/common.h
index 746af3c..12389dc 100644
--- a/include/blt/iterator/common.h
+++ b/include/blt/iterator/common.h
@@ -21,6 +21,7 @@
 
 #include <type_traits>
 #include <iterator>
+#include <blt/meta/meta.h>
 
 namespace blt::iterator
 {
@@ -37,7 +38,8 @@ namespace blt::iterator
         base_wrapper operator--(int)
         {
             static_assert(std::is_same_v<typename Derived::iterator_category, std::bidirectional_iterator_tag> ||
-                          std::is_same_v<typename Derived::iterator_category, std::random_access_iterator_tag>,
+                          std::is_same_v<typename Derived::iterator_category,
+                                  std::random_access_iterator_tag>,
                           "Iterator must allow random access");
             auto tmp = *this;
             --*this;
@@ -86,27 +88,22 @@ namespace blt::iterator
         
         friend bool operator==(const base_wrapper& a, const base_wrapper& b)
         {
-            return a.base() == b.base();
+            return static_cast<const Derived&>(a).base() == static_cast<const Derived&>(b).base();
         }
         
         friend bool operator!=(const base_wrapper& a, const base_wrapper& b)
         {
-            return !(a.base() == b.base()); // NOLINT
+            return !(static_cast<const Derived&>(a).base() == static_cast<const Derived&>(b).base()); // NOLINT
         }
     };
     
-    template<typename Iter, typename Derived>
+    template<typename Iter, typename Derived, bool dereference = false>
     struct passthrough_wrapper : public base_wrapper<Derived>
     {
         public:
             explicit passthrough_wrapper(Iter iter): iter(std::move(iter))
             {}
             
-            meta::deref_return_t<Iter> operator*() const
-            {
-                return *iter;
-            }
-            
             auto base() const
             {
                 return iter;
@@ -118,8 +115,189 @@ namespace blt::iterator
             }
         
         protected:
-            Iter iter;
+            mutable Iter iter;
     };
+    
+    template<typename Iter, typename Derived>
+    struct passthrough_wrapper<Iter, Derived, true> : public passthrough_wrapper<Iter, Derived>
+    {
+        using passthrough_wrapper<Iter, Derived>::passthrough_wrapper;
+        
+        meta::deref_return_t<Iter> operator*() const
+        {
+            return *this->iter;
+        }
+    };
+    
+    namespace impls
+    {
+        template<typename Iter>
+        struct skip_wrapper : public passthrough_wrapper<Iter, skip_wrapper<Iter>>
+        {
+            public:
+                using iterator_category = typename std::iterator_traits<Iter>::iterator_category;
+                using value_type = typename std::iterator_traits<Iter>::value_type;
+                using difference_type = typename std::iterator_traits<Iter>::difference_type;
+                using pointer = typename std::iterator_traits<Iter>::pointer;
+                using reference = typename std::iterator_traits<Iter>::reference;
+                
+                explicit skip_wrapper(Iter iter, blt::size_t n): passthrough_wrapper<Iter, skip_wrapper<Iter>>(std::move(iter)), skip(n)
+                {}
+                
+                meta::deref_return_t<Iter> operator*() const
+                {
+                    BLT_TRACE("Dereference Skip");
+                    forward_skip();
+                    return *this->iter;
+                }
+                
+                skip_wrapper& operator++()
+                {
+                    BLT_TRACE("Forward Skip");
+                    forward_skip();
+                    ++this->iter;
+                    return *this;
+                }
+                
+                skip_wrapper& operator--()
+                {
+                    BLT_TRACE("Backward Skip");
+                    forward_skip();
+                    --this->iter;
+                    return *this;
+                }
+                
+                friend skip_wrapper operator+(const skip_wrapper& a, blt::ptrdiff_t n)
+                {
+                    static_assert(std::is_same_v<iterator_category, std::random_access_iterator_tag>,
+                                  "Iterator must allow random access");
+                    return {a.base() + static_cast<blt::ptrdiff_t>(a.skip) + n, 0};
+                }
+                
+                friend skip_wrapper operator-(const skip_wrapper& a, blt::ptrdiff_t n)
+                {
+                    static_assert(std::is_same_v<iterator_category, std::random_access_iterator_tag>,
+                                  "Iterator must allow random access");
+                    return {a.base() - static_cast<blt::ptrdiff_t>(a.skip) - n, 0};
+                }
+            
+            private:
+                void forward_skip() const
+                {
+                    if constexpr (std::is_same_v<iterator_category, std::random_access_iterator_tag>)
+                    {
+                        if (skip > 0)
+                        {
+                            this->iter = this->iter + skip;
+                            skip = 0;
+                        }
+                    } else
+                    {
+                        while (skip > 0)
+                        {
+                            ++this->iter;
+                            --skip;
+                        }
+                    }
+                }
+                
+                mutable blt::size_t skip;
+        };
+        
+        template<typename Derived>
+        class take_t
+        {
+            private:
+                template<bool check>
+                auto take_base(blt::size_t n)
+                {
+                    static_assert(!std::is_same_v<typename Derived::iterator_category, std::input_iterator_tag>,
+                                  "Cannot .take() on an input iterator!");
+                    auto* d = static_cast<Derived*>(this);
+                    auto begin = d->begin();
+                    auto end = d->end();
+                    
+                    // take variant for forward and bidirectional iterators
+                    if constexpr (std::is_same_v<typename Derived::iterator_category, std::forward_iterator_tag> ||
+                                  std::is_same_v<typename Derived::iterator_category, std::bidirectional_iterator_tag>)
+                    {
+                        // with these guys we have to loop forward to move the iterators. an unfortunate inefficiency
+                        auto new_end = begin;
+                        for (blt::size_t i = 0; i < n; i++)
+                        {
+                            if constexpr (check)
+                            {
+                                if (new_end == end)
+                                    break;
+                            }
+                            ++new_end;
+                        }
+                        return Derived{std::move(begin), std::move(new_end)};
+                    } else if constexpr (std::is_same_v<typename Derived::iterator_category, std::random_access_iterator_tag>)
+                    {
+                        // random access iterators can have math directly applied to them.
+                        if constexpr (check)
+                        {
+                            return Derived{begin, begin + std::min(static_cast<blt::ptrdiff_t>(n), std::distance(begin, end))};
+                        } else
+                        {
+                            return Derived{begin, begin + n};
+                        }
+                    }
+                }
+            
+            public:
+                auto take(blt::size_t n)
+                { return take_base<false>(n); }
+                
+                auto take_or(blt::size_t n)
+                { return take_base<true>(n); }
+        };
+    }
+    
+    template<typename IterBase>
+    class iterator_container : public impls::take_t<iterator_container<IterBase>>
+    {
+        public:
+            using iterator_category = typename IterBase::iterator_category;
+            
+            iterator_container(IterBase begin, IterBase end): m_begin(std::move(begin)), m_end(std::move(end))
+            {}
+            
+            template<typename Iter>
+            iterator_container(Iter&& begin, Iter&& end): m_begin(std::forward<Iter>(begin)), m_end(std::forward<Iter>(end))
+            {}
+            
+            auto rev()
+            {
+                static_assert((std::is_same_v<typename IterBase::iterator_category, std::bidirectional_iterator_tag> ||
+                               std::is_same_v<typename IterBase::iterator_category, std::random_access_iterator_tag>),
+                              ".rev() must be used with bidirectional (or better) iterators!");
+                return iterator_container<std::reverse_iterator<IterBase>>{std::reverse_iterator<IterBase>{end()},
+                                                                           std::reverse_iterator<IterBase>{begin()}};
+            }
+            
+            auto skip(blt::size_t n)
+            {
+                return iterator_container<impls::skip_wrapper<IterBase>>{impls::skip_wrapper<IterBase>{begin(), n},
+                                                                         impls::skip_wrapper<IterBase>{end(), n}};
+            }
+            
+            auto begin() const
+            {
+                return m_begin;
+            }
+            
+            auto end() const
+            {
+                return m_end;
+            }
+        
+        protected:
+            IterBase m_begin;
+            IterBase m_end;
+    };
+    
 }
 
 #endif //BLT_ITERATOR_ITER_COMMON
diff --git a/include/blt/iterator/zip.h b/include/blt/iterator/zip.h
index 4efb86a..4a04d41 100644
--- a/include/blt/iterator/zip.h
+++ b/include/blt/iterator/zip.h
@@ -38,6 +38,9 @@ namespace blt
                 using pointer = value_type;
                 using reference = value_type;
                 
+                explicit zip_wrapper(std::tuple<Iter...> iter): iter(std::move(iter))
+                {}
+                
                 explicit zip_wrapper(Iter... iter): iter(std::make_tuple(iter...))
                 {}
                 
@@ -77,7 +80,7 @@ namespace blt
                     return sub(a, b, std::index_sequence_for<Iter...>());
                 }
                 
-                auto base()
+                auto base() const
                 {
                     return iter;
                 }
@@ -94,80 +97,6 @@ namespace blt
                     return min;
                 }
         };
-        
-        template<typename Iter, bool checked>
-        struct skip_wrapper : public passthrough_wrapper<Iter, skip_wrapper<Iter, checked>>
-        {
-            public:
-                using iterator_category = typename std::iterator_traits<Iter>::iterator_category;
-                using value_type = typename std::iterator_traits<Iter>::value_type;
-                using difference_type = typename std::iterator_traits<Iter>::difference_type;
-                using pointer = typename std::iterator_traits<Iter>::pointer;
-                using reference = typename std::iterator_traits<Iter>::reference;
-                
-                explicit skip_wrapper(Iter iter, blt::size_t n): passthrough_wrapper<Iter, skip_wrapper<Iter, checked>>(std::move(iter)), skip(n)
-                {}
-                
-                skip_wrapper& operator++()
-                {
-                    if constexpr (std::is_same_v<iterator_category, std::random_access_iterator_tag>)
-                    {
-                        if (skip > 0)
-                        {
-                            this->base() += skip;
-                            skip = 0;
-                        }
-                    } else
-                    {
-                        while (skip > 0)
-                        {
-                            ++this->base();
-                            --skip;
-                        }
-                    }
-                    
-                    ++this->base();
-                    return *this;
-                }
-                
-                skip_wrapper& operator--()
-                {
-                    if constexpr (std::is_same_v<iterator_category, std::random_access_iterator_tag>)
-                    {
-                        if (skip > 0)
-                        {
-                            this->base() -= skip;
-                            skip = 0;
-                        }
-                    } else
-                    {
-                        while (skip > 0)
-                        {
-                            --this->base();
-                            --skip;
-                        }
-                    }
-                    --this->base();
-                    return *this;
-                }
-                
-                friend skip_wrapper operator+(const skip_wrapper& a, blt::ptrdiff_t n)
-                {
-                    static_assert(std::is_same_v<iterator_category, std::random_access_iterator_tag>,
-                                  "Iterator must allow random access");
-                    return {a.base() + static_cast<blt::ptrdiff_t>(a.skip) + n, 0};
-                }
-                
-                friend skip_wrapper operator-(const skip_wrapper& a, blt::ptrdiff_t n)
-                {
-                    static_assert(std::is_same_v<iterator_category, std::random_access_iterator_tag>,
-                                  "Iterator must allow random access");
-                    return {a.base() - static_cast<blt::ptrdiff_t>(a.skip) - n, 0};
-                }
-            
-            private:
-                blt::size_t skip;
-        };
     }
     
     template<typename Iter>
@@ -183,92 +112,15 @@ namespace blt
     };
     
     template<typename... Iter>
-    class zip_iterator_storage;
-    
-    template<typename... Iter>
-    class zip_iterator_storage_rev;
-    
-    template<typename... Iter>
-    class zip_iterator_storage
+    class zip_iterator_storage : public iterator::iterator_container<iterator::zip_wrapper<Iter...>>
     {
         public:
-            using iterator_category = meta::lowest_iterator_category_t<Iter...>;
-        public:
-            zip_iterator_storage(iterator_pair<Iter>... iterator_pairs):
-                    m_begins(std::move(iterator_pairs.begin)...), m_ends(std::move(iterator_pairs.end)...)
+            using iterator::iterator_container<iterator::zip_wrapper<Iter...>>::iterator_container;
+            
+            explicit zip_iterator_storage(iterator_pair<Iter>... iterator_pairs):
+                    iterator::iterator_container<iterator::zip_wrapper<Iter...>>(iterator::zip_wrapper<Iter...>{std::move(iterator_pairs.begin)...},
+                                                                                 iterator::zip_wrapper<Iter...>{std::move(iterator_pairs.end)...})
             {}
-            
-            zip_iterator_storage(iterator::zip_wrapper<Iter...> begins, iterator::zip_wrapper<Iter...> ends):
-                    m_begins(std::move(begins)), m_ends(std::move(ends))
-            {}
-            
-            auto rev()
-            {
-                static_assert((std::is_same_v<iterator_category, std::bidirectional_iterator_tag> ||
-                               std::is_same_v<iterator_category, std::random_access_iterator_tag>),
-                              ".rev() must be used with bidirectional (or better) iterators!");
-                return zip_iterator_storage_rev{m_ends, m_begins};
-            }
-            
-            auto skip(blt::size_t n)
-            {
-            
-            }
-            
-            auto begin() const
-            {
-                return m_begins;
-            }
-            
-            auto end() const
-            {
-                return m_ends;
-            }
-        
-        private:
-            iterator::zip_wrapper<Iter...> m_begins;
-            iterator::zip_wrapper<Iter...> m_ends;
-    };
-    
-    template<typename... Iter>
-    class zip_iterator_storage_rev
-    {
-        public:
-            using iterator_category = meta::lowest_iterator_category_t<Iter...>;
-        public:
-            zip_iterator_storage_rev(iterator_pair<Iter>... iterator_pairs): m_begins(iterator_pairs.begin...), m_ends(iterator_pairs.end...)
-            {
-                static_assert((std::is_same_v<iterator_category, std::bidirectional_iterator_tag> ||
-                               std::is_same_v<iterator_category, std::random_access_iterator_tag>),
-                              "reverse iteration is only supported on bidirectional or better iterators!");
-            }
-            
-            zip_iterator_storage_rev(iterator::zip_wrapper<Iter...> begins,
-                                     iterator::zip_wrapper<Iter...> ends): m_begins(std::move(begins)), m_ends(std::move(ends))
-            {
-                static_assert((std::is_same_v<iterator_category, std::bidirectional_iterator_tag> ||
-                               std::is_same_v<iterator_category, std::random_access_iterator_tag>),
-                              "reverse iteration is only supported on bidirectional or better iterators!");
-            }
-            
-            auto rev()
-            {
-                return zip_iterator_storage{m_ends.base(), m_begins.base()};
-            }
-            
-            auto begin() const
-            {
-                return m_begins;
-            }
-            
-            auto end() const
-            {
-                return m_ends;
-            }
-        
-        private:
-            std::reverse_iterator<iterator::zip_wrapper<Iter...>> m_begins;
-            std::reverse_iterator<iterator::zip_wrapper<Iter...>> m_ends;
     };
     
     /*
@@ -281,11 +133,6 @@ namespace blt
     template<typename... Iter>
     zip_iterator_storage(std::initializer_list<Iter>...) -> zip_iterator_storage<Iter...>;
     
-    template<typename... Iter>
-    zip_iterator_storage_rev(iterator_pair<Iter>...) -> zip_iterator_storage_rev<Iter...>;
-    
-    template<typename... Iter>
-    zip_iterator_storage_rev(std::initializer_list<Iter>...) -> zip_iterator_storage_rev<Iter...>;
     
     /*
      * Helper functions for creating zip containers
diff --git a/libraries/parallel-hashmap b/libraries/parallel-hashmap
index 93201da..7ef2e73 160000
--- a/libraries/parallel-hashmap
+++ b/libraries/parallel-hashmap
@@ -1 +1 @@
-Subproject commit 93201da2ba5a6aba0a6e57ada64973555629b3e3
+Subproject commit 7ef2e733416953b222851f9a360d7fc72d068ee5
diff --git a/tests/iterator_tests.cpp b/tests/iterator_tests.cpp
index 0ee82fc..0fb5198 100644
--- a/tests/iterator_tests.cpp
+++ b/tests/iterator_tests.cpp
@@ -136,7 +136,7 @@ void test_zip()
         BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n";
     }
     BLT_TRACE("================================");
-    for (auto [a1, a2, a3] : blt::zip(array_1, array_2, list_1).take(3).rev())
+    for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).take(3).rev())
     {
         BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n";
     }
@@ -150,6 +150,11 @@ void test_zip()
     {
         BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n";
     }
+    BLT_TRACE("================================");
+    for (auto [a1, a2, a3] : blt::zip(array_1, array_2, array_3).skip(2).rev())
+    {
+        BLT_TRACE_STREAM << a1 << " : " << a2 << " : " << a3 << "\n";
+    }
 }
 
 int main()