pw_span#
std::span for C++17
Stable C++17 C++20
Standardized: pw::span matches C++20’s std::span as closely as possible.
Zero-cost: If
std::span
is available,pw::span
is simply an alias of it.
#include <span>
// With pw::span, a buffer is passed as a single argument.
// No need to handle pointer and size arguments.
bool ProcessBuffer(pw::span<uint8_t> buffer);
bool DoStuff() {
// ...
ProcessBuffer(c_array);
ProcessBuffer(array_object);
ProcessBuffer(pw::span(data_pointer, data_size));
}
pw::span
is a convenient abstraction that wraps a pointer and a
size. It’s especially useful in APIs. Spans support implicit conversions from
C arrays, std::array
, or any STL-style container, such as
std::string_view
.
Get started#
Add @pigweed//pw_span
to the deps
list in your Bazel target:
cc_library("...") {
# ...
deps = [
# ...
"@pigweed//pw_span",
# ...
]
}
Add $dir_pw_span
to the deps
list in your pw_executable()
build target:
pw_executable("...") {
# ...
deps = [
# ...
"$dir_pw_span",
# ...
]
}
Add pw_span
to your pw_add_library
or similar CMake target:
pw_add_library(my_library STATIC
HEADERS
...
PRIVATE_DEPS
# ...
pw_span
# ...
)
There are two ways to use pw_span
from a Zephyr project:
Depend on
pw_span
in your CMake target (see CMake tab). This is Pigweed Team’s suggested approach since it enables precise CMake dependency analysis.Add
CONFIG_PIGWEED_SPAN=y
to the Zephyr project’s configuration, which causespw_span
to become a global dependency and have the includes exposed to all targets. Pigweed team does not recommend this approach, though it is the typical Zephyr solution.
Guides#
pw::span
as a function parameter#
pw::span
objects should be passed by value.
Yes: Accept pw::span
object by value:
bool ProcessBuffer(pw::span<uint8_t> buffer);
No: Accept pw::span
object by reference:
bool ProcessBuffer(const pw::span<uint8_t>& buffer);
Rationale: Since a pw::span
object is essentially a pointer and a size,
references to pw::span
objects are almost always unnecessary indirection.
Operating on arrays of bytes#
When operating on an array of bytes you typically need pointer and size arguments:
bool ProcessBuffer(char* buffer, size_t buffer_size);
bool DoStuff() {
ProcessBuffer(c_array, sizeof(c_array));
ProcessBuffer(array_object.data(), array_object.size());
ProcessBuffer(data_pointer, data_size);
}
With pw::span
you can pass the buffer as a single argument instead:
#include <span>
// With pw::span, a buffer is passed as a single argument.
// No need to handle pointer and size arguments.
bool ProcessBuffer(pw::span<uint8_t> buffer);
bool DoStuff() {
// ...
ProcessBuffer(c_array);
ProcessBuffer(array_object);
ProcessBuffer(pw::span(data_pointer, data_size));
}
Working with spans of binary data#
Use pw::span<std::byte>
or pw::span<const std::byte>
to represent
spans of binary data. Convert spans to byte spans with pw::as_bytes
or
pw::as_writable_bytes
.
void ProcessData(pw::span<const std::byte> data);
void DoStuff() {
std::array<AnyType, 7> data = { ... };
ProcessData(pw::as_bytes(pw::span(data)));
}
pw_bytes/span.h
provides ByteSpan
and ConstByteSpan
aliases for
these types.
Convert byte spans back to their original type, or to spans of other 1-byte
types using pw::span_cast<T>
.
#include "pw_bytes/span.h"
#include "pw_span/cast.h"
void SDK_ReadData(uint8_t* data, size_t size);
void SDK_WriteData(const uint8_t* data, size_t size);
void Write(pw::ConstByteSpan buffer) {
auto data = pw::span_cast<const uint8_t>(buffer);
SDK_WriteData(data.data(), data.size());
}
void Read(pw::ByteSpan buffer) {
auto data = pw::span_cast<uint8_t>(buffer);
SDK_ReadData(data.data(), data.size());
}
Warning
pw::span_cast<T>
is only safe to use if the underlying data is actually
of the specified type, or if T
is another 1-byte type (e.g.
uint8_t
). You cannot safely use this function to reinterpret e.g. a raw
byte array from malloc()
as a span of integers.
API reference#
Moved: pw_span
pw_span/span.h#
See std::span.
The pw::span
API is designed to match the std::span
API.
pw_span/cast.h#
This header provides functions for casting between pw::span
types, and is
not part of the std::span
interface.
-
span<T> pw::span_cast(std::span<std::byte> bytes)#
Casts a
pw::span<std::byte>
(ByteSpan
) to a span of a different type.This function is only safe to use if the underlying data is actually of the specified type. You cannot safely use this function to reinterpret e.g. a raw byte array from
malloc()
as a span of integers.This function is essentially the inverse of
pw::as_writable_bytes
.If
kSourceExtentBytes
isdynamic_extent
, the returned span also has a dynamic extent. Otherwise, the returned span has a static extent ofkSourceExtentBytes / sizeof(ResultT)
.
-
span<const T> pw::span_cast(std::span<const std::byte> bytes)#
Casts a
pw::span<const std::byte>
(ConstByteSpan
) to a span of a different const type.This function is only safe to use if the underlying data is actually of the specified type. You cannot safely use this function to reinterpret e.g. a raw byte array from
malloc()
as a span of integers.This function is essentially the inverse of
pw::as_bytes
.If
kSourceExtentBytes
isdynamic_extent
, the returned span also has a dynamic extent. Otherwise, the returned span has a static extent ofkSourceExtentBytes / sizeof(ResultT)
.
Configuration options#
The following configurations can be adjusted via compile-time configuration of this module, see the module documentation for more details.