8#ifndef INCLUDED_BDLJSN_NUMBERUTIL
9#define INCLUDED_BDLJSN_NUMBERUTIL
153#include <bdlscm_version.h>
167#include <bsl_cerrno.h>
168#include <bsl_string.h>
169#include <bsl_string_view.h>
170#include <bsl_type_traits.h>
171#include <bsl_iostream.h>
176struct NumberUtil_ImpUtil;
285 template <
class t_INTEGER_TYPE>
286 static int asInteger(t_INTEGER_TYPE *result,
322template <
class t_TYPE>
335struct NumberUtil_ImpUtil {
339 k_EXPONENT_OUT_OF_RANGE = -1
349 static int appendDigits(bsls::Types::Uint64 *result,
350 bsls::Types::Uint64 startingValue,
351 const bsl::string_view& digits);
355 static int asInteger(bsls::Types::Uint64 *result,
356 const bsl::string_view& value);
357 template <class t_INTEGER_TYPE>
358 static int asInteger(t_INTEGER_TYPE *result,
359 const bsl::string_view& value);
366 template <class t_INTEGER_TYPE>
367 static int asIntegerDispatchImp(
368 t_INTEGER_TYPE *result,
369 const bsl::string_view& value,
370 bslmf::SelectTraitCase<NumberUtil_IsSigned>);
371 template <class t_INTEGER_TYPE>
372 static int asIntegerDispatchImp(t_INTEGER_TYPE *result,
373 const bsl::string_view& value,
374 bslmf::SelectTraitCase<>);
430 static void decompose(
433 bsl::string_view *integer,
434 bsl::string_view *fraction,
435 bsl::string_view *exponent,
436 bsl::string_view *significantDigits,
437 bsls::Types::Int64 *significantDigitsBias,
438 bsl::string_view::size_type *significantDigitsDotOffset,
439 const bsl::string_view& value);
448 static void logUnparseableJsonNumber(const bsl::string_view& value);
460double NumberUtil::asDouble(const bsl::string_view& value)
462 BSLS_ASSERT(NumberUtil::isValidNumber(value));
466 int rc = bdlb::NumericParseUtil::parseDouble(&result, value);
467 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(0 != rc && ERANGE != rc)) {
476 NumberUtil_ImpUtil::logUnparseableJsonNumber(value);
477 return bsl::numeric_limits<double>::quiet_NaN();
483float NumberUtil::asFloat(const bsl::string_view& value)
485 return static_cast<float>(asDouble(value));
489int NumberUtil::asInt(int *result, const bsl::string_view& value)
491 return asInteger(result, value);
495int NumberUtil::asInt64(Int64 *result, const bsl::string_view& value)
497 return asInteger(result, value);
501int NumberUtil::asUint(unsigned int *result, const bsl::string_view& value)
503 return asInteger(result, value);
506template <class t_INTEGER_TYPE>
507int NumberUtil::asInteger(t_INTEGER_TYPE *result,
508 const bsl::string_view& value)
510 BSLMF_ASSERT((bsl::is_integral<t_INTEGER_TYPE>::value &&
511 (sizeof(t_INTEGER_TYPE) <= 8) &&
512 !bsl::is_same<t_INTEGER_TYPE, bool>::value));
513 return NumberUtil_ImpUtil::asInteger(result, value);
521int NumberUtil_ImpUtil::asInteger(bsls::Types::Uint64 *result,
522 const bsl::string_view& value)
524 return NumberUtil::asUint64(result, value);
527template <class t_TYPE>
528int NumberUtil_ImpUtil::asInteger(t_TYPE *result,
529 const bsl::string_view& value)
531 BSLMF_ASSERT(bsl::is_integral<t_TYPE>::value);
533 typedef bslmf::SelectTrait<t_TYPE, NumberUtil_IsSigned> Selection;
534 return NumberUtil_ImpUtil::asIntegerDispatchImp(result,
539template <class t_INTEGER_TYPE>
540int NumberUtil_ImpUtil::asIntegerDispatchImp(
541 t_INTEGER_TYPE *result,
542 const bsl::string_view& value,
543 bslmf::SelectTraitCase<NumberUtil_IsSigned>)
545 BSLMF_ASSERT(bsl::is_integral<t_INTEGER_TYPE>::value);
546 BSLMF_ASSERT(bsl::numeric_limits<t_INTEGER_TYPE>::is_signed);
548 BSLS_ASSERT(NumberUtil::isValidNumber(value));
550 bsl::string_view positiveValue = value;
553 if ('-' == value[0]) {
555 positiveValue.remove_prefix(1);
561 const bsls::Types::Uint64 maxValue = static_cast<bsls::Types::Uint64>(
562 bsl::numeric_limits<t_INTEGER_TYPE>::max());
564 bsls::Types::Uint64 tmp;
566 const int rc = NumberUtil::asUint64(&tmp, positiveValue);
569 if (tmp > maxValue + 1) {
570 *result = bsl::numeric_limits<t_INTEGER_TYPE>::min();
571 return NumberUtil::k_UNDERFLOW;
573 *result = static_cast<t_INTEGER_TYPE>(tmp * -1ll );
576 if (tmp > maxValue) {
577 *result =
static_cast<t_INTEGER_TYPE
>(maxValue);
580 *result =
static_cast<t_INTEGER_TYPE
>(tmp);
585template <
class t_INTEGER_TYPE>
586int NumberUtil_ImpUtil::asIntegerDispatchImp(t_INTEGER_TYPE *result,
591 BSLMF_ASSERT(!bsl::numeric_limits<t_INTEGER_TYPE>::is_signed);
599 int rc = NumberUtil::asUint64(&tmp, value);
601 static_cast<Uint64
>(bsl::numeric_limits<t_INTEGER_TYPE>::max())) {
602 *result = bsl::numeric_limits<t_INTEGER_TYPE>::max();
603 return NumberUtil::k_OVERFLOW;
605 *result =
static_cast<t_INTEGER_TYPE
>(tmp);
Definition bdldfp_decimal.h:1834
Definition bslstl_stringview.h:441
Definition bslstl_string.h:1281
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdljsn_error.h:143
Definition bdljsn_numberutil.h:324
Definition bdljsn_numberutil.h:186
static bool isIntegralNumber(const bsl::string_view &value)
bsls::Types::Uint64 Uint64
Definition bdljsn_numberutil.h:189
static int asUint64(Uint64 *result, const bsl::string_view &value)
static int asDecimal64Exact(bdldfp::Decimal64 *result, const bsl::string_view &value)
static int asInteger(t_INTEGER_TYPE *result, const bsl::string_view &value)
Definition bdljsn_numberutil.h:507
static bool isValidNumber(const bsl::string_view &value)
static void stringify(bsl::string *result, Uint64 value)
static void stringify(bsl::string *result, const bdldfp::Decimal64 &value)
static float asFloat(const bsl::string_view &value)
Definition bdljsn_numberutil.h:483
static int asUint(unsigned int *result, const bsl::string_view &value)
Definition bdljsn_numberutil.h:501
static double asDouble(const bsl::string_view &value)
Definition bdljsn_numberutil.h:460
static void stringify(bsl::string *result, Int64 value)
@ k_UNDERFLOW
Definition bdljsn_numberutil.h:196
@ k_NOT_INTEGRAL
Definition bdljsn_numberutil.h:197
@ k_INEXACT
Definition bdljsn_numberutil.h:200
@ k_OVERFLOW
Definition bdljsn_numberutil.h:195
static bool areEqual(const bsl::string_view &lhs, const bsl::string_view &rhs)
bsls::Types::Int64 Int64
Definition bdljsn_numberutil.h:190
static bdldfp::Decimal64 asDecimal64(const bsl::string_view &value)
static void stringify(bsl::string *result, double value)
static int asInt(int *result, const bsl::string_view &value)
Definition bdljsn_numberutil.h:489
static int asInt64(Int64 *result, const bsl::string_view &value)
Definition bdljsn_numberutil.h:495
Definition bslmf_integralconstant.h:244
Definition bslmf_isintegral.h:130
Definition bslmf_selecttrait.h:438
unsigned long long Uint64
Definition bsls_types.h:137
long long Int64
Definition bsls_types.h:132