8#ifndef INCLUDED_BDLJSN_NUMBERUTIL
9#define INCLUDED_BDLJSN_NUMBERUTIL
154#include <bdlscm_version.h>
169#include <bsl_cerrno.h>
170#include <bsl_string.h>
171#include <bsl_string_view.h>
172#include <bsl_type_traits.h>
173#include <bsl_iostream.h>
178struct NumberUtil_ImpUtil;
310 template <
class t_INTEGER_TYPE>
311 static int asInteger(t_INTEGER_TYPE *result,
349template <
class t_TYPE>
364struct NumberUtil_ImpUtil {
368 k_EXPONENT_OUT_OF_RANGE = -1
378 static int appendDigits(bsls::Types::Uint64 *result,
379 bsls::Types::Uint64 startingValue,
380 const bsl::string_view& digits);
384 static int asInteger(bsls::Types::Uint64 *result,
385 const bsl::string_view& value);
386 template <class t_INTEGER_TYPE>
387 static int asInteger(t_INTEGER_TYPE *result,
388 const bsl::string_view& value);
395 template <class t_INTEGER_TYPE>
396 static int asIntegerDispatchImp(
397 t_INTEGER_TYPE *result,
398 const bsl::string_view& value,
399 bslmf::SelectTraitCase<NumberUtil_IsSigned>);
400 template <class t_INTEGER_TYPE>
401 static int asIntegerDispatchImp(t_INTEGER_TYPE *result,
402 const bsl::string_view& value,
403 bslmf::SelectTraitCase<>);
461 static void decompose(
464 bsl::string_view *integer,
465 bsl::string_view *fraction,
466 bsl::string_view *exponent,
467 bsl::string_view *significantDigits,
468 bsls::Types::Int64 *significantDigitsBias,
469 bsl::string_view::size_type *significantDigitsDotOffset,
470 const bsl::string_view& value);
480 static void logUnparseableJsonNumber(const bsl::string_view& value);
494double NumberUtil::asDouble(const bsl::string_view& value)
496 BSLS_ASSERT(NumberUtil::isValidNumber(value));
500 int rc = bdlb::NumericParseUtil::parseDouble(&result, value);
501 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(0 != rc && ERANGE != rc)) {
509 BSLS_ASSERT_UNREACHABLE("Unparseable JSON number");
510 NumberUtil_ImpUtil::logUnparseableJsonNumber(value);
511 return bsl::numeric_limits<double>::quiet_NaN();
517float NumberUtil::asFloat(const bsl::string_view& value)
519 return static_cast<float>(asDouble(value));
523int NumberUtil::asShort(short *result, const bsl::string_view& value)
525 return asInteger(result, value);
529int NumberUtil::asInt(int *result, const bsl::string_view& value)
531 return asInteger(result, value);
535int NumberUtil::asLong(long *result, const bsl::string_view& value)
537 return asInteger(result, value);
541int NumberUtil::asLonglong(long long *result, const bsl::string_view& value)
543 return asInteger(result, value);
547int NumberUtil::asInt64(Int64 *result, const bsl::string_view& value)
549 return asInteger(result, value);
553int NumberUtil::asUshort(unsigned short *result, const bsl::string_view& value)
555 return asInteger(result, value);
559int NumberUtil::asUint(unsigned int *result, const bsl::string_view& value)
561 return asInteger(result, value);
565int NumberUtil::asUlong(unsigned long *result, const bsl::string_view& value)
567 return asInteger(result, value);
571int NumberUtil::asUlonglong(unsigned long long *result,
572 const bsl::string_view& value)
574 return asInteger(result, value);
577template <class t_INTEGER_TYPE>
578int NumberUtil::asInteger(t_INTEGER_TYPE *result,
579 const bsl::string_view& value)
581 BSLMF_ASSERT((bsl::is_integral<t_INTEGER_TYPE>::value &&
582 (sizeof(t_INTEGER_TYPE) <= 8) &&
583 !bsl::is_same<t_INTEGER_TYPE, bool>::value));
584 return NumberUtil_ImpUtil::asInteger(result, value);
594int NumberUtil_ImpUtil::asInteger(bsls::Types::Uint64 *result,
595 const bsl::string_view& value)
597 return NumberUtil::asUint64(result, value);
600template <class t_TYPE>
601int NumberUtil_ImpUtil::asInteger(t_TYPE *result,
602 const bsl::string_view& value)
604 BSLMF_ASSERT(bsl::is_integral<t_TYPE>::value);
606 typedef bslmf::SelectTrait<t_TYPE, NumberUtil_IsSigned> Selection;
607 return NumberUtil_ImpUtil::asIntegerDispatchImp(result,
612template <class t_INTEGER_TYPE>
613int NumberUtil_ImpUtil::asIntegerDispatchImp(
614 t_INTEGER_TYPE *result,
615 const bsl::string_view& value,
616 bslmf::SelectTraitCase<NumberUtil_IsSigned>)
618 BSLMF_ASSERT(bsl::is_integral<t_INTEGER_TYPE>::value);
619 BSLMF_ASSERT(bsl::numeric_limits<t_INTEGER_TYPE>::is_signed);
621 BSLS_ASSERT(NumberUtil::isValidNumber(value));
623 bsl::string_view positiveValue = value;
626 if ('-' == value[0]) {
628 positiveValue.remove_prefix(1);
634 const bsls::Types::Uint64 maxValue = static_cast<bsls::Types::Uint64>(
635 bsl::numeric_limits<t_INTEGER_TYPE>::max());
637 bsls::Types::Uint64 tmp;
639 const int rc = NumberUtil::asUint64(&tmp, positiveValue);
642 if (tmp > maxValue + 1) {
643 *result = bsl::numeric_limits<t_INTEGER_TYPE>::min();
644 return NumberUtil::k_UNDERFLOW;
646 *result = static_cast<t_INTEGER_TYPE>(tmp * -1ll );
649 if (tmp > maxValue) {
650 *result =
static_cast<t_INTEGER_TYPE
>(maxValue);
653 *result =
static_cast<t_INTEGER_TYPE
>(tmp);
658template <
class t_INTEGER_TYPE>
659int NumberUtil_ImpUtil::asIntegerDispatchImp(t_INTEGER_TYPE *result,
664 BSLMF_ASSERT(!bsl::numeric_limits<t_INTEGER_TYPE>::is_signed);
672 int rc = NumberUtil::asUint64(&tmp, value);
674 static_cast<Uint64
>(bsl::numeric_limits<t_INTEGER_TYPE>::max())) {
675 *result = bsl::numeric_limits<t_INTEGER_TYPE>::max();
676 return NumberUtil::k_OVERFLOW;
678 *result =
static_cast<t_INTEGER_TYPE
>(tmp);
Definition bdldfp_decimal.h:1890
Definition bslstl_stringview.h:471
Definition bslstl_string.h:1252
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdljsn_error.h:142
Definition bdljsn_numberutil.h:351
Definition bdljsn_numberutil.h:190
static bool isIntegralNumber(const bsl::string_view &value)
bsls::Types::Uint64 Uint64
Definition bdljsn_numberutil.h:193
static int asUint64(Uint64 *result, const bsl::string_view &value)
static int asDecimal64Exact(bdldfp::Decimal64 *result, const bsl::string_view &value)
@ k_UNDERFLOW
Definition bdljsn_numberutil.h:200
@ k_NOT_INTEGRAL
Definition bdljsn_numberutil.h:201
@ k_INEXACT
Definition bdljsn_numberutil.h:204
@ k_OVERFLOW
Definition bdljsn_numberutil.h:199
static int asInteger(t_INTEGER_TYPE *result, const bsl::string_view &value)
Definition bdljsn_numberutil.h:578
static bool isValidNumber(const bsl::string_view &value)
static int asUlonglong(unsigned long long *result, const bsl::string_view &value)
Definition bdljsn_numberutil.h:571
static void stringify(bsl::string *result, const bdldfp::Decimal64 &value)
static float asFloat(const bsl::string_view &value)
Definition bdljsn_numberutil.h:517
static int asUint(unsigned int *result, const bsl::string_view &value)
Definition bdljsn_numberutil.h:559
static double asDouble(const bsl::string_view &value)
Definition bdljsn_numberutil.h:494
static int asLonglong(long long *result, const bsl::string_view &value)
Definition bdljsn_numberutil.h:541
static bool areEqual(const bsl::string_view &lhs, const bsl::string_view &rhs)
bsls::Types::Int64 Int64
Definition bdljsn_numberutil.h:194
static bdldfp::Decimal64 asDecimal64(const bsl::string_view &value)
static int asLong(long *result, const bsl::string_view &value)
Definition bdljsn_numberutil.h:535
static void stringify(bsl::string *result, double value)
static int asUlong(unsigned long *result, const bsl::string_view &value)
Definition bdljsn_numberutil.h:565
static int asShort(short *result, const bsl::string_view &value)
Definition bdljsn_numberutil.h:523
static int asInt(int *result, const bsl::string_view &value)
Definition bdljsn_numberutil.h:529
static void stringify(bsl::string *result, long long value)
static void stringify(bsl::string *result, unsigned long long value)
static int asUshort(unsigned short *result, const bsl::string_view &value)
Definition bdljsn_numberutil.h:553
static int asInt64(Int64 *result, const bsl::string_view &value)
Definition bdljsn_numberutil.h:547
Definition bslmf_integralconstant.h:261
Definition bslmf_isintegral.h:140
Definition bslmf_selecttrait.h:438
unsigned long long Uint64
Definition bsls_types.h:139
long long Int64
Definition bsls_types.h:134