9#ifndef INCLUDED_BSLFMT_FORMATTERINTEGRALBASE
10#define INCLUDED_BSLFMT_FORMATTERINTEGRALBASE
62#include <bslscm_version.h>
89template <
class t_VALUE_TYPE>
92 template <
class t_CHAR>
103 template <
class t_CHAR>
113 template <
class t_CHAR>
123 template <
class t_CHAR>
133 template <
class t_CHAR>
143 template <
class t_CHAR>
153 template <
class t_CHAR>
170template <
class t_VALUE,
class t_CHAR>
179 Specification d_spec;
185 template <
class t_ACTUAL_VALUE_TYPE>
186 bool isInRange(
const t_ACTUAL_VALUE_TYPE& value)
const;
193 template <
class t_PARSE_CONTEXT>
195 t_PARSE_CONTEXT& parseContext);
204 template <
class t_ACTUAL_VALUE_TYPE>
207 t_ACTUAL_VALUE_TYPE value)
const;
216 template <
class t_ACTUAL_VALUE_TYPE>
219 t_ACTUAL_VALUE_TYPE value)
const;
227 template <
class t_FORMAT_CONTEXT>
229 const char *prefixBegin,
230 const char *prefixEnd,
231 const t_CHAR *valueBegin,
232 const t_CHAR *valueEnd,
233 t_FORMAT_CONTEXT& formatContext)
const;
247template <
class t_VALUE_TYPE>
248template <
class t_CHAR>
257template <
class t_CHAR>
266template <
class t_CHAR>
275template <
class t_CHAR>
284template <
class t_CHAR>
293template <
class t_CHAR>
302template <
class t_CHAR>
315template <
class t_VALUE,
class t_CHAR>
316template <
class t_ACTUAL_VALUE_TYPE>
319 const t_ACTUAL_VALUE_TYPE& value)
const
321 const long double min =
322 static_cast<long double>(std::numeric_limits<t_CHAR>::min());
323 const long double max =
324 static_cast<long double>(std::numeric_limits<t_CHAR>::max());
325 const long double doubleValue =
static_cast<long double>(value);
327 return min <= doubleValue && max >= doubleValue;
330template <
class t_VALUE,
class t_CHAR>
331template <
class t_PARSE_CONTEXT>
336 d_spec.
parse(&parseContext,
339 if (d_spec.localeSpecificFlag()) {
341 bsl::format_error(
"Formatting L specifier not supported"));
344 if (d_spec.formatType() == Specification::e_CHARACTER_ESCAPED)
345 BSLS_THROW(bsl::format_error(
"Character escaping not supported"));
347 return parseContext.begin();
350template <
class t_VALUE,
class t_CHAR>
351template <
class t_ACTUAL_VALUE_TYPE>
356 t_ACTUAL_VALUE_TYPE value)
const
363 char *prefixEnd = prefixStorage;
368 switch (d_spec.sign()) {
369 case Specification::e_SIGN_POSITIVE: {
373 case Specification::e_SIGN_SPACE: {
396 const char *formatPrefix = 0;
397 int formatPrefixLength = 0;
398 switch (d_spec.formatType()) {
399 case Specification::e_INTEGRAL_BINARY: {
400 if (d_spec.alternativeFlag()) {
402 formatPrefixLength = 2;
405 case Specification::e_INTEGRAL_BINARY_UC: {
406 if (d_spec.alternativeFlag()) {
408 formatPrefixLength = 2;
411 case Specification::e_INTEGRAL_DECIMAL:
412 case Specification::e_INTEGRAL_CHARACTER: {
415 case Specification::e_INTEGRAL_OCTAL: {
416 if (d_spec.alternativeFlag() && 0 != value) {
418 formatPrefixLength = 1;
421 case Specification::e_INTEGRAL_HEX: {
422 if (d_spec.alternativeFlag()) {
424 formatPrefixLength = 2;
427 case Specification::e_INTEGRAL_HEX_UC: {
428 if (d_spec.alternativeFlag()) {
430 formatPrefixLength = 2;
434 BSLS_THROW(bsl::format_error(
"Invalid integer format type"));
438 prefixEnd = bsl::copy(formatPrefix,
439 formatPrefix + formatPrefixLength,
447template <
class t_VALUE,
class t_CHAR>
448template <
class t_ACTUAL_VALUE_TYPE>
451 t_CHAR *valueStorage,
453 t_ACTUAL_VALUE_TYPE value)
const
457 typedef BloombergLP::bslalg::NumericFormatterUtil NFUtil;
462 switch (d_spec.formatType()) {
463 case Specification::e_INTEGRAL_BINARY: {
466 case Specification::e_INTEGRAL_BINARY_UC: {
469 case Specification::e_INTEGRAL_CHARACTER: {
470 if (isInRange(value)) {
471 *valueStorage =
static_cast<t_CHAR
>(value);
472 return valueStorage + 1;
475 BSLS_THROW(bsl::format_error(
"Integer value is not in the range "
476 "of character representation"));
479 case Specification::e_INTEGRAL_DECIMAL: {
482 case Specification::e_INTEGRAL_OCTAL: {
485 case Specification::e_INTEGRAL_HEX: {
488 case Specification::e_INTEGRAL_HEX_UC: {
491 case Specification::e_POINTER_HEX: {
494 case Specification::e_POINTER_HEX_UC: {
498 BSLS_THROW(bsl::format_error(
"Invalid integer format type"));
507 const int maxValueSize =
508 NFUtil::ToCharsMaxLength<t_ACTUAL_VALUE_TYPE, 2>::k_VALUE;
511 char valueBuf[maxValueSize];
512 char *valueEnd = NFUtil::toChars(valueBuf,
513 valueBuf + maxValueSize,
517 if (Specification::e_INTEGRAL_HEX_UC == d_spec.formatType() ||
518 Specification::e_POINTER_HEX_UC == d_spec.formatType()) {
524 BloombergLP::bslfmt::FormatterCharUtil<char>::toUpper(valueBuf,
528 t_CHAR *convertedValueEnd = valueStorage;
531 BloombergLP::bslfmt::FormatterCharUtil<t_CHAR>::outputFromChar(
536 return convertedValueEnd;
539template <
class t_VALUE,
class t_CHAR>
540template <
class t_FORMAT_CONTEXT>
542typename t_FORMAT_CONTEXT::iterator
544 const char *prefixBegin,
545 const char *prefixEnd,
546 const t_CHAR *valueBegin,
547 const t_CHAR *valueEnd,
548 t_FORMAT_CONTEXT& formatContext)
const
554 const Specification& parsedSpec = this->specification();
555 Specification spec(parsedSpec);
556 spec.postprocess(formatContext);
558 NumericValue finalWidth(spec.postprocessedWidth());
560 bool representAsChar = Specification::e_INTEGRAL_CHARACTER ==
564 std::ptrdiff_t leftPadFillerCopiesNum = 0;
565 std::ptrdiff_t rightPadFillerCopiesNum = 0;
566 std::ptrdiff_t zeroPadFillerCopiesNum = 0;
568 std::ptrdiff_t commonLength = representAsChar
569 ? 1 + (prefixEnd - prefixBegin)
570 : (valueEnd - valueBegin) +
571 (prefixEnd - prefixBegin);
574 if (finalWidth.category() != NumericValue::e_DEFAULT &&
575 commonLength < finalWidth.value()) {
579 typedef typename Spec::FormatType FormatType;
581 typename Spec::Alignment alignment = spec.
alignment();
583 if (Spec::e_ALIGN_DEFAULT == alignment && spec.zeroPaddingFlag()) {
586 zeroPadFillerCopiesNum = finalWidth.value() - commonLength;
591 const FormatType fType = d_spec.formatType();
594 &rightPadFillerCopiesNum,
598 (Spec::e_INTEGRAL_CHARACTER == fType ||
599 Spec::e_CHARACTER_CHARACTER == fType ||
600 Spec::e_BOOLEAN_STRING == fType)
602 : Spec::e_ALIGN_RIGHT);
608 typename t_FORMAT_CONTEXT::iterator outIterator = formatContext.out();
612 const StringView pad(spec.filler(), spec.numFillerCharacters());
613 outIterator =
PadUtil::pad(outIterator, leftPadFillerCopiesNum, pad);
623 outIterator =
PadUtil::pad(outIterator, zeroPadFillerCopiesNum,
'0');
627 outIterator = bsl::copy(valueBegin, valueEnd, outIterator);
631 outIterator =
PadUtil::pad(outIterator, rightPadFillerCopiesNum, pad);
636template <
class t_VALUE,
class t_CHAR>
Definition bslstl_stringview.h:471
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_THROW(X)
Definition bsls_exceptionutil.h:374
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_CONSTEXPR_CPP20
Definition bsls_keyword.h:645
Definition bdlat_valuetypefunctions.h:939
Definition bslfmt_enablestreamedformatter.h:130
Definition bslfmt_padutil.h:151
static void computePadding(std::ptrdiff_t *leftPadding, std::ptrdiff_t *rightPadding, const NumericValue &widthValue, std::ptrdiff_t contentWidth, Alignment alignment, Alignment defaultAlign=Enums::e_ALIGN_LEFT)
Definition bslfmt_padutil.h:352
static t_ITERATOR pad(t_ITERATOR out, std::ptrdiff_t padWidth, const bsl::string_view &filler)
Definition bslfmt_padutil.h:401