staticlib_io  1.2.11
 All Classes Namespaces Files Functions Variables
span.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017, alex at staticlibs.net
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 /*
18  * File: span.hpp
19  * Author: alex
20  *
21  * Created on February 5, 2017, 4:41 PM
22  */
23 
24 #ifndef STATICLIB_SUPPORT_SPAN_HPP
25 #define STATICLIB_SUPPORT_SPAN_HPP
26 
27 #include <cstdint>
28 #include <array>
29 #include <ios>
30 #include <string>
31 #include <vector>
32 
33 #include "staticlib/config.hpp"
34 #include "staticlib/support.hpp"
35 
36 namespace staticlib {
37 namespace io {
38 
42 class bad_span_access_exception : public sl::support::exception {
43 public:
44 
48  bad_span_access_exception() = default;
49 
55  bad_span_access_exception(const std::string& msg) :
56  sl::support::exception(msg) { }
57 
58 };
59 
60 
64 template<typename T>
65 class span {
69  T* first_ptr = nullptr;
73  T* last_ptr = nullptr;
74 
75 public:
76 
84  template<typename IntType>
85  span(T* buffer, IntType length) :
86  first_ptr(buffer),
87  last_ptr(buffer) {
88  if (nullptr != buffer) {
89  // note: zero-length span is allowed
90  if (/* length > 0 && */ sl::support::is_sizet(length) && sl::support::is_streamsize(length)) {
91  last_ptr += static_cast<size_t> (length);
92  } else {
93  throw bad_span_access_exception(std::string() + "Invalid 'length' span parameter specified," +
94  " length: [" + sl::support::to_string(length) + "]");
95  }
96  } else if (0 != length) {
97  throw bad_span_access_exception(std::string() + "Invalid 'null' data pointer specified to span," +
98  " length: [" + sl::support::to_string(length) + "]");
99  }
100  }
101 
107  template<typename Convertible, size_t Length>
108  span(std::array<Convertible, Length>& buffer) :
109  span(buffer.size() > 0 ? buffer.data() : nullptr, buffer.size()) { }
110 
116  span(std::vector<T>& buffer) :
117  span(buffer.size() > 0 ? buffer.data() : nullptr, buffer.size()) { }
118 
124  template<typename Convertible>
125  span(std::vector<Convertible>& buffer) :
126  span(buffer.size() > 0 ? buffer.data() : nullptr, buffer.size()) { }
127 
133  span(std::string& buffer) :
134  span(buffer.length() > 0 ? std::addressof(buffer.front()) : nullptr, buffer.length()) { }
135 
141  span(const std::string& buffer) :
142  span(buffer.length() > 0 ? buffer.data() : nullptr, buffer.length()) { }
143 
149  template<size_t Size>
150  span(const char (&buffer)[Size]) :
151  span(Size > 1 ? static_cast<const char*>(buffer) : nullptr, Size - 1) { }
152 
158  span(const span<T>& other) :
159  first_ptr(other.first_ptr),
160  last_ptr(other.last_ptr) { }
161 
167  span<T>& operator=(const span<T>& other) {
168  first_ptr = other.first_ptr;
169  last_ptr = other.last_ptr;
170  return *this;
171  }
172 
180  T& operator[](size_t index) const {
181  if (index < size()) {
182  return *(first_ptr + index);
183  } else {
184  throw bad_span_access_exception(std::string() + "Invalid index access attempt," +
185  " span size: [" + sl::support::to_string(size()) + "],"
186  " index: [" + sl::support::to_string(index) + "]");
187  }
188  }
189 
195  T* data() const STATICLIB_NOEXCEPT {
196  return first_ptr;
197  }
198 
204  bool empty() const STATICLIB_NOEXCEPT {
205  return 0 == size();
206  }
207 
213  bool is_empty() const STATICLIB_NOEXCEPT {
214  return empty();
215  }
216 
222  bool is_null() const STATICLIB_NOEXCEPT {
223  return nullptr == first_ptr;
224  }
225 
231  size_t size() const STATICLIB_NOEXCEPT {
232  return nullptr == first_ptr ? 0 : last_ptr - first_ptr;
233  }
234 
240  std::streamsize size_signed() const STATICLIB_NOEXCEPT {
241  return static_cast<std::streamsize>(size());
242  }
243 
249  int size_int() const STATICLIB_NOEXCEPT {
250  return static_cast<int>(size());
251  }
252 
258  size_t size_bytes() const STATICLIB_NOEXCEPT {
259  return (size()) * sizeof(T);
260  }
261 
267  T* begin() const STATICLIB_NOEXCEPT {
268  return first_ptr;
269  }
270 
276  T* end() const STATICLIB_NOEXCEPT {
277  return last_ptr;
278  }
279 
280 };
281 
289 template<typename T, typename IntType>
290 span<T> make_span(T* buffer, IntType length) {
291  return span<T>(buffer, length);
292 }
293 
300 template<typename T, size_t Length>
301 span<T> make_span(std::array<T, Length>& buffer) {
302  return span<T>(buffer.data(), buffer.size());
303 }
304 
311 template<typename T>
312 span<T> make_span(std::vector<T>& buffer) {
313  return span<T>(buffer.data(), buffer.size());
314 }
315 
316 } // namespace
317 }
318 
319 #endif /* STATICLIB_SUPPORT_SPAN_HPP */
320