-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbuffer-writer.en.html
1095 lines (1043 loc) · 119 KB
/
buffer-writer.en.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>BufferWriter — AMC Traffic Server Documentation</title>
<link rel="stylesheet" href="_static/sphinxdoc.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '8.0.x',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt'
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="TSConfig / Lua" href="tsconfig-lua.en.html" />
<link rel="prev" title="Traffic Server Projects" href="ats-projects.en.html" />
</head>
<body>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="tsconfig-lua.en.html" title="TSConfig / Lua"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="ats-projects.en.html" title="Traffic Server Projects"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">SWOC Docs</a> »</li>
<li class="nav-item nav-item-1"><a href="ats-projects.en.html" accesskey="U">Traffic Server Projects</a> »</li>
</ul>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="index.html">
<img class="logo" src="_static/balcora-gate-400x400.jpg" alt="Logo"/>
</a></p>
<h3><a href="index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">BufferWriter</a><ul>
<li><a class="reference internal" href="#synopsis">Synopsis</a></li>
<li><a class="reference internal" href="#description">Description</a></li>
<li><a class="reference internal" href="#usage">Usage</a><ul>
<li><a class="reference internal" href="#writing">Writing</a></li>
<li><a class="reference internal" href="#reading">Reading</a></li>
<li><a class="reference internal" href="#advanced">Advanced</a></li>
</ul>
</li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#formatted-output">Formatted Output</a><ul>
<li><a class="reference internal" href="#usage-examples">Usage Examples</a></li>
</ul>
</li>
<li><a class="reference internal" href="#user-defined-formatting">User Defined Formatting</a><ul>
<li><a class="reference internal" href="#enum-example">Enum Example</a></li>
<li><a class="reference internal" href="#argument-forwarding">Argument Forwarding</a></li>
<li><a class="reference internal" href="#specialized-types">Specialized Types</a></li>
</ul>
</li>
<li><a class="reference internal" href="#global-names">Global Names</a></li>
<li><a class="reference internal" href="#working-with-standard-i-o">Working with standard I/O</a></li>
<li><a class="reference internal" href="#reference">Reference</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="ats-projects.en.html"
title="previous chapter">Traffic Server Projects</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="tsconfig-lua.en.html"
title="next chapter">TSConfig / Lua</a></p>
<div role="note" aria-label="source link">
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="_sources/buffer-writer.en.rst.txt"
rel="nofollow">Show Source</a></li>
</ul>
</div>
<div id="searchbox" style="display: none" role="search">
<h3>Quick search</h3>
<form class="search" action="search.html" method="get">
<div><input type="text" name="q" /></div>
<div><input type="submit" value="Go" /></div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<div class="section" id="bufferwriter">
<span id="id1"></span><h1>BufferWriter<a class="headerlink" href="#bufferwriter" title="Permalink to this headline">¶</a></h1>
<div class="section" id="synopsis">
<h2>Synopsis<a class="headerlink" href="#synopsis" title="Permalink to this headline">¶</a></h2>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf"><ts/BufferWriterForward.h> // Custom formatter support only.</span><span class="cp"></span>
<span class="cp">#include</span> <span class="cpf"><ts/BufferWriter.h> // General usage.</span><span class="cp"></span>
</pre></div>
</div>
</div>
<div class="section" id="description">
<h2>Description<a class="headerlink" href="#description" title="Permalink to this headline">¶</a></h2>
<p><a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> is intended to increase code reliability and reduce complexity in the common
circumstance of generating formatted output strings in fixed buffers. Current usage is a mixture of
<code class="code docutils literal"><span class="pre">snprintf</span></code> and <code class="code docutils literal"><span class="pre">memcpy</span></code> which provides a large scope for errors and verbose code to
check for buffer overruns. The goal is to provide a wrapper over buffer size tracking to make such
code simpler and less vulnerable to implementation error.</p>
<p><a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> itself is an abstract class to describe the base interface to wrappers for
various types of output buffers. As a common example, <a class="reference internal" href="#_CPPv217FixedBufferWriter" title="FixedBufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">FixedBufferWriter</span></code></a> is a subclass
designed to wrap a fixed size buffer. <a class="reference internal" href="#_CPPv217FixedBufferWriter" title="FixedBufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">FixedBufferWriter</span></code></a> is constructed by passing it a
buffer and a size, which it then tracks as data is written. Writing past the end of the buffer is
clipped to prevent overruns.</p>
<p>Consider current code that looks like this.</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="kt">char</span> <span class="n">buff</span><span class="p">[</span><span class="mi">1024</span><span class="p">];</span>
<span class="kt">char</span> <span class="o">*</span> <span class="n">ptr</span> <span class="o">=</span> <span class="n">buff</span><span class="p">;</span>
<span class="kt">size_t</span> <span class="n">len</span> <span class="o">=</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buff</span><span class="p">);</span>
<span class="c1">//...</span>
<span class="k">if</span> <span class="p">(</span><span class="n">len</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">auto</span> <span class="n">n</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">min</span><span class="p">(</span><span class="n">len</span><span class="p">,</span> <span class="n">thing1_len</span><span class="p">);</span>
<span class="n">memcpy</span><span class="p">(</span><span class="n">ptr</span><span class="p">,</span> <span class="n">thing1</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span>
<span class="n">len</span> <span class="o">-=</span> <span class="n">n</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">len</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">auto</span> <span class="n">n</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">min</span><span class="p">(</span><span class="n">len</span><span class="p">,</span> <span class="n">thing2_len</span><span class="p">);</span>
<span class="n">memcpy</span><span class="p">(</span><span class="n">ptr</span><span class="p">,</span> <span class="n">thing2</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span>
<span class="n">len</span> <span class="o">-=</span> <span class="n">n</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">len</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">auto</span> <span class="n">n</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">min</span><span class="p">(</span><span class="n">len</span><span class="p">,</span> <span class="n">thing3_len</span><span class="p">);</span>
<span class="n">memcpy</span><span class="p">(</span><span class="n">ptr</span><span class="p">,</span> <span class="n">thing3</span><span class="p">,</span> <span class="n">n</span><span class="p">);</span>
<span class="n">len</span> <span class="o">-=</span> <span class="n">n</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>This is changed to</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="kt">char</span> <span class="n">buff</span><span class="p">[</span><span class="mi">1024</span><span class="p">];</span>
<span class="n">ts</span><span class="o">::</span><span class="n">FixedBufferWriter</span> <span class="n">bw</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buff</span><span class="p">));</span>
<span class="c1">//...</span>
<span class="n">bw</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">thing1</span><span class="p">,</span> <span class="n">thing1_len</span><span class="p">);</span>
<span class="n">bw</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">thing2</span><span class="p">,</span> <span class="n">thing2_len</span><span class="p">);</span>
<span class="n">bw</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">thing3</span><span class="p">,</span> <span class="n">thing3_len</span><span class="p">);</span>
</pre></div>
</div>
<p>The remaining length is updated every time and checked every time. A series of checks, calls to
<code class="code docutils literal"><span class="pre">memcpy</span></code>, and size updates become a simple series of calls to <a class="reference internal" href="#_CPPv2N12BufferWriter5writeEPv6size_t" title="BufferWriter::write"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::write()</span></code></a>.</p>
<p>For other types of interaction, <a class="reference internal" href="#_CPPv217FixedBufferWriter" title="FixedBufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">FixedBufferWriter</span></code></a> provides access to the unused buffer via
<a class="reference internal" href="#_CPPv2NK12BufferWriter9auxBufferEv" title="BufferWriter::auxBuffer"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::auxBuffer()</span></code></a> and <a class="reference internal" href="#_CPPv2NK12BufferWriter9remainingEv" title="BufferWriter::remaining"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::remaining()</span></code></a>. This makes it possible to easily
use <code class="code docutils literal"><span class="pre">snprintf</span></code>, given that <code class="code docutils literal"><span class="pre">snprint</span></code> returns the number of bytes written.
<a class="reference internal" href="#_CPPv2N12BufferWriter4fillE6size_t" title="BufferWriter::fill"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::fill()</span></code></a> is used to indicate how much of the unused buffer was used. Therefore
something like (riffing off the previous example):</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="p">(</span><span class="n">len</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="n">len</span> <span class="o">-=</span> <span class="n">snprintf</span><span class="p">(</span><span class="n">ptr</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="s">"format string"</span><span class="p">,</span> <span class="n">args</span><span class="p">...);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>becomes:</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="n">bw</span><span class="p">.</span><span class="n">fill</span><span class="p">(</span><span class="n">snprintf</span><span class="p">(</span><span class="n">bw</span><span class="p">.</span><span class="n">auxBuffer</span><span class="p">(),</span> <span class="n">bw</span><span class="p">.</span><span class="n">remaining</span><span class="p">(),</span>
<span class="s">"format string"</span><span class="p">,</span> <span class="n">args</span><span class="p">...));</span>
</pre></div>
</div>
<p>By hiding the length tracking and checking, the result is a simple linear sequence of output chunks,
making the logic much eaier to follow.</p>
</div>
<div class="section" id="usage">
<h2>Usage<a class="headerlink" href="#usage" title="Permalink to this headline">¶</a></h2>
<p>The header files are divided in to two variants. <a class="reference external" href="https://github.com/apache/trafficserver/blob/master/lib/ts/BufferWriter.h">BufferWriter.h</a> provides the basic
capabilities of buffer output control. <a class="reference external" href="https://github.com/apache/trafficserver/blob/master/lib/ts/BufferWriterFormat.h">BufferWriterFormat.h</a> provides the basic
<a class="reference internal" href="#bw-formatting"><span class="std std-ref">formatted output mechanisms</span></a>, primarily the implementation and ancillary
classes for <a class="reference internal" href="#_CPPv27BWFSpec" title="BWFSpec"><code class="xref cpp cpp-class docutils literal"><span class="pre">BWFSpec</span></code></a> which is used to build formatters.</p>
<p><a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> is an abstract base class, in the style of <code class="code docutils literal"><span class="pre">std::ostream</span></code>. There are
several subclasses for various use cases. When passing around this is the common type.</p>
<p><a class="reference internal" href="#_CPPv217FixedBufferWriter" title="FixedBufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">FixedBufferWriter</span></code></a> writes to an externally provided buffer of a fixed length. The buffer must
be provided to the constructor. This will generally be used in a function where the target buffer is
external to the function or already exists.</p>
<p><a class="reference internal" href="#_CPPv2I_6size_tE17LocalBufferWriter" title="LocalBufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">LocalBufferWriter</span></code></a> is a templated class whose template argument is the size of an internal
buffer. This is useful when the buffer is local to a function and the results will be transferred
from the buffer to other storage after the output is assembled. Rather than having code like:</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="kt">char</span> <span class="n">buff</span><span class="p">[</span><span class="mi">1024</span><span class="p">];</span>
<span class="n">ts</span><span class="o">::</span><span class="n">FixedBufferWriter</span> <span class="n">bw</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">buff</span><span class="p">));</span>
</pre></div>
</div>
<p>it can be written more compactly as:</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="n">ts</span><span class="o">::</span><span class="n">LocalBufferWriter</span><span class="o"><</span><span class="mi">1024</span><span class="o">></span> <span class="n">bw</span><span class="p">;</span>
</pre></div>
</div>
<p>In many cases, when using <a class="reference internal" href="#_CPPv2I_6size_tE17LocalBufferWriter" title="LocalBufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">LocalBufferWriter</span></code></a> this is the only place the size of the buffer
needs to be specified and therefore can simply be a constant without the overhead of defining a size
to maintain consistency. The choice between <a class="reference internal" href="#_CPPv2I_6size_tE17LocalBufferWriter" title="LocalBufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">LocalBufferWriter</span></code></a> and <a class="reference internal" href="#_CPPv217FixedBufferWriter" title="FixedBufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">FixedBufferWriter</span></code></a>
comes down to the owner of the buffer - the former has its own buffer while the latter operates on
a buffer owned by some other object. Therefore if the buffer is declared locally, use
<a class="reference internal" href="#_CPPv2I_6size_tE17LocalBufferWriter" title="LocalBufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">LocalBufferWriter</span></code></a> and if the buffer is recevied from an external source (such as via a
function parameter) use <a class="reference internal" href="#_CPPv217FixedBufferWriter" title="FixedBufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">FixedBufferWriter</span></code></a>.</p>
<div class="section" id="writing">
<h3>Writing<a class="headerlink" href="#writing" title="Permalink to this headline">¶</a></h3>
<p>The basic mechanism for writing to a <a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> is <a class="reference internal" href="#_CPPv2N12BufferWriter5writeEPv6size_t" title="BufferWriter::write"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::write()</span></code></a>.
This is an overloaded method for a character (<code class="code docutils literal"><span class="pre">char</span></code>), a buffer (<code class="code docutils literal"><span class="pre">void</span> <span class="pre">*,</span> <span class="pre">size_t</span></code>)
and a string view (<code class="xref cpp cpp-class docutils literal"><span class="pre">string_view</span></code>). Because there is a constructor for <code class="xref cpp cpp-class docutils literal"><span class="pre">string_view</span></code>
that takes a <code class="code docutils literal"><span class="pre">const</span> <span class="pre">char*</span></code> as a C string, passing a literal string works as expected.</p>
<p>There are also stream operators in the style of C++ stream I/O. The basic template is</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o"><</span> <span class="k">typename</span> <span class="n">T</span> <span class="o">></span> <span class="n">ts</span><span class="o">::</span><span class="n">BufferWriter</span><span class="o">&</span> <span class="k">operator</span> <span class="o"><<</span> <span class="p">(</span><span class="n">ts</span><span class="o">::</span><span class="n">BufferWriter</span><span class="o">&</span> <span class="n">w</span><span class="p">,</span> <span class="n">T</span> <span class="k">const</span><span class="o">&</span> <span class="n">t</span><span class="p">);</span>
</pre></div>
</div>
<p>The stream operators are provided as a convenience, the primary mechanism for formatted output is
via overloading the <a class="reference internal" href="#_CPPv2I0E8bwformatR12BufferWriterR7BWFSpecR1V" title="bwformat"><code class="xref cpp cpp-func docutils literal"><span class="pre">bwformat()</span></code></a> function. Except for a limited set of cases the stream operators
are implemented by calling <a class="reference internal" href="#_CPPv2I0E8bwformatR12BufferWriterR7BWFSpecR1V" title="bwformat"><code class="xref cpp cpp-func docutils literal"><span class="pre">bwformat()</span></code></a> with the Buffer Writer, the argument, and a default
format specification.</p>
</div>
<div class="section" id="reading">
<h3>Reading<a class="headerlink" href="#reading" title="Permalink to this headline">¶</a></h3>
<p>Data in the buffer can be extracted using <a class="reference internal" href="#_CPPv2NK12BufferWriter4dataEv" title="BufferWriter::data"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::data()</span></code></a>. This and
<a class="reference internal" href="#_CPPv2NK12BufferWriter4sizeEv" title="BufferWriter::size"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::size()</span></code></a> return a pointer to the start of the buffer and the amount of data
written to the buffer. This is effectively the same as <a class="reference internal" href="#_CPPv2NK12BufferWriter4viewEv" title="BufferWriter::view"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::view()</span></code></a> which returns a
<code class="xref cpp cpp-class docutils literal"><span class="pre">string_view</span></code> which covers the output data. Calling <a class="reference internal" href="#_CPPv2NK12BufferWriter5errorEv" title="BufferWriter::error"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::error()</span></code></a> will indicate
if more data than space available was written (i.e. the buffer would have been overrun).
<a class="reference internal" href="#_CPPv2NK12BufferWriter6extentEv" title="BufferWriter::extent"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::extent()</span></code></a> returns the amount of data written to the <a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a>. This
can be used in a two pass style with a null / size 0 buffer to determine the buffer size required
for the full output.</p>
</div>
<div class="section" id="advanced">
<h3>Advanced<a class="headerlink" href="#advanced" title="Permalink to this headline">¶</a></h3>
<p>The <a class="reference internal" href="#_CPPv2N12BufferWriter4clipE6size_t" title="BufferWriter::clip"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::clip()</span></code></a> and <a class="reference internal" href="#_CPPv2N12BufferWriter6extendE6size_t" title="BufferWriter::extend"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::extend()</span></code></a> methods can be used to reserve space
in the buffer. A common use case for this is to guarantee matching delimiters in output if buffer
space is exhausted. <a class="reference internal" href="#_CPPv2N12BufferWriter4clipE6size_t" title="BufferWriter::clip"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::clip()</span></code></a> can be used to temporarily reduce the buffer size by
an amount large enough to hold the terminal delimiter. After writing the contained output,
<a class="reference internal" href="#_CPPv2N12BufferWriter6extendE6size_t" title="BufferWriter::extend"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::extend()</span></code></a> can be used to restore the capacity and then output the terminal
delimiter.</p>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last"><strong>Never</strong> call <a class="reference internal" href="#_CPPv2N12BufferWriter6extendE6size_t" title="BufferWriter::extend"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::extend()</span></code></a> without previously calling <a class="reference internal" href="#_CPPv2N12BufferWriter4clipE6size_t" title="BufferWriter::clip"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::clip()</span></code></a> and always pass the same argument value.</p>
</div>
<p><a class="reference internal" href="#_CPPv2NK12BufferWriter9remainingEv" title="BufferWriter::remaining"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::remaining()</span></code></a> returns the amount of buffer space not yet consumed.</p>
<p><a class="reference internal" href="#_CPPv2NK12BufferWriter9auxBufferEv" title="BufferWriter::auxBuffer"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::auxBuffer()</span></code></a> returns a pointer to the first byte of the buffer not yet used. This
is useful to do speculative output, or do bounded output in a manner similar to using
<a class="reference internal" href="#_CPPv2N12BufferWriter4clipE6size_t" title="BufferWriter::clip"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::clip()</span></code></a> and <a class="reference internal" href="#_CPPv2N12BufferWriter6extendE6size_t" title="BufferWriter::extend"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::extend()</span></code></a>. A new <a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> instance
can be constructed with</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="n">ts</span><span class="o">::</span><span class="n">FixedBufferWriter</span> <span class="n">subw</span><span class="p">(</span><span class="n">w</span><span class="p">.</span><span class="n">auxBuffer</span><span class="p">(),</span> <span class="n">w</span><span class="p">.</span><span class="n">remaining</span><span class="p">());</span>
</pre></div>
</div>
<p>or as a convenience</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="n">ts</span><span class="o">::</span><span class="n">FixedBuffer</span> <span class="n">subw</span><span class="p">{</span><span class="n">w</span><span class="p">.</span><span class="n">auxBuffer</span><span class="p">()};</span>
</pre></div>
</div>
<p>Output can be written to <em>subw</em>. If successful, then <code class="code docutils literal"><span class="pre">w.fill(subw.size())</span></code> will add that
output to the main buffer. Depending on the purpose, <code class="code docutils literal"><span class="pre">w.fill(subw.extent())</span></code> can be used -
this will track the attempted output if sizing is important. Note that space for any terminal
markers can be reserved by bumping down the size from <a class="reference internal" href="#_CPPv2NK12BufferWriter9remainingEv" title="BufferWriter::remaining"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::remaining()</span></code></a>. Be careful of
underrun as the argument is an unsigned type.</p>
<p>If there is an error then <em>subw</em> can be ignored and some suitable error output written to
<em>w</em> instead. A common use case is to verify there is sufficient space in the buffer and create
a “not enough space” message if not. E.g.</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="n">ts</span><span class="o">::</span><span class="n">FixedBufferWriter</span> <span class="n">subw</span><span class="p">{</span><span class="n">w</span><span class="p">.</span><span class="n">auxWriter</span><span class="p">()};</span>
<span class="k">this</span><span class="o">-></span><span class="n">write_some_output</span><span class="p">(</span><span class="n">subw</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">subw</span><span class="p">.</span><span class="n">error</span><span class="p">())</span> <span class="n">w</span><span class="p">.</span><span class="n">fill</span><span class="p">(</span><span class="n">subw</span><span class="p">.</span><span class="n">size</span><span class="p">());</span>
<span class="k">else</span> <span class="n">w</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">"Insufficient space"</span><span class="n">_sv</span><span class="p">);</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="examples">
<h2>Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h2>
<p>For example, error prone code that looks like</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="kt">char</span> <span class="n">new_via_string</span><span class="p">[</span><span class="mi">1024</span><span class="p">];</span> <span class="c1">// 512-bytes for hostname+via string, 512-bytes for the debug info</span>
<span class="kt">char</span> <span class="o">*</span> <span class="n">via_string</span> <span class="o">=</span> <span class="n">new_via_string</span><span class="p">;</span>
<span class="kt">char</span> <span class="o">*</span> <span class="n">via_limit</span> <span class="o">=</span> <span class="n">via_string</span> <span class="o">+</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">new_via_string</span><span class="p">);</span>
<span class="c1">// ...</span>
<span class="o">*</span> <span class="n">via_string</span><span class="o">++</span> <span class="o">=</span> <span class="sc">' '</span><span class="p">;</span>
<span class="o">*</span> <span class="n">via_string</span><span class="o">++</span> <span class="o">=</span> <span class="sc">'['</span><span class="p">;</span>
<span class="c1">// incoming_via can be max MAX_VIA_INDICES+1 long (i.e. around 25 or so)</span>
<span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="o">-></span><span class="n">txn_conf</span><span class="o">-></span><span class="n">insert_request_via_string</span> <span class="o">></span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Highest verbosity</span>
<span class="n">via_string</span> <span class="o">+=</span> <span class="n">nstrcpy</span><span class="p">(</span><span class="n">via_string</span><span class="p">,</span> <span class="n">incoming_via</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">memcpy</span><span class="p">(</span><span class="n">via_string</span><span class="p">,</span> <span class="n">incoming_via</span> <span class="o">+</span> <span class="n">VIA_CLIENT</span><span class="p">,</span> <span class="n">VIA_SERVER</span> <span class="o">-</span> <span class="n">VIA_CLIENT</span><span class="p">);</span>
<span class="n">via_string</span> <span class="o">+=</span> <span class="n">VIA_SERVER</span> <span class="o">-</span> <span class="n">VIA_CLIENT</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">*</span><span class="n">via_string</span><span class="o">++</span> <span class="o">=</span> <span class="sc">']'</span><span class="p">;</span>
</pre></div>
</div>
<p>becomes</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="n">ts</span><span class="o">::</span><span class="n">LocalBufferWriter</span><span class="o"><</span><span class="mi">1024</span><span class="o">></span> <span class="n">w</span><span class="p">;</span> <span class="c1">// 1K internal buffer.</span>
<span class="c1">// ...</span>
<span class="n">w</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">" ["</span><span class="n">_sv</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="o">-></span><span class="n">txn_conf</span><span class="o">-></span><span class="n">insert_request_via_string</span> <span class="o">></span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Highest verbosity</span>
<span class="n">w</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">incoming_via</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">w</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">ts</span><span class="o">::</span><span class="n">string_view</span><span class="p">{</span><span class="n">incoming_via</span> <span class="o">+</span> <span class="n">VIA_CLIENT</span><span class="p">,</span> <span class="n">VIA_SERVER</span> <span class="o">-</span> <span class="n">VIA_CLIENT</span><span class="p">});</span>
<span class="p">}</span>
<span class="n">w</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="sc">']'</span><span class="p">);</span>
</pre></div>
</div>
<p>There will be no overrun on the memory buffer in <em>w</em>, in strong contrast to the original code.
This can be done better, as</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="p">(</span><span class="n">w</span><span class="p">.</span><span class="n">remaining</span><span class="p">()</span> <span class="o">>=</span> <span class="mi">3</span><span class="p">)</span> <span class="p">{</span>
<span class="n">w</span><span class="p">.</span><span class="n">clip</span><span class="p">(</span><span class="mi">1</span><span class="p">).</span><span class="n">write</span><span class="p">(</span><span class="s">" ["</span><span class="n">_sv</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">s</span><span class="o">-></span><span class="n">txn_conf</span><span class="o">-></span><span class="n">insert_request_via_string</span> <span class="o">></span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Highest verbosity</span>
<span class="n">w</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">incoming_via</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">w</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">ts</span><span class="o">::</span><span class="n">string_view</span><span class="p">{</span><span class="n">incoming_via</span> <span class="o">+</span> <span class="n">VIA_CLIENT</span><span class="p">,</span> <span class="n">VIA_SERVER</span> <span class="o">-</span> <span class="n">VIA_CLIENT</span><span class="p">});</span>
<span class="p">}</span>
<span class="n">w</span><span class="p">.</span><span class="n">extend</span><span class="p">(</span><span class="mi">1</span><span class="p">).</span><span class="n">write</span><span class="p">(</span><span class="sc">']'</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>This has the result that the terminal bracket will always be present which is very much appreciated
by code that parses the resulting log file.</p>
</div>
<div class="section" id="formatted-output">
<span id="bw-formatting"></span><h2>Formatted Output<a class="headerlink" href="#formatted-output" title="Permalink to this headline">¶</a></h2>
<p>The base <a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> was made to provide memory safety for formatted output. Support for
formmatted output was made to provide <em>type</em> safety. The implementation deduces the types of the
arguments to be formatted and handles them in a type specific and safe way.</p>
<p>The formatting style is of the “prefix” or “printf” style - the format is specified first and then
all the arguments. This contrasts to the “infix” or “streaming” style where formatting, literals,
and argument are intermixed in the order of output. There are various arguments for both styles but
conversations within the Traffic Server community indicated a clear preference for the prefix style. Therefore
formatted out consists of a format string, containing <em>formats</em>, which are replaced during output
with the values of arguments to the print function.</p>
<p>The primary use case for formatting is formatted output to fixed buffers. This is by far the
dominant style of output in Traffic Server and during the design phase I was told any performance loss must be
minimal. While work has and will be done to extend <a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> to operate on non-fixed
buffers, such use is secondary to operating directly on memory.</p>
<div class="admonition important">
<p class="first admonition-title">Important</p>
<p class="last">The overriding design goal is to provide the type specific formatting and flexibility of C++
stream operators with the performance of <code class="code docutils literal"><span class="pre">snprintf</span></code> and <code class="code docutils literal"><span class="pre">memcpy</span></code>.</p>
</div>
<p>This will preserve the general style of output in Traffic Server while still reaping the benefits of type safe
formatting with little to no performance cost.</p>
<p>Type safe formatting has two major benefits -</p>
<ul class="simple">
<li>No mismatch between the format specifier and the argument. Although some modern compilers do
better at catching this at run time, there is still risk (especially with non-constant format
strings) and divergence between operating systems such that there is no <a class="reference external" href="https://github.com/apache/trafficserver/pull/3476/files">universally correct
choice</a>. In addition the number of
arguments can be verified to be correct which is often useful.</li>
<li>Formatting can be customized per type or even per partial type (e.g. <code class="code docutils literal"><span class="pre">T*</span></code> for generic
<code class="code docutils literal"><span class="pre">T</span></code>). This enables embedding common formatting work in the format system once, rather than
duplicating it in many places (e.g. converting enum values to names). This makes it easier for
developers to make useful error messages. See <a class="reference internal" href="#bwf-http-debug-name-example"><span class="std std-ref">this example</span></a>
for more detail.</li>
</ul>
<p>As a result of these benefits there has been other work on similar projects, to replace
<code class="code docutils literal"><span class="pre">printf</span></code> a better mechanism. Unfortunately most of these are rather project specific and don’t
suit the use case in Traffic Server. The two best options, <a class="reference external" href="https://www.boost.org/doc/libs/1_64_0/libs/format/">Boost.Format</a> and <a class="reference external" href="https://github.com/fmtlib/fmt">fmt</a>,
while good, are also not quite close enough to outweight the benefits of a version specifically
tuned for Traffic Server. <code class="docutils literal"><span class="pre">Boost.Format</span></code> is not acceptable because of the Boost footprint. <code class="docutils literal"><span class="pre">fmt</span></code> has the
problem of depending on C++ stream operators and therefore not having the required level of
performance or memory characteristics. Its main benefit, of reusing stream operators, doesn’t apply
to Traffic Server because of the nigh non-existence of such operators. The possibility of using C++ stream
operators was investigated but changing those to use pre-existing buffers not allocated internally
was very difficult, judged worse than building a relatively simple implementation from scratch. The
actual core implementation of formatted output for <a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> is not very large - most of
the overall work will be writing formatters, work which would need to be done in any case but in
contrast to current practice, only done once.</p>
<p><a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> supports formatting output in a style similar to Python formatting via
<a class="reference internal" href="#_CPPv2N12BufferWriter5printE8TextViewz" title="BufferWriter::print"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::print()</span></code></a>. Looking at the other versions of work in this area, almost all of them
have gone with this style. Boost.Format also takes basically this same approach, just using
different paired delimiters. Traffic Server contains increasing amounts of native Python code which means many
Traffic Server developers will already be familiar (or should become familiar) with this style of formatting.
While not <em>exactly</em> the same at the Python version, BWF (<a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> Formatting) tries to
be as similar as language and internal needs allow.</p>
<p>As noted previously and in the Python and even <code class="code docutils literal"><span class="pre">printf</span></code> way, a format string consists of
literal text in which formats are embedded. Each format marks a place where formatted data of
an argument will be placed, along with argument specific formatting. The format is divided in to
three parts, separated by colons.</p>
<p>While this seems a bit complex, all of it is optional. If default output is acceptable, then BWF
will work with just the format <code class="docutils literal"><span class="pre">{}</span></code>. In a sense, <code class="docutils literal"><span class="pre">{}</span></code> serves the same function for output as
<code class="code docutils literal"><span class="pre">auto</span></code> does for programming - the compiler knows the type, it should be able to do something
reasonable without the programmer needing to be explicit.</p>
<pre>
<strong id="grammar-token-format">format </strong> ::= "{" [name] [":" [specifier] [":" extension]] "}"
<strong id="grammar-token-name">name </strong> ::= index | ICHAR+
<strong id="grammar-token-index">index </strong> ::= non-negative integer
<strong id="grammar-token-extension">extension</strong> ::= ICHAR*
<strong id="grammar-token-ICHAR">ICHAR </strong> ::= a printable ASCII character except for '{', '}', ':'
</pre>
<dl class="docutils">
<dt><a class="reference internal" href="#grammar-token-name"><code class="xref std std-token docutils literal"><span class="pre">name</span></code></a></dt>
<dd><p class="first">The <a class="reference internal" href="#grammar-token-name"><code class="xref std std-token docutils literal"><span class="pre">name</span></code></a> of the argument to use. This can be a non-negative integer in which case it is
the zero based index of the argument to the method call. E.g. <code class="docutils literal"><span class="pre">{0}</span></code> means the first argument
and <code class="docutils literal"><span class="pre">{2}</span></code> is the third argument after the format.</p>
<blockquote>
<div><p><code class="docutils literal"><span class="pre">bw.print("{0}</span> <span class="pre">{1}",</span> <span class="pre">'a',</span> <span class="pre">'b')</span></code> => <code class="docutils literal"><span class="pre">a</span> <span class="pre">b</span></code></p>
<p><code class="docutils literal"><span class="pre">bw.print("{1}</span> <span class="pre">{0}",</span> <span class="pre">'a',</span> <span class="pre">'b')</span></code> => <code class="docutils literal"><span class="pre">b</span> <span class="pre">a</span></code></p>
</div></blockquote>
<p>The <a class="reference internal" href="#grammar-token-name"><code class="xref std std-token docutils literal"><span class="pre">name</span></code></a> can be omitted in which case it is treated as an index in parallel to the
position in the format string. Only the position in the format string matters, not what names
other format elements may have used.</p>
<blockquote>
<div><p><code class="docutils literal"><span class="pre">bw.print("{0}</span> <span class="pre">{2}</span> <span class="pre">{}",</span> <span class="pre">'a',</span> <span class="pre">'b',</span> <span class="pre">'c')</span></code> => <code class="docutils literal"><span class="pre">a</span> <span class="pre">c</span> <span class="pre">c</span></code></p>
<p><code class="docutils literal"><span class="pre">bw.print("{0}</span> <span class="pre">{2}</span> <span class="pre">{2}",</span> <span class="pre">'a',</span> <span class="pre">'b',</span> <span class="pre">'c')</span></code> => <code class="docutils literal"><span class="pre">a</span> <span class="pre">c</span> <span class="pre">c</span></code></p>
</div></blockquote>
<p>Note that an argument can be printed more than once if the name is used more than once.</p>
<blockquote>
<div><p><code class="docutils literal"><span class="pre">bw.print("{0}</span> <span class="pre">{}</span> <span class="pre">{0}",</span> <span class="pre">'a',</span> <span class="pre">'b')</span></code> => <code class="docutils literal"><span class="pre">a</span> <span class="pre">b</span> <span class="pre">a</span></code></p>
<p><code class="docutils literal"><span class="pre">bw.print("{0}</span> <span class="pre">{1}</span> <span class="pre">{0}",</span> <span class="pre">'a',</span> <span class="pre">'b')</span></code> => <code class="docutils literal"><span class="pre">a</span> <span class="pre">b</span> <span class="pre">a</span></code></p>
</div></blockquote>
<p class="last">Alphanumeric names refer to values in a global table. These will be described in more detail
someday. Such names, however, do not count in terms of default argument indexing.</p>
</dd>
<dt><a class="reference internal" href="#grammar-token-specifier"><code class="xref std std-token docutils literal"><span class="pre">specifier</span></code></a></dt>
<dd><p class="first">Basic formatting control.</p>
<pre>
<strong id="grammar-token-specifier">specifier</strong> ::= [[fill]align][sign]["#"]["0"][[min][.precision][,max][type]]
<strong id="grammar-token-fill">fill </strong> ::= fill-char | URI-char
<strong id="grammar-token-URI-char">URI-char </strong> ::= "%" hex-digit hex-digit
<strong id="grammar-token-fill-char">fill-char</strong> ::= printable character except "{", "}", ":", "%"
<strong id="grammar-token-align">align </strong> ::= "<" | ">" | "=" | "^"
<strong id="grammar-token-sign">sign </strong> ::= "+" | "-" | " "
<strong id="grammar-token-min">min </strong> ::= non-negative integer
<strong id="grammar-token-precision">precision</strong> ::= positive integer
<strong id="grammar-token-max">max </strong> ::= non-negative integer
<strong id="grammar-token-type">type </strong> ::= type: "g" | "s" | "S" | "x" | "X" | "d" | "o" | "b" | "B" | "p" | "P"
<strong id="grammar-token-hex-digit">hex-digit</strong> ::= "0" .. "9" | "a" .. "f" | "A" .. "F"
</pre>
<p>The output is placed in a field that is at least <a class="reference internal" href="#grammar-token-min"><code class="xref std std-token docutils literal"><span class="pre">min</span></code></a> wide and no more than <a class="reference internal" href="#grammar-token-max"><code class="xref std std-token docutils literal"><span class="pre">max</span></code></a> wide. If
the output is less than <a class="reference internal" href="#grammar-token-min"><code class="xref std std-token docutils literal"><span class="pre">min</span></code></a> then</p>
<blockquote>
<div><ul>
<li><p class="first">The <a class="reference internal" href="#grammar-token-fill"><code class="xref std std-token docutils literal"><span class="pre">fill</span></code></a> character is used for the extra space required. This can be an explicit
character or a URI encoded one (to allow otherwise reserved characters).</p>
</li>
<li><p class="first">The output is shifted according to the <a class="reference internal" href="#grammar-token-align"><code class="xref std std-token docutils literal"><span class="pre">align</span></code></a>.</p>
<dl class="docutils">
<dt><</dt>
<dd><p class="first last">Align to the left, fill to the right.</p>
</dd>
</dl>
<dl class="docutils">
<dt>></dt>
<dd><p class="first last">Align to the right, fill to the left.</p>
</dd>
</dl>
<dl class="docutils">
<dt>^</dt>
<dd><p class="first last">Align in the middle, fill to left and right.</p>
</dd>
</dl>
<dl class="docutils">
<dt>=</dt>
<dd><p class="first last">Numerically align, putting the fill between the sign character and the value.</p>
</dd>
</dl>
</li>
</ul>
</div></blockquote>
<p>The output is clipped by <a class="reference internal" href="#grammar-token-max"><code class="xref std std-token docutils literal"><span class="pre">max</span></code></a> width characters and by the end of the buffer.
<a class="reference internal" href="#grammar-token-precision"><code class="xref std std-token docutils literal"><span class="pre">precision</span></code></a> is used by floating point values to specify the number of places of precision.</p>
<p><a class="reference internal" href="#grammar-token-type"><code class="xref std std-token docutils literal"><span class="pre">type</span></code></a> is used to indicate type specific formatting. For integers it indicates the output
radix and if <code class="docutils literal"><span class="pre">#</span></code> is present the radix is prefix is generated (one of <code class="docutils literal"><span class="pre">0xb</span></code>, <code class="docutils literal"><span class="pre">0</span></code>, <code class="docutils literal"><span class="pre">0x</span></code>).
Format types of the same letter are equivalent, varying only in the character case used for
output. Most commonly ‘x’ prints values in lower cased hexadecimal (<code class="code docutils literal"><span class="pre">0x1337beef</span></code>) while ‘X’
prints in upper case hexadecimal (<code class="code docutils literal"><span class="pre">0X1337BEEF</span></code>). Note there is no upper case decimal or
octal type because case is irrelevant for those.</p>
<blockquote>
<div><table border="1" class="docutils">
<colgroup>
<col width="3%" />
<col width="97%" />
</colgroup>
<tbody valign="top">
<tr class="row-odd"><td>g</td>
<td>generic, default.</td>
</tr>
<tr class="row-even"><td>b</td>
<td>binary</td>
</tr>
<tr class="row-odd"><td>B</td>
<td>Binary</td>
</tr>
<tr class="row-even"><td>d</td>
<td>decimal</td>
</tr>
<tr class="row-odd"><td>o</td>
<td>octal</td>
</tr>
<tr class="row-even"><td>x</td>
<td>hexadecimal</td>
</tr>
<tr class="row-odd"><td>X</td>
<td>Hexadecimal</td>
</tr>
<tr class="row-even"><td>p</td>
<td>pointer (hexadecimal address)</td>
</tr>
<tr class="row-odd"><td>P</td>
<td>Pointer (Hexadecimal address)</td>
</tr>
<tr class="row-even"><td>s</td>
<td>string</td>
</tr>
<tr class="row-odd"><td>S</td>
<td>String (upper case)</td>
</tr>
</tbody>
</table>
</div></blockquote>
<p>For several specializations the hexadecimal format is taken to indicate printing the value as if
it were a hexidecimal value, in effect providing a hex dump of the value. This is the case for
<code class="xref cpp cpp-class docutils literal"><span class="pre">string_view</span></code> and therefore a hex dump of an object can be done by creating a
<code class="xref cpp cpp-class docutils literal"><span class="pre">string_view</span></code> covering the data and then printing it with <code class="code docutils literal"><span class="pre">{:x}</span></code>.</p>
<p class="last">The string type (‘s’ or ‘S’) is generally used to cause alphanumeric output for a value that would
normally use numeric output. For instance, a <code class="code docutils literal"><span class="pre">bool</span></code> is normally <code class="docutils literal"><span class="pre">0</span></code> or <code class="docutils literal"><span class="pre">1</span></code>. Using the
type ‘s’ yields <code class="docutils literal"><span class="pre">true`</span> <span class="pre">or</span> <span class="pre">``false</span></code>. The upper case form, ‘S’, applies only in these cases where the
formatter generates the text, it does not apply to normally text based values unless specifically noted.</p>
</dd>
<dt><a class="reference internal" href="#grammar-token-extension"><code class="xref std std-token docutils literal"><span class="pre">extension</span></code></a></dt>
<dd>Text (excluding braces) that is passed to the type specific formatter function. This can be used
to provide extensions for specific argument types (e.g., IP addresses). The base logic ignores it
but passes it on to the formatting function which can then behave different based on the
extension.</dd>
</dl>
<div class="section" id="usage-examples">
<h3>Usage Examples<a class="headerlink" href="#usage-examples" title="Permalink to this headline">¶</a></h3>
<p>Some examples, comparing <code class="code docutils literal"><span class="pre">snprintf</span></code> and <a class="reference internal" href="#_CPPv2N12BufferWriter5printE8TextViewz" title="BufferWriter::print"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::print()</span></code></a>.</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="p">(</span><span class="n">len</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">auto</span> <span class="n">n</span> <span class="o">=</span> <span class="n">snprintf</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="s">"count %d"</span><span class="p">,</span> <span class="n">count</span><span class="p">);</span>
<span class="n">len</span> <span class="o">-=</span> <span class="n">n</span><span class="p">;</span>
<span class="n">buff</span> <span class="o">+=</span> <span class="n">n</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"count {}"</span><span class="p">,</span> <span class="n">count</span><span class="p">);</span>
<span class="c1">// --</span>
<span class="k">if</span> <span class="p">(</span><span class="n">len</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">auto</span> <span class="n">n</span> <span class="o">=</span> <span class="n">snprintf</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="s">"Size %"</span> <span class="n">PRId64</span> <span class="s">" bytes"</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">thing</span><span class="p">));</span>
<span class="n">len</span> <span class="o">-=</span> <span class="n">n</span><span class="p">;</span>
<span class="n">buff</span> <span class="o">+=</span> <span class="n">n</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"Size {} bytes"</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">thing</span><span class="p">));</span>
<span class="c1">// --</span>
<span class="k">if</span> <span class="p">(</span><span class="n">len</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">auto</span> <span class="n">n</span> <span class="o">=</span> <span class="n">snprintf</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="s">"Number of items %ld"</span><span class="p">,</span> <span class="n">thing</span><span class="o">-></span><span class="n">count</span><span class="p">());</span>
<span class="n">len</span> <span class="o">-=</span> <span class="n">n</span><span class="p">;</span>
<span class="n">buff</span> <span class="o">+=</span> <span class="n">n</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"Number of items {}"</span><span class="p">,</span> <span class="n">thing</span><span class="o">-></span><span class="n">count</span><span class="p">());</span>
</pre></div>
</div>
<p>Enumerations become easier. Note in this case argument indices are used in order to print both a
name and a value for the enumeration. A key benefit here is the lack of need for a developer to know
the specific free function or method needed to do the name lookup. In this case,
<code class="code docutils literal"><span class="pre">HttpDebugNuames::get_server_state_name</span></code>. Rather than every developer having to memorize the
assocation between the type and the name lookup function, or grub through the code hoping for an
example, the compiler is told once and henceforth does the lookup. The internal implementation of
this is <a class="reference internal" href="#bwf-http-debug-name-example"><span class="std std-ref">here</span></a></p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="p">(</span><span class="n">len</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">auto</span> <span class="n">n</span> <span class="o">=</span> <span class="n">snprintf</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="s">"Unexpected event %d in state %s[%d] for %.*s"</span><span class="p">,</span>
<span class="n">event</span><span class="p">,</span>
<span class="n">HttpDebugNames</span><span class="o">::</span><span class="n">get_server_state_name</span><span class="p">(</span><span class="n">t_state</span><span class="p">.</span><span class="n">current</span><span class="p">.</span><span class="n">state</span><span class="p">),</span>
<span class="n">t_state</span><span class="p">.</span><span class="n">current</span><span class="p">.</span><span class="n">state</span><span class="p">,</span>
<span class="k">static_cast</span><span class="o"><</span><span class="kt">int</span><span class="o">></span><span class="p">(</span><span class="n">host_len</span><span class="p">),</span> <span class="n">host</span><span class="p">);</span>
<span class="n">buff</span> <span class="o">+=</span> <span class="n">n</span><span class="p">;</span>
<span class="n">len</span> <span class="o">-=</span> <span class="n">n</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"Unexpected event {0} in state {1}[{1:d}] for {2}"</span><span class="p">,</span>
<span class="n">event</span><span class="p">,</span> <span class="n">t_state</span><span class="p">.</span><span class="n">current</span><span class="p">.</span><span class="n">state</span><span class="p">,</span> <span class="n">string_view</span><span class="p">{</span><span class="n">host</span><span class="p">,</span> <span class="n">host_len</span><span class="p">});</span>
</pre></div>
</div>
<p>Using <code class="code docutils literal"><span class="pre">std::string</span></code>, which illustrates the advantage of a formatter overloading knowing how to
get the size from the object and not having to deal with restrictions on the numeric type (e.g.,
that <code class="code docutils literal"><span class="pre">%.*s</span></code> requires an <code class="code docutils literal"><span class="pre">int</span></code>, not a <code class="code docutils literal"><span class="pre">size_t</span></code>).</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="p">(</span><span class="n">len</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="n">len</span> <span class="o">-=</span> <span class="n">snprintf</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="s">"%.*s"</span><span class="p">,</span> <span class="k">static_cast</span><span class="o"><</span><span class="kt">int</span><span class="o">></span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">size</span><span class="p">()),</span> <span class="n">s</span><span class="p">.</span><span class="n">data</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"{}"</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span>
</pre></div>
</div>
<p>IP addresses are much easier. There are two big advantages here. One is not having to know the
conversion function name. The other is the lack of having to declare local variables and having to
remember what the appropriate size is. Beyond there this code is more performant because the output
is rendered directly in the output buffer, not rendered to a temporary and then copied over. This
lack of local variables can be particularly nice in the context of a <code class="code docutils literal"><span class="pre">switch</span></code> statement where
local variables for a <code class="code docutils literal"><span class="pre">case</span></code> mean having to add extra braces, or declare the temporaries at an
outer scope.</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="kt">char</span> <span class="n">ip_buff1</span><span class="p">[</span><span class="n">INET6_ADDRPORTSTRLEN</span><span class="p">];</span>
<span class="kt">char</span> <span class="n">ip_buff2</span><span class="p">[</span><span class="n">INET6_ADDRPORTSTRLEN</span><span class="p">];</span>
<span class="n">ats_ip_nptop</span><span class="p">(</span><span class="n">ip_buff1</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ip_buff1</span><span class="p">),</span> <span class="n">addr1</span><span class="p">);</span>
<span class="n">ats_ip_nptop</span><span class="p">(</span><span class="n">ip_buff2</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">ip_buff2</span><span class="p">),</span> <span class="n">add2</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">len</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="n">snprintf</span><span class="p">(</span><span class="n">buff</span><span class="p">,</span> <span class="n">len</span><span class="p">,</span> <span class="s">"Connecting to %s from %s"</span><span class="p">,</span> <span class="n">ip_buff1</span><span class="p">,</span> <span class="n">ip_buff2</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"Connecting to {} from {}"</span><span class="p">,</span> <span class="n">addr1</span><span class="p">,</span> <span class="n">addr2</span><span class="p">);</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="user-defined-formatting">
<h2>User Defined Formatting<a class="headerlink" href="#user-defined-formatting" title="Permalink to this headline">¶</a></h2>
<p>To get the full benefit of type safe formatting it is necessary to provide type specific formatting
functions which are called when a value of that type is formatted. This is how type specific
knowledge such as the names of enumeration values are encoded in a single location. Additional type
specific formatting can be provided via the <a class="reference internal" href="#grammar-token-extension"><code class="xref std std-token docutils literal"><span class="pre">extension</span></code></a> field. Without this, special formatting
requires extra functions and additional work at the call site, rather than a single consolidated
formatting function.</p>
<p>To provide a formatter for a type <code class="code docutils literal"><span class="pre">V</span></code> the function <code class="code docutils literal"><span class="pre">bwformat</span></code> is overloaded. The signature
would look like this:</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="n">BufferWriter</span><span class="o">&</span> <span class="n">ts</span><span class="o">::</span><span class="n">bwformat</span><span class="p">(</span><span class="n">BufferWriter</span><span class="o">&</span> <span class="n">w</span><span class="p">,</span> <span class="n">BWFSpec</span> <span class="k">const</span><span class="o">&</span> <span class="n">spec</span><span class="p">,</span> <span class="n">V</span> <span class="k">const</span><span class="o">&</span> <span class="n">v</span><span class="p">)</span>
</pre></div>
</div>
<p><em>w</em> is the output and <em>spec</em> the parsed specifier, including the extension (if any). The
calling framework will handle basic alignment as per <em>spec</em> therfore the overload does not need
to unless the alignment requirements are more detailed (e.g. integer alignment operations) or
performance is critical. In the latter case the formatter should make sure to use at least the
minimum width in order to disable any additional alignment operation.</p>
<p>It is important to note that a formatter can call another formatter. For example, the formatter for
pointers looks like:</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="c1">// Pointers that are not specialized.</span>
<span class="kr">inline</span> <span class="n">BufferWriter</span> <span class="o">&</span>
<span class="n">bwformat</span><span class="p">(</span><span class="n">BufferWriter</span> <span class="o">&</span><span class="n">w</span><span class="p">,</span> <span class="n">BWFSpec</span> <span class="k">const</span> <span class="o">&</span><span class="n">spec</span><span class="p">,</span> <span class="k">const</span> <span class="kt">void</span> <span class="o">*</span> <span class="n">ptr</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">BWFSpec</span> <span class="n">ptr_spec</span><span class="p">{</span><span class="n">spec</span><span class="p">};</span>
<span class="n">ptr_spec</span><span class="p">.</span><span class="n">_radix_lead_p</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">ptr_spec</span><span class="p">.</span><span class="n">_type</span> <span class="o">==</span> <span class="n">BWFSpec</span><span class="o">::</span><span class="n">DEFAULT_TYPE</span> <span class="o">||</span> <span class="n">ptr_spec</span><span class="p">.</span><span class="n">_type</span> <span class="o">==</span> <span class="sc">'p'</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// if default or specifically 'p', switch to lower case hex.</span>
<span class="n">ptr_spec</span><span class="p">.</span><span class="n">_type</span> <span class="o">=</span> <span class="sc">'x'</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">ptr_spec</span><span class="p">.</span><span class="n">_type</span> <span class="o">==</span> <span class="sc">'P'</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Incoming 'P' means upper case hex.</span>
<span class="n">ptr_spec</span><span class="p">.</span><span class="n">_type</span> <span class="o">=</span> <span class="sc">'X'</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">bw_fmt</span><span class="o">::</span><span class="n">Format_Integer</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">ptr_spec</span><span class="p">,</span>
<span class="k">reinterpret_cast</span><span class="o"><</span><span class="kt">intptr_t</span><span class="o">></span><span class="p">(</span><span class="n">ptr</span><span class="p">),</span> <span class="nb">false</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The code checks if the type <code class="docutils literal"><span class="pre">p</span></code> or <code class="docutils literal"><span class="pre">P</span></code> was used in order to select the appropriate case, then
delegates the actual rendering to the integer formatter with a type of <code class="docutils literal"><span class="pre">x</span></code> or <code class="docutils literal"><span class="pre">X</span></code> as
appropriate. In turn other formatters, if given the type <code class="docutils literal"><span class="pre">p</span></code> or <code class="docutils literal"><span class="pre">P</span></code> can cast the value to
<code class="code docutils literal"><span class="pre">const</span> <span class="pre">void*</span></code> and call <code class="code docutils literal"><span class="pre">bwformat</span></code> on that to output the value as a pointer.</p>
<p>To help reduce duplication, the output stream operator <code class="code docutils literal"><span class="pre">operator<<</span></code> is defined to call this
function with a default constructed <code class="code docutils literal"><span class="pre">BWFSpec</span></code> instance so that absent a specific overload
a BWF formatter will also provide a C++ stream output operator.</p>
<div class="section" id="enum-example">
<h3>Enum Example<a class="headerlink" href="#enum-example" title="Permalink to this headline">¶</a></h3>
<p id="bwf-http-debug-name-example">For a specific example of using BufferWriter formatting to make debug messages easier, consider the
case of <code class="code docutils literal"><span class="pre">HttpDebugNames</span></code>. This is a class that serves as a namespace to provide various
methods that convert state machine related data into descriptive strings. Currently this is
undocumented (and even uncommented) and is therefore used infrequently, as that requires either
blind cut and paste, or tracing through header files to understand the code. This can be greatly
simplified by adding formatters to <a class="reference external" href="https://github.com/apache/trafficserver/blob/master/proxy/http/HttpDebugNames.h">HttpDebugNames.h</a></p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="kr">inline</span> <span class="n">ts</span><span class="o">::</span><span class="n">BufferWriter</span> <span class="o">&</span>
<span class="n">bwformat</span><span class="p">(</span><span class="n">ts</span><span class="o">::</span><span class="n">BufferWriter</span> <span class="o">&</span><span class="n">w</span><span class="p">,</span> <span class="n">ts</span><span class="o">::</span><span class="n">BWFSpec</span> <span class="k">const</span> <span class="o">&</span><span class="n">spec</span><span class="p">,</span> <span class="n">HttpTransact</span><span class="o">::</span><span class="n">ServerState_t</span> <span class="n">state</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">spec</span><span class="p">.</span><span class="n">has_numeric_type</span><span class="p">())</span> <span class="p">{</span>
<span class="c1">// allow the user to force numeric output with '{:d}' or other numeric type.</span>
<span class="k">return</span> <span class="n">bwformat</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">spec</span><span class="p">,</span> <span class="k">static_cast</span><span class="o"><</span><span class="kt">uintmax_t</span><span class="o">></span><span class="p">(</span><span class="n">state</span><span class="p">));</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">bwformat</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="n">spec</span><span class="p">,</span> <span class="n">HttpDebugNames</span><span class="o">::</span><span class="n">get_server_state_name</span><span class="p">(</span><span class="n">state</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>With this in place, any one wanting to print the name of the server state enumeration can do</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"state {}"</span><span class="p">,</span> <span class="n">t_state</span><span class="p">.</span><span class="n">current_state</span><span class="p">);</span>
</pre></div>
</div>
<p>There is no need to remember names like <code class="code docutils literal"><span class="pre">HttpDebugNames</span></code> nor which method in it does the
conversion. The developer making the <code class="code docutils literal"><span class="pre">HttpDebugNames</span></code> class or equivalent can take care of
that in the same header file that provides the type.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">In actual practice, due to this method being so obscure it’s not actually used as far as I
can determine.</p>
</div>
</div>
<div class="section" id="argument-forwarding">
<h3>Argument Forwarding<a class="headerlink" href="#argument-forwarding" title="Permalink to this headline">¶</a></h3>
<p>It will frequently be useful for other libraries to allow local formatting (such as <code class="code docutils literal"><span class="pre">Errata</span></code>).
For such cases the class methods will need to take variable arguments and then forward them on to
the formatter. <a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> provides the <a class="reference internal" href="#_CPPv2IDpEN12BufferWriter6printvE8TextViewRRNSt5tupleIDp4ArgsEE" title="BufferWriter::printv"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::printv()</span></code></a> overload for this
purpose. Instead of taking variable arguments, these overloads take a <code class="code docutils literal"><span class="pre">std::tuple</span></code> of
arguments. Such as tuple is easily created with <a class="reference external" href="http://en.cppreference.com/w/cpp/utility/tuple/forward_as_tuple">std::forward_as_tuple</a>. A standard implementation that
uses the <code class="code docutils literal"><span class="pre">std::string</span></code> overload for <a class="reference internal" href="#_CPPv2IDpE7bwprintRNSt6stringE11string_viewDpRR4Args" title="bwprint"><code class="xref cpp cpp-func docutils literal"><span class="pre">bwprint()</span></code></a> would look like</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="k">template</span> <span class="o"><</span> <span class="k">typename</span> <span class="p">...</span> <span class="n">Args</span> <span class="o">></span>
<span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">message</span><span class="p">(</span><span class="n">string_view</span> <span class="n">fmt</span><span class="p">,</span> <span class="n">Args</span> <span class="o">&&</span><span class="p">...</span> <span class="n">args</span><span class="p">)</span> <span class="p">{</span>
<span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">zret</span><span class="p">;</span>
<span class="k">return</span> <span class="n">ts</span><span class="o">::</span><span class="n">bwprint</span><span class="p">(</span><span class="n">zret</span><span class="p">,</span> <span class="n">fmt</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">forward_as_tuple</span><span class="p">(</span><span class="n">args</span><span class="p">...));</span>
<span class="p">}</span>
</pre></div>
</div>
<p>This gathers the argument (generally references to the arguments) in to a single tuple which is then
passed by reference, to avoid restacking the arguments for every nested function call.</p>
</div>
<div class="section" id="specialized-types">
<h3>Specialized Types<a class="headerlink" href="#specialized-types" title="Permalink to this headline">¶</a></h3>
<p>These are types for which there exists a type specific BWF formatter.</p>
<dl class="docutils">
<dt><code class="xref cpp cpp-class docutils literal"><span class="pre">string_view</span></code></dt>
<dd><p class="first">Generally the contents of the view.</p>
<dl class="docutils">
<dt>‘x’ or ‘X’</dt>
<dd>A hexadecimal dump of the contents of the view in lower (‘x’) or upper (‘X’) case.</dd>
<dt>‘p’ or ‘P’</dt>
<dd>The pointer and length value of the view in lower (‘p’) or upper (‘P’) case.</dd>
</dl>
<p class="last">The <a class="reference internal" href="#grammar-token-precision"><code class="xref std std-token docutils literal"><span class="pre">precision</span></code></a> is interpreted specially for this type to mean “skip <a class="reference internal" href="#grammar-token-precision"><code class="xref std std-token docutils literal"><span class="pre">precision</span></code></a>
initial characters”. When combined with <a class="reference internal" href="#grammar-token-max"><code class="xref std std-token docutils literal"><span class="pre">max</span></code></a> this allows a mechanism for printing
substrings of the <code class="xref cpp cpp-class docutils literal"><span class="pre">string_view</span></code>. For instance, to print the 10th through 20th characters
the format <code class="docutils literal"><span class="pre">{:.10,20}</span></code> would suffice. Given the method <code class="code docutils literal"><span class="pre">substr</span></code> for <code class="xref cpp cpp-class docutils literal"><span class="pre">string_view</span></code>
is cheap, it’s unclear how useful this is.</p>
</dd>
<dt><code class="code docutils literal"><span class="pre">sockaddr</span> <span class="pre">const*</span></code></dt>
<dd><p class="first">The IP address is printed. Fill is used to fill in address segments if provided, not to the
minimum width if specified. <code class="xref cpp cpp-class docutils literal"><span class="pre">IpEndpoint</span></code> and <code class="xref cpp cpp-class docutils literal"><span class="pre">IpAddr</span></code> are supported with the same
formatting. The formatting support in this case is extensive because of the commonality and
importance of IP address data.</p>
<p>Type overrides</p>
<blockquote>
<div><dl class="docutils">
<dt>‘p’ or ‘P’</dt>
<dd>The pointer address is printed as hexadecimal lower (‘p’) or upper (‘P’) case.</dd>
</dl>
</div></blockquote>
<p>The extension can be used to control which parts of the address are printed. These can be in any order,
the output is always address, port, family. The default is the equivalent of “ap”. In addition, the
character ‘=’ (“numeric align”) can be used to internally right justify the elements.</p>
<dl class="docutils">
<dt>‘a’</dt>
<dd>The address.</dd>
<dt>‘p’</dt>
<dd>The port (host order).</dd>
<dt>‘f’</dt>
<dd>The IP address family.</dd>
<dt>‘=’</dt>
<dd>Internally justify the numeric values. This must be the first or second character. If it is the second
the first character is treated as the internal fill character. If omitted ‘0’ (zero) is used.</dd>
</dl>
<p>E.g.</p>
<div class="last highlight-cpp"><div class="highlight"><pre><span></span><span class="kt">void</span> <span class="nf">func</span><span class="p">(</span><span class="n">sockaddr</span> <span class="k">const</span><span class="o">*</span> <span class="n">addr</span><span class="p">)</span> <span class="p">{</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"To {}"</span><span class="p">,</span> <span class="n">addr</span><span class="p">);</span> <span class="c1">// -> "To 172.19.3.105:4951"</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"To {0::a} on port {0::p}"</span><span class="p">,</span> <span class="n">addr</span><span class="p">);</span> <span class="c1">// -> "To 172.19.3.105 on port 4951"</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"To {::=}"</span><span class="p">,</span> <span class="n">addr</span><span class="p">);</span> <span class="c1">// -> "To 127.019.003.105:04951"</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"Using address family {::f}"</span><span class="p">,</span> <span class="n">addr</span><span class="p">);</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"{::a}"</span><span class="p">,</span><span class="n">addr</span><span class="p">);</span> <span class="c1">// -> "172.19.3.105"</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"{::=a}"</span><span class="p">,</span><span class="n">addr</span><span class="p">);</span> <span class="c1">// -> "172.019.003.105"</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"{::0=a}"</span><span class="p">,</span><span class="n">addr</span><span class="p">);</span> <span class="c1">// -> "172.019.003.105"</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"{:: =a}"</span><span class="p">,</span><span class="n">addr</span><span class="p">);</span> <span class="c1">// -> "172. 19. 3.105"</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"{:>20:a}"</span><span class="p">,</span><span class="n">addr</span><span class="p">);</span> <span class="c1">// -> " 172.19.3.105"</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"{:>20:=a}"</span><span class="p">,</span><span class="n">addr</span><span class="p">);</span> <span class="c1">// -> " 172.019.003.105"</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"{:>20: =a}"</span><span class="p">,</span><span class="n">addr</span><span class="p">);</span> <span class="c1">// -> " 172. 19. 3.105"</span>
<span class="p">}</span>
</pre></div>
</div>
</dd>
</dl>
</div>
</div>
<div class="section" id="global-names">
<h2>Global Names<a class="headerlink" href="#global-names" title="Permalink to this headline">¶</a></h2>
<p>As a convenience, there are a few predefined global names that can be used to generate output. These
do not take any arguments to <a class="reference internal" href="#_CPPv2N12BufferWriter5printE8TextViewz" title="BufferWriter::print"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::print()</span></code></a>, the data needed for output is either
process or thread global and is retrieved directly. They also are not counted for automatic indexing.</p>
<dl class="docutils">
<dt>now</dt>
<dd>The epoch time in seconds.</dd>
<dt>tick</dt>
<dd>The high resolution clock tick.</dd>
<dt>timestamp</dt>
<dd>UTC time in the format “Year Month Date Hour:Minute:Second”, e.g. “2018 Apr 17 14:23:47”.</dd>
<dt>thread-id</dt>
<dd>The id of the current thread.</dd>
<dt>thread-name</dt>
<dd>The name of the current thread.</dd>
<dt>ts-thread</dt>
<dd>A pointer to the Traffic Server <code class="xref cpp cpp-class docutils literal"><span class="pre">Thread</span></code> object for the current thread. This is useful for comparisons.</dd>
<dt>ts-ethread</dt>
<dd>A pointer to the Traffic Server <code class="xref cpp cpp-class docutils literal"><span class="pre">EThread</span></code> object for the current thread. This is useful for comparisons
or to indicate if the thread is an <code class="xref cpp cpp-class docutils literal"><span class="pre">EThread</span></code> (if not, the value will be <code class="code docutils literal"><span class="pre">nullptr</span></code>).</dd>
</dl>
<p>For example, to have the same output as the normal diagnostic messages with a timestamp and the current thread:</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"{timestamp} {ts-thread} Counter is {}"</span><span class="p">,</span> <span class="n">counter</span><span class="p">);</span>
</pre></div>
</div>
<p>Note that even though no argument is provided the global names do not count as part of the argument
indexing, therefore the preceeding example could be written as:</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"{timestamp} {ts-thread} Counter is {0}"</span><span class="p">,</span> <span class="n">counter</span><span class="p">);</span>
</pre></div>
</div>
</div>
<div class="section" id="working-with-standard-i-o">
<h2>Working with standard I/O<a class="headerlink" href="#working-with-standard-i-o" title="Permalink to this headline">¶</a></h2>
<p><a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> can be used with some of the basic I/O functionality of a C++ environment. At the lowest
level the output stream operator can be used with a file descriptor or a <code class="code docutils literal"><span class="pre">std::ostream</span></code>. For these
examples assume <code class="code docutils literal"><span class="pre">bw</span></code> is an instance of <a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> with data in it.</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="kt">int</span> <span class="n">fd</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="s">"some_file"</span><span class="p">,</span> <span class="n">O_RDWR</span><span class="p">);</span>
<span class="n">bw</span> <span class="o">>></span> <span class="n">fd</span><span class="p">;</span> <span class="c1">// Write to file.</span>
<span class="n">bw</span> <span class="o">>></span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="p">;</span> <span class="c1">// write to standard out.</span>
</pre></div>
</div>
<p>For convenience a stream operator for <code class="code docutils literal"><span class="pre">std::stream</span></code> is provided to make the use more natural.</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="n">bw</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="n">bw</span><span class="p">.</span><span class="n">view</span><span class="p">();</span> <span class="c1">// identical effect as the previous line.</span>
</pre></div>
</div>
<p>Using a <a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> with <code class="code docutils literal"><span class="pre">printf</span></code> is straight forward by use of the sized string
format code.</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="n">ts</span><span class="o">::</span><span class="n">LocalBufferWriter</span><span class="o"><</span><span class="mi">256</span><span class="o">></span> <span class="n">bw</span><span class="p">;</span>
<span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"Failed to connect to {}"</span><span class="p">,</span> <span class="n">addr1</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"%.*s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="k">static_cast</span><span class="o"><</span><span class="kt">int</span><span class="o">></span><span class="p">(</span><span class="n">bw</span><span class="p">.</span><span class="n">size</span><span class="p">()),</span> <span class="n">bw</span><span class="p">.</span><span class="n">data</span><span class="p">());</span>
</pre></div>
</div>
<p>Alternatively the output can be null terminated in the formatting to avoid having to pass the size.</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="n">ts</span><span class="o">::</span><span class="n">LocalBufferWriter</span><span class="o"><</span><span class="mi">256</span><span class="o">></span> <span class="n">bw</span><span class="p">;</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"%s</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">bw</span><span class="p">.</span><span class="n">print</span><span class="p">(</span><span class="s">"Failed to connect to {}</span><span class="se">\0</span><span class="s">"</span><span class="p">,</span> <span class="n">addr1</span><span class="p">).</span><span class="n">data</span><span class="p">());</span>
</pre></div>
</div>
<p>When using C++ stream I/O, writing to a stream can be done without any local variables at all.</p>
<div class="highlight-cpp"><div class="highlight"><pre><span></span><span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="n">ts</span><span class="o">::</span><span class="n">LocalBufferWriter</span><span class="o"><</span><span class="mi">256</span><span class="o">></span><span class="p">().</span><span class="n">print</span><span class="p">(</span><span class="s">"Failed to connect to {}</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="n">addr1</span><span class="p">);</span>
</pre></div>
</div>
<p>This is handy for temporary debugging messages as it avoids having to clean up local variable
declarations later, particularly when the types involved themselves require additional local
declarations (such as in this example, an IP address which would normally require a local text
buffer for conversion before printing). As noted previously this is particularly useful inside a
<code class="code docutils literal"><span class="pre">case</span></code> where local variables are more annoying to set up.</p>
</div>
<div class="section" id="reference">
<h2>Reference<a class="headerlink" href="#reference" title="Permalink to this headline">¶</a></h2>
<dl class="class">
<dt id="_CPPv212BufferWriter">
<span id="BufferWriter"></span><em class="property">class </em><code class="descclassname"></code><code class="descname">BufferWriter</code><a class="headerlink" href="#_CPPv212BufferWriter" title="Permalink to this definition">¶</a><br /></dt>
<dd><p><a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> is the abstract base class which defines the basic client interface. This
is intended to be the reference type used when passing concrete instances rather than having to
support the distinct types.</p>
<dl class="function">
<dt id="_CPPv2N12BufferWriter5writeEPv6size_t">
<span id="BufferWriter::write__voidP.s"></span><a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter">BufferWriter</a> &<code class="descclassname"></code><code class="descname">write</code><span class="sig-paren">(</span>void *<em>data</em>, <a class="reference internal" href="external-types.en.html#_CPPv26size_t" title="size_t">size_t</a> <em>length</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N12BufferWriter5writeEPv6size_t" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Write to the buffer starting at <em>data</em> for at most <em>length</em> bytes. If there is not
enough room to fit all the data, none is written.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N12BufferWriter5writeE11string_view">
<span id="BufferWriter::write__string_view"></span><a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter">BufferWriter</a> &<code class="descclassname"></code><code class="descname">write</code><span class="sig-paren">(</span>string_view <em>str</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N12BufferWriter5writeE11string_view" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Write the string <em>str</em> to the buffer. If there is not enough room to write the string no
data is written.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N12BufferWriter5writeEc">
<span id="BufferWriter::write__c"></span><a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter">BufferWriter</a> &<code class="descclassname"></code><code class="descname">write</code><span class="sig-paren">(</span>char <em>c</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N12BufferWriter5writeEc" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Write the character <em>c</em> to the buffer. If there is no space in the buffer the character
is not written.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N12BufferWriter4fillE6size_t">
<span id="BufferWriter::fill__s"></span><a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter">BufferWriter</a> &<code class="descclassname"></code><code class="descname">fill</code><span class="sig-paren">(</span><a class="reference internal" href="external-types.en.html#_CPPv26size_t" title="size_t">size_t</a> <em>n</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N12BufferWriter4fillE6size_t" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Increase the output size by <em>n</em> without changing the buffer contents. This is used in
conjuction with <a class="reference internal" href="#_CPPv2NK12BufferWriter9auxBufferEv" title="BufferWriter::auxBuffer"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::auxBuffer()</span></code></a> after writing output to the buffer returned by
that method. If this method is not called then such output will not be counted by
<a class="reference internal" href="#_CPPv2NK12BufferWriter4sizeEv" title="BufferWriter::size"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::size()</span></code></a> and will be overwritten by subsequent output.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2NK12BufferWriter4dataEv">
<span id="BufferWriter::dataC"></span>char *<code class="descclassname"></code><code class="descname">data</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK12BufferWriter4dataEv" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Return a pointer to start of the buffer.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2NK12BufferWriter4sizeEv">
<span id="BufferWriter::sizeC"></span><a class="reference internal" href="external-types.en.html#_CPPv26size_t" title="size_t">size_t</a> <code class="descclassname"></code><code class="descname">size</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK12BufferWriter4sizeEv" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Return the number of valid (written) bytes in the buffer.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2NK12BufferWriter4viewEv">
<span id="BufferWriter::viewC"></span>string_view <code class="descclassname"></code><code class="descname">view</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK12BufferWriter4viewEv" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Return a <code class="xref cpp cpp-class docutils literal"><span class="pre">string_view</span></code> that covers the valid data in the buffer.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2NK12BufferWriter9remainingEv">
<span id="BufferWriter::remainingC"></span><a class="reference internal" href="external-types.en.html#_CPPv26size_t" title="size_t">size_t</a> <code class="descclassname"></code><code class="descname">remaining</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK12BufferWriter9remainingEv" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Return the number of available remaining bytes that could be written to the buffer.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2NK12BufferWriter8capacityEv">
<span id="BufferWriter::capacityC"></span><a class="reference internal" href="external-types.en.html#_CPPv26size_t" title="size_t">size_t</a> <code class="descclassname"></code><code class="descname">capacity</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK12BufferWriter8capacityEv" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Return the number of bytes in the buffer.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2NK12BufferWriter9auxBufferEv">
<span id="BufferWriter::auxBufferC"></span>char *<code class="descclassname"></code><code class="descname">auxBuffer</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK12BufferWriter9auxBufferEv" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Return a pointer to the first byte in the buffer not yet consumed.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N12BufferWriter4clipE6size_t">
<span id="BufferWriter::clip__s"></span><a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter">BufferWriter</a> &<code class="descclassname"></code><code class="descname">clip</code><span class="sig-paren">(</span><a class="reference internal" href="external-types.en.html#_CPPv26size_t" title="size_t">size_t</a> <em>n</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N12BufferWriter4clipE6size_t" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Reduce the available space by <em>n</em> bytes.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N12BufferWriter6extendE6size_t">
<span id="BufferWriter::extend__s"></span><a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter">BufferWriter</a> &<code class="descclassname"></code><code class="descname">extend</code><span class="sig-paren">(</span><a class="reference internal" href="external-types.en.html#_CPPv26size_t" title="size_t">size_t</a> <em>n</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N12BufferWriter6extendE6size_t" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Increase the available space by <em>n</em> bytes. Extreme care must be used with this method as
<a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> will trust the argument, having no way to verify it. In general this
should only be used after calling <a class="reference internal" href="#_CPPv2N12BufferWriter4clipE6size_t" title="BufferWriter::clip"><code class="xref cpp cpp-func docutils literal"><span class="pre">BufferWriter::clip()</span></code></a> and passing the same value.
Together these allow the buffer to be temporarily reduced to reserve space for the trailing
element of a required pair of output strings, e.g. making sure a closing quote can be written
even if part of the string is not.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2NK12BufferWriter5errorEv">
<span id="BufferWriter::errorC"></span>bool <code class="descclassname"></code><code class="descname">error</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK12BufferWriter5errorEv" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Return <code class="code docutils literal"><span class="pre">true</span></code> if the buffer has overflowed from writing, <code class="code docutils literal"><span class="pre">false</span></code> if not.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2NK12BufferWriter6extentEv">
<span id="BufferWriter::extentC"></span><a class="reference internal" href="external-types.en.html#_CPPv26size_t" title="size_t">size_t</a> <code class="descclassname"></code><code class="descname">extent</code><span class="sig-paren">(</span><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK12BufferWriter6extentEv" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Return the total number of bytes in all attempted writes to this buffer. This value allows a
successful retry in case of overflow, presuming the output data doesn’t change. This works
well with the standard “try before you buy” approach of attempting to write output, counting
the characters needed, then allocating a sufficiently sized buffer and actually writing.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N12BufferWriter5printE8TextViewz">
<span id="BufferWriter::print__TextView.z"></span><a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter">BufferWriter</a> &<code class="descclassname"></code><code class="descname">print</code><span class="sig-paren">(</span>TextView <em>fmt</em>, ...<span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N12BufferWriter5printE8TextViewz" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Print the arguments according to the format. See <a class="reference internal" href="#bw-formatting">bw-formatting</a>.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2IDpEN12BufferWriter6printvE8TextViewRRNSt5tupleIDp4ArgsEE">
template<typename ...<code class="descname">Args</code>><br /><a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter">BufferWriter</a> &<code class="descclassname"></code><code class="descname">printv</code><span class="sig-paren">(</span>TextView <em>fmt</em>, <a class="reference internal" href="external-types.en.html#_CPPv2St" title="std">std</a>::tuple<<a class="reference internal" href="#_CPPv2IDpEN12BufferWriter6printvE8TextViewRRNSt5tupleIDp4ArgsEE" title="BufferWriter::printv::Args">Args</a>...> &&<em>args</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2IDpEN12BufferWriter6printvE8TextViewRRNSt5tupleIDp4ArgsEE" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Print the arguments in the tuple <em>args</em> according to the format. See <a class="reference internal" href="#bw-formatting">bw-formatting</a>.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2NK12BufferWriterrsERNSt7ostreamE">
<span id="BufferWriter::rshift-operator__osRC"></span><a class="reference internal" href="external-types.en.html#_CPPv2St" title="std">std</a>::ostream &<code class="descclassname"></code><code class="descname">operator>></code><span class="sig-paren">(</span><a class="reference internal" href="external-types.en.html#_CPPv2St" title="std">std</a>::ostream &<em>stream</em><span class="sig-paren">)</span> <em class="property">const</em><a class="headerlink" href="#_CPPv2NK12BufferWriterrsERNSt7ostreamE" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Write the contents of the buffer to <em>stream</em> and return <em>stream</em>.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N12BufferWriterrsEi">
<span id="BufferWriter::rshift-operator__i"></span>ssize_t <code class="descclassname"></code><code class="descname">operator>></code><span class="sig-paren">(</span>int <em>fd</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N12BufferWriterrsEi" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Write the contents of the buffer to file descriptor <em>fd</em> and return the number of bytes
write (the results of the call to file <code class="code docutils literal"><span class="pre">write()</span></code>).</p>
</dd></dl>
</dd></dl>
<dl class="class">
<dt id="_CPPv217FixedBufferWriter">
<span id="FixedBufferWriter"></span><em class="property">class </em><code class="descclassname"></code><code class="descname">FixedBufferWriter</code> : <em class="property">public</em> <a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter">BufferWriter</a><a class="headerlink" href="#_CPPv217FixedBufferWriter" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>This is a class that implements <a class="reference internal" href="#_CPPv212BufferWriter" title="BufferWriter"><code class="xref cpp cpp-class docutils literal"><span class="pre">BufferWriter</span></code></a> on a fixed buffer, passed in to the constructor.</p>
<dl class="function">
<dt id="_CPPv2N17FixedBufferWriter17FixedBufferWriterEPv6size_t">
<span id="FixedBufferWriter::FixedBufferWriter__voidP.s"></span><code class="descclassname"></code><code class="descname">FixedBufferWriter</code><span class="sig-paren">(</span>void *<em>buffer</em>, <a class="reference internal" href="external-types.en.html#_CPPv26size_t" title="size_t">size_t</a> <em>length</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N17FixedBufferWriter17FixedBufferWriterEPv6size_t" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Construct an instance that will write to <em>buffer</em> at most <em>length</em> bytes. If more
data is written, all data past the maximum size is discarded.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N17FixedBufferWriter6reduceE6size_t">
<span id="FixedBufferWriter::reduce__s"></span><a class="reference internal" href="#_CPPv217FixedBufferWriter" title="FixedBufferWriter">FixedBufferWriter</a> &<code class="descclassname"></code><code class="descname">reduce</code><span class="sig-paren">(</span><a class="reference internal" href="external-types.en.html#_CPPv26size_t" title="size_t">size_t</a> <em>n</em><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N17FixedBufferWriter6reduceE6size_t" title="Permalink to this definition">¶</a><br /></dt>
<dd><p>Roll back the output to have <em>n</em> valid (used) bytes.</p>
</dd></dl>
<dl class="function">
<dt id="_CPPv2N17FixedBufferWriter5resetEv">
<span id="FixedBufferWriter::reset"></span><a class="reference internal" href="#_CPPv217FixedBufferWriter" title="FixedBufferWriter">FixedBufferWriter</a> &<code class="descclassname"></code><code class="descname">reset</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#_CPPv2N17FixedBufferWriter5resetEv" title="Permalink to this definition">¶</a><br /></dt>