unilink  0.4.3
A simple C++ library for unified async communication
safe_span.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2025 Jinwoo Sung
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <cstdint>
20 #include <stdexcept>
21 #include <type_traits>
22 
23 namespace unilink {
24 namespace memory {
25 
37 template <typename T>
38 class SafeSpan {
39  public:
40  using element_type = T;
41  using value_type = std::remove_cv_t<T>;
42  using size_type = std::size_t;
43  using difference_type = std::ptrdiff_t;
44  using pointer = T*;
45  using const_pointer = const T*;
46  using reference = T&;
47  using const_reference = const T&;
48  using iterator = T*;
49  using const_iterator = const T*;
50  using reverse_iterator = std::reverse_iterator<iterator>;
51  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
52 
53  // Constructors
54  constexpr SafeSpan() noexcept : data_(nullptr), size_(0) {}
55 
56  constexpr SafeSpan(pointer data, size_type size) noexcept : data_(data), size_(size) {}
57 
58  template <typename Container>
59  constexpr SafeSpan(Container& container) noexcept : data_(container.data()), size_(container.size()) {}
60 
61  template <typename Container>
62  constexpr SafeSpan(const Container& container) noexcept
63  : data_(const_cast<pointer>(container.data())), size_(container.size()) {}
64 
65  // Access methods
66  constexpr reference operator[](size_type index) const { return data_[index]; }
67 
68  constexpr reference at(size_type index) const {
69  if (index >= size_) {
70  throw std::out_of_range("SafeSpan index out of range");
71  }
72  return data_[index];
73  }
74 
75  constexpr reference front() const { return data_[0]; }
76 
77  constexpr reference back() const { return data_[size_ - 1]; }
78 
79  constexpr pointer data() const noexcept { return data_; }
80 
81  constexpr size_type size() const noexcept { return size_; }
82 
83  constexpr size_type size_bytes() const noexcept { return size_ * sizeof(T); }
84 
85  constexpr bool empty() const noexcept { return size_ == 0; }
86 
87  // Iterator support
88  constexpr iterator begin() const noexcept { return data_; }
89 
90  constexpr iterator end() const noexcept { return data_ + size_; }
91 
92  constexpr const_iterator cbegin() const noexcept { return data_; }
93 
94  constexpr const_iterator cend() const noexcept { return data_ + size_; }
95 
96  constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
97 
98  constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
99 
100  constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
101 
102  constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
103 
104  // Subspan operations
105  constexpr SafeSpan<T> subspan(size_type offset, size_type count = SIZE_MAX) const {
106  if (offset > size_) {
107  throw std::out_of_range("SafeSpan subspan offset out of range");
108  }
109  size_type actual_count = (count == SIZE_MAX) ? (size_ - offset) : count;
110  if (offset + actual_count > size_) {
111  throw std::out_of_range("SafeSpan subspan count out of range");
112  }
113  return SafeSpan<T>(data_ + offset, actual_count);
114  }
115 
116  constexpr SafeSpan<T> first(size_type count) const { return subspan(0, count); }
117 
118  constexpr SafeSpan<T> last(size_type count) const { return subspan(size_ - count, count); }
119 
120  private:
121  pointer data_;
122  size_type size_;
123 };
124 
125 // Type aliases for common types
130 
131 } // namespace memory
132 } // namespace unilink