76 lines
3.6 KiB
ReStructuredText
76 lines
3.6 KiB
ReStructuredText
.. _module-pw_string-design:
|
|
|
|
================
|
|
pw_string design
|
|
================
|
|
``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
|
|
------------
|
|
:cpp:type:`pw::InlineString` / :cpp:class:`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:** :cpp:type:`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:** :cpp:type:`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:** :cpp:type:`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 :cpp:type:`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
|
|
========
|
|
:cpp:type:`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
|
|
:cpp:type:`InlineBasicString` template inherits from a
|
|
:cpp:type:`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 :cpp:type:`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
|
|
------------------------
|
|
|
|
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
|
|
:cpp:func:`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 :cpp:func:`pw::string::NullTerminatedLength`. This will only
|
|
return a length if the string is null-terminated.
|