pw_string design#
Pigweed AI summary: The pw_string module provides string classes and utility functions prioritizing safety and static allocation. The APIs are similar to those of the C++ standard library, but with differences to improve performance on embedded systems. The InlineString and InlineBasicString classes match the std::string and std::basic_string<T> API as closely as possible, but with fixed capacity, minimal overhead, and constexpr support. The module also provides string utility functions, including safer alternatives to std::strlen for extremely long and potentially not null
pw_string provides string classes and utility functions designed to
prioritize safety and static allocation. The APIs are broadly similar to those
of the string classes in the C++ standard library, so familiarity with those
classes will provide some context around pw_string design decisions.
InlineString#
Pigweed AI summary: The article discusses the benefits of using pw::InlineString and pw::InlineBasicString over std::string and std::basic_string<T> for embedded systems. These classes have fixed capacity, minimal overhead, and support constexpr contexts. However, they do not provide complete API compatibility with std::string and std::basic_string<T>. The article also explains the capacity of InlineBasicString and how exceeding the capacity results in a crash. Helpers are provided to avoid this situation.
pw::InlineString / pw::InlineBasicString are designed
to match the std::string / std::basic_string<T> API as closely as
possible, but with key differences to improve performance on embedded systems:
Fixed capacity: Operations that add characters to the string beyond its capacity are an error. These trigger a
PW_ASSERTat runtime. When detectable, these situations trigger astatic_assertat compile time.Minimal overhead:
pw::InlineStringoperations never allocate. Reading the contents of the string is a direct memory access within the string object, without pointer indirection.Constexpr support:
pw::InlineStringworks inconstexprcontexts, which is not supported bystd::stringuntil C++20.
We don’t aim to provide complete API compatibility with
std::string / std::basic_string<T>. Some areas of deviation include:
Compile-time capacity checks:
InlineStringprovides overloads specific to character arrays. These perform compile-time capacity checks and are used for class template argument deduction.Implicit conversions from
std::string_view: Specifying the capacity parameter is cumbersome, so implicit conversions are helpful. Also, implicitly creating aInlineStringis less costly than creating astd::string. As withstd::string, explicit conversions are required from types that convert tostd::string_view.No dynamic allocation functions: Functions that allocate memory, like
reserve(),shrink_to_fit(), andget_allocator(), are simply not present.
Capacity#
Pigweed AI summary: The InlineBasicString template has a capacity parameter, but users do not need to know the capacity to use the string safely. The template inherits from a specialization with a reserved capacity value, and the actual capacity is stored alongside the size. This allows code to work with strings of any capacity through a reference. However, any operations that exceed the string's capacity will result in a crash, but helpers are provided to return a status instead of failing an assert.
InlineBasicString has a template parameter for the capacity, but the
capacity does not need to be known by the user to use the string safely. The
InlineBasicString template inherits from a
InlineBasicString specialization with capacity of the reserved value
pw::InlineString<>::npos. The actual capacity is stored in a single word
alongside the size. This allows code to work with strings of any capacity
through a InlineString<> or InlineBasicString<T> reference.
Exceeding the capacity#
Pigweed AI summary: The article discusses how exceeding the capacity of a pw::InlineString operation can result in a crash. It suggests using helpers provided in pw_string/util.h that return pw::Status::ResourceExhausted() instead of failing an assert when the capacity is exceeded.
Any pw::InlineString operations that exceed the string’s capacity
fail an assertion, resulting in a crash. Helpers are provided in
pw_string/util.h that return pw::Status::ResourceExhausted() instead of
failing an assert when the capacity would be exceeded.
String utility functions#
Pigweed AI summary: This module provides two safer alternatives to std::strlen for checking the length of a potentially long or non-null-terminated string. The first option is a constexpr alternative to C11's strnlen_s, which returns a string_view that does not require null-termination. The second option is a constexpr specialized form that requires null termination and will only return a length if the string is null-terminated.
Safe length checking#
Pigweed AI summary: The "Safe length checking" module provides two alternatives to std::strlen for extremely long or potentially not null-terminated strings. The first option is a constexpr alternative to C11's strnlen_s, which returns a string_view that does not require null-termination. The second option is a constexpr specialized form that requires null termination and will only return a length if the string is null-terminated.
This module provides two safer alternatives to std::strlen in case the
string is extremely long and/or potentially not null-terminated.
First, a constexpr alternative to C11’s strnlen_s is offerred through
pw::string::ClampedCString(). This does not return a length by
design and instead returns a string_view which does not require
null-termination.
Second, a constexpr specialized form is offered where null termination is
required through pw::string::NullTerminatedLength(). This will only
return a length if the string is null-terminated.