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