xref: /aosp_15_r20/external/pigweed/pw_string/guide.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_string-guide:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker====================
4*61c4878aSAndroid Build Coastguard WorkerGet Started & Guides
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.. _module-pw_string-get-started:
10*61c4878aSAndroid Build Coastguard Worker
11*61c4878aSAndroid Build Coastguard WorkerGet Started
12*61c4878aSAndroid Build Coastguard Worker===========
13*61c4878aSAndroid Build Coastguard Worker.. tab-set::
14*61c4878aSAndroid Build Coastguard Worker
15*61c4878aSAndroid Build Coastguard Worker   .. tab-item:: Bazel
16*61c4878aSAndroid Build Coastguard Worker
17*61c4878aSAndroid Build Coastguard Worker      Add ``@pigweed//pw_string`` to the ``deps`` list in your Bazel target:
18*61c4878aSAndroid Build Coastguard Worker
19*61c4878aSAndroid Build Coastguard Worker      .. code-block::
20*61c4878aSAndroid Build Coastguard Worker
21*61c4878aSAndroid Build Coastguard Worker         cc_library("...") {
22*61c4878aSAndroid Build Coastguard Worker           # ...
23*61c4878aSAndroid Build Coastguard Worker           deps = [
24*61c4878aSAndroid Build Coastguard Worker             # ...
25*61c4878aSAndroid Build Coastguard Worker             "@pigweed//pw_string",
26*61c4878aSAndroid Build Coastguard Worker             # ...
27*61c4878aSAndroid Build Coastguard Worker           ]
28*61c4878aSAndroid Build Coastguard Worker         }
29*61c4878aSAndroid Build Coastguard Worker
30*61c4878aSAndroid Build Coastguard Worker      If only one part of the module is needed, depend only on it; for example
31*61c4878aSAndroid Build Coastguard Worker      ``@pigweed//pw_string:format``.
32*61c4878aSAndroid Build Coastguard Worker
33*61c4878aSAndroid Build Coastguard Worker      This assumes ``@pigweed`` is the name you pulled Pigweed into your Bazel
34*61c4878aSAndroid Build Coastguard Worker      ``WORKSPACE`` as.
35*61c4878aSAndroid Build Coastguard Worker
36*61c4878aSAndroid Build Coastguard Worker   .. tab-item:: GN
37*61c4878aSAndroid Build Coastguard Worker
38*61c4878aSAndroid Build Coastguard Worker      Add ``$dir_pw_string`` to the ``deps`` list in your ``pw_executable()``
39*61c4878aSAndroid Build Coastguard Worker      build target:
40*61c4878aSAndroid Build Coastguard Worker
41*61c4878aSAndroid Build Coastguard Worker      .. code-block::
42*61c4878aSAndroid Build Coastguard Worker
43*61c4878aSAndroid Build Coastguard Worker         pw_executable("...") {
44*61c4878aSAndroid Build Coastguard Worker           # ...
45*61c4878aSAndroid Build Coastguard Worker           deps = [
46*61c4878aSAndroid Build Coastguard Worker             # ...
47*61c4878aSAndroid Build Coastguard Worker             "$dir_pw_string",
48*61c4878aSAndroid Build Coastguard Worker             # ...
49*61c4878aSAndroid Build Coastguard Worker           ]
50*61c4878aSAndroid Build Coastguard Worker         }
51*61c4878aSAndroid Build Coastguard Worker
52*61c4878aSAndroid Build Coastguard Worker      See `//source/BUILD.gn <https://pigweed.googlesource.com/pigweed/sample_project/+/refs/heads/main/source/BUILD.gn>`_
53*61c4878aSAndroid Build Coastguard Worker      in the Pigweed Sample Project for an example.
54*61c4878aSAndroid Build Coastguard Worker
55*61c4878aSAndroid Build Coastguard Worker   .. tab-item:: CMake
56*61c4878aSAndroid Build Coastguard Worker
57*61c4878aSAndroid Build Coastguard Worker      Add ``pw_string`` to your ``pw_add_library`` or similar CMake target:
58*61c4878aSAndroid Build Coastguard Worker
59*61c4878aSAndroid Build Coastguard Worker      .. code-block::
60*61c4878aSAndroid Build Coastguard Worker
61*61c4878aSAndroid Build Coastguard Worker         pw_add_library(my_library STATIC
62*61c4878aSAndroid Build Coastguard Worker           HEADERS
63*61c4878aSAndroid Build Coastguard Worker             ...
64*61c4878aSAndroid Build Coastguard Worker           PRIVATE_DEPS
65*61c4878aSAndroid Build Coastguard Worker             # ...
66*61c4878aSAndroid Build Coastguard Worker             pw_string
67*61c4878aSAndroid Build Coastguard Worker             # ...
68*61c4878aSAndroid Build Coastguard Worker         )
69*61c4878aSAndroid Build Coastguard Worker
70*61c4878aSAndroid Build Coastguard Worker      For a narrower dependency, depend on subtargets like
71*61c4878aSAndroid Build Coastguard Worker      ``pw_string.builder``, etc.
72*61c4878aSAndroid Build Coastguard Worker
73*61c4878aSAndroid Build Coastguard Worker   .. tab-item:: Zephyr
74*61c4878aSAndroid Build Coastguard Worker
75*61c4878aSAndroid Build Coastguard Worker      There are two ways to use ``pw_string`` from a Zephyr project:
76*61c4878aSAndroid Build Coastguard Worker
77*61c4878aSAndroid Build Coastguard Worker      #. Depend on ``pw_string`` in your CMake target (see CMake tab). This is
78*61c4878aSAndroid Build Coastguard Worker         Pigweed Team's suggested approach since it enables precise CMake
79*61c4878aSAndroid Build Coastguard Worker         dependency analysis.
80*61c4878aSAndroid Build Coastguard Worker
81*61c4878aSAndroid Build Coastguard Worker      #. Add ``CONFIG_PIGWEED_STRING=y`` to the Zephyr project's configuration,
82*61c4878aSAndroid Build Coastguard Worker         which causes ``pw_string`` to become a global dependency and have the
83*61c4878aSAndroid Build Coastguard Worker         includes exposed to all targets. Pigweed team does not recommend this
84*61c4878aSAndroid Build Coastguard Worker         approach, though it is the typical Zephyr solution.
85*61c4878aSAndroid Build Coastguard Worker
86*61c4878aSAndroid Build Coastguard WorkerChoose between pw::InlineString and pw::StringBuilder
87*61c4878aSAndroid Build Coastguard Worker=====================================================
88*61c4878aSAndroid Build Coastguard Worker`pw::InlineString` is intended to replace typical null terminated character
89*61c4878aSAndroid Build Coastguard Workerarrays in embedded data structures. Use :cpp:type:`pw::InlineString` if you
90*61c4878aSAndroid Build Coastguard Workerneed:
91*61c4878aSAndroid Build Coastguard Worker
92*61c4878aSAndroid Build Coastguard Worker* Compatibility with ``std::string``
93*61c4878aSAndroid Build Coastguard Worker* Storage internal to the object
94*61c4878aSAndroid Build Coastguard Worker* A string object to persist in other data structures
95*61c4878aSAndroid Build Coastguard Worker* Lower code size overhead
96*61c4878aSAndroid Build Coastguard Worker
97*61c4878aSAndroid Build Coastguard Worker`pw::StringBuilder` is intended to ease constructing strings in external data;
98*61c4878aSAndroid Build Coastguard Workertypically created on the stack and disposed of in the same function. Use
99*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::StringBuilder` if you need:
100*61c4878aSAndroid Build Coastguard Worker
101*61c4878aSAndroid Build Coastguard Worker* Compatibility with ``std::ostringstream``, including custom object support
102*61c4878aSAndroid Build Coastguard Worker* Storage external to the object
103*61c4878aSAndroid Build Coastguard Worker* Non-fatal handling of failed append/format operations
104*61c4878aSAndroid Build Coastguard Worker* Tracking of the status of a series of operations
105*61c4878aSAndroid Build Coastguard Worker* A temporary stack object to aid string construction
106*61c4878aSAndroid Build Coastguard Worker* Medium code size overhead
107*61c4878aSAndroid Build Coastguard Worker
108*61c4878aSAndroid Build Coastguard WorkerAn example of when to prefer :cpp:type:`pw::InlineString` is wrapping a
109*61c4878aSAndroid Build Coastguard Workerlength-delimited string (e.g. ``std::string_view``) for APIs that require null
110*61c4878aSAndroid Build Coastguard Workertermination:
111*61c4878aSAndroid Build Coastguard Worker
112*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
113*61c4878aSAndroid Build Coastguard Worker
114*61c4878aSAndroid Build Coastguard Worker   #include <string>
115*61c4878aSAndroid Build Coastguard Worker   #include "pw_log/log.h"
116*61c4878aSAndroid Build Coastguard Worker   #include "pw_string/string_builder.h"
117*61c4878aSAndroid Build Coastguard Worker
118*61c4878aSAndroid Build Coastguard Worker   void ProcessName(std::string_view name) {
119*61c4878aSAndroid Build Coastguard Worker     // %s format strings require null terminated strings, so create one on the
120*61c4878aSAndroid Build Coastguard Worker     // stack with size up to kMaxNameLen, copy the string view `name` contents
121*61c4878aSAndroid Build Coastguard Worker     // into it, add a null terminator, and log it.
122*61c4878aSAndroid Build Coastguard Worker     PW_LOG_DEBUG("The name is %s",
123*61c4878aSAndroid Build Coastguard Worker                  pw::InlineString<kMaxNameLen>(name).c_str());
124*61c4878aSAndroid Build Coastguard Worker   }
125*61c4878aSAndroid Build Coastguard Worker
126*61c4878aSAndroid Build Coastguard WorkerAn example of when to prefer :cpp:class:`pw::StringBuilder` is when
127*61c4878aSAndroid Build Coastguard Workerconstructing a string for external use.
128*61c4878aSAndroid Build Coastguard Worker
129*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
130*61c4878aSAndroid Build Coastguard Worker
131*61c4878aSAndroid Build Coastguard Worker   #include "pw_string/string_builder.h"
132*61c4878aSAndroid Build Coastguard Worker
133*61c4878aSAndroid Build Coastguard Worker   pw::Status FlushSensorValueToUart(int32_t sensor_value) {
134*61c4878aSAndroid Build Coastguard Worker     pw::StringBuffer<42> sb;
135*61c4878aSAndroid Build Coastguard Worker     sb << "Sensor value: ";
136*61c4878aSAndroid Build Coastguard Worker     sb << sensor_value;  // Formats as int.
137*61c4878aSAndroid Build Coastguard Worker     FlushCStringToUart(sb.c_str());
138*61c4878aSAndroid Build Coastguard Worker
139*61c4878aSAndroid Build Coastguard Worker     if (!sb.status().ok) {
140*61c4878aSAndroid Build Coastguard Worker       format_error_metric.Increment();  // Track overflows.
141*61c4878aSAndroid Build Coastguard Worker     }
142*61c4878aSAndroid Build Coastguard Worker     return sb.status();
143*61c4878aSAndroid Build Coastguard Worker   }
144*61c4878aSAndroid Build Coastguard Worker
145*61c4878aSAndroid Build Coastguard Worker.. _module-pw_string-guide-stringbuilder:
146*61c4878aSAndroid Build Coastguard Worker
147*61c4878aSAndroid Build Coastguard WorkerBuild a string with pw::StringBuilder
148*61c4878aSAndroid Build Coastguard Worker=====================================
149*61c4878aSAndroid Build Coastguard WorkerThe following shows basic use of a :cpp:class:`pw::StringBuilder`.
150*61c4878aSAndroid Build Coastguard Worker
151*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
152*61c4878aSAndroid Build Coastguard Worker
153*61c4878aSAndroid Build Coastguard Worker   #include "pw_log/log.h"
154*61c4878aSAndroid Build Coastguard Worker   #include "pw_string/string_builder.h"
155*61c4878aSAndroid Build Coastguard Worker
156*61c4878aSAndroid Build Coastguard Worker   pw::Status LogProducedData(std::string_view func_name,
157*61c4878aSAndroid Build Coastguard Worker                              span<const std::byte> data) {
158*61c4878aSAndroid Build Coastguard Worker     // pw::StringBuffer allocates a pw::StringBuilder with a built-in buffer.
159*61c4878aSAndroid Build Coastguard Worker     pw::StringBuffer<42> sb;
160*61c4878aSAndroid Build Coastguard Worker
161*61c4878aSAndroid Build Coastguard Worker     // Append a std::string_view to the buffer.
162*61c4878aSAndroid Build Coastguard Worker     sb << func_name;
163*61c4878aSAndroid Build Coastguard Worker
164*61c4878aSAndroid Build Coastguard Worker     // Append a format string to the buffer.
165*61c4878aSAndroid Build Coastguard Worker     sb.Format(" produced %d bytes of data: ", static_cast<int>(data.data()));
166*61c4878aSAndroid Build Coastguard Worker
167*61c4878aSAndroid Build Coastguard Worker     // Append bytes as hex to the buffer.
168*61c4878aSAndroid Build Coastguard Worker     sb << data;
169*61c4878aSAndroid Build Coastguard Worker
170*61c4878aSAndroid Build Coastguard Worker     // Log the final string.
171*61c4878aSAndroid Build Coastguard Worker     PW_LOG_DEBUG("%s", sb.c_str());
172*61c4878aSAndroid Build Coastguard Worker
173*61c4878aSAndroid Build Coastguard Worker     // Errors encountered while mutating the string builder are tracked.
174*61c4878aSAndroid Build Coastguard Worker     return sb.status();
175*61c4878aSAndroid Build Coastguard Worker   }
176*61c4878aSAndroid Build Coastguard Worker
177*61c4878aSAndroid Build Coastguard WorkerBuild a string with pw::InlineString
178*61c4878aSAndroid Build Coastguard Worker====================================
179*61c4878aSAndroid Build Coastguard Worker:cpp:type:`pw::InlineString` objects must be constructed by specifying a fixed
180*61c4878aSAndroid Build Coastguard Workercapacity for the string.
181*61c4878aSAndroid Build Coastguard Worker
182*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
183*61c4878aSAndroid Build Coastguard Worker
184*61c4878aSAndroid Build Coastguard Worker   #include "pw_string/string.h"
185*61c4878aSAndroid Build Coastguard Worker
186*61c4878aSAndroid Build Coastguard Worker   // Initialize from a C string.
187*61c4878aSAndroid Build Coastguard Worker   pw::InlineString<32> inline_string = "Literally";
188*61c4878aSAndroid Build Coastguard Worker   inline_string.append('?', 3);   // contains "Literally???"
189*61c4878aSAndroid Build Coastguard Worker
190*61c4878aSAndroid Build Coastguard Worker   // Supports copying into known-capacity strings.
191*61c4878aSAndroid Build Coastguard Worker   pw::InlineString<64> other = inline_string;
192*61c4878aSAndroid Build Coastguard Worker
193*61c4878aSAndroid Build Coastguard Worker   // Supports various helpful std::string functions
194*61c4878aSAndroid Build Coastguard Worker   if (inline_string.starts_with("Lit") || inline_string == "not\0literally"sv) {
195*61c4878aSAndroid Build Coastguard Worker     other += inline_string;
196*61c4878aSAndroid Build Coastguard Worker   }
197*61c4878aSAndroid Build Coastguard Worker
198*61c4878aSAndroid Build Coastguard Worker   // Like std::string, InlineString is always null terminated when accessed
199*61c4878aSAndroid Build Coastguard Worker   // through c_str(). InlineString can be used to null-terminate
200*61c4878aSAndroid Build Coastguard Worker   // length-delimited strings for APIs that expect null-terminated strings.
201*61c4878aSAndroid Build Coastguard Worker   std::string_view file(".gif");
202*61c4878aSAndroid Build Coastguard Worker   if (std::fopen(pw::InlineString<kMaxNameLen>(file).c_str(), "r") == nullptr) {
203*61c4878aSAndroid Build Coastguard Worker     return;
204*61c4878aSAndroid Build Coastguard Worker   }
205*61c4878aSAndroid Build Coastguard Worker
206*61c4878aSAndroid Build Coastguard Worker   // pw::InlineString integrates well with std::string_view. It supports
207*61c4878aSAndroid Build Coastguard Worker   // implicit conversions to and from std::string_view.
208*61c4878aSAndroid Build Coastguard Worker   inline_string = std::string_view("not\0literally", 12);
209*61c4878aSAndroid Build Coastguard Worker
210*61c4878aSAndroid Build Coastguard Worker   FunctionThatTakesAStringView(inline_string);
211*61c4878aSAndroid Build Coastguard Worker
212*61c4878aSAndroid Build Coastguard Worker   FunctionThatTakesAnInlineString(std::string_view("1234", 4));
213*61c4878aSAndroid Build Coastguard Worker
214*61c4878aSAndroid Build Coastguard WorkerBuild a string inside an pw::InlineString with a pw::StringBuilder
215*61c4878aSAndroid Build Coastguard Worker==================================================================
216*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::StringBuilder` can build a string in a
217*61c4878aSAndroid Build Coastguard Worker:cpp:type:`pw::InlineString`:
218*61c4878aSAndroid Build Coastguard Worker
219*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
220*61c4878aSAndroid Build Coastguard Worker
221*61c4878aSAndroid Build Coastguard Worker   #include "pw_string/string.h"
222*61c4878aSAndroid Build Coastguard Worker
223*61c4878aSAndroid Build Coastguard Worker   void DoFoo() {
224*61c4878aSAndroid Build Coastguard Worker     InlineString<32> inline_str;
225*61c4878aSAndroid Build Coastguard Worker     StringBuilder sb(inline_str);
226*61c4878aSAndroid Build Coastguard Worker     sb << 123 << "456";
227*61c4878aSAndroid Build Coastguard Worker     // inline_str contains "456"
228*61c4878aSAndroid Build Coastguard Worker   }
229*61c4878aSAndroid Build Coastguard Worker
230*61c4878aSAndroid Build Coastguard WorkerPass an pw::InlineString object as a parameter
231*61c4878aSAndroid Build Coastguard Worker==============================================
232*61c4878aSAndroid Build Coastguard Worker:cpp:type:`pw::InlineString` objects can be passed to non-templated functions
233*61c4878aSAndroid Build Coastguard Workervia type erasure. This saves code size in most cases, since it avoids template
234*61c4878aSAndroid Build Coastguard Workerexpansions triggered by string size differences.
235*61c4878aSAndroid Build Coastguard Worker
236*61c4878aSAndroid Build Coastguard WorkerUnknown size strings
237*61c4878aSAndroid Build Coastguard Worker--------------------
238*61c4878aSAndroid Build Coastguard WorkerTo operate on :cpp:type:`pw::InlineString` objects without knowing their type,
239*61c4878aSAndroid Build Coastguard Workeruse the ``pw::InlineString<>`` type, shown in the examples below:
240*61c4878aSAndroid Build Coastguard Worker
241*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
242*61c4878aSAndroid Build Coastguard Worker
243*61c4878aSAndroid Build Coastguard Worker   // Note that the first argument is a generically-sized InlineString.
244*61c4878aSAndroid Build Coastguard Worker   void RemoveSuffix(pw::InlineString<>& string, std::string_view suffix) {
245*61c4878aSAndroid Build Coastguard Worker     if (string.ends_with(suffix)) {
246*61c4878aSAndroid Build Coastguard Worker        string.resize(string.size() - suffix.size());
247*61c4878aSAndroid Build Coastguard Worker     }
248*61c4878aSAndroid Build Coastguard Worker   }
249*61c4878aSAndroid Build Coastguard Worker
250*61c4878aSAndroid Build Coastguard Worker   void DoStuff() {
251*61c4878aSAndroid Build Coastguard Worker     pw::InlineString<32> str1 = "Good morning!";
252*61c4878aSAndroid Build Coastguard Worker     RemoveSuffix(str1, " morning!");
253*61c4878aSAndroid Build Coastguard Worker
254*61c4878aSAndroid Build Coastguard Worker     pw::InlineString<40> str2 = "Good";
255*61c4878aSAndroid Build Coastguard Worker     RemoveSuffix(str2, " morning!");
256*61c4878aSAndroid Build Coastguard Worker
257*61c4878aSAndroid Build Coastguard Worker     PW_ASSERT(str1 == str2);
258*61c4878aSAndroid Build Coastguard Worker   }
259*61c4878aSAndroid Build Coastguard Worker
260*61c4878aSAndroid Build Coastguard WorkerHowever, generically sized :cpp:type:`pw::InlineString` objects don't work in
261*61c4878aSAndroid Build Coastguard Worker``constexpr`` contexts.
262*61c4878aSAndroid Build Coastguard Worker
263*61c4878aSAndroid Build Coastguard WorkerKnown size strings
264*61c4878aSAndroid Build Coastguard Worker------------------
265*61c4878aSAndroid Build Coastguard Worker:cpp:type:`pw::InlineString` operations on known-size strings may be used in
266*61c4878aSAndroid Build Coastguard Worker``constexpr`` expressions.
267*61c4878aSAndroid Build Coastguard Worker
268*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
269*61c4878aSAndroid Build Coastguard Worker
270*61c4878aSAndroid Build Coastguard Worker   static constexpr pw::InlineString<64> kMyString = [] {
271*61c4878aSAndroid Build Coastguard Worker     pw::InlineString<64> string;
272*61c4878aSAndroid Build Coastguard Worker
273*61c4878aSAndroid Build Coastguard Worker     for (int i = 0; i < 10; ++i) {
274*61c4878aSAndroid Build Coastguard Worker       string += "Hello";
275*61c4878aSAndroid Build Coastguard Worker     }
276*61c4878aSAndroid Build Coastguard Worker
277*61c4878aSAndroid Build Coastguard Worker     return string;
278*61c4878aSAndroid Build Coastguard Worker   }();
279*61c4878aSAndroid Build Coastguard Worker
280*61c4878aSAndroid Build Coastguard WorkerInitialization of pw::InlineString objects
281*61c4878aSAndroid Build Coastguard Worker===========================================
282*61c4878aSAndroid Build Coastguard Worker:cpp:type:`pw::InlineBasicString` supports class template argument deduction
283*61c4878aSAndroid Build Coastguard Worker(CTAD) in C++17 and newer. Since :cpp:type:`pw::InlineString` is an alias, CTAD
284*61c4878aSAndroid Build Coastguard Workeris not supported until C++20.
285*61c4878aSAndroid Build Coastguard Worker
286*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
287*61c4878aSAndroid Build Coastguard Worker
288*61c4878aSAndroid Build Coastguard Worker   // Deduces a capacity of 5 characters to match the 5-character string literal
289*61c4878aSAndroid Build Coastguard Worker   // (not counting the null terminator).
290*61c4878aSAndroid Build Coastguard Worker   pw::InlineBasicString inline_string = "12345";
291*61c4878aSAndroid Build Coastguard Worker
292*61c4878aSAndroid Build Coastguard Worker   // In C++20, CTAD may be used with the pw::InlineString alias.
293*61c4878aSAndroid Build Coastguard Worker   pw::InlineString my_other_string("123456789");
294*61c4878aSAndroid Build Coastguard Worker
295*61c4878aSAndroid Build Coastguard WorkerCustom types with pw::StringBuilder
296*61c4878aSAndroid Build Coastguard Worker===================================
297*61c4878aSAndroid Build Coastguard WorkerAs with ``std::ostream``, pw::StringBuilder supports printing custom types by
298*61c4878aSAndroid Build Coastguard Workeroverriding the ``<<`` operator. This is is done by defining ``operator<<`` in
299*61c4878aSAndroid Build Coastguard Workerthe same namespace as the custom type. For example:
300*61c4878aSAndroid Build Coastguard Worker
301*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
302*61c4878aSAndroid Build Coastguard Worker
303*61c4878aSAndroid Build Coastguard Worker   namespace my_project {
304*61c4878aSAndroid Build Coastguard Worker
305*61c4878aSAndroid Build Coastguard Worker   struct MyType {
306*61c4878aSAndroid Build Coastguard Worker     int foo;
307*61c4878aSAndroid Build Coastguard Worker     const char* bar;
308*61c4878aSAndroid Build Coastguard Worker   };
309*61c4878aSAndroid Build Coastguard Worker
310*61c4878aSAndroid Build Coastguard Worker   pw::StringBuilder& operator<<(pw::StringBuilder& sb, const MyType& value) {
311*61c4878aSAndroid Build Coastguard Worker     return sb << "MyType(" << value.foo << ", " << value.bar << ')';
312*61c4878aSAndroid Build Coastguard Worker   }
313*61c4878aSAndroid Build Coastguard Worker
314*61c4878aSAndroid Build Coastguard Worker   }  // namespace my_project
315*61c4878aSAndroid Build Coastguard Worker
316*61c4878aSAndroid Build Coastguard WorkerInternally, ``StringBuilder`` uses the ``ToString`` function to print. The
317*61c4878aSAndroid Build Coastguard Worker``ToString`` template function can be specialized to support custom types with
318*61c4878aSAndroid Build Coastguard Worker``StringBuilder``, though it is recommended to overload ``operator<<`` instead.
319*61c4878aSAndroid Build Coastguard WorkerThis example shows how to specialize ``pw::ToString``:
320*61c4878aSAndroid Build Coastguard Worker
321*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
322*61c4878aSAndroid Build Coastguard Worker
323*61c4878aSAndroid Build Coastguard Worker   #include "pw_string/to_string.h"
324*61c4878aSAndroid Build Coastguard Worker
325*61c4878aSAndroid Build Coastguard Worker   namespace pw {
326*61c4878aSAndroid Build Coastguard Worker
327*61c4878aSAndroid Build Coastguard Worker   template <>
328*61c4878aSAndroid Build Coastguard Worker   StatusWithSize ToString<MyStatus>(MyStatus value, span<char> buffer) {
329*61c4878aSAndroid Build Coastguard Worker     return Copy(MyStatusString(value), buffer);
330*61c4878aSAndroid Build Coastguard Worker   }
331*61c4878aSAndroid Build Coastguard Worker
332*61c4878aSAndroid Build Coastguard Worker   }  // namespace pw
333