BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdljsn_numberutil.h
Go to the documentation of this file.
1/// @file bdljsn_numberutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdljsn_numberutil.h -*-C++-*-
8#ifndef INCLUDED_BDLJSN_NUMBERUTIL
9#define INCLUDED_BDLJSN_NUMBERUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdljsn_numberutil bdljsn_numberutil
15/// @brief Provide utilities converting between JSON text and numeric types.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdljsn
19/// @{
20/// @addtogroup bdljsn_numberutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdljsn_numberutil-purpose"> Purpose</a>
25/// * <a href="#bdljsn_numberutil-classes"> Classes </a>
26/// * <a href="#bdljsn_numberutil-description"> Description </a>
27/// * <a href="#bdljsn_numberutil-usage"> Usage </a>
28/// * <a href="#bdljsn_numberutil-example-1-interpreting-a-json-number-string"> Example 1: Interpreting a JSON Number String </a>
29///
30/// # Purpose {#bdljsn_numberutil-purpose}
31/// Provide utilities converting between JSON text and numeric types.
32///
33/// # Classes {#bdljsn_numberutil-classes}
34///
35/// - bdljsn::NumberUtil: conversion between JSON text and numeric types
36///
37/// # Description {#bdljsn_numberutil-description}
38/// This component provides a struct, `bdljsn::NumberUtil`, that is
39/// a namespace for a suite of functions for working with the JSON number text
40/// format. `bdljsn::NumberUtil` provides a function `isValidNumber` to
41/// determine whether a string is a valid JSON number. Many of the other
42/// operations in this component have, as a precondition, that `isValidNumber`
43/// is `true` for the text. For information about the JSON number specification
44/// and additional background on the behavior of numbers in `bdljsn` see
45/// {bdljsn_jsonnumber}.
46///
47/// Many of the operations in this component have `isValidNumber` as a
48/// precondition in order to provide simpler and more efficient implementations.
49/// In the context of `JsonNumber`, the text will always be validated prior to
50/// performing other operations.
51///
52/// ## Usage {#bdljsn_numberutil-usage}
53///
54///
55/// This section illustrates intended use of this component.
56///
57/// ### Example 1: Interpreting a JSON Number String {#bdljsn_numberutil-example-1-interpreting-a-json-number-string}
58///
59///
60/// This example demonstrates using `bdljsn::NumberUtil` to work with a JSON
61/// number string. Imagine we are given and array of strings for numbers we
62/// expect to be integers, for each string we want to render some properties for
63/// that number.
64///
65/// First, we define an interesting set of example data:
66/// @code
67/// const char *EXAMPLE_DATA[] = {
68/// // value converted int value & notes
69/// // ----- ---------------------------
70/// "NaN", // invalid number
71/// "INF", // invalid number
72/// "1", // 1, exact
73/// "1.5", // 1, not an integer
74/// "-9223372036854775809", // INT64_MIN, underflow
75/// "1.5e27", // INT64_MAX, overflow
76/// };
77/// const int NUM_DATA = sizeof(EXAMPLE_DATA) / sizeof(*EXAMPLE_DATA);
78/// @endcode
79/// Then, for each number, we first check whether it is a valid JSON Number
80/// (note that the behavior for the other methods is undefined unless the text
81/// is a valid JSON Number):
82/// @code
83/// for (int i = 0; i < NUM_DATA; ++i) {
84/// const char *EXAMPLE = EXAMPLE_DATA[i];
85/// bsl::cout << "\"" << EXAMPLE << "\": " << bsl::endl;
86/// if (!bdljsn::NumberUtil::isValidNumber(EXAMPLE)) {
87/// bsl::cout << " * is NOT a JSON Number" << bsl::endl;
88/// continue; // CONTINUE
89/// }
90/// @endcode
91/// Next we verify that the number is an integer. This will return an accurate
92/// result even when the integer cannot be represented.
93/// @code
94/// if (bdljsn::NumberUtil::isIntegralNumber(EXAMPLE)) {
95/// bsl::cout << " * is an integer" << bsl::endl;
96/// }
97/// else {
98/// bsl::cout << " * is not an integer" << bsl::endl;
99/// }
100/// @endcode
101/// Finally, we convert that number to an integer:
102/// @code
103/// bsls::Types::Int64 value;
104/// int rc = bdljsn::NumberUtil::asInt64(&value, EXAMPLE);
105///
106/// bsl::cout << " * value: " << value;
107///
108/// if (bdljsn::NumberUtil::k_NOT_INTEGRAL == rc) {
109/// bsl::cout << " (truncated)";
110/// }
111/// if (bdljsn::NumberUtil::k_OVERFLOW == rc) {
112/// bsl::cout << " (overflow)";
113/// }
114/// if (bdljsn::NumberUtil::k_UNDERFLOW == rc) {
115/// bsl::cout << " (underflow)";
116/// }
117/// bsl::cout << bsl::endl;
118/// }
119/// @endcode
120/// This will output the text:
121/// @code
122/// "NaN":
123/// * is NOT a JSON Number
124/// "INF":
125/// * is NOT a JSON Number
126/// "1":
127/// * is an integer
128/// * value: 1
129/// "1.5":
130/// * is not an integer
131/// * value: 1 (truncated)
132/// "-9223372036854775809":
133/// * is an integer
134/// * value: -9223372036854775808 (underflow)
135/// "1.5e27":
136/// * is an integer
137/// * value: 9223372036854775807 (overflow)
138/// @endcode
139/// @}
140/** @} */
141/** @} */
142
143/** @addtogroup bdl
144 * @{
145 */
146/** @addtogroup bdljsn
147 * @{
148 */
149/** @addtogroup bdljsn_numberutil
150 * @{
151 */
152
153#include <bdlscm_version.h>
154
155#include <bdlb_float.h>
157#include <bdldfp_decimal.h>
159
160#include <bsla_nodiscard.h>
161#include <bslmf_assert.h>
162#include <bslmf_selecttrait.h>
163#include <bsls_assert.h>
164#include <bsls_performancehint.h>
165#include <bsls_types.h>
166
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>
172
173
174namespace bdljsn {
175
176struct NumberUtil_ImpUtil;
177
178 // =================
179 // struct NumberUtil
180 // =================
181
182/// This `struct` provides a namespace for a suite of functions that convert
183/// between a JSON formated numeric value and various numerical types. The
184/// valid syntax for a JSON formatted numeric value is spelled out in
185/// `https://www.rfc-editor.org/rfc/rfc8259#section-6`.
187
188 // PUBLIC TYPES
191
192 // PUBLIC CONSTANTS
193 enum {
194 // special integer conversion status values
195 k_OVERFLOW = -1, // the number is above the representable range
196 k_UNDERFLOW = -2, // the number is below the representable range
197 k_NOT_INTEGRAL = -3, // the number is not an integer
198
199 // special exact Decimal64 conversion status values
200 k_INEXACT = -4
201 };
202
203 // CLASS METHODS
204
205 // validation
206
207 /// Return `true` if the specified `value` is a valid integral JSON
208 /// number. Note that this function may return `true` even if `value`
209 /// cannot be represented in a fundamental integral type. The behavior
210 /// is undefined unless `isValidNumber(value)` is `true`.
211 static bool isIntegralNumber(const bsl::string_view& value);
212
213 /// Return `true` if the specified `value` is a valid JSON number. Note
214 /// that this function may return `true` even if `value` cannot be
215 /// represented in any particular number type.
216 static bool isValidNumber(const bsl::string_view& value);
217
218 // basic floating point conversions
219
220 /// Return the closest floating point representation to the specified
221 /// `value`. If `value` is outside the representable range, return +INF or
222 /// -INF (as appropriate). The behavior is undefined unless
223 /// `isValidNumber(value)` is `true`.
225 static double asDouble(const bsl::string_view& value);
226 static float asFloat(const bsl::string_view& value);
227
228 // exact floating point conversions
229
230 /// Load the specified `result` with the specified `value`, even if a
231 /// non-zero status is returned. Return 0 if `value` can be represented
232 /// exactly, and return `k_INEXACT` and load `result` with the closest
233 /// approximation of `value` if `value` cannot be represented exactly.
234 /// A `value` can be represented exactly as a `Decimal64` if, for the
235 /// significand and exponent of `value`,
236 /// `abs(significand) <= 9,999,999,999,999,999` and
237 /// `-398 <= exponent <= 369`. The behavior is undefined unless
238 /// `isValidNumber(value)` is `true`.
240 const bsl::string_view& value);
241
242 // typed integer conversions
243
244 static int asInt(int *result, const bsl::string_view& value);
245 static int asInt64(Int64 *result, const bsl::string_view& value);
246 static int asUint(unsigned int *result, const bsl::string_view& value);
247 /// Load the specified `result` with the specified `value`, even if a
248 /// non-zero status is returned (truncating fractional digits if
249 /// necessary). Return 0 on success, `k_OVERFLOW` if `value` is larger
250 /// than can be represented by `result`, `k_UNDERFLOW` if `value` is
251 /// smaller than can be represented by `result`, and `k_NOT_INTEGRAL` if
252 /// `value` is not an integral number (i.e., there is a fractional part).
253 /// For underflow, `result` will be loaded with the minimum representable
254 /// value, for overflow, `result` will be loaded with the maximum
255 /// representable value, for non-integral values `result` will be loaded
256 /// with the integer part of `value` (truncating the fractional part of
257 /// `value`). The behavior is undefined unless `isValidNumber(value)` is
258 /// `true`. Note that this operation will correctly handle exponents
259 /// (e.g., a `value` of "0.00000000000000000001e20" will produce a `result`
260 /// of 1).
261 static int asUint64(Uint64 *result, const bsl::string_view& value);
262
263 // generic integer conversion
264
265 /// Load into the specified `result` (of the template parameter type
266 /// `t_INTEGER_TYPE`) with the specified `value`, even if a non-zero
267 /// status is returned (truncating fractional digits if necessary).
268 /// Return 0 on success, `k_OVERFLOW` if `value` is larger than can be
269 /// represented by `result`, `k_UNDERFLOW` if `value` is smaller than
270 /// can be represented by `result`, and `k_NOT_INTEGRAL` if `value` is
271 /// not an integral number (i.e., there is a fractional part). For
272 /// underflow, `result` will be loaded with the minimum representable
273 /// value, for overflow, `result` will be loaded with the maximum
274 /// representable value, for non-integral values `result` will be loaded
275 /// with the integer part of `value` (truncating the value to the
276 /// nearest integer). If the result is not an integer and also either
277 /// overflows or underflows, it is treated as an overflow or underflow
278 /// (respectively). The (template parameter) `t_INTEGER_TYPE` shall be
279 /// either a signed or unsigned integer type (that is not `bool`) where
280 /// `sizeof(t_INTEGER_TYPE) <= 8`. The behavior is undefined unless
281 /// `isValidNumber(value)` is `true`. Note that this operation will
282 /// correctly handle exponents (e.g., a `value` of
283 /// "0.00000000000000000001e20" will produce a `result` of
284 /// 1).
285 template <class t_INTEGER_TYPE>
286 static int asInteger(t_INTEGER_TYPE *result,
287 const bsl::string_view& value);
288
289 // conversions to string
290
291 static void stringify(bsl::string *result, Int64 value);
292 static void stringify(bsl::string *result, Uint64 value);
293 static void stringify(bsl::string *result, double value);
294 /// Load into the specified `result` a string representation of
295 /// specified numerical `value`.
296 static void stringify(bsl::string *result, const bdldfp::Decimal64& value);
297
298 // comparison
299
300 /// Return `true` if the specified `lhs` and `rhs` represent the same
301 /// numeric value, and `false` otherwise. This function will return
302 /// `true` for differing representations of the same number (e.g.,
303 /// `1.0`, "1", "0.1e+1" are all equivalent) *except* in cases where the
304 /// exponent cannot be represented by a 64-bit integer. If the exponent
305 /// is outside the range of a 64-bit integer, `true` will be returned if
306 /// `lhs == rhs`. For example, comparing "1e18446744073709551615" with
307 /// itself will return `true`, but comparing it to
308 /// "10e18446744073709551614" will return `false`. The behavior is
309 /// undefined unless `isValidNumber(lhs)` and `isValidNumber(rhs)`.
310 static bool areEqual(const bsl::string_view& lhs,
311 const bsl::string_view& rhs);
312};
313
314 // ==========================
315 // struct NumberUtil_IsSigned
316 // ==========================
317
318/// This class will be a `bsl::true_type` if the specified (template
319/// parameter type) `t_TYPE` is a signed type, and `bsl::false_type`
320/// otherwise. `t_TYPE` shall be an integral type. Note that currently
321/// bsl::is_signed is not available for C++03 platforms.
322template <class t_TYPE>
324: bsl::integral_constant<bool, (t_TYPE(-1) < t_TYPE(0))> {
325};
326
327 // =========================
328 // struct NumberUtil_ImpUtil
329 // =========================
330
331/// [**PRIVATE**] This private implementation `struct` provides a namespace
332/// for a suite of functions used to help implement `NumberUtil`. These
333/// functions are private to this component and should not be used by
334/// clients.
335struct NumberUtil_ImpUtil {
336
337 // PUBLIC CONSTANTS
338 enum {
339 k_EXPONENT_OUT_OF_RANGE = -1 // exponent is out of a supported range
340 };
341
342 // CLASS METHODS
343
344 /// Load the specified `result` by appending the specified `digits` to
345 /// the specified `startingValue`. Return 0 on success,
346 /// `NumberUtil::k_OVERFLOW` if the result cannot be represented in a
347 /// `Uint64`. For example, appending "345" to 12 will return a `result`
348 /// of 12345.
349 static int appendDigits(bsls::Types::Uint64 *result,
350 bsls::Types::Uint64 startingValue,
351 const bsl::string_view& digits);
352
353 /// These function overloads implement `NumberUtil::asInteger`, and are
354 /// documented there.
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);
360
361 /// These functions are the template dispatched implementations for the
362 /// `NumberUtil_ImpUtil::asInteger` template function, and serve
363 /// distinguish the signed from the (default-case) unsigned
364 /// implementation. These functions are documented by
365 /// `NumberUtil::asInteger`.
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<>);
375
376 /// Decompose the specified `value` into constituent elements, loading
377 /// the specified `isNegative` with a flag indicating if `value` is
378 /// negative, the specified `isExponentNegative` with a flag indicating
379 /// whether the exponent of `value` is negative, the specified `integer`
380 /// with the integer portion of `value`, the specified `fraction` with
381 /// the fraction portion of `value`, the specified `exponent` with the
382 /// exponent portion of `value`, the specified `significantDigits` with
383 /// the significant digits of `value`, the specified
384 /// `significantDigitsBias` with a bias to add to the exponent when
385 /// considering the value of the significant digits, and the
386 /// `significantDigitsDotOffset` with the offset of the `.` character in
387 /// `significantDigits` (if one exists). The returned
388 /// `significantDigits` may include a `.` character (whose offset into
389 /// `significantDigits` is given by `significantDigitsOffset`) which
390 /// should simply be ignored when considering the significant digits.
391 /// If `significantDigits` does not include a `.` character,
392 /// `significantDigitsOffset` will be `bsl::string_view::npos`. The
393 /// behavior is undefined unless `NumberUtil::isValidNumber(value)` is
394 /// `true`. Note that if `significantDigits[0]` is `0` then `value`
395 /// must be 0.
396 ///
397 /// For example, here are some examples of decompose results for an
398 /// input `value` (`isNegative` and `isExpNegative` are omitted for
399 /// readability):
400 /// @code
401 /// | value | int | frac | exp | sigDigit | sigDotOff | sigBias |
402 /// |----------|-------|-------|-----|----------|-----------|---------|
403 /// | "0.00" | "0" | "00" | "" | "0" | npos | 0 |
404 /// | "100e+1" | "100" | "" | "1" | "1" | npos | 2 |
405 /// | "0.020" | "0" | "020" | "" | "2" | npos | -2 |
406 /// | "1.12e5" | "1" | "12" | "5" | "1.12" | 1 | -2 |
407 /// | "34.50" | "34" | "50" | "" | "34.5" | 2 | -1 |
408 /// | "0.060" | "0" | "060" | "" | "6" | npos | -2 |
409 /// | "10e-2" | "0" | "1" | "2" | "1" | npos | 1 |
410 /// @endcode
411 /// Notice that the `.` is ignored when considering `significantDigits`
412 /// (so "34.5" is treated as "345", and the bias is -1).
413 ///
414 /// Finally, note that `significantDigits`, `significantDigitBias`, and
415 /// `significantDigitsDotOffset` are useful when considering a canonical
416 /// representation for a JSON Number, which consists of a whole number
417 /// (with leading and trailing zeros removed) and an exponent. This
418 /// canonical representation can be used when determining whether two
419 /// JSON numbers are equal. For example, "-12.30e-4" would have a
420 /// canonical representation -123e-5. This canonical representation can
421 /// be computed by taking the returned `significantDigits`, "12.3",
422 /// ignoring the `.` character at `significantDigitsOffset` and
423 /// incorporating `isNegative` to get the canonical significant digits
424 /// -123, then combining `exponent` ("4") with `isExponentNegative` to
425 /// get the exponent of -4 and then adding the returned
426 /// `significantDigitsBias` of -1 to that exponent to get the canonical
427 /// exponent of -5. Combining the canonical significant digits (-123)
428 /// and the canonical exponent (-5) results in the canonical
429 /// representation -123e-5.
430 static void decompose(
431 bool *isNegative,
432 bool *isExpNegative,
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);
440
441 /// Log the specified `value` (for which `isValidNumber` should be
442 /// `true`) could not be correctly parsed into a binary floating point
443 /// representation. Note that this function should be unreachable (and
444 /// no test input has been found for which it is needed) but exists to
445 /// record an issue in case some gap were found between the JSON number
446 /// specification and the underlying floating point parsing functions
447 /// (whose quality may be outside of our control and vary by platform).
448 static void logUnparseableJsonNumber(const bsl::string_view& value);
449};
450
451// ============================================================================
452// INLINE DEFINITIONS
453// ============================================================================
454
455 // -----------------
456 // struct NumberUtil
457 // -----------------
458
459inline
460double NumberUtil::asDouble(const bsl::string_view& value)
461{
462 BSLS_ASSERT(NumberUtil::isValidNumber(value));
463
464 double result;
465
466 int rc = bdlb::NumericParseUtil::parseDouble(&result, value);
467 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(0 != rc && ERANGE != rc)) {
468 // This should not be possible and no test has found a case where this
469 // is occurs. However, to prevent a possible denial of service attack
470 // if some gap were to be found in the implementation of low-level
471 // floating point parsing functions and the JSON number spec, we
472 // provide in-contract defined behavior for optimized (production)
473 // builds.
474
475 BSLS_ASSERT(false);
476 NumberUtil_ImpUtil::logUnparseableJsonNumber(value);
477 return bsl::numeric_limits<double>::quiet_NaN(); // RETURN
478 }
479 return result;
480}
481
482inline
483float NumberUtil::asFloat(const bsl::string_view& value)
484{
485 return static_cast<float>(asDouble(value));
486}
487
488inline
489int NumberUtil::asInt(int *result, const bsl::string_view& value)
490{
491 return asInteger(result, value);
492}
493
494inline
495int NumberUtil::asInt64(Int64 *result, const bsl::string_view& value)
496{
497 return asInteger(result, value);
498}
499
500inline
501int NumberUtil::asUint(unsigned int *result, const bsl::string_view& value)
502{
503 return asInteger(result, value);
504}
505
506template <class t_INTEGER_TYPE>
507int NumberUtil::asInteger(t_INTEGER_TYPE *result,
508 const bsl::string_view& value)
509{
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);
514}
515
516 // -------------------------
517 // struct NumberUtil_ImpUtil
518 // -------------------------
519
520inline
521int NumberUtil_ImpUtil::asInteger(bsls::Types::Uint64 *result,
522 const bsl::string_view& value)
523{
524 return NumberUtil::asUint64(result, value);
525}
526
527template <class t_TYPE>
528int NumberUtil_ImpUtil::asInteger(t_TYPE *result,
529 const bsl::string_view& value)
530{
531 BSLMF_ASSERT(bsl::is_integral<t_TYPE>::value);
532
533 typedef bslmf::SelectTrait<t_TYPE, NumberUtil_IsSigned> Selection;
534 return NumberUtil_ImpUtil::asIntegerDispatchImp(result,
535 value,
536 Selection());
537}
538
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>)
544{
545 BSLMF_ASSERT(bsl::is_integral<t_INTEGER_TYPE>::value);
546 BSLMF_ASSERT(bsl::numeric_limits<t_INTEGER_TYPE>::is_signed);
547
548 BSLS_ASSERT(NumberUtil::isValidNumber(value));
549
550 bsl::string_view positiveValue = value;
551
552 bool isNegative;
553 if ('-' == value[0]) {
554 isNegative = true;
555 positiveValue.remove_prefix(1);
556 }
557 else {
558 isNegative = false;
559 }
560
561 const bsls::Types::Uint64 maxValue = static_cast<bsls::Types::Uint64>(
562 bsl::numeric_limits<t_INTEGER_TYPE>::max());
563
564 bsls::Types::Uint64 tmp;
565
566 const int rc = NumberUtil::asUint64(&tmp, positiveValue);
567
568 if (isNegative) {
569 if (tmp > maxValue + 1) {
570 *result = bsl::numeric_limits<t_INTEGER_TYPE>::min();
571 return NumberUtil::k_UNDERFLOW; // RETURN
572 }
573 *result = static_cast<t_INTEGER_TYPE>(tmp * -1ll );
574 }
575 else {
576 if (tmp > maxValue) {
577 *result = static_cast<t_INTEGER_TYPE>(maxValue);
578 return NumberUtil::k_OVERFLOW; // RETURN
579 }
580 *result = static_cast<t_INTEGER_TYPE>(tmp);
581 }
582 return rc;
583}
584
585template <class t_INTEGER_TYPE>
586int NumberUtil_ImpUtil::asIntegerDispatchImp(t_INTEGER_TYPE *result,
587 const bsl::string_view& value,
589{
591 BSLMF_ASSERT(!bsl::numeric_limits<t_INTEGER_TYPE>::is_signed);
592
593 BSLS_ASSERT(NumberUtil::isValidNumber(value));
594
595 typedef bsls::Types::Uint64 Uint64;
596
597 Uint64 tmp;
598
599 int rc = NumberUtil::asUint64(&tmp, value);
600 if (tmp >
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; // RETURN
604 }
605 *result = static_cast<t_INTEGER_TYPE>(tmp);
606 return rc;
607}
608
609} // close package namespace
610
611
612#endif // INCLUDED_BDLJSN_NUMBERUTIL
613
614// ----------------------------------------------------------------------------
615// Copyright 2022 Bloomberg Finance L.P.
616//
617// Licensed under the Apache License, Version 2.0 (the "License");
618// you may not use this file except in compliance with the License.
619// You may obtain a copy of the License at
620//
621// http://www.apache.org/licenses/LICENSE-2.0
622//
623// Unless required by applicable law or agreed to in writing, software
624// distributed under the License is distributed on an "AS IS" BASIS,
625// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
626// See the License for the specific language governing permissions and
627// limitations under the License.
628// ----------------------------- END-OF-FILE ----------------------------------
629
630/** @} */
631/** @} */
632/** @} */
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