From 9487f0e564bbb5163ad33860d82f2be16b7ab562 Mon Sep 17 00:00:00 2001
From: Steven Le Rouzic <steven.lerouzic@gmail.com>
Date: Sat, 18 Jan 2025 23:31:54 +0100
Subject: Add contiguous iterators

---
 asl/buffer.hpp      |  7 +++++++
 asl/format.cpp      | 26 +++++++++++---------------
 asl/hash_map.hpp    | 16 +++++++++++++++-
 asl/span.hpp        | 43 +++++++++++++++++++++++++++++++++++++++++--
 asl/string_view.hpp |  7 ++++---
 5 files changed, 78 insertions(+), 21 deletions(-)

(limited to 'asl')

diff --git a/asl/buffer.hpp b/asl/buffer.hpp
index 93f811b..9fd8162 100644
--- a/asl/buffer.hpp
+++ b/asl/buffer.hpp
@@ -357,6 +357,13 @@ public:
         }
     }
 
+    // @Todo(C++23) Use deducing this
+    constexpr contiguous_iterator<const T> begin() const { return contiguous_iterator{data()}; }
+    constexpr contiguous_iterator<const T> end() const { return contiguous_iterator{data() + size()}; }
+    
+    constexpr contiguous_iterator<T> begin() { return contiguous_iterator{data()}; }
+    constexpr contiguous_iterator<T> end() { return contiguous_iterator{data() + size()}; }
+
     // @Todo(C++23) Deducing this
     constexpr operator span<const T>() const // NOLINT(*-explicit-conversions)
     {
diff --git a/asl/format.cpp b/asl/format.cpp
index 1371431..9e31888 100644
--- a/asl/format.cpp
+++ b/asl/format.cpp
@@ -10,8 +10,8 @@ void asl::format_internals::format(
 {
     Formatter f(writer);
 
-    const auto* arg_it = args.begin();
-    const auto* arg_end = args.end();
+    auto arg_it = args.begin();
+    auto arg_end = args.end();
     
     isize_t i = 0;
     while (i < fmt.size())
@@ -22,23 +22,19 @@ void asl::format_internals::format(
             {
                 if (fmt[i + 1] == '}')
                 {
-                    if (arg_it >= arg_end)
-                    {
-                        f.write(fmt.substr(0, i));
-                        fmt = fmt.substr(i + 2);
-                        i = 0;
-
-                        f.write("<ERROR>");
-
-                        continue;
-                    }
-                    
                     f.write(fmt.substr(0, i));
                     fmt = fmt.substr(i + 2);
                     i = 0;
 
-                    arg_it->fn(f, arg_it->data);
-                    arg_it++; // NOLINT(*-pointer-arithmetic)
+                    if (arg_it == arg_end)
+                    {
+                        f.write("<ERROR>");
+                    }
+                    else
+                    {
+                        arg_it->fn(f, arg_it->data);
+                        arg_it++;
+                    }
 
                     continue;
                 }
diff --git a/asl/hash_map.hpp b/asl/hash_map.hpp
index 300ffdb..93f93e7 100644
--- a/asl/hash_map.hpp
+++ b/asl/hash_map.hpp
@@ -147,9 +147,23 @@ public:
         // NOLINTEND(*-pointer-arithmetic)
     }
     
+    // @Todo(C++23) Deducing this
     template<typename U>
     requires key_hasher<KeyHasher, U> && key_comparator<KeyComparator, K, U>
-    V* get(const U& value) const
+    const V* get(const U& value) const
+    {
+        isize_t index = Base::find_slot_lookup(value);
+        if (index >= 0)
+        {
+            // NOLINTNEXTLINE(*-pointer-arithmetic)
+            return &Base::m_values[index].as_init_unsafe().value;
+        }
+        return nullptr;
+    }
+    
+    template<typename U>
+    requires key_hasher<KeyHasher, U> && key_comparator<KeyComparator, K, U>
+    V* get(const U& value)
     {
         isize_t index = Base::find_slot_lookup(value);
         if (index >= 0)
diff --git a/asl/span.hpp b/asl/span.hpp
index 8f6fb4a..730ef71 100644
--- a/asl/span.hpp
+++ b/asl/span.hpp
@@ -10,6 +10,38 @@ namespace asl
 
 static constexpr isize_t dynamic_size = -1;
 
+template<typename T>
+class contiguous_iterator
+{
+    T* m_ptr;
+
+public:
+    constexpr explicit contiguous_iterator(T* ptr) : m_ptr{ptr} {}
+
+    constexpr bool operator==(const contiguous_iterator& other) const
+    {
+        return other.m_ptr == m_ptr;
+    }
+
+    constexpr contiguous_iterator& operator++()
+    {
+        m_ptr += 1;
+        return *this;
+    }
+
+    constexpr contiguous_iterator operator++(int)
+    {
+        return contiguous_iterator{ exchange(m_ptr, m_ptr + 1) };
+    }
+
+    constexpr T& operator*() const { return *m_ptr; }
+
+    constexpr T* operator->() const { return m_ptr; }
+};
+
+template<typename T>
+contiguous_iterator(T) -> contiguous_iterator<T>;
+
 template<is_object T, isize_t kSize = dynamic_size>
 class span
 {
@@ -88,8 +120,15 @@ public:
 
     constexpr T* data() const { return m_data; }
 
-    constexpr T* begin() const { return m_data; }
-    constexpr T* end() const { return m_data + size(); }
+    constexpr contiguous_iterator<T> begin() const
+    {
+        return contiguous_iterator{m_data};
+    }
+    
+    constexpr contiguous_iterator<T> end() const
+    {
+        return contiguous_iterator{m_data + size()};
+    }
 
     constexpr T& operator[](isize_t i) const
     {
diff --git a/asl/string_view.hpp b/asl/string_view.hpp
index 673e3bc..f53fff9 100644
--- a/asl/string_view.hpp
+++ b/asl/string_view.hpp
@@ -46,9 +46,10 @@ public:
 
     constexpr const char* data() const { return m_data; }
 
-    constexpr const char* begin() const { return m_data; }
-    
-    constexpr const char* end() const { return m_data + m_size; } // NOLINT(*-pointer-arithmetic)
+    constexpr contiguous_iterator<const char> begin() const { return contiguous_iterator{m_data}; }
+
+    // NOLINTNEXTLINE(*-pointer-arithmetic)
+    constexpr contiguous_iterator<const char> end() const { return contiguous_iterator{m_data + m_size}; }
 
     constexpr span<const char> as_span() const { return span<const char>(m_data, m_size); }
 
-- 
cgit