BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslalg_numericformatterutil.h
Go to the documentation of this file.
1/// @file bslalg_numericformatterutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslalg_numericformatterutil.h -*-C++-*-
8#ifndef INCLUDED_BSLALG_NUMERICFORMATTERUTIL
9#define INCLUDED_BSLALG_NUMERICFORMATTERUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslalg_numericformatterutil bslalg_numericformatterutil
15/// @brief Provide a utility for formatting numbers into strings.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslalg
19/// @{
20/// @addtogroup bslalg_numericformatterutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslalg_numericformatterutil-purpose"> Purpose</a>
25/// * <a href="#bslalg_numericformatterutil-classes"> Classes </a>
26/// * <a href="#bslalg_numericformatterutil-description"> Description </a>
27/// * <a href="#bslalg_numericformatterutil-shortest-decimal-representation-for-binary-floating-point-values"> Shortest (Textual) Decimal Representation for Binary Floating Point Values </a>
28/// * <a href="#bslalg_numericformatterutil-default-floating-point-format"> Default Floating Point Format </a>
29/// * <a href="#bslalg_numericformatterutil-special-floating-point-values"> Special Floating Point Values </a>
30/// * <a href="#bslalg_numericformatterutil-usage"> Usage </a>
31/// * <a href="#bslalg_numericformatterutil-example-1-writing-an-integer-to-a-streambuf"> Example 1: Writing an Integer to a streambuf </a>
32/// * <a href="#bslalg_numericformatterutil-example-2-writing-the-minimal-form-of-a-double"> Example 2: Writing the Minimal Form of a double </a>
33/// * <a href="#bslalg_numericformatterutil-example-3-determining-the-necessary-minimum-buffer-size"> Example 3: Determining The Necessary Minimum Buffer Size </a>
34///
35/// # Purpose {#bslalg_numericformatterutil-purpose}
36/// Provide a utility for formatting numbers into strings.
37///
38/// # Classes {#bslalg_numericformatterutil-classes}
39///
40/// - bslalg::NumericFormatterUtil: namespace for `toChars` and support functions
41///
42/// # Description {#bslalg_numericformatterutil-description}
43/// This component, @ref bslalg_numericformatterutil provides a
44/// namespace `struct`, `bslalg::NumericFormatterUtil`, containing the
45/// overloaded function `toChars`, that converts integral and floating point
46/// types into ASCII strings.
47///
48/// ## Shortest (Textual) Decimal Representation for Binary Floating Point Values {#bslalg_numericformatterutil-shortest-decimal-representation-for-binary-floating-point-values}
49///
50///
51/// The floating point `toChars` implementations (for `float` and `double`) of
52/// this component provide the shortest (textual) decimal representation that
53/// can (later) be parsed back to the original binary value (i.e., a
54/// "round-trip" conversion). Such round-tripping enables precise, and
55/// human-friendly (textual) communication protocols, and storage formats that
56/// use minimal necessary bandwidth or storage.
57///
58/// Scientific notation, when chosen, always uses the minimum number of
59/// fractional digits necessary to restore the exact binary floating point
60/// value. The shortest *decimal* notation of a binary floating point number is
61/// text that has enough decimal **fractional** digits so that there can be no
62/// ambiguity in which binary representation value is closest to it. Notice
63/// that the previous sentence only addresses the number of *fractional* digits
64/// in the decimal notation. Floating point values that are mathematically
65/// integer are always written as their exact integer value in decimal notation.
66/// For large integers it would not strictly be necessary to use the exact
67/// decimal value as many integers (differing in some lower-decimal digits) may
68/// resolve to the same binary value, but readers may not expect integers to be
69/// "rounded", so C and C++ chose to standardize on the exact value.
70///
71/// Note that strictly speaking the C++-defined shortest round trip
72/// representation is not the shortest *possible* one as the C++ scientific
73/// notation is defined to possibly contain up to two extra characters: the sign
74/// of the exponent is always written (even for positive exponents), and at
75/// least 2 decimal digits of the exponent are always written.
76///
77/// More information about the difficulty of rendering binary floating point
78/// numbers as decimals can be found at
79/// https://bloomberg.github.io/bde/articles/binary_decimal_conversion.html .
80/// In short, IEEE-754 double precision binary floating point numbers (`double`)
81/// are guaranteed to round-trip when represented by 17 significant decimal
82/// digits, while single precisions (`float`) needs 9 digits. However those
83/// numbers are the *maximum* decimal digits that *may* be necessary, and in
84/// fact many values can be precisely represented precisely by less. `toChars`
85/// renders the minimum number of digits needed, so that the value can later be
86/// restored.
87///
88/// ## Default Floating Point Format {#bslalg_numericformatterutil-default-floating-point-format}
89///
90///
91/// The default floating point format (that is used when no `format` argument is
92/// present in the signature) uses the shortest representation from the decimal
93/// notation and the scientific notation, favoring decimal notation in case of a
94/// tie.
95///
96/// ## Special Floating Point Values {#bslalg_numericformatterutil-special-floating-point-values}
97///
98///
99/// Floating point values may also be special-numerical or non-numerical(*)
100/// values in addition to what we consider normal numbers.
101///
102/// The special numerical value is really just one, and that is negative zero.
103///
104/// For non-numerical special value both IEEE-754 and W3C XML Schema Definition
105/// Language (XSD) 1.1(**) `numericalSpecialRep` requires there to be three
106/// distinct values supported: positive infinity, negative infinity, and NaN.
107/// We represent those values according to the XSD lexical mapping
108/// specification. That also means that these values will round trip in text
109/// *only* if the reader algorithm recognizes those representations.
110///
111/// @code
112/// +-------------------+----------------+
113/// | Special Value | Textual Repr. |
114/// +-------------------+----------------+
115/// | positive zero | "0", "0e+00" |
116/// +-------------------+----------------+
117/// | negative zero | "-0", "-0e+00" |
118/// +-------------------+----------------+
119/// | positive infinity | "+INF" |
120/// +-------------------+----------------+
121/// | negative infinity | "-INF" |
122/// +-------------------+----------------+
123/// | Not-a-number | "NaN" |
124/// +-------------------+----------------+
125/// @endcode
126///
127/// (*) Non-numerical values do not represent a specific mathematical value. Do
128/// not confuse non-numerical values with Not-a-Number. NaN is just one of
129/// the possible non-numerical values. The positive and negative infinity
130/// represent *all* values too large (in their absolute value) to store. NaN
131/// represents all other values that cannot be represented by a real number.
132/// Non-numerical values normally come from computation results such as the
133/// square root of -1 resulting in Not-a-Number.
134///
135/// (**) https://www.w3.org/TR/xmlschema11-2/
136///
137/// ## Usage {#bslalg_numericformatterutil-usage}
138///
139///
140/// In this section we show the intended use of this component.
141///
142/// ### Example 1: Writing an Integer to a streambuf {#bslalg_numericformatterutil-example-1-writing-an-integer-to-a-streambuf}
143///
144///
145/// Suppose we want to define a function that writes an `int` to a `streambuf`.
146/// We can use `bsl::to_chars` to write the `int` to a buffer, then write the
147/// buffer to the `streambuf`.
148///
149/// First, we declare our function:
150/// @code
151/// void writeJsonScalar(std::streambuf *result, int value)
152/// // Write the specified 'value', in decimal, to the specified 'result'.
153/// {
154/// @endcode
155/// Then, we declare a buffer long enough to store any `int` value in decimal.
156/// @code
157/// char buffer[bslalg::NumericFormatterUtil::
158/// ToCharsMaxLength<int>::k_VALUE];
159/// // size large enough to write 'INT_MIN', the
160/// // worst-case value, in decimal.
161/// @endcode
162/// Next, we call the function:
163/// @code
164/// char *ret = bslalg::NumericFormatterUtil::toChars(
165/// buffer,
166/// buffer + sizeof buffer,
167/// value);
168/// @endcode
169/// Then, we check that the buffer was long enough, which should always be the
170/// case:
171/// @code
172/// assert(0 != ret);
173/// @endcode
174/// Now, we write our buffer to the `streambuf`:
175/// @code
176/// result->sputn(buffer, ret - buffer);
177/// }
178/// @endcode
179/// Finally, we use an output string stream buffer to exercise the
180/// `writeJsonScalar` function for `int`:
181/// @code
182/// std::ostringstream oss;
183/// std::streambuf* sb = oss.rdbuf();
184///
185/// writeJsonScalar(sb, 0);
186/// assert("0" == oss.str());
187///
188/// oss.str("");
189/// writeJsonScalar(sb, 99);
190/// assert("99" == oss.str());
191///
192/// oss.str("");
193/// writeJsonScalar(sb, -1234567890); // worst case: max string length
194/// assert("-1234567890" == oss.str());
195/// @endcode
196///
197/// ### Example 2: Writing the Minimal Form of a double {#bslalg_numericformatterutil-example-2-writing-the-minimal-form-of-a-double}
198///
199///
200/// Suppose we want to store a floating point number using decimal text (such as
201/// JSON) for later retrieval, using the minimum number of digits that ensures
202/// we can later restore the same binary floating point value.
203///
204/// First, we declare our writer function:
205/// @code
206/// void writeJsonScalar(std::streambuf *result,
207/// double value,
208/// bool stringNonNumericValues = false)
209/// // Write the specified 'value' in the shortest round-trip decimal
210/// // format into the specified 'result'. Write non-numeric values
211/// // according to the optionally specified 'stringNonNumericValues'
212/// // either as strings "NaN", "+Infinity", or "-Infinity" when
213/// // 'stringNonNumericValues' is 'true', or a null when it is 'false' or
214/// // not specified.
215/// {
216/// @endcode
217/// Then, we handle non-numeric values (`toChars` would write them the XSD way):
218/// @code
219/// if (isnan(value) || isinf(value)) {
220/// if (false == stringNonNumericValues) { // JSON standard output
221/// result->sputn("null", 4);
222/// }
223/// else { // Frequent JSON extension
224/// if (isnan(value)) {
225/// result->sputn("\"NaN\"", 5);
226/// }
227/// else if (isinf(value)) {
228/// result->sputn(value < 0 ? "\"-" : "\"+", 2);
229/// result->sputn("Infinity\"", 9);
230/// }
231/// }
232/// return; // RETURN
233/// }
234/// @endcode
235/// Next, we declare a buffer long enough to store any `double` value written in
236/// this minimal-length form:
237/// @code
238/// char buffer[bslalg::NumericFormatterUtil::
239/// ToCharsMaxLength<double>::k_VALUE];
240/// // large enough to write the longest 'double'
241/// // without a null terminator character.
242/// @endcode
243/// Then, we call the function:
244/// @code
245/// char *ret = bslalg::NumericFormatterUtil::toChars(
246/// buffer,
247/// buffer + sizeof buffer,
248/// value);
249/// @endcode
250/// Finally, we can write our buffer to the `streambuf`:
251/// @code
252/// result->sputn(buffer, ret - buffer);
253/// }
254/// @endcode
255/// Finally, we use the output string stream buffer defined earlier to exercise
256/// the floating point `writeJsonScalar` function:
257/// @code
258/// oss.str("");
259/// writeJsonScalar(sb, 20211017.0);
260/// assert("20211017" == oss.str());
261///
262/// oss.str("");
263/// writeJsonScalar(sb, 3.1415926535897932);
264/// assert("3.141592653589793" == oss.str());
265///
266/// oss.str("");
267/// writeJsonScalar(sb, 2e5);
268/// assert("2e+05" == oss.str());
269///
270/// oss.str(""); // Non-numeric are written as null by default
271/// writeJsonScalar(sb, std::numeric_limits<double>::quiet_NaN());
272/// assert("null" == oss.str()); oss.str("");
273///
274/// oss.str(""); // Non-numeric can be printed as strings
275/// writeJsonScalar(sb, std::numeric_limits<double>::quiet_NaN(), true);
276/// assert("\"NaN\"" == oss.str()); oss.str("");
277/// @endcode
278///
279/// ### Example 3: Determining The Necessary Minimum Buffer Size {#bslalg_numericformatterutil-example-3-determining-the-necessary-minimum-buffer-size}
280///
281///
282/// Suppose you are writing code that uses `bslalg::NumericFormatterUtil` to
283/// convert values to text. Determining the necessary buffer sizes to ensure
284/// successful conversions, especially for floating point types, is non-trivial,
285/// and frankly usually strikes as a distraction in the flow of the work. This
286/// component provides the `ToCharsMaxLength` `struct` "overloaded" template
287/// that parallels the overloaded `toChars` function variants and provides the
288/// well-vetted and tested minimum sufficient buffer size values as compile time
289/// constants.
290///
291/// Determining the sufficient buffer size for any conversion starts with
292/// determining "What type are we converting?" and "Do we use an argument to
293/// control the conversion, and is that argument a compile time time constant?
294///
295/// First, because of the descriptive type names we may want to start by locally
296/// shortening them using a `typedef`:
297/// @code
298/// typedef bslalg::NumericFormatterUtil NfUtil;
299/// @endcode
300/// Next, we determine the sufficient buffer size for converting a `long` to
301/// decimal. `long` is a type that has different `sizeof` on different 64 bit
302/// platforms, so it is especially convenient to have that difference hidden:
303/// @code
304/// const size_t k_LONG_DEC_SIZE = NfUtil::ToCharsMaxLength<long>::k_VALUE;
305/// // Sufficient buffer size to convert any 'long' value to decimal text.
306/// @endcode
307/// Then, we can write the longest possible `long` successfully into a buffer:
308/// @code
309/// char longDecimalBuffer[k_LONG_DEC_SIZE];
310/// // We can write any 'long' in decimal into this buffer using
311/// // 'NfUtil::toChars' safely.
312///
313/// char *p = NfUtil::toChars(longDecimalBuffer,
314/// longDecimalBuffer + sizeof longDecimalBuffer,
315/// LONG_MIN);
316/// assert(p != 0);
317/// @endcode
318/// Next, we can get the sufficient size for conversion of an `unsigned int` to
319/// octal:
320/// @code
321/// const size_t k_UINT_OCT_SIZE = NfUtil::ToCharsMaxLength<unsigned,
322/// 8>::k_VALUE;
323/// @endcode
324/// Then, if we do not know what `base` value `toChars` will use we have to,
325/// assume the longest, which is always base 2:
326/// @code
327/// const size_t k_SHRT_MAX_SIZE = NfUtil::ToCharsMaxLength<short, 2>::k_VALUE;
328/// @endcode
329/// Now, floating point types have an optional `format` argument instead of a
330/// `base`, with "default" format as the default, and "fixed" and "scientific"
331/// formats are selectable when a `format` argument is specified:
332/// @code
333/// const size_t k_DBL_DFL_SIZE = NfUtil::ToCharsMaxLength<double>::k_VALUE;
334///
335/// const size_t k_FLT_DEC_SIZE = NfUtil::ToCharsMaxLength<
336/// float,
337/// NfUtil::e_FIXED>::k_VALUE;
338///
339/// const size_t k_DBL_SCI_SIZE = NfUtil::ToCharsMaxLength<
340/// double,
341/// NfUtil::e_SCIENTIFIC>::k_VALUE;
342/// @endcode
343/// Finally, the longest floating point format is `e_FIXED`, so if the `format`
344/// argument is not known at compile time, `e_FIXED` should be used:
345/// @code
346/// const size_t k_DBL_MAX_SIZE = NfUtil::ToCharsMaxLength<
347/// double,
348/// NfUtil::e_FIXED>::k_VALUE;
349/// @endcode
350/// @}
351/** @} */
352/** @} */
353
354/** @addtogroup bsl
355 * @{
356 */
357/** @addtogroup bslalg
358 * @{
359 */
360/** @addtogroup bslalg_numericformatterutil
361 * @{
362 */
363
364#include <bslscm_version.h>
365
366#include <bslmf_assert.h>
367#include <bslmf_conditional.h>
368#include <bslmf_isintegral.h>
369#include <bslmf_issame.h>
370#include <bslmf_removecv.h>
371
372#include <bsls_assert.h>
373#include <bsls_keyword.h>
374
375#include <limits> // 'bsl' cannot be used in 'bslalg'
376
377
378namespace bslalg {
379
380 // ===========================
381 // struct NumericFormatterUtil
382 // ===========================
383
384/// Namespace `struct` for free functions supporting `to_chars`.
386
387 private:
388 // PRIVATE CLASS METHODS
389
390 /// Write the specified `value` into the character buffer starting a the
391 /// specified `first` and ending at the specified `last`, rendering the
392 /// value in the specified base `base`. On success, return a the
393 /// address one past the lowest order digit written, on failure, return
394 /// 0. The only reason for failure is if the range `[ first, last )` is
395 /// not large enough to contain the result. The written result is to
396 /// begin at `first` with leftover room following the return value. The
397 /// behavior is undefined unless `first <= last` and `base` is in the
398 /// range `[ 2 .. 36 ]`.
399 static char *toCharsImpl(char *first,
400 char *last,
401 unsigned value,
402 int base) BSLS_KEYWORD_NOEXCEPT;
403
404 /// Write the specified `value` into the character buffer starting a the
405 /// specified `first` and ending at the specified `last`, ing the value
406 /// in the specified base `base`. On success, return a the address one
407 /// past the lowest order digit written, on failure, return 0. The only
408 /// reason for failure is if the range `[ first, last )` is not large
409 /// enough to contain the result. The written result is to begin at
410 /// `first` with leftover room following the return value. The behavior
411 /// is undefined unless `first <= last` and `base` is in the range
412 /// `[ 2 .. 36 ]`.
413 static
414 char *toCharsImpl(char *first,
415 char *last,
416 unsigned long long int value,
417 int base) BSLS_KEYWORD_NOEXCEPT;
418
419 /// Write the textual representation of the specified `value` in the
420 /// specified `base` into the character buffer starting a the specified
421 /// `first` and ending at the specified `last`. Return the address one
422 /// past the lowest order digit written on success, or 0 on failure.
423 /// The only possible reason for failure is if the range
424 /// `[ first, last )` is not large enough to contain the result. The
425 /// written result is to begin at `first` with leftover room following
426 /// the return value. The behavior is undefined unless `first < last`
427 /// and `base` is in the range `[ 2 .. 36 ]`. The behavior is also
428 /// undefined unless the specified `TYPE` is a fundamental integral type
429 /// not larger than 64 bits.
430 template <class TYPE>
431 static char *toCharsIntegral(char *first,
432 char *last,
433 TYPE value,
434 int base) BSLS_KEYWORD_NOEXCEPT;
435
436 /// Write the textual representation of the specified `value` in decimal
437 /// notation into the character buffer starting a the specified `first` and
438 /// ending at the specified `last`. Return the address one past the lowest
439 /// order digit written on success, or 0 on failure. The only possible
440 /// reason for failure is if the range `[ first, last )` is not large
441 /// enough to contain the result. The written result is to begin at
442 /// `first` with leftover room following the return value.
443 static char *toCharsDecimal(char *first,
444 char *last,
445 double value) BSLS_KEYWORD_NOEXCEPT;
446 static char *toCharsDecimal(char *first,
447 char *last,
448 float value) BSLS_KEYWORD_NOEXCEPT;
449
450 /// Write the textual representation of the specified `value` in scientific
451 /// notation into the character buffer starting a the specified `first` and
452 /// ending at the specified `last`. Return the address one past the lowest
453 /// order digit of the exponent written on success, or 0 on failure. The
454 /// only possible reason for failure is if the range `[ first, last )` is
455 /// not large enough to contain the result. The written result is to begin
456 /// at `first` with leftover room following the return value.
457 static char *toCharsScientific(char *first,
458 char *last,
459 double value) BSLS_KEYWORD_NOEXCEPT;
460 static char *toCharsScientific(char *first,
461 char *last,
462 float value) BSLS_KEYWORD_NOEXCEPT;
463
464 private:
465 // NOT IMPLEMENTED
466
467 /// This deleted/private method declaration exists to prevent `toChars`
468 /// being called with a `bool` input argument.
469 static char *toChars(char*, char*, bool, int = 10) BSLS_KEYWORD_NOEXCEPT
471
472 private:
473 // PRIVATE TYPES
474
475 /// This enumerator is used internally to achieve "type safe"
476 /// pseudo-overloading of the `ToCharsMaxLength` template to mimic the
477 /// different `toChars` class method overloads.
478 enum { k_MAXLEN_ARG_DEFAULT = -256 };
479
480 // PRIVATE METAFUNCTIONS
481
482 /// This `struct` template implements a meta-function to determine the
483 /// minimum sufficient size (in characters) of an output buffer to
484 /// successfully convert any value of the specified `FLT_TYPE` floating
485 /// point type into text of the specified `FORMAT` using `toChars`.
486 /// Format may be any of the `Format` enumerator values or an
487 /// unspecified value for default format. The floating point types are
488 /// assumed to be IEEE-754 binary types. The result ("return value") is
489 /// a member enumerator `k_VALUE`. This meta-function is private and
490 /// contains no defensive checks.
491 template <class FLT_TYPE, int FORMAT>
492 struct FltMaxLen;
493
494 /// This `struct` template implements a meta-function to determine the
495 /// minimum sufficient size (in characters) of an output buffer to
496 /// successfully convert any value of a fundamental integer type to text
497 /// into the specified `BASE` using `toChars`. The integer type is
498 /// described by the specified `IS_SIGNED` and `SIZEOF` parameters, and
499 /// is assumed to be two's complement. The result ("return value") is
500 /// an enumerator `k_VALUE`. The meta-function is private and contains
501 /// no defensive checks.
502 template <bool IS_SIGNED, unsigned SIZEOF, int BASE>
503 struct IntMaxLen;
504
505 /// This `struct` template implements the meta-function to determine if
506 /// the specified `TYPE` is a supported floating point type for the
507 /// `toChars` overloaded method-set. The result ("return value") is an
508 /// enumerator `k_SUPPORTED` that has a non-zero value if `TYPE` is a
509 /// supported floating point type, or zero otherwise.
510 template <class TYPE>
511 struct IsSupportedFloatingPoint;
512
513 /// This `struct` template implements the meta-function to determine if
514 /// the specified `TYPE` is a supported integral type for the `toChars`
515 /// overloaded method-set. The result ("return value") is an enumerator
516 /// `k_SUPPORTED` that has a non-zero value if `TYPE` is a supported
517 /// integral type, or zero otherwise.
518 template <class TYPE>
519 struct IsSupportedIntegral;
520
521 public:
522 // PUBLIC TYPES
523 enum Format {
524 // This enumeration lists the supported, explicitly specified 'toChars'
525 // formatting options for floating point values. (The default format
526 // option, shortest round-trip, is specified implicitly by omitting the
527 // 'format' argument.) Additional enumerators are reserved for future
528 // use:
529 //: 'e_HEX = 0x100'
530 //: 'e_GENERAL = e_SCIENTIFIC | e_FIXED'
531 // and correspond to the C++17 'std::chars_format' 'hex', and 'general'
532 // enumerators. See {Adding 'Format's} in the {Implementation Notes}
533 // of the implementation (.cpp) file.
534
536 e_FIXED = 0x80
537 };
538
539 // PUBLIC METAFUNCTIONS
540
541 /// This `struct` template implements the meta-function to determine the
542 /// minimum sufficient size of a buffer to successfully convert any
543 /// numeric value of a specified `TYPE` supported by one of the
544 /// `toChars` function overloads in `NumericFormatterUtil`. The
545 /// meta-function allows specifying an argument value to the `toChars`
546 /// overloads, as a non-type template parameter. That value stands for
547 /// the `base` parameter for integral conversions, and the `format`
548 /// parameter for floating point conversions. A second non-type
549 /// template parameter is reserved for further addition in case the
550 /// `precision` parameter overloads are implemented for floating point
551 /// conversions (in addition to the `format` parameter). The
552 /// compile-time "return value" of `ToCharsMaxLength` is an enumerator
553 /// name `k_VALUE`. For usage examples see {Example 3: Determining The
554 /// Required Buffer Size}.
555 template <class TYPE,
556 int ARG = k_MAXLEN_ARG_DEFAULT>
557 struct ToCharsMaxLength;
558
559 // PUBLIC CLASS METHODS
560
561 /// Write the specified `value` into the character buffer starting a the
562 /// specified `first` and ending at the specified `last`, `last` not
563 /// included. In integer conversions, if the optionally specified `base`
564 /// argument is not present or specified, base 10 is used. In floating
565 /// point conversions, if the optionally specified `format` argument is not
566 /// present or specified, the {Default Floating Point Format} is used. If
567 /// a `format` argument is specified (`e_DECIMAL` or `e_SCIENTIFIC`), the
568 /// {Shortest (Textual) Decimal Representation for Binary Floating Point
569 /// Values} is used in that format (that will produce the exact binary
570 /// floating point `value` when converted back to the original type from
571 /// text), but see possible exceptions under {Special Floating Point
572 /// Values}. Return the address one past the last character (lowest order
573 /// digit or last digit of the exponent) written on success, or `0` on
574 /// failure. The only reason for failure is when the range
575 /// `[ first, last )` is not large enough to contain the result. The
576 /// written result is to begin at `first` with leftover room following the
577 /// return value. The behavior is undefined unless `first <= last`, and
578 /// `base` is in the range `[ 2 .. 36 ]`. Note that the type `bool` for
579 /// the `value` parameter is explicitly disabled in the "NOT IMPLEMENTED"
580 /// `private` section, because `bool` would otherwise be promoted to `int`
581 /// and printed as `0` or `1`, instead of the (possibly) expected `false`
582 /// and `true`; and `bool` is not an integral or numeric type either. Also
583 /// note that these functions do **not** null-terminate the result.
584 static
585 char *toChars(char *first,
586 char *last,
587 char value,
588 int base = 10) BSLS_KEYWORD_NOEXCEPT;
589 static
590 char *toChars(char *first,
591 char *last,
592 signed char value,
593 int base = 10) BSLS_KEYWORD_NOEXCEPT;
594 static
595 char *toChars(char *first,
596 char *last,
597 unsigned char value,
598 int base = 10) BSLS_KEYWORD_NOEXCEPT;
599 static
600 char *toChars(char *first,
601 char *last,
602 signed short int value,
603 int base = 10) BSLS_KEYWORD_NOEXCEPT;
604 static
605 char *toChars(char *first,
606 char *last,
607 unsigned short int value,
608 int base = 10) BSLS_KEYWORD_NOEXCEPT;
609 static
610 char *toChars(char *first,
611 char *last,
612 signed int value,
613 int base = 10) BSLS_KEYWORD_NOEXCEPT;
614 static
615 char *toChars(char *first,
616 char *last,
617 unsigned int value,
618 int base = 10) BSLS_KEYWORD_NOEXCEPT;
619 static
620 char *toChars(char *first,
621 char *last,
622 signed long int value,
623 int base = 10) BSLS_KEYWORD_NOEXCEPT;
624 static
625 char *toChars(char *first,
626 char *last,
627 unsigned long int value,
628 int base = 10) BSLS_KEYWORD_NOEXCEPT;
629 static
630 char *toChars(char *first,
631 char *last,
632 signed long long int value,
633 int base = 10) BSLS_KEYWORD_NOEXCEPT;
634 static
635 char *toChars(char *first,
636 char *last,
637 unsigned long long int value,
638 int base = 10) BSLS_KEYWORD_NOEXCEPT;
639 static
640 char *toChars(char *first,
641 char *last,
642 double value) BSLS_KEYWORD_NOEXCEPT;
643 static
644 char *toChars(char *first,
645 char *last,
646 float value) BSLS_KEYWORD_NOEXCEPT;
647 static
648 char *toChars(char *first,
649 char *last,
650 double value,
652 static
653 char *toChars(char *first,
654 char *last,
655 float value,
657};
658
659 // -----------------------------------------------
660 // template struct NumericFormatterUtil::FltMaxLen
661 // -----------------------------------------------
662
663template <class FLT_TYPE, int FORMAT>
664struct NumericFormatterUtil::FltMaxLen {
665 private:
666 // PRIVATE TYPES
667
668 /// For more readable lines below.
669 typedef typename bsl::remove_cv<FLT_TYPE>::type NoCvT;
670 public:
671 // PUBLIC TYPES
672 enum Enum {
673 // The default and 'e_SCIENTIFIC' formats have the same maximum size,
674 // so we simplify the expression.
675
677 ? FORMAT == NumericFormatterUtil::e_FIXED ? 327 : 24
678 : FORMAT == NumericFormatterUtil::e_FIXED ? 48 : 15
679 };
680};
681
682 // -----------------------------------------------
683 // template struct NumericFormatterUtil::IntMaxLen
684 // -----------------------------------------------
685
686#define BSLALG_NUMERICFORMATTERUTIL_INTMAXLEN_ONE(issigned, bytes, \
687 val02, val03, val04, val05, val06, val07, val08, val09, val10, \
688 val11, val12, val13, val14, val15, val16, val17, val18, val19, val20, \
689 val21, val22, val23, val24, val25, val26, val27, val28, val29, val30, \
690 val31, val32, val33, val34, val35, val36) \
691 template <int BASE> \
692 struct NumericFormatterUtil::IntMaxLen<issigned, bytes, BASE> { \
693 enum Enum { \
694 k_VALUE = (BASE == 2) ? val02 \
695 : (BASE == 3) ? val03 \
696 : (BASE == 4) ? val04 \
697 : (BASE == 5) ? val05 \
698 : (BASE == 6) ? val06 \
699 : (BASE == 7) ? val07 \
700 : (BASE == 8) ? val08 \
701 : (BASE == 9) ? val09 \
702 : (BASE == 10) ? val10 \
703 : (BASE == 11) ? val11 \
704 : (BASE == 12) ? val12 \
705 : (BASE == 13) ? val13 \
706 : (BASE == 14) ? val14 \
707 : (BASE == 15) ? val15 \
708 : (BASE == 16) ? val16 \
709 : (BASE == 17) ? val17 \
710 : (BASE == 18) ? val18 \
711 : (BASE == 19) ? val19 \
712 : (BASE == 20) ? val20 \
713 : (BASE == 21) ? val21 \
714 : (BASE == 22) ? val22 \
715 : (BASE == 23) ? val23 \
716 : (BASE == 24) ? val24 \
717 : (BASE == 25) ? val25 \
718 : (BASE == 26) ? val26 \
719 : (BASE == 27) ? val27 \
720 : (BASE == 28) ? val28 \
721 : (BASE == 29) ? val29 \
722 : (BASE == 30) ? val30 \
723 : (BASE == 31) ? val31 \
724 : (BASE == 32) ? val32 \
725 : (BASE == 33) ? val33 \
726 : (BASE == 34) ? val34 \
727 : (BASE == 35) ? val35 \
728 : (BASE == 36) ? val36 \
729 : val10 /* default value */ \
730 }; \
731 }
732
733// BDE_VERIFY pragma: push // Relax mandatory tag rules for macro-created
734// BDE_VERIFY pragma: -KS00 // template specializations
736 9, // base 2: "-10000000"
737 6, // base 3: "-11202"
738 5, // base 4: "-2000"
739 5, // base 5: "-1003"
740 4, // base 6: "-332"
741 4, // base 7: "-242"
742 4, // base 8: "-200"
743 4, // base 9: "-152"
744 4, // base 10: "-128"
745 4, // base 11: "-107"
746 3, // base 12: "-a8"
747 3, // base 13: "-9b"
748 3, // base 14: "-92"
749 3, // base 15: "-88"
750 3, // base 16: "-80"
751 3, // base 17: "-79"
752 3, // base 18: "-72"
753 3, // base 19: "-6e"
754 3, // base 20: "-68"
755 3, // base 21: "-62"
756 3, // base 22: "-5i"
757 3, // base 23: "-5d"
758 3, // base 24: "-58"
759 3, // base 25: "-53"
760 3, // base 26: "-4o"
761 3, // base 27: "-4k"
762 3, // base 28: "-4g"
763 3, // base 29: "-4c"
764 3, // base 30: "-48"
765 3, // base 31: "-44"
766 3, // base 32: "-40"
767 3, // base 33: "-3t"
768 3, // base 34: "-3q"
769 3, // base 35: "-3n"
770 3); // base 36: "-3k"
771
773 8, // base 2: "11111111"
774 6, // base 3: "100110"
775 4, // base 4: "3333"
776 4, // base 5: "2010"
777 4, // base 6: "1103"
778 3, // base 7: "513"
779 3, // base 8: "377"
780 3, // base 9: "313"
781 3, // base 10: "255"
782 3, // base 11: "212"
783 3, // base 12: "193"
784 3, // base 13: "168"
785 3, // base 14: "143"
786 3, // base 15: "120"
787 2, // base 16: "ff"
788 2, // base 17: "f0"
789 2, // base 18: "e3"
790 2, // base 19: "d8"
791 2, // base 20: "cf"
792 2, // base 21: "c3"
793 2, // base 22: "bd"
794 2, // base 23: "b2"
795 2, // base 24: "af"
796 2, // base 25: "a5"
797 2, // base 26: "9l"
798 2, // base 27: "9c"
799 2, // base 28: "93"
800 2, // base 29: "8n"
801 2, // base 30: "8f"
802 2, // base 31: "87"
803 2, // base 32: "7v"
804 2, // base 33: "7o"
805 2, // base 34: "7h"
806 2, // base 35: "7a"
807 2); // base 36: "73"
808
810 17, // base 2: "-1000000000000000"
811 11, // base 3: "-1122221122"
812 9, // base 4: "-20000000"
813 8, // base 5: "-2022033"
814 7, // base 6: "-411412"
815 7, // base 7: "-164351"
816 7, // base 8: "-100000"
817 6, // base 9: "-48848"
818 6, // base 10: "-32768"
819 6, // base 11: "-2268a"
820 6, // base 12: "-16b68"
821 6, // base 13: "-11bb8"
822 5, // base 14: "-bd28"
823 5, // base 15: "-9a98"
824 5, // base 16: "-8000"
825 5, // base 17: "-6b69"
826 5, // base 18: "-5b28"
827 5, // base 19: "-4eec"
828 5, // base 20: "-41i8"
829 5, // base 21: "-3b68"
830 5, // base 22: "-31fa"
831 5, // base 23: "-2flg"
832 5, // base 24: "-28l8"
833 5, // base 25: "-22ai"
834 5, // base 26: "-1mc8"
835 5, // base 27: "-1hph"
836 5, // base 28: "-1dm8"
837 5, // base 29: "-19rr"
838 5, // base 30: "-16c8"
839 5, // base 31: "-1331"
840 5, // base 32: "-1000"
841 4, // base 33: "-u2w"
842 4, // base 34: "-sbq"
843 4, // base 35: "-qq8"
844 4); // base 36: "-pa8"
845
847 16, // base 2: "1111111111111111"
848 11, // base 3: "10022220020"
849 8, // base 4: "33333333"
850 7, // base 5: "4044120"
851 7, // base 6: "1223223"
852 6, // base 7: "362031"
853 6, // base 8: "177777"
854 6, // base 9: "108806"
855 5, // base 10: "65535"
856 5, // base 11: "45268"
857 5, // base 12: "31b13"
858 5, // base 13: "23aa2"
859 5, // base 14: "19c51"
860 5, // base 15: "14640"
861 4, // base 16: "ffff"
862 4, // base 17: "d5d0"
863 4, // base 18: "b44f"
864 4, // base 19: "9aa4"
865 4, // base 20: "83gf"
866 4, // base 21: "71cf"
867 4, // base 22: "638j"
868 4, // base 23: "58k8"
869 4, // base 24: "4hif"
870 4, // base 25: "44la"
871 4, // base 26: "3iof"
872 4, // base 27: "38o6"
873 4, // base 28: "2rgf"
874 4, // base 29: "2jqo"
875 4, // base 30: "2cof"
876 4, // base 31: "2661"
877 4, // base 32: "1vvv"
878 4, // base 33: "1r5u"
879 4, // base 34: "1mnh"
880 4, // base 35: "1ihf"
881 4); // base 36: "1ekf"
882
884 33, // base 2: "-10000000000000000000000000000000"
885 21, // base 3: "-12112122212110202102"
886 17, // base 4: "-2000000000000000"
887 15, // base 5: "-13344223434043"
888 13, // base 6: "-553032005532"
889 13, // base 7: "-104134211162"
890 12, // base 8: "-20000000000"
891 11, // base 9: "-5478773672"
892 11, // base 10: "-2147483648"
893 10, // base 11: "-a02220282"
894 10, // base 12: "-4bb2308a8"
895 10, // base 13: "-282ba4aab"
896 10, // base 14: "-1652ca932"
897 9, // base 15: "-c87e66b8"
898 9, // base 16: "-80000000"
899 9, // base 17: "-53g7f549"
900 9, // base 18: "-3928g3h2"
901 9, // base 19: "-27c57h33"
902 9, // base 20: "-1db1f928"
903 9, // base 21: "-140h2d92"
904 8, // base 22: "-ikf5bf2"
905 8, // base 23: "-ebelf96"
906 8, // base 24: "-b5gge58"
907 8, // base 25: "-8jmdnkn"
908 8, // base 26: "-6oj8ioo"
909 8, // base 27: "-5ehnckb"
910 8, // base 28: "-4clm98g"
911 8, // base 29: "-3hk7988"
912 8, // base 30: "-2sb6cs8"
913 8, // base 31: "-2d09uc2"
914 8, // base 32: "-2000000"
915 8, // base 33: "-1lsqtl2"
916 8, // base 34: "-1d8xqrq"
917 8, // base 35: "-15v22un"
918 7); // base 36: "-zik0zk"
919
921 32, // base 2: "11111111111111111111111111111111"
922 21, // base 3: "102002022201221111210"
923 16, // base 4: "3333333333333333"
924 14, // base 5: "32244002423140"
925 13, // base 6: "1550104015503"
926 12, // base 7: "211301422353"
927 11, // base 8: "37777777777"
928 11, // base 9: "12068657453"
929 10, // base 10: "4294967295"
930 10, // base 11: "1904440553"
931 9, // base 12: "9ba461593"
932 9, // base 13: "535a79888"
933 9, // base 14: "2ca5b7463"
934 9, // base 15: "1a20dcd80"
935 8, // base 16: "ffffffff"
936 8, // base 17: "a7ffda90"
937 8, // base 18: "704he7g3"
938 8, // base 19: "4f5aff65"
939 8, // base 20: "3723ai4f"
940 8, // base 21: "281d55i3"
941 8, // base 22: "1fj8b183"
942 8, // base 23: "1606k7ib"
943 7, // base 24: "mb994af"
944 7, // base 25: "hek2mgk"
945 7, // base 26: "dnchbnl"
946 7, // base 27: "b28jpdl"
947 7, // base 28: "8pfgih3"
948 7, // base 29: "76beigf"
949 7, // base 30: "5qmcpqf"
950 7, // base 31: "4q0jto3"
951 7, // base 32: "3vvvvvv"
952 7, // base 33: "3aokq93"
953 7, // base 34: "2qhxjlh"
954 7, // base 35: "2br45qa"
955 7); // base 36: "1z141z3"
956
958 65, // base 2: "-10000000000000000000....00000000000000000000"
959 41, // base 3: "-2021110011022210012102010021220101220222"
960 33, // base 4: "-20000000000000000000000000000000"
961 29, // base 5: "-1104332401304422434310311213"
962 26, // base 6: "-1540241003031030222122212"
963 24, // base 7: "-22341010611245052052301"
964 23, // base 8: "-1000000000000000000000"
965 21, // base 9: "-67404283172107811828"
966 20, // base 10: "-9223372036854775808"
967 20, // base 11: "-1728002635214590698"
968 19, // base 12: "-41a792678515120368"
969 19, // base 13: "-10b269549075433c38"
970 18, // base 14: "-4340724c6c71dc7a8"
971 18, // base 15: "-160e2ad3246366808"
972 17, // base 16: "-8000000000000000"
973 17, // base 17: "-33d3d8307b214009"
974 17, // base 18: "-16agh595df825fa8"
975 16, // base 19: "-ba643dci0ffeehi"
976 16, // base 20: "-5cbfjia3fh26ja8"
977 16, // base 21: "-2heiciiie82dh98"
978 16, // base 22: "-1adaibb21dckfa8"
979 15, // base 23: "-i6k448cf4192c3"
980 15, // base 24: "-acd772jnc9l0l8"
981 15, // base 25: "-64ie1focnn5g78"
982 15, // base 26: "-3igoecjbmca688"
983 15, // base 27: "-27c48l5b37oaoq"
984 15, // base 28: "-1bk39f3ah3dmq8"
985 14, // base 29: "-q1se8f0m04isc"
986 14, // base 30: "-hajppbc1fc208"
987 14, // base 31: "-bm03i95hia438"
988 14, // base 32: "-8000000000000"
989 14, // base 33: "-5hg4ck9jd4u38"
990 14, // base 34: "-3tdtk1v8j6tpq"
991 14, // base 35: "-2pijmikexrxp8"
992 14); // base 36: "-1y2p0ij32e8e8"
993
995 64, // base 2: "11111111111111111111....11111111111111111111"
996 41, // base 3: "11112220022122120101211020120210210211220"
997 32, // base 4: "33333333333333333333333333333333"
998 28, // base 5: "2214220303114400424121122430"
999 25, // base 6: "3520522010102100444244423"
1000 23, // base 7: "45012021522523134134601"
1001 22, // base 8: "1777777777777777777777"
1002 21, // base 9: "145808576354216723756"
1003 20, // base 10: "18446744073709551615"
1004 19, // base 11: "335500516a429071284"
1005 18, // base 12: "839365134a2a240713"
1006 18, // base 13: "219505a9511a867b72"
1007 17, // base 14: "8681049adb03db171"
1008 17, // base 15: "2c1d56b648c6cd110"
1009 16, // base 16: "ffffffffffffffff"
1010 16, // base 17: "67979g60f5428010"
1011 16, // base 18: "2d3fgb0b9cg4bd2f"
1012 16, // base 19: "141c8786h1ccaagg"
1013 15, // base 20: "b53bjh07be4dj0f"
1014 15, // base 21: "5e8g4ggg7g56dif"
1015 15, // base 22: "2l4lf104353j8kf"
1016 15, // base 23: "1ddh88h2782i515"
1017 14, // base 24: "l12ee5fn0ji1if"
1018 14, // base 25: "c9c336o0mlb7ef"
1019 14, // base 26: "7b7n2pcniokcgf"
1020 14, // base 27: "4eo8hfam6fllmo"
1021 14, // base 28: "2nc6j26l66rhof"
1022 14, // base 29: "1n3rsh11f098rn"
1023 14, // base 30: "14l9lkmo30o40f"
1024 13, // base 31: "nd075ib45k86f"
1025 13, // base 32: "fvvvvvvvvvvvv"
1026 13, // base 33: "b1w8p7j5q9r6f"
1027 13, // base 34: "7orp63sh4dphh"
1028 13, // base 35: "5g24a25twkwff"
1029 13); // base 36: "3w5e11264sgsf"
1030// BDE_VERIFY pragma: pop // End of macro-created template specializations
1031
1032#undef BSLALG_NUMERICFORMATTERUTIL_INTMAXLEN_ONE
1033
1034 // ==============================================================
1035 // template struct NumericFormatterUtil::IsSupportedFloatingPoint
1036 // ==============================================================
1037
1038template <class TYPE>
1039struct NumericFormatterUtil::IsSupportedFloatingPoint {
1040 private:
1041 // PRIVATE TYPES
1042
1043 /// For more readable lines below.
1044 typedef typename bsl::remove_cv<TYPE>::type NoCvT;
1045 public:
1046 // PUBLIC TYPES
1047 enum Enum {
1048 k_SUPPORTED = bsl::is_same<NoCvT, float>::value ||
1050 };
1051};
1052
1053 // ---------------------------------------------------------
1054 // template struct NumericFormatterUtil::IsSupportedIntegral
1055 // ---------------------------------------------------------
1056
1057template <class TYPE>
1058struct NumericFormatterUtil::IsSupportedIntegral {
1059 private:
1060 // PRIVATE TYPES
1061
1062 /// For more readable lines below.
1063 typedef typename bsl::remove_cv<TYPE>::type NoCvT;
1064 public:
1065 // PUBLIC TYPES
1066 enum Enum {
1067 k_SUPPORTED =
1079 };
1080};
1081
1082 // ------------------------------------------------------
1083 // template struct NumericFormatterUtil::ToCharsMaxLength
1084 // ------------------------------------------------------
1085
1086template <class TYPE, int ARG>
1088 private:
1089 // PRIVATE TYPES
1090
1091 /// This type alias exists to make the lines below shorter, therefore
1092 /// easier to read at a glance.
1093 typedef const bool Cbool;
1094
1095 // PRIVATE CONSTANTS
1096 // Type Related
1097
1098 static Cbool k_INTEGRAL_TYPE = IsSupportedIntegral<TYPE>::k_SUPPORTED;
1099 static Cbool k_FLOAT_TYPE = IsSupportedFloatingPoint<TYPE>::k_SUPPORTED;
1100
1101 static Cbool k_UNSUPPORTED_INPUT_TYPE = !k_INTEGRAL_TYPE && !k_FLOAT_TYPE;
1102
1103 // Argument Related
1104
1105 static Cbool k_ARG_NOT_BASE = (ARG < 2 || ARG > 37);
1106 static Cbool k_ARG_NOT_FORMAT = (ARG != e_FIXED && ARG != e_SCIENTIFIC);
1107
1108 static Cbool k_ARGUMENT_VALUE_IS_WRONG = !( // We negate the valid cases
1109 // for easier human consumption
1110 (ARG == k_MAXLEN_ARG_DEFAULT) ||
1111 // The default value is always valid, regardless of the type
1112
1113 (k_INTEGRAL_TYPE && !k_ARG_NOT_BASE) ||
1114 // Integral types with a valid 'base' value (2-36) are supported
1115
1116 (k_FLOAT_TYPE && !k_ARG_NOT_FORMAT) ||
1117 // Floating point types with a valid 'format' are supported
1118
1119 (k_UNSUPPORTED_INPUT_TYPE && !(k_ARG_NOT_BASE && k_ARG_NOT_FORMAT)));
1120 // In case of an unsupported type we accept any argument value that
1121 // would be supported for any valid (supported) type. This way we
1122 // avoid burdening the user (programmer) with unhelpful extra
1123 // compiler error messages.
1124
1125 // CONTRACT VERIFICATION
1126 BSLMF_ASSERT(false == k_UNSUPPORTED_INPUT_TYPE);
1127 BSLMF_ASSERT(false == k_ARGUMENT_VALUE_IS_WRONG);
1128
1129 public:
1130 // PUBLIC TYPES
1132 k_VALUE = k_INTEGRAL_TYPE
1133 ? IntMaxLen<std::numeric_limits<TYPE>::is_signed,
1134 static_cast<unsigned>(sizeof(TYPE)),
1135 ARG>::k_VALUE
1136 : k_FLOAT_TYPE
1137 ? FltMaxLen<TYPE, ARG>::k_VALUE
1138 : -1 // In case of bad 'TYPE' or 'ARG'
1140};
1141
1142// ============================================================================
1143// INLINE FUNCTION DEFINITIONS
1144// ============================================================================
1145
1146 // ---------------------------
1147 // struct NumericFormatterUtil
1148 // ---------------------------
1149
1150// PPRIVATE CLASS METHODS
1151template <class TYPE>
1152inline
1153char *NumericFormatterUtil::toCharsIntegral(char *first,
1154 char *last,
1155 TYPE value,
1156 int base) BSLS_KEYWORD_NOEXCEPT
1157{
1158 BSLS_ASSERT_SAFE(2 <= base);
1159 BSLS_ASSERT_SAFE(base <= 36);
1160 BSLS_ASSERT_SAFE(first <= last);
1161
1163 BSLMF_ASSERT(sizeof(TYPE) <= sizeof(unsigned long long int));
1164
1165 typedef typename bsl::conditional<(sizeof(unsigned) < sizeof(TYPE)),
1166 unsigned long long int,
1167 unsigned>::type VirtualUnsignedType;
1168
1169 if (first == last) {
1170 // The ISO equivalent of this function allows empty ranges, so we shall
1171 // allow them, too. The early return is necessary due to the sign
1172 // "trick" below.
1173 return 0; // RETURN
1174 }
1175
1176 // Note that if 'value' is a negative value and 'TYPE' is smaller than
1177 // 'VirtualUnsignedType', assigning it here will extend the sign, even
1178 // though 'VirtualUnsignedType' is an unsigned type.
1179
1180 VirtualUnsignedType uValue = value;
1181
1182 if (value < 0) {
1183 uValue = ~uValue + 1; // Absolute value -- note this works even for
1184 // 'numeric_limits<TYPE>::min()'.
1185 *first++ = '-';
1186 }
1187
1188 return toCharsImpl(first, last, uValue, base);
1189}
1190
1191// PUBLIC CLASS METHODS
1192inline
1193char *NumericFormatterUtil::toChars(char *first,
1194 char *last,
1195 char value,
1196 int base) BSLS_KEYWORD_NOEXCEPT
1197{
1198 return toCharsIntegral(first, last, value, base);
1199}
1200
1201inline
1202char *NumericFormatterUtil::toChars(char *first,
1203 char *last,
1204 signed char value,
1205 int base) BSLS_KEYWORD_NOEXCEPT
1206{
1207 return toCharsIntegral(first, last, value, base);
1208}
1209
1210inline
1211char *NumericFormatterUtil::toChars(char *first,
1212 char *last,
1213 unsigned char value,
1214 int base) BSLS_KEYWORD_NOEXCEPT
1215{
1216 return toCharsIntegral(first, last, value, base);
1217}
1218
1219inline
1220char *
1221NumericFormatterUtil::toChars(char *first,
1222 char *last,
1223 signed short int value,
1224 int base) BSLS_KEYWORD_NOEXCEPT
1225{
1226 return toCharsIntegral(first, last, value, base);
1227}
1228
1229inline
1230char *NumericFormatterUtil::toChars(char *first,
1231 char *last,
1232 unsigned short int value,
1233 int base)
1235{
1236 return toCharsIntegral(first, last, value, base);
1237}
1238
1239inline
1240char *NumericFormatterUtil::toChars(char *first,
1241 char *last,
1242 signed int value,
1243 int base) BSLS_KEYWORD_NOEXCEPT
1244{
1245 return toCharsIntegral(first, last, value, base);
1246}
1247
1248inline
1249char *NumericFormatterUtil::toChars(char *first,
1250 char *last,
1251 unsigned int value,
1252 int base) BSLS_KEYWORD_NOEXCEPT
1253{
1254 return toCharsIntegral(first, last, value, base);
1255}
1256
1257inline
1258char *NumericFormatterUtil::toChars(char *first,
1259 char *last,
1260 signed long int value,
1261 int base)
1263{
1264 return toCharsIntegral(first, last, value, base);
1265}
1266
1267inline
1268char *NumericFormatterUtil::toChars(char *first,
1269 char *last,
1270 unsigned long int value,
1271 int base)
1273{
1274 return toCharsIntegral(first, last, value, base);
1275}
1276
1277inline
1278char *NumericFormatterUtil::toChars(char *first,
1279 char *last,
1280 signed long long int value,
1281 int base)
1283{
1284 return toCharsIntegral(first, last, value, base);
1285}
1286
1287inline
1288char *NumericFormatterUtil::toChars(char *first,
1289 char *last,
1290 unsigned long long int value,
1291 int base)
1293{
1294 return toCharsIntegral(first, last, value, base);
1295}
1296
1297inline
1298char *NumericFormatterUtil::toChars(char *first,
1299 char *last,
1300 double value,
1302{
1303 switch (format) {
1304 case e_FIXED: return toCharsDecimal(first, last, value); // RETURN
1305 case e_SCIENTIFIC: return toCharsScientific(first, last, value);// RETURN
1306 }
1307
1308 BSLS_ASSERT_INVOKE_NORETURN("Invalid 'format' argument value.");
1309 return 0; // To avoid warning from AIX xlC
1310}
1311
1312inline
1313char *NumericFormatterUtil::toChars(char *first,
1314 char *last,
1315 float value,
1317{
1318 switch (format) {
1319 case e_FIXED: return toCharsDecimal(first, last, value); // RETURN
1320 case e_SCIENTIFIC: return toCharsScientific(first, last, value);// RETURN
1321 }
1322
1323 BSLS_ASSERT_INVOKE_NORETURN("Invalid 'format' argument value.");
1324 return 0; // To avoid warning from AIX xlC
1325}
1326
1327} // close package namespace
1328
1329
1330#endif
1331
1332// ----------------------------------------------------------------------------
1333// Copyright 2021 Bloomberg Finance L.P.
1334//
1335// Licensed under the Apache License, Version 2.0 (the "License");
1336// you may not use this file except in compliance with the License.
1337// You may obtain a copy of the License at
1338//
1339// http://www.apache.org/licenses/LICENSE-2.0
1340//
1341// Unless required by applicable law or agreed to in writing, software
1342// distributed under the License is distributed on an "AS IS" BASIS,
1343// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1344// See the License for the specific language governing permissions and
1345// limitations under the License.
1346// ----------------------------- END-OF-FILE ----------------------------------
1347
1348/** @} */
1349/** @} */
1350/** @} */
#define BSLALG_NUMERICFORMATTERUTIL_INTMAXLEN_ONE(issigned, bytes, val02, val03, val04, val05, val06, val07, val08, val09, val10, val11, val12, val13, val14, val15, val16, val17, val18, val19, val20, val21, val22, val23, val24, val25, val26, val27, val28, val29, val30, val31, val32, val33, val34, val35, val36)
Definition bslalg_numericformatterutil.h:686
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_ASSERT_INVOKE_NORETURN(X)
Definition bsls_assert.h:1895
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:609
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:632
Definition bdlc_flathashmap.h:1805
Definition bslmf_conditional.h:120
Definition bslmf_isintegral.h:130
Definition bslmf_issame.h:146
remove_const< typenameremove_volatile< t_TYPE >::type >::type type
Definition bslmf_removecv.h:126
Definition bslalg_numericformatterutil.h:1087
ValueType
Definition bslalg_numericformatterutil.h:1131
Namespace struct for free functions supporting to_chars.
Definition bslalg_numericformatterutil.h:385
Format
Definition bslalg_numericformatterutil.h:523
@ e_FIXED
Definition bslalg_numericformatterutil.h:536
@ e_SCIENTIFIC
Definition bslalg_numericformatterutil.h:535