diff options
author | Chad Norvell <chadnorvell@google.com> | 2023-03-11 00:00:35 +0000 |
---|---|---|
committer | CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-03-11 00:00:35 +0000 |
commit | 85cbe67e0f3d474498a648d99b041b80e00edce4 (patch) | |
tree | 28abef1a8a2baadef6938d19f1853fbe077d04e4 /pw_string | |
parent | 2d3495c8c24f014d8e51d7878d2d1ab97373b6e2 (diff) | |
download | pigweed-85cbe67e0f3d474498a648d99b041b80e00edce4.tar.gz |
pw_string: Improve API and design docs
Change-Id: Id441cba35e23539bf00e2e00bac6b39fa5128d53
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/133611
Reviewed-by: Keir Mierle <keir@google.com>
Commit-Queue: Chad Norvell <chadnorvell@google.com>
Diffstat (limited to 'pw_string')
-rw-r--r-- | pw_string/api.rst | 45 | ||||
-rw-r--r-- | pw_string/design.rst | 92 | ||||
-rw-r--r-- | pw_string/public/pw_string/string.h | 36 | ||||
-rw-r--r-- | pw_string/public/pw_string/string_builder.h | 4 |
4 files changed, 96 insertions, 81 deletions
diff --git a/pw_string/api.rst b/pw_string/api.rst index cead6428f..a526023eb 100644 --- a/pw_string/api.rst +++ b/pw_string/api.rst @@ -1,22 +1,41 @@ .. _module-pw_string-api: -======================= -pw_string API reference -======================= +============= +API Reference +============= -------- Overview -------- +This module provides two types of strings, and utility functions for working +with strings. + +**pw::StringBuilder** + +.. doxygenfile:: pw_string/string_builder.h + :sections: briefdescription + +**pw::InlineString** + .. doxygenfile:: pw_string/string.h :sections: briefdescription + +**String utility functions** + .. doxygenfile:: pw_string/util.h :sections: briefdescription + +----------------- +pw::StringBuilder +----------------- .. doxygenfile:: pw_string/string_builder.h :sections: briefdescription +.. doxygenclass:: pw::StringBuilder + :members: ---------------------- -pw::InlineBasicString ---------------------- +---------------- +pw::InlineString +---------------- .. doxygenfile:: pw_string/string.h :sections: detaileddescription @@ -25,9 +44,9 @@ pw::InlineBasicString .. doxygentypedef:: pw::InlineString ----------- -pw::string ----------- +------------------------ +String utility functions +------------------------ pw::string::Assign() -------------------- @@ -70,11 +89,3 @@ pw::string::NullTerminatedLength() pw::string::PrintableCopy() --------------------------- .. doxygenfunction:: pw::string::PrintableCopy(const std::string_view& source, span<char> dest) - ------------------ -pw::StringBuilder ------------------ -.. doxygenfile:: pw_string/string_builder.h - :sections: briefdescription -.. doxygenclass:: pw::StringBuilder - :members: diff --git a/pw_string/design.rst b/pw_string/design.rst index 817171e16..91202e185 100644 --- a/pw_string/design.rst +++ b/pw_string/design.rst @@ -3,44 +3,65 @@ ================ pw_string design ================ -``pw_string`` is designed to prioritize safety and static allocation. It matches -the ``std::string`` API as closely as possible, but isn't intended to provide -complete API compatibility. - -:cpp:type:`pw::InlineString` / :cpp:class:`pw::InlineBasicString` follows the -``std::string`` / ``std::basic_string<T>`` API, with a few variations: - -- :cpp:type:`pw::InlineString` provides overloads specific to character arrays. - These perform compile-time capacity checks and are used for class template - argument deduction. Like ``std::string``, character arrays are treated as - null-terminated strings. -- :cpp:type:`pw::InlineString` allows implicit conversions from - ``std::string_view``. Specifying the capacity parameter is cumbersome, so - implicit conversions are helpful. Also, implicitly creating a - :cpp:type:`pw::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``. -- Functions related to dynamic memory allocation are not present (``reserve()``, - ``shrink_to_fit()``, ``get_allocator()``). -- ``resize_and_overwrite()`` only takes the ``Operation`` argument, since the - underlying string buffer cannot be resized. - -See the `std::string documentation -<https://en.cppreference.com/w/cpp/string/basic_string>`_ for full details. - -Key differences from ``std::string`` ------------------------------------- -- **Fixed capacity** -- Operations that add characters to the string beyond its +``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 +- **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`` +- **Constexpr support:** :cpp:type:`pw::InlineString` works in ``constexpr`` contexts, which is not supported by ``std::string`` until C++20. -Safe Length Checking --------------------- +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. @@ -52,10 +73,3 @@ 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. - -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. diff --git a/pw_string/public/pw_string/string.h b/pw_string/public/pw_string/string.h index daaa9a900..a6041f52a 100644 --- a/pw_string/public/pw_string/string.h +++ b/pw_string/public/pw_string/string.h @@ -42,19 +42,20 @@ namespace pw { /// @brief `pw::InlineBasicString` is a fixed-capacity version of -/// `std::basic_string`. +/// `std::basic_string`. In brief: /// -/// It is C++14-compatible and null-terminated. It stores the string contents -/// inline and uses no dynamic memory. It implements mostly the same API as -/// `std::basic_string`, but the capacity of the string is fixed at construction -/// and cannot grow. Attempting to increase the size beyond the capacity -/// triggers an assert. `pw::InlineBasicString` has a template parameter for the -/// capacity, but the capacity does not have to be known to use the string. The -/// `pw::InlineBasicString` template inherits from a `pw::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 `pw::InlineString<>` or `pw::InlineBasicString<T>` reference. +/// - It is C++14-compatible and null-terminated. +/// - It stores the string contents inline and uses no dynamic memory. +/// - It implements mostly the same API as `std::basic_string`, but the capacity +/// of the string is fixed at construction and cannot grow. Attempting to +/// increase the size beyond the capacity triggers an assert. +/// +/// `pw::InlineBasicString` is efficient and compact. The current size and +/// capacity are stored in a single word. Accessing its contents is a simple +/// array access within the object, with no pointer indirection, even when +/// working from a generic reference `pw::InlineBasicString<T>` where the +/// capacity is not specified as a template argument. A string object can be +/// used safely without the need to know its capacity. /// /// See also `pw::InlineString`, which is an alias of /// `pw::InlineBasicString<char>` and is equivalent to `std::string`. @@ -576,17 +577,6 @@ constexpr bool operator>=(const T* lhs, /// @brief `pw::InlineString` is an alias of `pw::InlineBasicString<char>` and /// is equivalent to `std::string`. -/// -/// `pw::InlineString` takes the fixed capacity as a template argument, but may -/// be used generically without specifying the capacity. The capacity value is -/// stored in a member variable, which the generic `pw::InlineString<>` / -/// `pw::InlineBasicString<T>` specialization uses in place of the template -/// parameter. -/// -/// `pw::InlineString` is efficient and compact. The current size and capacity -/// are stored in a single word. Accessing the contents of a `pw::InlineString` -/// is a simple array access within the object, with no pointer indirection, -/// even when working from a generic `pw::InlineString<>` reference. template <string_impl::size_type kCapacity = string_impl::kGeneric> using InlineString = InlineBasicString<char, kCapacity>; diff --git a/pw_string/public/pw_string/string_builder.h b/pw_string/public/pw_string/string_builder.h index 322546485..c3c9d1760 100644 --- a/pw_string/public/pw_string/string_builder.h +++ b/pw_string/public/pw_string/string_builder.h @@ -15,8 +15,8 @@ /// @file pw_string/string_builder.h /// /// @brief `pw::StringBuilder` facilitates creating formatted strings in a -/// fixed-sized buffer or `pw::InlineString`. It is designed to give the -/// flexibility of `std::ostringstream`, but with a small footprint. +/// fixed-sized buffer or in a `pw::InlineString`. It is designed to give the +/// flexibility of std::ostringstream, but with a small footprint. #include <algorithm> #include <cstdarg> |