BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslfmt_format_imp.h
Go to the documentation of this file.
1/// @file bslfmt_format_imp.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslfmt_format_imp.h -*-C++-*-
8
9#ifndef INCLUDED_BSLFMT_FORMAT_IMP
10#define INCLUDED_BSLFMT_FORMAT_IMP
11
12#include <bsls_ident.h>
13BSLS_IDENT("$Id: $")
14
15/// @defgroup bslfmt_format_imp bslfmt_format_imp
16/// @brief Provide a standard compliant `format` implementation
17/// @addtogroup bsl
18/// @{
19/// @addtogroup bslfmt
20/// @{
21/// @addtogroup bslfmt_format_imp
22/// @{
23///
24/// <h1> Outline </h1>
25/// * <a href="#bslfmt_format_imp-purpose"> Purpose</a>
26/// * <a href="#bslfmt_format_imp-classes"> Classes </a>
27/// * <a href="#bslfmt_format_imp-canonical-header"> Canonical Header </a>
28/// * <a href="#bslfmt_format_imp-description"> Description </a>
29/// * <a href="#bslfmt_format_imp-user-provided-formatters"> User-provided formatters </a>
30/// * <a href="#bslfmt_format_imp-usage"> Usage </a>
31/// * <a href="#bslfmt_format_imp-example-1-simple-integer-formatting"> Example 1: Simple integer formatting </a>
32///
33/// # Purpose {#bslfmt_format_imp-purpose}
34/// Provide a standard compliant `format` implementation
35///
36/// # Classes {#bslfmt_format_imp-classes}
37///
38/// - bslfmt::format_to_n_result: result type for format_to_n.
39///
40/// # Canonical Header {#bslfmt_format_imp-canonical-header}
41/// bsl_format.h
42///
43/// @see ISO C++ Standard, <format>
44///
45/// # Description {#bslfmt_format_imp-description}
46/// This component will provide, in the `bslfmt` namespace,
47/// compliant implementations of the following free functions exposed by the
48/// standard <format> header. These are available for C++03 and later.
49///
50/// * format
51/// * format_to
52/// * format_to_n
53/// * formatted_size
54/// * vformat
55/// * vformat_to
56///
57/// Note 1: The overloads taking a `locale` parameter are *not* provided.
58/// Note 2: Compile-time format string checking is *not* performed.
59///
60/// This header is not intended to be included directly. Please include
61/// `<bsl_format.h>` to be able to use `bsl::format_to_n_result`.
62///
63/// ## User-provided formatters {#bslfmt_format_imp-user-provided-formatters}
64///
65///
66///
67/// User-provided formatters are supported by the BSL implementation, just as
68/// they are by the standard library implementation. However, in order for them
69/// to be compatible with both implementations, there are specific requirements,
70/// notably:
71///
72/// - If you will define a formatter for your type `T`, do so in the same
73/// component header that defines `T` itself. This avoids issues due to
74/// users forgetting to include the header for the formatter.
75/// - Define `bsl::formatter<T>` - *DO NOT* define `std::formatter<T>` - Use
76/// template arguments for the format context and parse context
77/// parameters. This is essential as the parameter type passed in will
78/// depend upon underlying implementation.
79/// - The `parse` function should be constexpr in C++20, but this is not
80/// required (and may not be possible) for earlier C++ standards.
81///
82/// An example of a user defined formatter is as follows:
83///
84/// @code
85/// namespace bsl {
86///
87/// template <class t_CHAR> struct formatter<UserDefinedType, t_CHAR> {
88/// template <class t_PARSE_CONTEXT>
89/// BSLS_KEYWORD_CONSTEXPR_CPP20
90/// t_PARSE_CONTEXT::iterator parse(t_PARSE_CONTEXT& pc)
91/// {
92/// // implementation goes here
93/// }
94///
95/// template <class t_FORMAT_CONTEXT>
96/// t_FORMAT_CONTEXT::iterator format(UserDefinedType s,
97/// t_FORMAT_CONTEXT& ctx) const
98/// {
99/// // implementation goes here
100/// }
101/// };
102///
103/// } // close namespace bsl
104/// @endcode
105///
106/// ## Usage {#bslfmt_format_imp-usage}
107///
108///
109/// This section illustrates the intended use of this component.
110///
111/// ### Example 1: Simple integer formatting {#bslfmt_format_imp-example-1-simple-integer-formatting}
112///
113///
114///
115/// @code
116/// #include <bslfmt_format.h>
117/// #include <bsl_iostring.h>
118///
119/// bsl::string doFormat(int value)
120/// {
121/// bsl::string res = bslfmt::format("{}", value);
122/// return res;
123/// }
124///
125/// int main()
126/// {
127/// bsl::cout << doFormat(99) << bsl::endl;
128/// return 0;
129/// }
130/// @endcode
131/// @}
132/** @} */
133/** @} */
134
135/** @addtogroup bsl
136 * @{
137 */
138/** @addtogroup bslfmt
139 * @{
140 */
141/** @addtogroup bslfmt_format_imp
142 * @{
143 */
144
145#include <bslscm_version.h>
146
148
149#include <bslmf_conditional.h>
150#include <bslmf_enableif.h>
152#include <bslmf_isintegral.h>
153#include <bslmf_issame.h>
154#include <bslmf_movableref.h>
155
157#include <bsls_exceptionutil.h>
158#include <bsls_libraryfeatures.h>
159#include <bsls_unspecifiedbool.h>
160#include <bsls_util.h>
161
162#include <bslstl_iterator.h>
163#include <bslstl_string.h>
164#include <bslstl_stringview.h>
165#include <bslstl_array.h>
166#include <bslstl_monostate.h>
167#include <bslstl_utility.h>
168#include <bslstl_variant.h>
169
170#include <bslfmt_formaterror.h>
171#include <bslfmt_format_arg.h>
172#include <bslfmt_format_args.h>
174#include <bslfmt_format_string.h>
176
177#include <bslfmt_formatterbase.h>
178#include <bslfmt_formatterbool.h>
184
185#include <iterator> // 'back_insert_iterator'
186
187#include <stddef.h> // 'size_t', 'ptrdiff_t'
188
189#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
190// clang-format off
191// Include version that can be compiled with C++03
192// Generated on Wed Mar 5 09:57:03 2025
193// Command line: sim_cpp11_features.pl bslfmt_format_imp.h
194
195# define COMPILING_BSLFMT_FORMAT_IMP_H
197# undef COMPILING_BSLFMT_FORMAT_IMP_H
198
199// clang-format on
200#else
201
202#if defined(BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES) && \
203 defined(BSLS_COMPILERFEATURES_SUPPORT_VARIADIC_TEMPLATES)
204# define BSLFMT_FORMAT_STRING_PARAMETER bslfmt::format_string<t_ARGS...>
205# define BSLFMT_FORMAT_WSTRING_PARAMETER bslfmt::wformat_string<t_ARGS...>
206#else
207// We cannot define format_string<t_ARGS...> in a C++03 compliant manner, so
208// have to use non-template versions instead.
209# define BSLFMT_FORMAT_STRING_PARAMETER bslfmt::format_string
210# define BSLFMT_FORMAT_WSTRING_PARAMETER bslfmt::wformat_string
211#endif // BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
212
213
214namespace bslfmt {
215
216 // ===================================
217 // class Format_Imp_TruncatingIterator
218 // ===================================
219
220/// This component-private type provides a stateful output iterator whose
221/// purpose is to count the number of characters written for use by the
222/// @ref formatted_size free functions. It holds an underlying output iterator (to
223/// which writes are delegated), a maximum character count permitted and a
224/// current character count to keep track of how many characters would be
225/// written if there were no limit.
226///
227/// See @ref bslfmt_format_imp
228template <class t_ITERATOR, class t_VALUE_TYPE, class t_DIFF_TYPE>
230 private:
231 // TYPES
232 typedef typename bsl::iterator_traits<t_ITERATOR>::difference_type DT;
233
234 // DATA
235 t_ITERATOR d_iterator; // underlying iterator
236 t_DIFF_TYPE d_limit; // character limit
237 t_DIFF_TYPE d_count; // current character count
238
239 private:
240 // NOT IMPLEMENTED
241
242 /// The postfix operator must be deleted because, as a counting iterator,
243 /// return by value can cause data inconsistency.
245
246 public:
247 // TYPES
248 typedef bsl::output_iterator_tag iterator_category;
249 typedef t_DIFF_TYPE difference_type;
250 typedef t_VALUE_TYPE value_type;
251 typedef void reference;
252 typedef void pointer;
253
254 // CREATORS
255
256 /// Create a instance containing a copy of the specified `iterator` as
257 /// underlying iterater with the maximum character count set to the
258 /// specified `limit` and the current character count set to zero.
259 Format_Imp_TruncatingIterator(t_ITERATOR iterator, t_DIFF_TYPE limit);
260
261 // MANIPULATORS
262
263 /// Do nothing and return a reference to this object. This is included to
264 /// ensure compliance with the C++ Standard's LegacyOutputIterator
265 /// requirements.
267
268 /// Increment the current character count. If the current character count
269 /// is less than the maximum character count (set on construction), assign
270 /// the specified `x` to the stored underlying iterator and increment the
271 /// stored underlying iterator.
272 void operator=(t_VALUE_TYPE x);
273
274 /// Do nothing and return a reference to this object. This is included to
275 /// ensure compliance with the C++ Standard's LegacyOutputIterator
276 /// requirements.
278
279 // ACCESSORS
280
281 /// Return the current character count.
282 /// \note Note that this is the number of
283 /// calls to `operator=` regardless of whether the limit has been breached.
284 t_DIFF_TYPE count() const;
285
286 /// Return the underlying iterator.
287 t_ITERATOR underlying() const;
288};
289
290
291 // -------------------------------
292 // class format_to_n_result<t_OUT>
293 // -------------------------------
294
295
296#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_FORMAT)
297// It is necessary to alias the standard library type where available, to
298// ensure clients of the @ref format_to_n can use the BSL and the Standard Library
299// implementations interchaneably without having to convert between return
300// types.
301using std::format_to_n_result;
302#else
303/// This type mirrors the @ref format_to_n_result type as specified in the
304/// standard. It exists to enable the @ref format_to_n function to return both an
305/// output iterator (the specified `t_OUT` template parameter) and the
306/// untrunctated size.
307///
308/// See @ref bslfmt_format_imp
309template <class t_OUT>
311 public:
312 // PUBLIC DATA
313 t_OUT out; // Output iterator
314 typename bsl::iterator_traits<t_OUT>::difference_type
315 size; // Untruncated size
316};
317#endif
318
319 // ---------------------------------------------------
320 // class Format_Imp_Visitor<t_ITERATOR, t_OUT, t_CHAR>
321 // ---------------------------------------------------
322
323/// Component-private type acting as the visitor in a call to
324/// @ref visit_format_arg .
325///
326/// See @ref bslfmt_format_imp
327template <class t_OUT, class t_CHAR>
329 private:
330 // DATA
331 basic_format_parse_context<t_CHAR> *d_parseContext_p; // context for
332 // format string.
333 basic_format_context<t_OUT, t_CHAR> *d_formatContext_p; // context for
334 // output iterator.
335
336 // PRIVATE TYPES
337 typedef
339 handle;
340
341 public:
342 // CREATORS
343
344 /// Create an instance of this type referencing the specified `pc` and the
345 /// specified `fc` for format strings and output iterators respectively.
348
349 // MANIPULATORS
350
351 /// Throw a @ref format_error exception to indicate this overload should never
352 /// get called.
353 void operator()(bsl::monostate) const;
354
355 /// Write a string representation of the specified `x` to the output
356 /// iterator in `d_format_context_p`, formatted according to the parse
357 /// string referenced by `d_formatContext_p`. This is done by constructing
358 /// an appropriate `formatter` of a type corresponding to the argument type
359 /// of the specified `x`, then call `parse` and `format` on that
360 /// constructed `formatter`.
361 void operator()(bool value) const;
362 void operator()(t_CHAR value) const;
363 void operator()(unsigned value) const;
364 void operator()(long long value) const;
365 void operator()(unsigned long long value) const;
366 void operator()(float value) const;
367 void operator()(double value) const;
368 void operator()(long double value) const;
369 void operator()(const t_CHAR *value) const;
370 void operator()(const void *value) const;
371 void operator()(int value) const;
373
374 /// Write a string representation of type referenced by the specified `h`
375 /// to the output iterator in `d_format_context_p`, formatted according to
376 /// the parse string referenced by `d_formatContext_p`. This is done by
377 /// delegating to the `handle::format` function.
378 void operator()(const handle& h) const;
379};
380
381 // ----------------------------------
382 // class Format_Imp_Processor<t_CHAR>
383 // ----------------------------------
384
385/// This component-private namespace struct provides access to formatting
386/// implementation functions to which the `bslfmt::format` family of free
387/// functions can delegate.
388///
389/// See @ref bslfmt_format_imp
390template <class t_CHAR>
392 private:
393 // PRIVATE CLASS METHODS
394
395 /// Format the specified `args` according to the format string specified by
396 /// `fmtStr` and write the result to the output iterator specified by
397 /// `out`. Return an iterator one past the end of the output range.
398 template <class t_OUT>
399 static t_OUT processImp(
400 t_OUT& out,
403
404 public:
405 // CLASS METHODS
406
407 /// Format the specified `args` according to the format string specified by
408 /// `fmtStr` and write the result to the output iterator specified by
409 /// `out`. Return an iterator one past the end of the output range. This
410 /// function participates in overload resolution if `out` is of
411 /// `Format_ContextOutputIteratorRef` type.
415 const basic_format_args<
417 t_CHAR> >& args);
418
419 /// Format the specified `args` according to the format string specified by
420 /// `fmtStr` and write the result to the output iterator specified by
421 /// `out`. Return an iterator one past the end of the output range. This
422 /// function participates in overload resolution if `out` is not of
423 /// `Format_ContextOutputIteratorRef` type.
424 template <class t_OUT, class t_CONTEXT>
425 static t_OUT process(t_OUT out,
427 const basic_format_args<t_CONTEXT>& args);
428};
429
430 // --------------
431 // FREE FUNCTIONS
432 // --------------
433
434// FREE FUNCTIONS
435
436/// Format the specified `args` according to the specification given by the
437/// specified `fmtStr`, and write the result of this operation into the output
438/// iterator given by the specified `out` parameter. In the event of an error
439/// the exception @ref format_error is thrown. Behavior is undefined if `out` is
440/// not a valid output iterator.
441template <class t_OUT>
442inline
443t_OUT vformat_to(t_OUT out, bsl::string_view fmtStr, format_args args);
444
445/// Format the specified `args` according to the specification given by the
446/// specified `fmtStr`, and write the result of this operation into the output
447/// iterator given by the specified `out` parameter. In the event of an error
448/// the exception @ref format_error is thrown. Behavior is undefined if `out` is
449/// not a valid output iterator.
450template <class t_OUT>
451inline
452t_OUT vformat_to(t_OUT out, bsl::wstring_view fmtStr, wformat_args args);
453
454/// Format the specified `args` according to the specification given by the
455/// specified `fmtStr`, and write the result of this operation into the string
456/// addressed by the specified `out` parameter. In the event of an error the
457/// exception @ref format_error is thrown. Behavior is undefined if `out` does
458/// not point to a valid `bsl::string` object.
459inline
460void vformat_to(bsl::string *out, bsl::string_view fmtStr, format_args args);
461
462/// Format the specified `args` according to the specification given by the
463/// specified `fmtStr`, and write the result of this operation into the string
464/// addressed by the specified `out` parameter. In the event of an error the
465/// exception @ref format_error is thrown. Behavior is undefined if `out` does
466/// not point to a valid `bsl::string` object.
467inline
468void vformat_to(bsl::wstring *out,
469 bsl::wstring_view fmtStr,
470 wformat_args args);
471
472/// Format the specified `args` according to the specification given by the
473/// specified `fmt` and return the result. In the event of an error the
474/// exception @ref format_error is thrown.
475inline
477
478/// Format the specified `args` according to the specification given by the
479/// specified `fmtStr` and return the result. In the event of an error the
480/// exception @ref format_error is thrown.
481inline
483
484/// Format the specified `args` according to the specification given by the
485/// specified `fmtStr`, using the specified `allocator` to supply memory (if
486/// required), and return the result. In the event of an error the exception
487/// @ref format_error is thrown.
488inline
490 bsl::string_view fmtStr,
491 format_args args);
492
493/// Format the specified `args` according to the specification given by the
494/// specified `fmtStr`, using the specified `allocator` to supply memory (if
495/// required), and return the result. In the event of an error the exception
496/// @ref format_error is thrown.
497inline
499 bsl::wstring_view fmtStr,
500 wformat_args args);
501
502#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
503/// Format the specified `args` according to the specification given by the
504/// specified `fmtStr`, and write the result of this operation into the output
505/// iterator given by the specified `out` parameter. In the event of an error
506/// the exception @ref format_error is thrown. Behavior is undefined if `out`
507/// does not point to a valid output parameter.
508template <class t_OUT, class... t_ARGS>
509typename bsl::enable_if<
511 t_OUT>::type
512inline
513format_to(t_OUT out,
515 const t_ARGS&... args);
516
517/// Format the specified `args` according to the specification given by the
518/// specified `fmtStr`, and write the result of this operation into the output
519/// iterator given by the specified `out` parameter. In the event of an error
520/// the exception @ref format_error is thrown. Behavior is undefined if `out`
521/// does not point to a valid output parameter.
522template <class t_OUT, class... t_ARGS>
523typename bsl::enable_if<
525 t_OUT>::type
526inline
527format_to(t_OUT out,
529 const t_ARGS&... args);
530
531/// Format the specified `args` according to the specification given by the
532/// specified `fmtStr`, and write the result of this operation into the string
533/// addressed by the specified `out` parameter. In the event of an error the
534/// exception @ref format_error is thrown. Behavior is undefined if `out` does
535/// not point to a valid `bsl::string` object.
536template <class... t_ARGS>
537inline
538void format_to(bsl::string *out,
540 const t_ARGS&... args);
541
542/// Format the specified `args` according to the specification given by the
543/// specified `fmtStr`, and write the result of this operation into the string
544/// addressed by the specified `out` parameter. In the event of an error the
545/// exception @ref format_error is thrown. Behavior is undefined if `out` does
546/// not point to a valid `bsl::string` object.
547template <class... t_ARGS>
548inline
549void format_to(bsl::wstring *out,
551 const t_ARGS&... args);
552
553/// Format the specified `args` according to the specification given by the
554/// specified `fmtStr` and return the result as a `bsl::string`. In the event
555/// of an error the exception @ref format_error is thrown.
556template <class... t_ARGS>
557inline
559 const t_ARGS&... args);
560
561/// Format the specified `args` according to the specification given by the
562/// specified `fmtStr` and return the result as a `bsl::string`. In the event
563/// of an error the exception @ref format_error is thrown.
564template <class... t_ARGS>
565inline
567 const t_ARGS&... args);
568
569/// Format the specified `args` according to the specification given by the
570/// specified `fmtStr`, using the specified `alloc` to supply memory (if
571/// required), and return the result. In the event of an error the exception
572/// @ref format_error is thrown.
573template <class... t_ARGS>
574inline
577 const t_ARGS&... args);
578
579/// Format the specified `args` according to the specification given by the
580/// specified `fmtStr`, using the specified `alloc` to supply memory (if
581/// required), and return the result. In the event of an error the exception
582/// @ref format_error is thrown.
583template <class... t_ARGS>
584inline
587 const t_ARGS&... args);
588
589/// Calculate the length of the resulting string if the specified `args` were
590/// to be formatted according to the specification given by the specified
591/// `fmtStr`, and return the result.
592template <class... t_ARGS>
593inline
595 const t_ARGS&... args);
596
597/// Calculate the length of the resulting string if the specified `args` were
598/// to be formatted according to the specification given by the specified
599/// `fmtStr`, and return the result.
600template <class... t_ARGS>
601inline
603 const t_ARGS&... args);
604
605/// Format the specified `args` according to the specification given by the
606/// specified `fmtStr`, and write at most the specified `maxNumChars`
607/// characters of the result of this operation into the output iterator
608/// referenced by the specified `out` parameter. Return a @ref format_to_n_result
609/// object whose `size` member holds the number of characters that would have
610/// been written to `out` were such writing not truncated, and whose `out`
611/// member holds an iterator one past the end of the output range. In the
612/// event of an error the exception @ref format_error is thrown. Behavior is
613/// undefined if `out` does not point to a valid output iterator.
614template <class t_OUT, class... t_ARGS>
615inline
617format_to_n(t_OUT out,
618 typename bsl::iterator_traits<t_OUT>::difference_type maxNumChars,
620 const t_ARGS&... args);
621
622/// Format the specified `args` according to the specification given by the
623/// specified `fmtStr`, and write at most the specified `maxNumChars`
624/// characters of the result of this operation into the output iterator
625/// referenced by the specified `out` parameter. Return a @ref format_to_n_result
626/// object whose `size` member holds the number of characters that would have
627/// been written to `out` were such writing not truncated, and whose `out`
628/// member holds an iterator one past the end of the output range. In the
629/// event of an error the exception @ref format_error is thrown. Behavior is
630/// undefined if `out` does not point to a valid output iterator.
631template <class t_OUT, class... t_ARGS>
632inline
634format_to_n(t_OUT out,
635 typename bsl::iterator_traits<t_OUT>::difference_type maxNumChars,
637 const t_ARGS&... args);
638
639#endif
640
641
642// ============================================================================
643// INLINE DEFINITIONS
644// ============================================================================
645
646 // -----------------------------------
647 // class Format_Imp_TruncatingIterator
648 // -----------------------------------
649
650// CREATORS
651template <class t_ITERATOR, class t_VALUE_TYPE, class t_DIFF_TYPE>
653 Format_Imp_TruncatingIterator(t_ITERATOR iterator, t_DIFF_TYPE limit)
654: d_iterator(iterator)
655, d_limit(limit)
656, d_count(0)
657{
658}
659
660// MANIPULATORS
661template <class t_ITERATOR, class t_VALUE_TYPE, class t_DIFF_TYPE>
668
669template <class t_ITERATOR, class t_VALUE_TYPE, class t_DIFF_TYPE>
671operator=(t_VALUE_TYPE x)
672{
673 if (d_count++ < d_limit) {
674 *d_iterator = x;
675 // We deliberately use prefix not postfix increment, as the postfix
676 // increment operator returns by value which could cause issues with
677 // counting or other stateful iterators.
678 ++d_iterator;
679 }
680}
681
682template <class t_ITERATOR, class t_VALUE_TYPE, class t_DIFF_TYPE>
689
690// ACCESSORS
691template <class t_ITERATOR, class t_VALUE_TYPE, class t_DIFF_TYPE>
692t_DIFF_TYPE
698
699template <class t_ITERATOR, class t_VALUE_TYPE, class t_DIFF_TYPE>
700t_ITERATOR Format_Imp_TruncatingIterator<t_ITERATOR,
701 t_VALUE_TYPE,
702 t_DIFF_TYPE>::underlying() const
703{
704 return d_iterator;
705}
706
707 // ------------------------
708 // class Format_Imp_Visitor
709 // ------------------------
710
711// CREATORS
712
713template <class t_OUT, class t_CHAR>
717: d_parseContext_p(&pc)
718, d_formatContext_p(&fc)
719{
720}
721
722// MANIPULATORS
723
724template <class t_OUT, class t_CHAR>
726{
728 "This call should be impossible - arg uninitialized");
730 format_error("This call should be impossible - arg uninitialized"));
731}
732
733template <class t_OUT, class t_CHAR>
735{
737 d_parseContext_p->advance_to(f.parse(*d_parseContext_p));
738 d_formatContext_p->advance_to(bsl::as_const(f).format(value,
739 *d_formatContext_p));
740}
741
742template <class t_OUT, class t_CHAR>
744{
746 d_parseContext_p->advance_to(f.parse(*d_parseContext_p));
747 d_formatContext_p->advance_to(bsl::as_const(f).format(value,
748 *d_formatContext_p));
749}
750
751template <class t_OUT, class t_CHAR>
753{
755 d_parseContext_p->advance_to(f.parse(*d_parseContext_p));
756 d_formatContext_p->advance_to(bsl::as_const(f).format(value,
757 *d_formatContext_p));
758}
759
760template <class t_OUT, class t_CHAR>
762{
764 d_parseContext_p->advance_to(f.parse(*d_parseContext_p));
765 d_formatContext_p->advance_to(bsl::as_const(f).format(value,
766 *d_formatContext_p));
767}
768
769template <class t_OUT, class t_CHAR>
771 unsigned long long value) const
772{
774 d_parseContext_p->advance_to(f.parse(*d_parseContext_p));
775 d_formatContext_p->advance_to(bsl::as_const(f).format(value,
776 *d_formatContext_p));
777}
778
779template <class t_OUT, class t_CHAR>
781{
783 d_parseContext_p->advance_to(f.parse(*d_parseContext_p));
784 d_formatContext_p->advance_to(bsl::as_const(f).format(value,
785 *d_formatContext_p));
786}
787
788template <class t_OUT, class t_CHAR>
790{
792 d_parseContext_p->advance_to(f.parse(*d_parseContext_p));
793 d_formatContext_p->advance_to(bsl::as_const(f).format(value,
794 *d_formatContext_p));
795}
796
797template <class t_OUT, class t_CHAR>
799{
801 d_parseContext_p->advance_to(f.parse(*d_parseContext_p));
802 d_formatContext_p->advance_to(bsl::as_const(f).format(value,
803 *d_formatContext_p));
804}
805
806template <class t_OUT, class t_CHAR>
808{
810 d_parseContext_p->advance_to(f.parse(*d_parseContext_p));
811 d_formatContext_p->advance_to(bsl::as_const(f).format(value,
812 *d_formatContext_p));
813}
814
815template <class t_OUT, class t_CHAR>
817{
819 d_parseContext_p->advance_to(f.parse(*d_parseContext_p));
820 d_formatContext_p->advance_to(bsl::as_const(f).format(value,
821 *d_formatContext_p));
822}
823
824template <class t_OUT, class t_CHAR>
826{
828 d_parseContext_p->advance_to(f.parse(*d_parseContext_p));
829 d_formatContext_p->advance_to(bsl::as_const(f).format(value,
830 *d_formatContext_p));
831}
832
833template <class t_OUT, class t_CHAR>
836{
838 d_parseContext_p->advance_to(f.parse(*d_parseContext_p));
839 d_formatContext_p->advance_to(bsl::as_const(f).format(value,
840 *d_formatContext_p));
841}
842
843template <class t_OUT, class t_CHAR>
845{
846 h.format(*d_parseContext_p, *d_formatContext_p);
847}
848
849 // --------------------------
850 // class Format_Imp_Processor
851 // --------------------------
852
853template <class t_CHAR>
854template <class t_OUT>
856 t_OUT& out,
859 // The actual meat of the implementation.
860{
861 const size_t argSize = Format_ArgsUtil::formatArgsSize(args);
862
863 basic_format_parse_context<t_CHAR> pc(fmtStr, argSize);
866 Format_Imp_Visitor<t_OUT, t_CHAR> visitor(pc, fc);
867
868 typename bsl::basic_string_view<t_CHAR>::iterator it = pc.begin();
869
870 while (it != pc.end()) {
871 if (*it == '{') {
872 ++it;
873 if (it == pc.end()) {
874 BSLS_THROW(format_error("unmatched {"));
875 }
876 else if (*it == '{') {
877 // literal {
878 ++it;
879 out = fc.out();
880 *out = '{';
881 ++out; // prefer prefix increment
882 fc.advance_to(out);
883 continue; // CONTINUE
884 }
885 size_t id = -1;
886 if (*it >= '0' && *it <= '9') {
887 // numeric ID
888 id = 0;
889 while (it != pc.end() && *it >= '0' && *it <= '9') {
890 id = 10 * id + (*it - '0');
891 ++it;
892 if (id >= argSize) {
893 BSLS_THROW(format_error("arg id too large"));
894 }
895 }
896 if (it == pc.end()) {
897 BSLS_THROW(format_error("unmatched {"));
898 }
899 }
900 if (id == size_t(-1)) {
901 id = pc.next_arg_id();
902 }
903 else {
904 pc.check_arg_id(id);
905 }
906
907 // Separator between arg Id and format specification
908
909 if (*it == ':') {
910 ++it;
911 }
912 else if (*it != '}') {
913 BSLS_THROW(format_error("Separator ':' missing"));
914 }
915
916 pc.advance_to(it);
917 visit_format_arg(visitor, args.get(id));
918 it = pc.begin();
919 if (it != pc.end()) {
920 if (*it != '}') {
921 BSLS_THROW(format_error("parsing terminated before }"));
922 }
923 // advance past the terminating }
924 ++it;
925 }
926 out = fc.out();
927 }
928 else if (*it == '}') {
929 // must be escaped
930 ++it;
931 if (it == pc.end() || *it != '}') {
932 BSLS_THROW(format_error("} must be escaped"));
933 }
934 ++it;
935 out = fc.out();
936 *out = '}';
937 ++out; // prefer prefix increment
938 fc.advance_to(out);
939 }
940 else {
941 // just copy it
942 out = fc.out();
943 *out = *it;
944 ++out;
945 ++it;
946 fc.advance_to(out);
947 }
948 }
949 return fc.out();
950}
951
952template <class t_CHAR>
963
964template <class t_CHAR>
965template <class t_OUT, class t_CONTEXT>
967 t_OUT out,
970{
972 Format_ContextOutputIteratorRef<t_CHAR> wrappedOutRef(&wrappedOut);
973 processImp(wrappedOutRef, fmtStr, args);
974 return out;
975}
976
977// FREE FUNCTIONS
978
979template <class t_OUT>
980inline
981t_OUT vformat_to(t_OUT out, bsl::string_view fmtStr, format_args args)
982{
983 return Format_Imp_Processor<char>::process(out, fmtStr, args);
984}
985
986template <class t_OUT>
987inline
988t_OUT vformat_to(t_OUT out, bsl::wstring_view fmtStr, wformat_args args)
989{
990 return Format_Imp_Processor<wchar_t>::process(out, fmtStr, args);
991}
992
993inline
995{
996 vformat_to(bsl::back_inserter(*out), fmtStr, args);
997}
998
999inline
1001{
1002 vformat_to(bsl::back_inserter(*out), fmtStr, args);
1003}
1004
1005inline
1007{
1008 bsl::string result;
1009 vformat_to(&result, fmtStr, args);
1010 return result;
1011}
1012
1013inline
1015{
1016 bsl::wstring result;
1017 vformat_to(&result, fmtStr, args);
1018 return result;
1019}
1020
1021inline
1023 bsl::string_view fmtStr,
1024 format_args args)
1025{
1026 bsl::string result(alloc);
1027 vformat_to(&result, fmtStr, args);
1028 return bsl::string(result, alloc);
1029}
1030
1031inline
1033 bsl::wstring_view fmtStr,
1034 wformat_args args)
1035{
1036 bsl::wstring result(alloc);
1037 vformat_to(&result, fmtStr, args);
1038 return bsl::wstring(result, alloc);
1039}
1040
1041#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1042template <class t_OUT, class... t_ARGS>
1043typename bsl::enable_if<
1045 t_OUT>::type
1046format_to(t_OUT out,
1048 const t_ARGS&... args)
1049{
1050 return vformat_to(out, fmtStr.get(), bslfmt::make_format_args(args...));
1051}
1052
1053template <class t_OUT, class... t_ARGS>
1054typename bsl::enable_if<
1056 t_OUT>::type
1057format_to(t_OUT out,
1059 const t_ARGS&... args)
1060{
1061 return vformat_to(out, fmtStr.get(), bslfmt::make_wformat_args(args...));
1062}
1063
1064template <class... t_ARGS>
1067 const t_ARGS&... args)
1068{
1069 vformat_to(bsl::back_inserter(*out),
1070 fmtStr.get(),
1071 bslfmt::make_format_args(args...));
1072}
1073
1074template <class... t_ARGS>
1077 const t_ARGS&... args)
1078{
1079 vformat_to(bsl::back_inserter(*out),
1080 fmtStr.get(),
1081 bslfmt::make_wformat_args(args...));
1082}
1083
1084template <class... t_ARGS>
1086{
1087 bsl::string result;
1088 vformat_to(&result, fmtStr.get(), bslfmt::make_format_args(args...));
1089 return result;
1090}
1091
1092template <class... t_ARGS>
1094 const t_ARGS&... args)
1095{
1096 bsl::wstring result;
1097 vformat_to(&result, fmtStr.get(), bslfmt::make_wformat_args(args...));
1098 return result;
1099}
1100
1101template <class... t_ARGS>
1104 const t_ARGS&... args)
1105{
1106 bsl::string result(alloc);
1107 vformat_to(&result, fmtStr.get(), bslfmt::make_format_args(args...));
1108 return bsl::string(result, alloc);
1109}
1110
1111template <class... t_ARGS>
1114 const t_ARGS&... args)
1115{
1116 bsl::wstring result(alloc);
1117 vformat_to(&result, fmtStr.get(), bslfmt::make_wformat_args(args...));
1118 return bsl::wstring(result, alloc);
1119}
1120
1121template <class... t_ARGS>
1123 const t_ARGS&... args)
1124{
1126 TruncatingIterator;
1127
1128 TruncatingIterator it(0, 0);
1129 TruncatingIterator end = format_to(it, fmtStr, args...);
1130 return end.count();
1131}
1132
1133template <class... t_ARGS>
1135 const t_ARGS&... args)
1136{
1138 TruncatingIterator;
1139
1140 TruncatingIterator it(0, 0);
1141 TruncatingIterator end = format_to(it, fmtStr, args...);
1142 return end.count();
1143}
1144
1145
1146template <class t_OUT, class... t_ARGS>
1147format_to_n_result<t_OUT>
1148format_to_n(t_OUT out,
1149 typename bsl::iterator_traits<t_OUT>::difference_type maxNumChars,
1151 const t_ARGS&... args)
1152{
1153 if (maxNumChars < 0)
1154 maxNumChars = 0;
1155
1157 t_OUT,
1158 typename bsl::iterator_traits<t_OUT>::value_type,
1159 typename bsl::iterator_traits<t_OUT>::difference_type>
1160 TruncatingIterator;
1161
1162 TruncatingIterator it(out, maxNumChars);
1163
1164 TruncatingIterator end = format_to(it, fmtStr, args...);
1165
1167 result.out = end.underlying();
1168 result.size = end.count();
1169 return result;
1170}
1171
1172template <class t_OUT, class... t_ARGS>
1173format_to_n_result<t_OUT>
1174format_to_n(t_OUT out,
1175 typename bsl::iterator_traits<t_OUT>::difference_type maxNumChars,
1177 const t_ARGS&... args)
1178{
1179 if (maxNumChars < 0)
1180 maxNumChars = 0;
1181
1183 t_OUT,
1184 typename bsl::iterator_traits<t_OUT>::value_type,
1185 typename bsl::iterator_traits<t_OUT>::difference_type>
1186 TruncatingIterator;
1187
1188 TruncatingIterator it(out, maxNumChars);
1189
1190 TruncatingIterator end = format_to(it, fmtStr, args...);
1191
1193 result.out = end.underlying();
1194 result.size = end.count();
1195 return result;
1196}
1197#endif
1198
1199
1200} // close package namespace
1201
1202
1203#undef BSLFMT_FORMAT_STRING_PARAMETER
1204#undef BSLFMT_FORMAT_WSTRING_PARAMETER
1205
1206#endif // End C++11 code
1207
1208#endif // INCLUDED_BSLFMT_FORMAT_IMP
1209
1210// ----------------------------------------------------------------------------
1211// Copyright 2023 Bloomberg Finance L.P.
1212//
1213// Licensed under the Apache License, Version 2.0 (the "License");
1214// you may not use this file except in compliance with the License.
1215// You may obtain a copy of the License at
1216//
1217// http://www.apache.org/licenses/LICENSE-2.0
1218//
1219// Unless required by applicable law or agreed to in writing, software
1220// distributed under the License is distributed on an "AS IS" BASIS,
1221// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1222// See the License for the specific language governing permissions and
1223// limitations under the License.
1224// ----------------------------- END-OF-FILE ----------------------------------
1225
1226/** @} */
1227/** @} */
1228/** @} */
Definition bslma_bslallocator.h:588
Definition bslstl_stringview.h:471
const_iterator iterator
Definition bslstl_stringview.h:482
Definition bslstl_string.h:1252
static size_t formatArgsSize(const basic_format_args< t_CONTEXT > &args)
Definition bslfmt_format_args.h:444
static basic_format_context< t_OUT, t_CHAR > construct(t_OUT out, const basic_format_args< basic_format_context< t_OUT, t_CHAR > > &args)
Definition bslfmt_format_context.h:527
Definition bslfmt_format_context.h:232
Definition bslfmt_format_context.h:262
Definition bslfmt_format_imp.h:229
void operator=(t_VALUE_TYPE x)
Definition bslfmt_format_imp.h:671
t_DIFF_TYPE difference_type
Definition bslfmt_format_imp.h:249
Format_Imp_TruncatingIterator(t_ITERATOR iterator, t_DIFF_TYPE limit)
Definition bslfmt_format_imp.h:653
Format_Imp_TruncatingIterator & operator*()
Definition bslfmt_format_imp.h:664
t_VALUE_TYPE value_type
Definition bslfmt_format_imp.h:250
t_ITERATOR underlying() const
Return the underlying iterator.
Definition bslfmt_format_imp.h:702
void pointer
Definition bslfmt_format_imp.h:252
void reference
Definition bslfmt_format_imp.h:251
bsl::output_iterator_tag iterator_category
Definition bslfmt_format_imp.h:248
Format_Imp_TruncatingIterator & operator++()
Definition bslfmt_format_imp.h:685
t_DIFF_TYPE count() const
Definition bslfmt_format_imp.h:693
Definition bslfmt_format_arg.h:162
Definition bslfmt_format_args.h:275
Definition bslfmt_format_context.h:316
Definition bslfmt_formatparsecontext.h:86
Definition bslfmt_formaterror.h:118
#define BSLFMT_FORMAT_WSTRING_PARAMETER
Definition bslfmt_format_imp.h:210
#define BSLFMT_FORMAT_STRING_PARAMETER
Definition bslfmt_format_imp.h:209
#define BSLS_ASSERT_OPT_UNREACHABLE(X)
Definition bsls_assert.h:2065
#define BSLS_THROW(X)
Definition bsls_exceptionutil.h:374
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:651
basic_string< wchar_t > wstring
Definition bslstl_string.h:845
basic_string< char > string
Definition bslstl_string.h:844
BSLS_KEYWORD_CONSTEXPR bsl::add_const< TYPE >::type & as_const(TYPE &t) BSLS_KEYWORD_NOEXCEPT
Return a reference offering non-modifiable access to the specified t.
Definition bslstl_utility.h:129
Definition bslfmt_enablestreamedformatter.h:130
bsl::string vformat(bsl::string_view fmt, format_args args)
Definition bslfmt_format_imp.h:1006
format_to_n_result< t_OUT > format_to_n(t_OUT out, typename bsl::iterator_traits< t_OUT >::difference_type maxNumChars, BSLFMT_FORMAT_STRING_PARAMETER fmtStr, const t_ARGS &... args)
Definition bslfmt_format_imp.h:1148
bsl::invoke_result< t_VISITOR &, bsl::monostate & >::type visit_format_arg(t_VISITOR &visitor, basic_format_arg< t_CONTEXT > arg)
Definition bslfmt_format_arg.h:907
bsl::enable_if<!bsl::is_same< typenamebsl::decay< t_OUT >::type, bsl::string * >::value, t_OUT >::type format_to(t_OUT out, BSLFMT_FORMAT_STRING_PARAMETER fmtStr, const t_ARGS &... args)
Definition bslfmt_format_imp.h:1046
std::size_t formatted_size(BSLFMT_FORMAT_STRING_PARAMETER fmtStr, const t_ARGS &... args)
Definition bslfmt_format_imp.h:1122
Format_ArgsStore< format_context, t_ARGS... > make_format_args(t_ARGS &... fmt_args)
Definition bslfmt_format_args.h:461
bsl::string format(BSLFMT_FORMAT_STRING_PARAMETER fmtStr, const t_ARGS &... args)
Definition bslfmt_format_imp.h:1085
t_OUT vformat_to(t_OUT out, bsl::string_view fmtStr, format_args args)
Definition bslfmt_format_imp.h:981
Format_ArgsStore< wformat_context, t_ARGS... > make_wformat_args(t_ARGS &... fmt_args)
Definition bslfmt_format_args.h:469
Definition bslmf_enableif.h:530
Definition bslfmt_formatterbase.h:426
Definition bslmf_issame.h:146
Definition bslstl_monostate.h:77
Definition bslfmt_format_imp.h:391
static Format_ContextOutputIteratorRef< t_CHAR > process(Format_ContextOutputIteratorRef< t_CHAR > out, bsl::basic_string_view< t_CHAR > fmtStr, const basic_format_args< basic_format_context< Format_ContextOutputIteratorRef< t_CHAR >, t_CHAR > > &args)
Definition bslfmt_format_imp.h:953
Definition bslfmt_format_imp.h:328
void operator()(bsl::monostate) const
Definition bslfmt_format_imp.h:725
Format_Imp_Visitor(basic_format_parse_context< t_CHAR > &pc, basic_format_context< t_OUT, t_CHAR > &fc)
Definition bslfmt_format_imp.h:714
Definition bslfmt_format_imp.h:310
t_OUT out
Definition bslfmt_format_imp.h:313
bsl::iterator_traits< t_OUT >::difference_type size
Definition bslfmt_format_imp.h:315