| 1 | // Copyright (C) 2021 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
| 3 | |
| 4 | #ifndef QLOCALE_TOOLS_P_H |
| 5 | #define QLOCALE_TOOLS_P_H |
| 6 | |
| 7 | // |
| 8 | // W A R N I N G |
| 9 | // ------------- |
| 10 | // |
| 11 | // This file is not part of the Qt API. It exists for the convenience |
| 12 | // of internal files. This header file may change from version to version |
| 13 | // without notice, or even be removed. |
| 14 | // |
| 15 | // We mean it. |
| 16 | // |
| 17 | |
| 18 | #include "qlocale_p.h" |
| 19 | #include "qstring.h" |
| 20 | |
| 21 | #if !defined(QT_SUPPORTS_INT128) && (defined(Q_CC_MSVC) && (_MSC_VER >= 1930) && __has_include(<__msvc_int128.hpp>)) |
| 22 | #include <__msvc_int128.hpp> |
| 23 | #define QT_USE_MSVC_INT128 |
| 24 | #endif |
| 25 | |
| 26 | QT_BEGIN_NAMESPACE |
| 27 | |
| 28 | #if defined(QT_SUPPORTS_INT128) |
| 29 | using qinternalint128 = qint128; |
| 30 | using qinternaluint128 = quint128; |
| 31 | #elif defined(QT_USE_MSVC_INT128) |
| 32 | using qinternalint128 = std::_Signed128; |
| 33 | using qinternaluint128 = std::_Unsigned128; |
| 34 | #endif |
| 35 | |
| 36 | enum StrayCharacterMode { |
| 37 | TrailingJunkProhibited, |
| 38 | TrailingJunkAllowed, |
| 39 | WhitespacesAllowed |
| 40 | }; |
| 41 | |
| 42 | // API note: this function can't process a number with more than 2.1 billion digits |
| 43 | [[nodiscard]] QSimpleParsedNumber<double> |
| 44 | qt_asciiToDouble(const char *num, qsizetype numLen, |
| 45 | StrayCharacterMode strayCharMode = TrailingJunkProhibited); |
| 46 | void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, |
| 47 | char *buf, qsizetype bufSize, |
| 48 | bool &sign, int &length, int &decpt); |
| 49 | |
| 50 | [[nodiscard]] QString qulltoBasicLatin(qulonglong l, int base, bool negative); |
| 51 | [[nodiscard]] QString qulltoa(qulonglong l, int base, const QStringView zero); |
| 52 | [[nodiscard]] char *qulltoa2(char *p, qulonglong n, int base); |
| 53 | [[nodiscard]] Q_CORE_EXPORT QString qdtoa(qreal d, int *decpt, int *sign); |
| 54 | [[nodiscard]] QString qdtoBasicLatin(double d, QLocaleData::DoubleForm form, |
| 55 | int precision, bool uppercase); |
| 56 | [[nodiscard]] QByteArray qdtoAscii(double d, QLocaleData::DoubleForm form, |
| 57 | int precision, bool uppercase); |
| 58 | |
| 59 | #if defined(QT_SUPPORTS_INT128) || defined(QT_USE_MSVC_INT128) |
| 60 | [[nodiscard]] Q_CORE_EXPORT QString quint128toBasicLatin(qinternaluint128 number, |
| 61 | int base = 10); |
| 62 | [[nodiscard]] Q_CORE_EXPORT QString qint128toBasicLatin(qinternalint128 number, |
| 63 | int base = 10); |
| 64 | #endif |
| 65 | |
| 66 | [[nodiscard]] constexpr inline bool isZero(double d) |
| 67 | { |
| 68 | return qIsNull(d); |
| 69 | } |
| 70 | |
| 71 | // Enough space for the digits before the decimal separator: |
| 72 | [[nodiscard]] inline int wholePartSpace(double d) |
| 73 | { |
| 74 | Q_ASSERT(d >= 0); // caller should call qAbs() if needed |
| 75 | // Optimize for numbers between -512k and 512k - otherwise, use the |
| 76 | // maximum number of digits in the whole number part of a double: |
| 77 | return d > (1 << 19) ? std::numeric_limits<double>::max_exponent10 + 1 : 6; |
| 78 | } |
| 79 | |
| 80 | // Returns code-point of same kind (UCS2 or UCS4) as zero; digit is 0 through 9 |
| 81 | template <typename UcsInt> |
| 82 | [[nodiscard]] inline UcsInt unicodeForDigit(uint digit, UcsInt zero) |
| 83 | { |
| 84 | // Must match qlocale.cpp's NumberTokenizer's digit-digestion. |
| 85 | Q_ASSERT(digit < 10); |
| 86 | if (!digit) |
| 87 | return zero; |
| 88 | |
| 89 | // See QTBUG-85409: Suzhou's digits are U+3007, U+3021, ..., U+3029 |
| 90 | if (zero == u'\u3007') |
| 91 | return u'\u3020' + digit; |
| 92 | // In util/locale_database/ldml.py, LocaleScanner.numericData() asserts no |
| 93 | // other number system in CLDR has discontinuous digits. |
| 94 | |
| 95 | return zero + digit; |
| 96 | } |
| 97 | |
| 98 | [[nodiscard]] Q_CORE_EXPORT double qstrntod(const char *s00, qsizetype len, |
| 99 | char const **se, bool *ok); |
| 100 | [[nodiscard]] inline double qstrtod(const char *s00, char const **se, bool *ok) |
| 101 | { |
| 102 | qsizetype len = qsizetype(strlen(s: s00)); |
| 103 | return qstrntod(s00, len, se, ok); |
| 104 | } |
| 105 | |
| 106 | [[nodiscard]] Q_AUTOTEST_EXPORT |
| 107 | QSimpleParsedNumber<qlonglong> qstrntoll(const char *nptr, qsizetype size, int base); |
| 108 | [[nodiscard]] QSimpleParsedNumber<qulonglong> qstrntoull(const char *nptr, qsizetype size, int base); |
| 109 | |
| 110 | QT_END_NAMESPACE |
| 111 | |
| 112 | #endif |
| 113 | |