xref: /aosp_15_r20/external/pigweed/pw_string/design.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_string-design:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker================
4*61c4878aSAndroid Build Coastguard WorkerDesign & Roadmap
5*61c4878aSAndroid Build Coastguard Worker================
6*61c4878aSAndroid Build Coastguard Worker.. pigweed-module-subpage::
7*61c4878aSAndroid Build Coastguard Worker   :name: pw_string
8*61c4878aSAndroid Build Coastguard Worker
9*61c4878aSAndroid Build Coastguard Worker``pw_string`` provides string classes and utility functions designed to
10*61c4878aSAndroid Build Coastguard Workerprioritize safety and static allocation. The APIs are broadly similar to those
11*61c4878aSAndroid Build Coastguard Workerof the string classes in the C++ standard library, so familiarity with those
12*61c4878aSAndroid Build Coastguard Workerclasses will provide some context around ``pw_string`` design decisions.
13*61c4878aSAndroid Build Coastguard Worker
14*61c4878aSAndroid Build Coastguard Worker.. _module-pw_string-design-inlinestring:
15*61c4878aSAndroid Build Coastguard Worker
16*61c4878aSAndroid Build Coastguard Worker--------------------------
17*61c4878aSAndroid Build Coastguard WorkerDesign of pw::InlineString
18*61c4878aSAndroid Build Coastguard Worker--------------------------
19*61c4878aSAndroid Build Coastguard Worker:cpp:type:`pw::InlineString` / :cpp:class:`pw::InlineBasicString` are designed
20*61c4878aSAndroid Build Coastguard Workerto match the ``std::string`` / ``std::basic_string<T>`` API as closely as
21*61c4878aSAndroid Build Coastguard Workerpossible, but with key differences to improve performance on embedded systems:
22*61c4878aSAndroid Build Coastguard Worker
23*61c4878aSAndroid Build Coastguard Worker- **Fixed capacity:** Operations that add characters to the string beyond its
24*61c4878aSAndroid Build Coastguard Worker  capacity are an error. These trigger a ``PW_ASSERT`` at runtime. When
25*61c4878aSAndroid Build Coastguard Worker  detectable, these situations trigger a ``static_assert`` at compile time.
26*61c4878aSAndroid Build Coastguard Worker- **Minimal overhead:** :cpp:type:`pw::InlineString` operations never
27*61c4878aSAndroid Build Coastguard Worker  allocate. Reading the contents of the string is a direct memory access within
28*61c4878aSAndroid Build Coastguard Worker  the string object, without pointer indirection.
29*61c4878aSAndroid Build Coastguard Worker- **Constexpr support:** :cpp:type:`pw::InlineString` works in ``constexpr``
30*61c4878aSAndroid Build Coastguard Worker  contexts, which is not supported by ``std::string`` until C++20.
31*61c4878aSAndroid Build Coastguard Worker
32*61c4878aSAndroid Build Coastguard WorkerWe don't aim to provide complete API compatibility with
33*61c4878aSAndroid Build Coastguard Worker``std::string`` / ``std::basic_string<T>``. Some areas of deviation include:
34*61c4878aSAndroid Build Coastguard Worker
35*61c4878aSAndroid Build Coastguard Worker- **Compile-time capacity checks:** :cpp:type:`InlineString` provides overloads
36*61c4878aSAndroid Build Coastguard Worker  specific to character arrays. These perform compile-time capacity checks and
37*61c4878aSAndroid Build Coastguard Worker  are used for class template argument deduction.
38*61c4878aSAndroid Build Coastguard Worker- **Implicit conversions from** ``std::string_view`` **:** Specifying the
39*61c4878aSAndroid Build Coastguard Worker  capacity parameter is cumbersome, so implicit conversions are helpful. Also,
40*61c4878aSAndroid Build Coastguard Worker  implicitly creating a :cpp:type:`InlineString` is less costly than creating a
41*61c4878aSAndroid Build Coastguard Worker  ``std::string``. As with ``std::string``, explicit conversions are required
42*61c4878aSAndroid Build Coastguard Worker  from types that convert to ``std::string_view``.
43*61c4878aSAndroid Build Coastguard Worker- **No dynamic allocation functions:** Functions that allocate memory, like
44*61c4878aSAndroid Build Coastguard Worker  ``reserve()``, ``shrink_to_fit()``, and ``get_allocator()``, are simply not
45*61c4878aSAndroid Build Coastguard Worker  present.
46*61c4878aSAndroid Build Coastguard Worker
47*61c4878aSAndroid Build Coastguard WorkerCapacity
48*61c4878aSAndroid Build Coastguard Worker========
49*61c4878aSAndroid Build Coastguard Worker:cpp:type:`InlineBasicString` has a template parameter for the capacity, but the
50*61c4878aSAndroid Build Coastguard Workercapacity does not need to be known by the user to use the string safely. The
51*61c4878aSAndroid Build Coastguard Worker:cpp:type:`InlineBasicString` template inherits from a
52*61c4878aSAndroid Build Coastguard Worker:cpp:type:`InlineBasicString` specialization with capacity of the reserved value
53*61c4878aSAndroid Build Coastguard Worker``pw::InlineString<>::npos``. The actual capacity is stored in a single word
54*61c4878aSAndroid Build Coastguard Workeralongside the size. This allows code to work with strings of any capacity
55*61c4878aSAndroid Build Coastguard Workerthrough a ``InlineString<>`` or ``InlineBasicString<T>`` reference.
56*61c4878aSAndroid Build Coastguard Worker
57*61c4878aSAndroid Build Coastguard WorkerExceeding the capacity
58*61c4878aSAndroid Build Coastguard Worker----------------------
59*61c4878aSAndroid Build Coastguard WorkerAny :cpp:type:`pw::InlineString` operations that exceed the string's capacity
60*61c4878aSAndroid Build Coastguard Workerfail an assertion, resulting in a crash. Helpers are provided in
61*61c4878aSAndroid Build Coastguard Worker``pw_string/util.h`` that return ``pw::Status::ResourceExhausted()`` instead of
62*61c4878aSAndroid Build Coastguard Workerfailing an assert when the capacity would be exceeded.
63*61c4878aSAndroid Build Coastguard Worker
64*61c4878aSAndroid Build Coastguard Worker----------------------------------
65*61c4878aSAndroid Build Coastguard WorkerDesign of string utility functions
66*61c4878aSAndroid Build Coastguard Worker----------------------------------
67*61c4878aSAndroid Build Coastguard Worker
68*61c4878aSAndroid Build Coastguard WorkerSafe length checking
69*61c4878aSAndroid Build Coastguard Worker====================
70*61c4878aSAndroid Build Coastguard WorkerThis module provides two safer alternatives to ``std::strlen`` in case the
71*61c4878aSAndroid Build Coastguard Workerstring is extremely long and/or potentially not null-terminated.
72*61c4878aSAndroid Build Coastguard Worker
73*61c4878aSAndroid Build Coastguard WorkerFirst, a constexpr alternative to C11's ``strnlen_s`` is offerred through
74*61c4878aSAndroid Build Coastguard Worker:cpp:func:`pw::string::ClampedCString`. This does not return a length by
75*61c4878aSAndroid Build Coastguard Workerdesign and instead returns a string_view which does not require
76*61c4878aSAndroid Build Coastguard Workernull-termination.
77*61c4878aSAndroid Build Coastguard Worker
78*61c4878aSAndroid Build Coastguard WorkerSecond, a constexpr specialized form is offered where null termination is
79*61c4878aSAndroid Build Coastguard Workerrequired through :cpp:func:`pw::string::NullTerminatedLength`. This will only
80*61c4878aSAndroid Build Coastguard Workerreturn a length if the string is null-terminated.
81*61c4878aSAndroid Build Coastguard Worker
82*61c4878aSAndroid Build Coastguard Worker.. _module-pw_string-roadmap:
83*61c4878aSAndroid Build Coastguard Worker
84*61c4878aSAndroid Build Coastguard Worker-------
85*61c4878aSAndroid Build Coastguard WorkerRoadmap
86*61c4878aSAndroid Build Coastguard Worker-------
87*61c4878aSAndroid Build Coastguard Worker* The fixed size cost of :cpp:type:`pw::StringBuilder` can be dramatically
88*61c4878aSAndroid Build Coastguard Worker  reduced by limiting support for 64-bit integers.
89*61c4878aSAndroid Build Coastguard Worker* ``pw_string`` may be integrated with :ref:`module-pw_tokenizer`.
90