Design & Roadmap#
pw_string: Efficient, easy, and safe string manipulation
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.
Design of pw::InlineString#
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::InlineString operations never allocate. Reading the contents of the string is a direct memory access within the string object, without pointer indirection.
Constexpr support: pw::InlineString works in
constexprcontexts, 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: InlineString provides 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 a InlineString is 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#
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#
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.
Design of string utility functions#
Safe length checking#
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 std::string_view which does not require null-termination.
Second, a constexpr pw::string::NullTerminatedLength() function is provided. This function only returns the length if the string is null-terminated within a maximum length.
Roadmap#
The fixed size cost of pw::StringBuilder can be dramatically reduced by limiting support for 64-bit integers.
pw_stringmay be integrated with pw_tokenizer.