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_ASSERT
at runtime. When detectable, these situations trigger astatic_assert
at 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 inconstexpr
contexts, which is not supported bystd::string
until 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 aInlineString
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 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.
Roadmap#
The fixed size cost of
pw::StringBuilder
can be dramatically reduced by limiting support for 64-bit integers.pw_string
may be integrated with pw_tokenizer.