Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
span.h
Go to the documentation of this file.
1// Copyright 2024 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CORE_FXCRT_SPAN_H_
6#define CORE_FXCRT_SPAN_H_
7
8#include <stddef.h>
9#include <stdint.h>
10
11#include <array>
12#include <iterator>
13#include <type_traits>
14
15#include "core/fxcrt/check.h"
16#include "core/fxcrt/compiler_specific.h"
17#include "core/fxcrt/unowned_ptr_exclusion.h"
18
19// SAFETY: TODO(crbug.com/pdfium/2085): this entire file is to be replaced
20// with the fully annotated one that is being prepared in base/.
21
22namespace pdfium {
23
24constexpr size_t dynamic_extent = static_cast<size_t>(-1);
25
26template <typename T>
28
29template <typename T,
30 size_t Extent = dynamic_extent,
31 typename InternalPtr = DefaultSpanInternalPtr<T>>
32class span;
33
34namespace internal {
35
36template <typename T>
37struct IsSpanImpl : std::false_type {};
38
39template <typename T>
40struct IsSpanImpl<span<T>> : std::true_type {};
41
42template <typename T>
43using IsSpan = IsSpanImpl<typename std::decay<T>::type>;
44
45template <typename T>
46struct IsStdArrayImpl : std::false_type {};
47
48template <typename T, size_t N>
49struct IsStdArrayImpl<std::array<T, N>> : std::true_type {};
50
51template <typename T>
52using IsStdArray = IsStdArrayImpl<typename std::decay<T>::type>;
53
54template <typename From, typename To>
55using IsLegalSpanConversion = std::is_convertible<From*, To*>;
56
57template <typename Container, typename T>
59 IsLegalSpanConversion<typename std::remove_pointer<decltype(
60 std::declval<Container>().data())>::type,
61 T>;
62template <typename Container>
64 std::is_integral<decltype(std::declval<Container>().size())>;
65
66template <typename From, typename To>
69
70// SFINAE check if Container can be converted to a span<T>. Note that the
71// implementation details of this check differ slightly from the requirements in
72// the working group proposal: in particular, the proposal also requires that
73// the container conversion constructor participate in overload resolution only
74// if two additional conditions are true:
75//
76// 1. Container implements operator[].
77// 2. Container::value_type matches remove_const_t<element_type>.
78//
79// The requirements are relaxed slightly here: in particular, not requiring (2)
80// means that an immutable span can be easily constructed from a mutable
81// container.
82template <typename Container, typename T>
88
89template <typename Container, typename T>
91 typename std::enable_if<std::is_const<T>::value &&
96
97} // namespace internal
98
99// A span is a value type that represents an array of elements of type T. Since
100// it only consists of a pointer to memory with an associated size, it is very
101// light-weight. It is cheap to construct, copy, move and use spans, so that
102// users are encouraged to use it as a pass-by-value parameter. A span does not
103// own the underlying memory, so care must be taken to ensure that a span does
104// not outlive the backing store.
105//
106// span is somewhat analogous to StringPiece, but with arbitrary element types,
107// allowing mutation if T is non-const.
108//
109// span is implicitly convertible from C++ arrays, as well as most [1]
110// container-like types that provide a data() and size() method (such as
111// std::vector<T>). A mutable span<T> can also be implicitly converted to an
112// immutable span<const T>.
113//
114// Consider using a span for functions that take a data pointer and size
115// parameter: it allows the function to still act on an array-like type, while
116// allowing the caller code to be a bit more concise.
117//
118// For read-only data access pass a span<const T>: the caller can supply either
119// a span<const T> or a span<T>, while the callee will have a read-only view.
120// For read-write access a mutable span<T> is required.
121//
122// Without span:
123// Read-Only:
124// // std::string HexEncode(const uint8_t* data, size_t size);
125// std::vector<uint8_t> data_buffer = GenerateData();
126// std::string r = HexEncode(data_buffer.data(), data_buffer.size());
127//
128// Mutable:
129// // ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, Args...);
130// char str_buffer[100];
131// SafeSNPrintf(str_buffer, sizeof(str_buffer), "Pi ~= %lf", 3.14);
132//
133// With span:
134// Read-Only:
135// // std::string HexEncode(base::span<const uint8_t> data);
136// std::vector<uint8_t> data_buffer = GenerateData();
137// std::string r = HexEncode(data_buffer);
138//
139// Mutable:
140// // ssize_t SafeSNPrintf(base::span<char>, const char* fmt, Args...);
141// char str_buffer[100];
142// SafeSNPrintf(str_buffer, "Pi ~= %lf", 3.14);
143//
144// Spans with "const" and pointers
145// -------------------------------
146//
147// Const and pointers can get confusing. Here are vectors of pointers and their
148// corresponding spans (you can always make the span "more const" too):
149//
150// const std::vector<int*> => base::span<int* const>
151// std::vector<const int*> => base::span<const int*>
152// const std::vector<const int*> => base::span<const int* const>
153//
154// Differences from the working group proposal
155// -------------------------------------------
156//
157// https://wg21.link/P0122 is the latest working group proposal, Chromium
158// currently implements R6. The biggest difference is span does not support a
159// static extent template parameter. Other differences are documented in
160// subsections below.
161//
162// Differences in constants and types:
163// - no element_type type alias
164// - no index_type type alias
165// - no different_type type alias
166// - no extent constant
167//
168// Differences from [span.cons]:
169// - no constructor from a pointer range
170//
171// Differences from [span.sub]:
172// - using size_t instead of ptrdiff_t for indexing
173//
174// Differences from [span.obs]:
175// - using size_t instead of ptrdiff_t to represent size()
176//
177// Differences from [span.elem]:
178// - no operator ()()
179// - using size_t instead of ptrdiff_t for indexing
180//
181// Additions beyond the C++ standard draft
182// - as_chars() function.
183// - as_writable_chars() function.
184// - as_byte_span() function.
185// - as_writable_byte_span() function.
186// - span_from_ref() function.
187// - byte_span_from_ref() function.
188
189// [span], class template span
190template <typename T, size_t Extent, typename InternalPtr>
192 public:
193 using value_type = typename std::remove_cv<T>::type;
194 using pointer = T*;
195 using reference = T&;
196 using iterator = T*;
197 using const_iterator = const T*;
198 using reverse_iterator = std::reverse_iterator<iterator>;
199 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
200
201 // [span.cons], span constructors, copy, assignment, and destructor
202 constexpr span() noexcept = default;
203
204 UNSAFE_BUFFER_USAGE constexpr span(T* data, size_t size) noexcept
205 : data_(data), size_(size) {
206// DCHECK(data_ || size_ == 0);
207 }
208
209 // TODO(dcheng): Implement construction from a |begin| and |end| pointer.
210 template <size_t N>
211 constexpr span(T (&array)[N]) noexcept : span(array, N) {
212 static_assert(Extent == dynamic_extent || Extent == N);
213 }
214
215 template <size_t N>
216 constexpr span(std::array<T, N>& array) noexcept : span(array.data(), N) {
217 static_assert(Extent == dynamic_extent || Extent == N);
218 }
219
220 template <size_t N>
221 constexpr span(const std::array<std::remove_cv_t<T>, N>& array) noexcept
222 : span(array.data(), N) {
223 static_assert(Extent == dynamic_extent || Extent == N);
224 }
225
226 // Conversion from a container that provides |T* data()| and |integral_type
227 // size()|. Note that |data()| may not return nullptr for some empty
228 // containers, which can lead to container overflow errors when probing
229 // raw ptrs.
230#if defined(ADDRESS_SANITIZER) && defined(PDF_USE_PARTITION_ALLOC)
231 template <typename Container,
233 constexpr span(Container& container)
234 : span(container.size() ? container.data() : nullptr, container.size()) {}
235#else
236 template <typename Container,
238 constexpr span(Container& container)
239 : span(container.data(), container.size()) {}
240#endif
241
242 template <
243 typename Container,
245 span(const Container& container) : span(container.data(), container.size()) {}
246
247 constexpr span(const span& other) noexcept = default;
248
249 // Conversions from spans of compatible types: this allows a span<T> to be
250 // seamlessly used as a span<const T>, but not the other way around.
251 template <typename U,
252 size_t M,
253 typename R,
255 constexpr span(const span<U, M, R>& other)
256 : span(other.data(), other.size()) {}
257
258 span& operator=(const span& other) noexcept {
259 if (this != &other) {
260 data_ = other.data_;
261 size_ = other.size_;
262 }
263 return *this;
264 }
265 ~span() noexcept = default;
266
267 // [span.sub], span subviews
268 template <size_t Count>
269 span first() const {
270 // TODO(tsepez): The following check isn't yet good enough to replace
271 // the runtime check since we are still allowing unchecked conversions
272 // to arbitrary non-dynamic_extent spans.
273 static_assert(Extent == dynamic_extent || Count <= Extent);
274 return first(Count);
275 }
276 const span first(size_t count) const {
277 CHECK(count <= size_);
278 // SAFETY: CHECK() on line above.
279 return UNSAFE_BUFFERS(span(static_cast<T*>(data_), count));
280 }
281
282 template <size_t Count>
283 span last() const {
284 // TODO(tsepez): The following check isn't yet good enough to replace
285 // the runtime check since we are still allowing unchecked conversions
286 // to arbitrary non-dynamic_extent spans.
287 static_assert(Extent == dynamic_extent || Count <= Extent);
288 return last(Count);
289 }
290 const span last(size_t count) const {
291 CHECK(count <= size_);
292 return UNSAFE_BUFFERS(
293 span(static_cast<T*>(data_) + (size_ - count), count));
294 }
295
296 template <size_t Offset, size_t Count = dynamic_extent>
297 span subspan() const {
298 // TODO(tsepez): The following check isn't yet good enough to replace
299 // the runtime check since we are still allowing unchecked conversions
300 // to arbitrary non-dynamic_extent spans.
301 static_assert(Extent == dynamic_extent || Count == dynamic_extent ||
302 Offset + Count <= Extent);
303 return subspan(Offset, Count);
304 }
305 const span subspan(size_t pos, size_t count = dynamic_extent) const {
306 CHECK(pos <= size_);
307 CHECK(count == dynamic_extent || count <= size_ - pos);
308 // SAFETY: CHECK()s on lines above.
309 return UNSAFE_BUFFERS(span(static_cast<T*>(data_) + pos,
310 count == dynamic_extent ? size_ - pos : count));
311 }
312
313 // [span.obs], span observers
314 constexpr size_t size() const noexcept { return size_; }
315 constexpr size_t size_bytes() const noexcept { return size() * sizeof(T); }
316 constexpr bool empty() const noexcept { return size_ == 0; }
317
318 // [span.elem], span element access
319 T& operator[](size_t index) const noexcept {
320 CHECK(index < size_);
321 return UNSAFE_BUFFERS(static_cast<T*>(data_)[index]);
322 }
323
324 constexpr T& front() const noexcept {
325 CHECK(!empty());
326 return *data();
327 }
328
329 constexpr T& back() const noexcept {
330 CHECK(!empty());
331 return UNSAFE_BUFFERS(*(data() + size() - 1));
332 }
333
334 constexpr T* data() const noexcept { return static_cast<T*>(data_); }
335
336 // [span.iter], span iterator support
337 constexpr iterator begin() const noexcept { return static_cast<T*>(data_); }
338 constexpr iterator end() const noexcept {
339 return UNSAFE_BUFFERS(begin() + size_);
340 }
341
342 constexpr const_iterator cbegin() const noexcept { return begin(); }
343 constexpr const_iterator cend() const noexcept { return end(); }
344
345 constexpr reverse_iterator rbegin() const noexcept {
346 return reverse_iterator(end());
347 }
348 constexpr reverse_iterator rend() const noexcept {
350 }
351
352 constexpr const_reverse_iterator crbegin() const noexcept {
354 }
355 constexpr const_reverse_iterator crend() const noexcept {
357 }
358
359 private:
360 template <typename U>
361 friend constexpr span<U> make_span(U* data, size_t size) noexcept;
362
363 InternalPtr data_ = nullptr;
364 size_t size_ = 0;
365};
366
367// Type-deducing helpers for constructing a span.
368template <typename T>
369UNSAFE_BUFFER_USAGE constexpr span<T> make_span(T* data, size_t size) noexcept {
370 return UNSAFE_BUFFERS(span<T>(data, size));
371}
372
373template <typename T, size_t N>
374constexpr span<T> make_span(T (&array)[N]) noexcept {
375 return span<T>(array);
376}
377
378template <typename T, size_t N>
379constexpr span<T> make_span(std::array<T, N>& array) noexcept {
380 return span<T>(array);
381}
382
383template <typename Container,
384 typename T = typename Container::value_type,
386constexpr span<T> make_span(Container& container) {
387 return span<T>(container);
388}
389
390template <
391 typename Container,
392 typename T = typename std::add_const<typename Container::value_type>::type,
394constexpr span<T> make_span(const Container& container) {
395 return span<T>(container);
396}
397
398// [span.objectrep], views of object representation
399template <typename T, size_t N, typename P>
400span<const uint8_t> as_bytes(span<T, N, P> s) noexcept {
401 // SAFETY: from size_bytes() method.
402 return UNSAFE_BUFFERS(
403 make_span(reinterpret_cast<const uint8_t*>(s.data()), s.size_bytes()));
404}
405
406template <typename T,
407 size_t N,
408 typename P,
409 typename U = typename std::enable_if<!std::is_const<T>::value>::type>
410span<uint8_t> as_writable_bytes(span<T, N, P> s) noexcept {
411 // SAFETY: from size_bytes() method.
412 return UNSAFE_BUFFERS(
413 make_span(reinterpret_cast<uint8_t*>(s.data()), s.size_bytes()));
414}
415
416template <typename T, size_t N, typename P>
417span<const char> as_chars(span<T, N, P> s) noexcept {
418 // SAFETY: from size_bytes() method.
419 return UNSAFE_BUFFERS(
420 make_span(reinterpret_cast<const char*>(s.data()), s.size_bytes()));
421}
422
423template <typename T,
424 size_t N,
425 typename P,
426 typename U = typename std::enable_if<!std::is_const<T>::value>::type>
427span<char> as_writable_chars(span<T, N, P> s) noexcept {
428 // SAFETY: from size_bytes() method.
429 return UNSAFE_BUFFERS(
430 make_span(reinterpret_cast<char*>(s.data()), s.size_bytes()));
431}
432
433// `span_from_ref` converts a reference to T into a span of length 1. This is a
434// non-std helper that is inspired by the `std::slice::from_ref()` function from
435// Rust.
436template <typename T>
437static constexpr span<T> span_from_ref(T& single_object) noexcept {
438 // SAFETY: single object passed by reference.
439 return UNSAFE_BUFFERS(make_span<T>(&single_object, 1u));
440}
441
442// `byte_span_from_ref` converts a reference to T into a span of uint8_t of
443// length sizeof(T). This is a non-std helper that is a sugar for
444// `as_writable_bytes(span_from_ref(x))`.
445template <typename T>
446static constexpr span<const uint8_t> byte_span_from_ref(
447 const T& single_object) noexcept {
448 return as_bytes(span_from_ref(single_object));
449}
450template <typename T>
451static constexpr span<uint8_t> byte_span_from_ref(T& single_object) noexcept {
452 return as_writable_bytes(span_from_ref(single_object));
453}
454
455// Convenience function for converting an object which is itself convertible
456// to span into a span of bytes (i.e. span of const uint8_t). Typically used
457// to convert std::string or string-objects holding chars, or std::vector
458// or vector-like objects holding other scalar types, prior to passing them
459// into an API that requires byte spans.
460template <typename T>
461span<const uint8_t> as_byte_span(const T& arg) {
462 return as_bytes(make_span(arg));
463}
464template <typename T>
465span<const uint8_t> as_byte_span(T&& arg) {
466 return as_bytes(make_span(arg));
467}
468
469// Convenience function for converting an object which is itself convertible
470// to span into a span of mutable bytes (i.e. span of uint8_t). Typically used
471// to convert std::string or string-objects holding chars, or std::vector
472// or vector-like objects holding other scalar types, prior to passing them
473// into an API that requires mutable byte spans.
474template <typename T>
475constexpr span<uint8_t> as_writable_byte_span(T&& arg) {
476 return as_writable_bytes(make_span(arg));
477}
478
479} // namespace pdfium
480
481#endif // CORE_FXCRT_SPAN_H_
T & reference
Definition span.h:195
constexpr span(T(&array)[N]) noexcept
Definition span.h:211
constexpr reverse_iterator rend() const noexcept
Definition span.h:348
span last() const
Definition span.h:283
constexpr reverse_iterator rbegin() const noexcept
Definition span.h:345
T * iterator
Definition span.h:196
constexpr const_reverse_iterator crend() const noexcept
Definition span.h:355
span first() const
Definition span.h:269
std::reverse_iterator< iterator > reverse_iterator
Definition span.h:198
const span first(size_t count) const
Definition span.h:276
typename std::remove_cv< T >::type value_type
Definition span.h:193
span & operator=(const span &other) noexcept
Definition span.h:258
constexpr const_iterator cbegin() const noexcept
Definition span.h:342
constexpr const_iterator cend() const noexcept
Definition span.h:343
constexpr const_reverse_iterator crbegin() const noexcept
Definition span.h:352
const span last(size_t count) const
Definition span.h:290
constexpr bool empty() const noexcept
Definition span.h:316
constexpr size_t size() const noexcept
Definition span.h:314
constexpr span(Container &container)
Definition span.h:238
friend constexpr span< U > make_span(U *data, size_t size) noexcept
span subspan() const
Definition span.h:297
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition span.h:199
const span subspan(size_t pos, size_t count=dynamic_extent) const
Definition span.h:305
constexpr iterator begin() const noexcept
Definition span.h:337
constexpr size_t size_bytes() const noexcept
Definition span.h:315
constexpr span() noexcept=default
span(const Container &container)
Definition span.h:245
constexpr span(std::array< T, N > &array) noexcept
Definition span.h:216
T * pointer
Definition span.h:194
constexpr T & back() const noexcept
Definition span.h:329
constexpr span(const std::array< std::remove_cv_t< T >, N > &array) noexcept
Definition span.h:221
constexpr T * data() const noexcept
Definition span.h:334
constexpr T & front() const noexcept
Definition span.h:324
constexpr span(const span &other) noexcept=default
UNSAFE_BUFFER_USAGE constexpr span(T *data, size_t size) noexcept
Definition span.h:204
constexpr span(const span< U, M, R > &other)
Definition span.h:255
T & operator[](size_t index) const noexcept
Definition span.h:319
constexpr iterator end() const noexcept
Definition span.h:338
const T * const_iterator
Definition span.h:197
~span() noexcept=default
#define UNSAFE_BUFFERS(...)
#define GSL_POINTER
#define TRIVIAL_ABI
#define UNSAFE_BUFFER_USAGE
void CRYPT_MD5Finish(CRYPT_md5_context *context, pdfium::span< uint8_t, 16 > digest)
Definition fx_crypt.cpp:203
#define P(a, b, c, d, k, s, t)
void CRYPT_MD5Generate(pdfium::span< const uint8_t > data, pdfium::span< uint8_t, 16 > digest)
Definition fx_crypt.cpp:219
#define S(x, n)
void CRYPT_ArcFourCryptBlock(pdfium::span< uint8_t > data, pdfium::span< const uint8_t > key)
Definition fx_crypt.cpp:157
void CRYPT_ArcFourSetup(CRYPT_rc4_context *context, pdfium::span< const uint8_t > key)
Definition fx_crypt.cpp:131
void CRYPT_MD5Update(CRYPT_md5_context *context, pdfium::span< const uint8_t > data)
Definition fx_crypt.cpp:175
void CRYPT_ArcFourCrypt(CRYPT_rc4_context *context, pdfium::span< uint8_t > data)
Definition fx_crypt.cpp:146
CRYPT_md5_context CRYPT_MD5Start()
Definition fx_crypt.cpp:164
void CRYPT_AESEncrypt(CRYPT_aes_context *ctx, pdfium::span< uint8_t > dest, pdfium::span< const uint8_t > src)
void CRYPT_AESSetIV(CRYPT_aes_context *ctx, const uint8_t *iv)
void CRYPT_AESDecrypt(CRYPT_aes_context *ctx, uint8_t *dest, const uint8_t *src, uint32_t size)
void CRYPT_AESSetKey(CRYPT_aes_context *ctx, const uint8_t *key, uint32_t keylen)
std::is_integral< decltype(std::declval< Container >().size())> ContainerHasIntegralSize
Definition span.h:63
IsSpanImpl< typename std::decay< T >::type > IsSpan
Definition span.h:43
std::is_convertible< From *, To * > IsLegalSpanConversion
Definition span.h:55
IsStdArrayImpl< typename std::decay< T >::type > IsStdArray
Definition span.h:52
constexpr span< T > make_span(T(&array)[N]) noexcept
Definition span.h:374
span< char > as_writable_chars(span< T, N, P > s) noexcept
Definition span.h:427
span< const uint8_t > as_bytes(span< T, N, P > s) noexcept
Definition span.h:400
constexpr size_t dynamic_extent
Definition span.h:24
static constexpr span< T > span_from_ref(T &single_object) noexcept
Definition span.h:437
static constexpr span< const uint8_t > byte_span_from_ref(const T &single_object) noexcept
Definition span.h:446
UNSAFE_BUFFER_USAGE constexpr span< T > make_span(T *data, size_t size) noexcept
Definition span.h:369
span< const uint8_t > as_byte_span(T &&arg)
Definition span.h:465
span< const char > as_chars(span< T, N, P > s) noexcept
Definition span.h:417
span< const uint8_t > as_byte_span(const T &arg)
Definition span.h:461
UNOWNED_PTR_EXCLUSION T * DefaultSpanInternalPtr
Definition span.h:27
span< uint8_t > as_writable_bytes(span< T, N, P > s) noexcept
Definition span.h:410
constexpr span< T > make_span(std::array< T, N > &array) noexcept
Definition span.h:379
constexpr span< T > make_span(Container &container)
Definition span.h:386
constexpr span< uint8_t > as_writable_byte_span(T &&arg)
Definition span.h:475
static constexpr span< uint8_t > byte_span_from_ref(T &single_object) noexcept
Definition span.h:451
constexpr span< T > make_span(const Container &container)
Definition span.h:394
#define CHECK(cvref)
std::array< uint32_t, kMaxNb > iv
std::array< uint32_t, kSchedSize > invkeysched
static constexpr int kMaxNr
static constexpr int kSchedSize
static constexpr int kMaxNb
std::array< uint32_t, kSchedSize > keysched
uint8_t buffer[64]
Definition fx_crypt.h:28
std::array< uint32_t, 4 > state
Definition fx_crypt.h:27
std::array< uint32_t, 2 > total
Definition fx_crypt.h:26
std::array< int32_t, kPermutationLength > m
Definition fx_crypt.h:22
static constexpr int32_t kPermutationLength
Definition fx_crypt.h:18
#define UNOWNED_PTR_EXCLUSION