BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslfmt_padutil.h
Go to the documentation of this file.
1/// @file bslfmt_padutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslfmt_padutil.h -*-C++-*-
8#ifndef INCLUDED_BSLFMT_PADUTIL
9#define INCLUDED_BSLFMT_PADUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslfmt_padutil bslfmt_padutil
15/// @brief Provide padding utilities for the `bslfmt` package and clients.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslfmt
19/// @{
20/// @addtogroup bslfmt_padutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslfmt_padutil-purpose"> Purpose</a>
25/// * <a href="#bslfmt_padutil-classes"> Classes </a>
26/// * <a href="#bslfmt_padutil-description"> Description </a>
27/// * <a href="#bslfmt_padutil-usage"> Usage </a>
28///
29/// # Purpose {#bslfmt_padutil-purpose}
30/// Provide padding utilities for the `bslfmt` package and clients.
31///
32/// # Classes {#bslfmt_padutil-classes}
33///
34/// - bslfmt::PadUtil: formatter padding utilities
35///
36/// # Description {#bslfmt_padutil-description}
37/// `PadUtil` is a `struct` that serves as a namespace containing
38/// functions suitable for padding output. It consists of 2 functions,
39/// `computePadding` which computes the amount of left and right padding, and
40/// `pad`, which repeatedly outputs a sequence to an iterator.
41///
42/// ## Usage {#bslfmt_padutil-usage}
43///
44///
45/// Suppose we have a string and we want to be able to pad it with any desired
46/// filler string, and pad it to the left or right, or pad it on both sides, to
47/// reach a desired total width.
48///
49/// First, we define a couple of typedef's to shorten some bslfmt package types:
50/// @code
51/// typedef bslfmt::FormatterSpecificationNumericValue NumericValue;
52/// typedef bslfmt::FormatSpecificationParserEnums ParserEnums;
53/// typedef bslfmt::PadUtil<char> PadUtil;
54/// @endcode
55/// Then, we are now able to define a function `paddedString` which will take a
56/// a string, `content`, and pad it to a given `fieldWidth` with the specified
57/// `filler`. `pad` does not assume that `filler` is a single Unicode code
58/// point, though that will normally be the case.
59/// @code
60/// void paddedString(bsl::string *result,
61/// const bsl::string_view& content,
62/// unsigned fieldWidth,
63/// ParserEnums::Alignment alignment,
64/// const bsl::string_view& filler)
65/// {
66/// std::ptrdiff_t leftPadding, rightPadding;
67///
68/// PadUtil::computePadding(&leftPadding,
69/// &rightPadding,
70/// NumericValue(NumericValue::e_VALUE,
71/// fieldWidth),
72/// content.length(),
73/// alignment,
74/// ParserEnums::e_ALIGN_LEFT);
75///
76/// result->resize(filler.length() * (leftPadding + rightPadding) +
77/// content.length());
78///
79/// bsl::string::iterator it = result->begin();
80/// it = PadUtil::pad(it, leftPadding, filler);
81///
82/// it = bsl::copy(content.begin(), content.end(), it);
83///
84/// it = PadUtil::pad(it, rightPadding, filler);
85///
86/// assert(result->end() == it);
87/// }
88/// @endcode
89/// Next, we use our new `paddedString` to create a string with "John Brown"
90/// padded on either side to a total width of 20 bytes, padding with dashes:
91/// @code
92/// bsl::string s;
93/// paddedString(&s, "John Brown", 20, ParserEnums::e_ALIGN_MIDDLE, "-");
94/// assert("-----John Brown-----" == s);
95/// @endcode
96/// Now, let's pad to right with Unicode `Euro` symbols to a total width of 20
97/// bytes:
98/// @code
99/// const char *euro = "\xe2\x82\xac"; // Unicode for the Euro symbol.
100/// paddedString(&s, "Seven Euros: ", 20, ParserEnums::e_ALIGN_LEFT, euro);
101/// assert("Seven Euros: €€€€€€€" == s);
102/// @endcode
103/// Note that because `euro` is not a single byte, the output is longer than
104/// `fieldWidth`, which was 20:
105/// @code
106/// assert(34 == s.length());
107/// @endcode
108/// @}
109/** @} */
110/** @} */
111
112/** @addtogroup bsl
113 * @{
114 */
115/** @addtogroup bslfmt
116 * @{
117 */
118/** @addtogroup bslfmt_padutil
119 * @{
120 */
121
122#include <bslscm_version.h>
123
126
127#include <bslstl_algorithm.h>
128#include <bslstl_iterator.h>
129#include <bslstl_stringview.h>
130
131#include <bslmf_assert.h>
132#include <bslmf_issame.h>
133
134#include <bsls_performancehint.h>
135#include <bsls_platform.h>
136
137#include <cstddef>
138
139
140namespace bslfmt {
141
142 // =======
143 // PadUtil
144 // =======
145
146/// This `struct` serves as a namespace for static functions related to padding
147/// output by bslfmt.
148///
149/// See @ref bslfmt_padutil
150template <class t_CHAR>
151struct PadUtil {
154
155 // PUBLIC TYPES
159
160 private:
161 // PRIVATE TYPES
162 template <class t_ITERATOR>
163 struct IteratorTypeIsOK {
164 typedef typename bsl::iterator_traits<t_ITERATOR>::value_type
165 IteratorCharType;
166 static const bool value =
169 };
170
171 struct CharConverter {
172 /// Return the specified `c` cast to type `t_CHAR`.
173 template <class t_INPUT_CHAR>
174 t_CHAR operator()(t_INPUT_CHAR c) const
175 {
176 return static_cast<t_CHAR>(c);
177 }
178 };
179
180 // PRIVATE CLASS METHODS
181
182#ifdef BSLS_ASSERT_IS_USED
183 /// Return `true` if the specified `filler` is a valid filler character for
184 /// padding, and `false` otherwise.
185 static bool fillerIsOK(t_CHAR filler);
186 static bool fillerIsOK(const bsl::basic_string_view<t_CHAR>& filler);
187 template <class t_INPUT_CHAR>
188 static bool fillerIsOK(t_INPUT_CHAR filler);
189 template <class t_INPUT_CHAR>
190 static bool fillerIsOK(const bsl::basic_string_view<t_INPUT_CHAR>& filler);
191#endif
192
193 /// Output the specified `filler` to the specified `out` once and return
194 /// the new output iterator.
195 template <class t_ITERATOR, class t_INPUT_CHAR>
196 static t_ITERATOR writeFiller(
197 t_ITERATOR out,
199 template <class t_ITERATOR, class t_INPUT_CHAR>
200 static t_ITERATOR writeFiller(
201 t_ITERATOR out,
202 const t_INPUT_CHAR& filler);
203
204 /// Output the specified `filler` to the specified `out` the specified
205 /// `width` times and return the new output iterator.
206 template <class t_ITERATOR, class t_FILLER>
207 static t_ITERATOR padImpl(
208 t_ITERATOR out,
209 std::ptrdiff_t width,
210 const t_FILLER& filler);
211
212 public:
213 // CLASS METHODS
214
215 /// Compute the left and right padding values needed to format content with
216 /// the specified `contentWidth` within a field of the width specified by
217 /// `widthValue` using the specified `alignment`. If
218 /// `Enums::e_ALIGN_DEFAULT` is passed to `alignment`, use the specified
219 /// `defaultAlign` instead. Load the computed padding values into the
220 /// specified `leftPadding` and `rightPadding`. If the category of
221 /// `widthValue` is not `e_VALUE` or if the value indicated by `widthValue`
222 /// is less than `contentWidth`, the padding is zero.
223 ///
224 /// \pre The behavior is undefined if `contentWidth` specifies a negative width, or if
225 /// `defaultAlign` specifies `e_ALIGN_DEFAULT`.
226 static void computePadding(
227 std::ptrdiff_t *leftPadding,
228 std::ptrdiff_t *rightPadding,
229 const NumericValue& widthValue,
230 std::ptrdiff_t contentWidth,
231 Alignment alignment,
232 Alignment defaultAlign = Enums::e_ALIGN_LEFT);
233
234 /// Write the specified `filler` (possibly a multi-byte unicode sequence)
235 /// to the specified `out` the specified `padWidth` times and return the
236 /// new output iterator. If `padWidth < 0`, no output is done.
237 ///
238 /// \pre The behavior is undefined unless the character type of `filler` is the same as `t_CHAR` or `filler` is entirely ascii.
239 ///
240 /// \note Note that the overloads
241 /// that input a single character have an advantage over `bsl::fill_n` in
242 /// that they will automatically widen or narrow the input character to
243 /// `t_CHAR` if necessary.
244 template <class t_ITERATOR>
245 static t_ITERATOR pad(t_ITERATOR out,
246 std::ptrdiff_t padWidth,
247 const bsl::string_view& filler);
248 template <class t_ITERATOR>
249 static t_ITERATOR pad(t_ITERATOR out,
250 std::ptrdiff_t padWidth,
251 const bsl::wstring_view& filler);
252 template <class t_ITERATOR>
253 static t_ITERATOR pad(t_ITERATOR out,
254 std::ptrdiff_t padWidth,
255 char filler);
256 template <class t_ITERATOR>
257 static t_ITERATOR pad(t_ITERATOR out,
258 std::ptrdiff_t padWidth,
259 wchar_t filler);
260};
261
262 // -------
263 // PadUtil
264 // -------
265
266// PRIVATE CLASS METHODS
267
268#ifdef BSLS_ASSERT_IS_USED
269template <class t_CHAR>
270inline
271bool PadUtil<t_CHAR>::fillerIsOK(t_CHAR)
272{
273 return true;
274}
275
276template <class t_CHAR>
277inline
278bool PadUtil<t_CHAR>::fillerIsOK(const bsl::basic_string_view<t_CHAR>&)
279{
280 return true;
281}
282
283template <class t_CHAR>
284template <class t_INPUT_CHAR>
285inline
286bool PadUtil<t_CHAR>::fillerIsOK(t_INPUT_CHAR filler)
287{
288 return 0 == (~0x7f & filler);
289}
290
291template <class t_CHAR>
292template <class t_INPUT_CHAR>
293inline
294bool PadUtil<t_CHAR>::fillerIsOK(
296{
298 for (Iter it = filler.begin(); it != filler.end(); ++it) {
299 if (!fillerIsOK(*it)) {
300 return false; // RETURN
301 }
302 }
303
304 return true;
305}
306#endif
307
308template <class t_CHAR>
309template <class t_ITERATOR, class t_INPUT_CHAR>
310inline
311t_ITERATOR PadUtil<t_CHAR>::writeFiller(
312 t_ITERATOR out,
314{
315 return bsl::transform(filler.begin(), filler.end(), out, CharConverter());
316}
317
318template <class t_CHAR>
319template <class t_ITERATOR, class t_INPUT_CHAR>
320inline
321t_ITERATOR PadUtil<t_CHAR>::writeFiller(
322 t_ITERATOR out,
323 const t_INPUT_CHAR& filler)
324{
327
328 *out++ = CharConverter()(filler);
329
330 return out;
331}
332
333template <class t_CHAR>
334template <class t_ITERATOR, class t_FILLER>
335inline
336t_ITERATOR PadUtil<t_CHAR>::padImpl(t_ITERATOR out,
337 std::ptrdiff_t width,
338 const t_FILLER& filler)
339{
340 BSLMF_ASSERT(IteratorTypeIsOK<t_ITERATOR>::value);
341 BSLS_ASSERT(fillerIsOK(filler));
342
343 while (0 < width--) {
344 out = writeFiller(out, filler);
345 }
346
347 return out;
348}
349
350// PUBLIC CLASS METHODS
351template <class t_CHAR>
352void PadUtil<t_CHAR>::computePadding(std::ptrdiff_t *leftPadding,
353 std::ptrdiff_t *rightPadding,
354 const NumericValue& widthValue,
355 std::ptrdiff_t contentWidth,
356 Alignment alignment,
357 Alignment defaultAlign)
358{
359 BSLS_ASSERT(0 <= contentWidth);
360 BSLS_ASSERT(Enums::e_ALIGN_DEFAULT != defaultAlign);
361
362 if (NumericValue::e_VALUE != widthValue.category()) {
363 *leftPadding = 0;
364 *rightPadding = 0;
365 return; // RETURN
366 }
367 const std::ptrdiff_t width = widthValue.value();
368
369 if (width <= contentWidth) {
370 *leftPadding = 0;
371 *rightPadding = 0;
372 return; // RETURN
373 }
374 const std::ptrdiff_t totalPadding = width - contentWidth;
375
376 if (Enums::e_ALIGN_DEFAULT == alignment) {
377 alignment = defaultAlign;
378 }
379
380 switch (alignment) {
381 case Enums::e_ALIGN_LEFT: {
382 *leftPadding = 0;
383 *rightPadding = totalPadding;
384 } break;
385 case Enums::e_ALIGN_RIGHT: {
386 *leftPadding = totalPadding;
387 *rightPadding = 0;
388 } break;
389 case Enums::e_ALIGN_MIDDLE: {
390 *leftPadding = totalPadding / 2;
391 *rightPadding = totalPadding - *leftPadding;
392 } break;
393 default: {
394 BSLS_ASSERT_INVOKE_NORETURN("invalid alignment");
395 }
396 }
397}
398
399template <class t_CHAR>
400template <class t_ITERATOR>
401t_ITERATOR PadUtil<t_CHAR>::pad(t_ITERATOR out,
402 std::ptrdiff_t padWidth,
403 const bsl::string_view& filler)
404{
405 return padImpl(out, padWidth, filler);
406}
407
408template <class t_CHAR>
409template <class t_ITERATOR>
410t_ITERATOR PadUtil<t_CHAR>::pad(t_ITERATOR out,
411 std::ptrdiff_t padWidth,
412 const bsl::wstring_view& filler)
413{
414 return padImpl(out, padWidth, filler);
415}
416
417template <class t_CHAR>
418template <class t_ITERATOR>
419inline
420t_ITERATOR PadUtil<t_CHAR>::pad(t_ITERATOR out,
421 std::ptrdiff_t padWidth,
422 char filler)
423{
424 return padImpl(out, padWidth, filler);
425}
426
427template <class t_CHAR>
428template <class t_ITERATOR>
429inline
430t_ITERATOR PadUtil<t_CHAR>::pad(t_ITERATOR out,
431 std::ptrdiff_t padWidth,
432 wchar_t filler)
433{
434 return padImpl(out, padWidth, filler);
435}
436
437} // close package namespace
438
439
440#endif
441
442// ----------------------------------------------------------------------------
443// Copyright 2025 Bloomberg Finance L.P.
444//
445// Licensed under the Apache License, Version 2.0 (the "License");
446// you may not use this file except in compliance with the License.
447// You may obtain a copy of the License at
448//
449// http://www.apache.org/licenses/LICENSE-2.0
450//
451// Unless required by applicable law or agreed to in writing, software
452// distributed under the License is distributed on an "AS IS" BASIS,
453// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
454// See the License for the specific language governing permissions and
455// limitations under the License.
456// ----------------------------- END-OF-FILE ----------------------------------
457
458/** @} */
459/** @} */
460/** @} */
Definition bslstl_stringview.h:471
BSLS_KEYWORD_CONSTEXPR const_iterator end() const BSLS_KEYWORD_NOEXCEPT
Return the past-the-end iterator for this view.
Definition bslstl_stringview.h:1848
const value_type * const_iterator
Definition bslstl_stringview.h:481
BSLS_KEYWORD_CONSTEXPR const_iterator begin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_stringview.h:1830
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_INVOKE_NORETURN(X)
Definition bsls_assert.h:2101
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bslfmt_enablestreamedformatter.h:130
Definition bslmf_issame.h:146
Definition bslfmt_formatspecificationparser.h:105
Alignment
Definition bslfmt_formatspecificationparser.h:114
@ e_ALIGN_LEFT
Definition bslfmt_formatspecificationparser.h:116
Definition bslfmt_formatterspecificationnumericvalue.h:100
BSLS_KEYWORD_CONSTEXPR_CPP20 int value() const
Definition bslfmt_formatterspecificationnumericvalue.h:399
BSLS_KEYWORD_CONSTEXPR_CPP20 Category category() const
Return the category attribute of this object.
Definition bslfmt_formatterspecificationnumericvalue.h:416
Definition bslfmt_padutil.h:151
static void computePadding(std::ptrdiff_t *leftPadding, std::ptrdiff_t *rightPadding, const NumericValue &widthValue, std::ptrdiff_t contentWidth, Alignment alignment, Alignment defaultAlign=Enums::e_ALIGN_LEFT)
Definition bslfmt_padutil.h:352
Enums::Alignment Alignment
Definition bslfmt_padutil.h:158
static t_ITERATOR pad(t_ITERATOR out, std::ptrdiff_t padWidth, const bsl::string_view &filler)
Definition bslfmt_padutil.h:401
FormatterSpecificationNumericValue NumericValue
Definition bslfmt_padutil.h:156
BSLMF_ASSERT((bsl::is_same< t_CHAR, char >::value||bsl::is_same< t_CHAR, wchar_t >::value))
FormatSpecificationParserEnums Enums
Definition bslfmt_padutil.h:157