blob: 552a9fde7fd1af45b702fdbc86723efa495e901e [file] [edit]
.. _module-pw_string-design:
================
Design & Roadmap
================
.. pigweed-module-subpage::
:name: pw_string
``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.
.. _module-pw_string-design-inlinestring:
--------------------------
Design of pw::InlineString
--------------------------
:cc:`pw::InlineString` / :cc:`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 a ``static_assert`` at compile time.
- **Minimal overhead:** :cc:`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:** :cc:`pw::InlineString` works in ``constexpr`` contexts,
which is not supported by ``std::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:** :cc:`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 :cc:`InlineString` is less costly than creating a
``std::string``. As with ``std::string``, explicit conversions are required
from types that convert to ``std::string_view``.
- **No dynamic allocation functions:** Functions that allocate memory, like
``reserve()``, ``shrink_to_fit()``, and ``get_allocator()``, are simply not
present.
Capacity
========
:cc:`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
:cc:`InlineBasicString` template inherits from a :cc:`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 :cc:`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
:cc:`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 :cc:`pw::string::NullTerminatedLength` function is provided.
This function only returns the length if the string is null-terminated within a
maximum length.
.. _module-pw_string-roadmap:
-------
Roadmap
-------
* The fixed size cost of :cc:`pw::StringBuilder` can be dramatically reduced by
limiting support for 64-bit integers.
* ``pw_string`` may be integrated with :ref:`module-pw_tokenizer`.