1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2016 Intel Corporation.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtCore module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39****************************************************************************/
40
41#include "qlocale_tools_p.h"
42#include "qdoublescanprint_p.h"
43#include "qlocale_p.h"
44#include "qstring.h"
45
46#include <private/qnumeric_p.h>
47
48#include <ctype.h>
49#include <errno.h>
50#include <float.h>
51#include <limits.h>
52#include <math.h>
53#include <stdlib.h>
54#include <time.h>
55
56#if defined(Q_OS_LINUX) && !defined(__UCLIBC__)
57# include <fenv.h>
58#endif
59
60// Sizes as defined by the ISO C99 standard - fallback
61#ifndef LLONG_MAX
62# define LLONG_MAX Q_INT64_C(0x7fffffffffffffff)
63#endif
64#ifndef LLONG_MIN
65# define LLONG_MIN (-LLONG_MAX - Q_INT64_C(1))
66#endif
67#ifndef ULLONG_MAX
68# define ULLONG_MAX Q_UINT64_C(0xffffffffffffffff)
69#endif
70
71QT_BEGIN_NAMESPACE
72
73QT_WARNING_PUSH
74 /* "unary minus operator applied to unsigned type, result still unsigned" */
75QT_WARNING_DISABLE_MSVC(4146)
76#include "../../3rdparty/freebsd/strtoull.c"
77#include "../../3rdparty/freebsd/strtoll.c"
78QT_WARNING_POP
79
80QT_CLOCALE_HOLDER
81
82void qt_doubleToAscii(double d, QLocaleData::DoubleForm form, int precision, char *buf, int bufSize,
83 bool &sign, int &length, int &decpt)
84{
85 if (bufSize == 0) {
86 decpt = 0;
87 sign = d < 0;
88 length = 0;
89 return;
90 }
91
92 // Detect special numbers (nan, +/-inf)
93 // We cannot use the high-level API of libdouble-conversion as we need to
94 // apply locale-specific formatting, such as decimal points, grouping
95 // separators, etc. Because of this, we have to check for infinity and NaN
96 // before calling DoubleToAscii.
97 if (qt_is_inf(d)) {
98 sign = d < 0;
99 if (bufSize >= 3) {
100 buf[0] = 'i';
101 buf[1] = 'n';
102 buf[2] = 'f';
103 length = 3;
104 } else {
105 length = 0;
106 }
107 return;
108 } else if (qt_is_nan(d)) {
109 if (bufSize >= 3) {
110 buf[0] = 'n';
111 buf[1] = 'a';
112 buf[2] = 'n';
113 length = 3;
114 } else {
115 length = 0;
116 }
117 return;
118 }
119
120 if (form == QLocaleData::DFSignificantDigits && precision == 0)
121 precision = 1; // 0 significant digits is silently converted to 1
122
123#if !defined(QT_NO_DOUBLECONVERSION) && !defined(QT_BOOTSTRAPPED)
124 // one digit before the decimal dot, counts as significant digit for DoubleToStringConverter
125 if (form == QLocaleData::DFExponent && precision >= 0)
126 ++precision;
127
128 double_conversion::DoubleToStringConverter::DtoaMode mode;
129 if (precision == QLocale::FloatingPointShortest) {
130 mode = double_conversion::DoubleToStringConverter::SHORTEST;
131 } else if (form == QLocaleData::DFSignificantDigits || form == QLocaleData::DFExponent) {
132 mode = double_conversion::DoubleToStringConverter::PRECISION;
133 } else {
134 mode = double_conversion::DoubleToStringConverter::FIXED;
135 }
136 double_conversion::DoubleToStringConverter::DoubleToAscii(d, mode, precision, buf, bufSize,
137 &sign, &length, &decpt);
138#else // QT_NO_DOUBLECONVERSION || QT_BOOTSTRAPPED
139
140 // Cut the precision at 999, to fit it into the format string. We can't get more than 17
141 // significant digits, so anything after that is mostly noise. You do get closer to the "middle"
142 // of the range covered by the given double with more digits, so to a degree it does make sense
143 // to honor higher precisions. We define that at more than 999 digits that is not the case.
144 if (precision > 999)
145 precision = 999;
146 else if (precision == QLocale::FloatingPointShortest)
147 precision = std::numeric_limits<double>::max_digits10; // snprintf lacks "shortest" mode
148
149 if (isZero(d)) {
150 // Negative zero is expected as simple "0", not "-0". We cannot do d < 0, though.
151 sign = false;
152 buf[0] = '0';
153 length = 1;
154 decpt = 1;
155 return;
156 } else if (d < 0) {
157 sign = true;
158 d = -d;
159 } else {
160 sign = false;
161 }
162
163 const int formatLength = 7; // '%', '.', 3 digits precision, 'f', '\0'
164 char format[formatLength];
165 format[formatLength - 1] = '\0';
166 format[0] = '%';
167 format[1] = '.';
168 format[2] = char((precision / 100) % 10) + '0';
169 format[3] = char((precision / 10) % 10) + '0';
170 format[4] = char(precision % 10) + '0';
171 int extraChars;
172 switch (form) {
173 case QLocaleData::DFDecimal:
174 format[formatLength - 2] = 'f';
175 // <anything> '.' <precision> '\0'
176 extraChars = wholePartSpace(d) + 2;
177 break;
178 case QLocaleData::DFExponent:
179 format[formatLength - 2] = 'e';
180 // '.', 'e', '-', <exponent> '\0'
181 extraChars = 7;
182 break;
183 case QLocaleData::DFSignificantDigits:
184 format[formatLength - 2] = 'g';
185
186 // either the same as in the 'e' case, or '.' and '\0'
187 // precision covers part before '.'
188 extraChars = 7;
189 break;
190 default:
191 Q_UNREACHABLE();
192 }
193
194 QVarLengthArray<char> target(precision + extraChars);
195
196 length = qDoubleSnprintf(target.data(), target.size(), QT_CLOCALE, format, d);
197 int firstSignificant = 0;
198 int decptInTarget = length;
199
200 // Find the first significant digit (not 0), and note any '.' we encounter.
201 // There is no '-' at the front of target because we made sure d > 0 above.
202 while (firstSignificant < length) {
203 if (target[firstSignificant] == '.')
204 decptInTarget = firstSignificant;
205 else if (target[firstSignificant] != '0')
206 break;
207 ++firstSignificant;
208 }
209
210 // If no '.' found so far, search the rest of the target buffer for it.
211 if (decptInTarget == length)
212 decptInTarget = std::find(target.data() + firstSignificant, target.data() + length, '.') -
213 target.data();
214
215 int eSign = length;
216 if (form != QLocaleData::DFDecimal) {
217 // In 'e' or 'g' form, look for the 'e'.
218 eSign = std::find(target.data() + firstSignificant, target.data() + length, 'e') -
219 target.data();
220
221 if (eSign < length) {
222 // If 'e' is found, the final decimal point is determined by the number after 'e'.
223 // Mind that the final decimal point, decpt, is the offset of the decimal point from the
224 // start of the resulting string in buf. It may be negative or larger than bufSize, in
225 // which case the missing digits are zeroes. In the 'e' case decptInTarget is always 1,
226 // as variants of snprintf always generate numbers with one digit before the '.' then.
227 // This is why the final decimal point is offset by 1, relative to the number after 'e'.
228 bool ok;
229 const char *endptr;
230 decpt = qstrtoll(target.data() + eSign + 1, &endptr, 10, &ok) + 1;
231 Q_ASSERT(ok);
232 Q_ASSERT(endptr - target.data() <= length);
233 } else {
234 // No 'e' found, so it's the 'f' form. Variants of snprintf generate numbers with
235 // potentially multiple digits before the '.', but without decimal exponent then. So we
236 // get the final decimal point from the position of the '.'. The '.' itself takes up one
237 // character. We adjust by 1 below if that gets in the way.
238 decpt = decptInTarget - firstSignificant;
239 }
240 } else {
241 // In 'f' form, there can not be an 'e', so it's enough to look for the '.'
242 // (and possibly adjust by 1 below)
243 decpt = decptInTarget - firstSignificant;
244 }
245
246 // Move the actual digits from the snprintf target to the actual buffer.
247 if (decptInTarget > firstSignificant) {
248 // First move the digits before the '.', if any
249 int lengthBeforeDecpt = decptInTarget - firstSignificant;
250 memcpy(buf, target.data() + firstSignificant, qMin(lengthBeforeDecpt, bufSize));
251 if (eSign > decptInTarget && lengthBeforeDecpt < bufSize) {
252 // Then move any remaining digits, until 'e'
253 memcpy(buf + lengthBeforeDecpt, target.data() + decptInTarget + 1,
254 qMin(eSign - decptInTarget - 1, bufSize - lengthBeforeDecpt));
255 // The final length of the output is the distance between the first significant digit
256 // and 'e' minus 1, for the '.', except if the buffer is smaller.
257 length = qMin(eSign - firstSignificant - 1, bufSize);
258 } else {
259 // 'e' was before the decpt or things didn't fit. Don't subtract the '.' from the length.
260 length = qMin(eSign - firstSignificant, bufSize);
261 }
262 } else {
263 if (eSign > firstSignificant) {
264 // If there are any significant digits at all, they are all after the '.' now.
265 // Just copy them straight away.
266 memcpy(buf, target.data() + firstSignificant, qMin(eSign - firstSignificant, bufSize));
267
268 // The decimal point was before the first significant digit, so we were one off above.
269 // Consider 0.1 - buf will be just '1', and decpt should be 0. But
270 // "decptInTarget - firstSignificant" will yield -1.
271 ++decpt;
272 length = qMin(eSign - firstSignificant, bufSize);
273 } else {
274 // No significant digits means the number is just 0.
275 buf[0] = '0';
276 length = 1;
277 decpt = 1;
278 }
279 }
280#endif // QT_NO_DOUBLECONVERSION || QT_BOOTSTRAPPED
281 while (length > 1 && buf[length - 1] == '0') // drop trailing zeroes
282 --length;
283}
284
285double qt_asciiToDouble(const char *num, qsizetype numLen, bool &ok, int &processed,
286 StrayCharacterMode strayCharMode)
287{
288 auto string_equals = [](const char *needle, const char *haystack, qsizetype haystackLen) {
289 qsizetype needleLen = strlen(needle);
290 return needleLen == haystackLen && memcmp(needle, haystack, haystackLen) == 0;
291 };
292
293 if (numLen == 0) {
294 ok = false;
295 processed = 0;
296 return 0.0;
297 }
298
299 ok = true;
300
301 // We have to catch NaN before because we need NaN as marker for "garbage" in the
302 // libdouble-conversion case and, in contrast to libdouble-conversion or sscanf, we don't allow
303 // "-nan" or "+nan"
304 if (string_equals("nan", num, numLen)) {
305 processed = 3;
306 return qt_qnan();
307 } else if (string_equals("+nan", num, numLen) || string_equals("-nan", num, numLen)) {
308 processed = 0;
309 ok = false;
310 return 0.0;
311 }
312
313 // Infinity values are implementation defined in the sscanf case. In the libdouble-conversion
314 // case we need infinity as overflow marker.
315 if (string_equals("+inf", num, numLen)) {
316 processed = 4;
317 return qt_inf();
318 } else if (string_equals("inf", num, numLen)) {
319 processed = 3;
320 return qt_inf();
321 } else if (string_equals("-inf", num, numLen)) {
322 processed = 4;
323 return -qt_inf();
324 }
325
326 double d = 0.0;
327#if !defined(QT_NO_DOUBLECONVERSION) && !defined(QT_BOOTSTRAPPED)
328 int conv_flags = double_conversion::StringToDoubleConverter::NO_FLAGS;
329 if (strayCharMode == TrailingJunkAllowed) {
330 conv_flags = double_conversion::StringToDoubleConverter::ALLOW_TRAILING_JUNK;
331 } else if (strayCharMode == WhitespacesAllowed) {
332 conv_flags = double_conversion::StringToDoubleConverter::ALLOW_LEADING_SPACES
333 | double_conversion::StringToDoubleConverter::ALLOW_TRAILING_SPACES;
334 }
335 double_conversion::StringToDoubleConverter conv(conv_flags, 0.0, qt_qnan(), nullptr, nullptr);
336 if (int(numLen) != numLen) {
337 // a number over 2 GB in length is silly, just assume it isn't valid
338 ok = false;
339 processed = 0;
340 return 0.0;
341 } else {
342 d = conv.StringToDouble(num, numLen, &processed);
343 }
344
345 if (!qIsFinite(d)) {
346 ok = false;
347 if (qIsNaN(d)) {
348 // Garbage found. We don't accept it and return 0.
349 processed = 0;
350 return 0.0;
351 } else {
352 // Overflow. That's not OK, but we still return infinity.
353 return d;
354 }
355 }
356#else
357 // need to ensure that our input is null-terminated for sscanf
358 // (this is a QVarLengthArray<char, 128> but this code here is too low-level for QVLA)
359 char reasonableBuffer[128];
360 char *buffer;
361 if (numLen < qsizetype(sizeof(reasonableBuffer)) - 1)
362 buffer = reasonableBuffer;
363 else
364 buffer = static_cast<char *>(malloc(numLen + 1));
365 memcpy(buffer, num, numLen);
366 buffer[numLen] = '\0';
367
368 if (qDoubleSscanf(buffer, QT_CLOCALE, "%lf%n", &d, &processed) < 1)
369 processed = 0;
370
371 if (buffer != reasonableBuffer)
372 free(buffer);
373
374 if ((strayCharMode == TrailingJunkProhibited && processed != numLen) || qIsNaN(d)) {
375 // Implementation defined nan symbol or garbage found. We don't accept it.
376 processed = 0;
377 ok = false;
378 return 0.0;
379 }
380
381 if (!qIsFinite(d)) {
382 // Overflow. Check for implementation-defined infinity symbols and reject them.
383 // We assume that any infinity symbol has to contain a character that cannot be part of a
384 // "normal" number (that is 0-9, ., -, +, e).
385 ok = false;
386 for (int i = 0; i < processed; ++i) {
387 char c = num[i];
388 if ((c < '0' || c > '9') && c != '.' && c != '-' && c != '+' && c != 'e' && c != 'E') {
389 // Garbage found
390 processed = 0;
391 return 0.0;
392 }
393 }
394 return d;
395 }
396#endif // !defined(QT_NO_DOUBLECONVERSION) && !defined(QT_BOOTSTRAPPED)
397
398 // Otherwise we would have gotten NaN or sorted it out above.
399 Q_ASSERT(strayCharMode == TrailingJunkAllowed || processed == numLen);
400
401 // Check if underflow has occurred.
402 if (isZero(d)) {
403 for (int i = 0; i < processed; ++i) {
404 if (num[i] >= '1' && num[i] <= '9') {
405 // if a digit before any 'e' is not 0, then a non-zero number was intended.
406 ok = false;
407 return 0.0;
408 } else if (num[i] == 'e' || num[i] == 'E') {
409 break;
410 }
411 }
412 }
413 return d;
414}
415
416unsigned long long
417qstrtoull(const char * nptr, const char **endptr, int base, bool *ok)
418{
419 // strtoull accepts negative numbers. We don't.
420 // Use a different variable so we pass the original nptr to strtoul
421 // (we need that so endptr may be nptr in case of failure)
422 const char *begin = nptr;
423 while (ascii_isspace(*begin))
424 ++begin;
425 if (*begin == '-') {
426 *ok = false;
427 return 0;
428 }
429
430 *ok = true;
431 errno = 0;
432 char *endptr2 = nullptr;
433 unsigned long long result = qt_strtoull(nptr, &endptr2, base);
434 if (endptr)
435 *endptr = endptr2;
436 if ((result == 0 || result == std::numeric_limits<unsigned long long>::max())
437 && (errno || endptr2 == nptr)) {
438 *ok = false;
439 return 0;
440 }
441 return result;
442}
443
444long long
445qstrtoll(const char * nptr, const char **endptr, int base, bool *ok)
446{
447 *ok = true;
448 errno = 0;
449 char *endptr2 = nullptr;
450 long long result = qt_strtoll(nptr, &endptr2, base);
451 if (endptr)
452 *endptr = endptr2;
453 if ((result == 0 || result == std::numeric_limits<long long>::min()
454 || result == std::numeric_limits<long long>::max())
455 && (errno || nptr == endptr2)) {
456 *ok = false;
457 return 0;
458 }
459 return result;
460}
461
462QString qulltoa(qulonglong number, int base, const QStringView zero)
463{
464 // Length of MAX_ULLONG in base 2 is 64; and we may need a surrogate pair
465 // per digit. We do not need a terminator.
466 const unsigned maxlen = 128;
467 static_assert(CHAR_BIT * sizeof(number) <= maxlen);
468 char16_t buff[maxlen];
469 char16_t *const end = buff + maxlen, *p = end;
470
471 if (base != 10 || zero == u"0") {
472 while (number != 0) {
473 int c = number % base;
474 *--p = c < 10 ? '0' + c : c - 10 + 'a';
475 number /= base;
476 }
477 } else if (zero.size() && !zero.at(0).isSurrogate()) {
478 const char16_t zeroUcs2 = zero.at(0).unicode();
479 while (number != 0) {
480 *(--p) = unicodeForDigit(number % base, zeroUcs2);
481
482 number /= base;
483 }
484 } else if (zero.size() == 2 && zero.at(0).isHighSurrogate()) {
485 const char32_t zeroUcs4 = QChar::surrogateToUcs4(zero.at(0), zero.at(1));
486 while (number != 0) {
487 const char32_t digit = unicodeForDigit(number % base, zeroUcs4);
488
489 *(--p) = QChar::lowSurrogate(digit);
490 *(--p) = QChar::highSurrogate(digit);
491
492 number /= base;
493 }
494 } else {
495 return QString();
496 }
497
498 return QString(reinterpret_cast<QChar *>(p), end - p);
499}
500
501/*!
502 \internal
503
504 Converts the initial portion of the string pointed to by \a s00 to a double, using the 'C' locale.
505 */
506double qstrntod(const char *s00, qsizetype len, const char **se, bool *ok)
507{
508 int processed = 0;
509 bool nonNullOk = false;
510 double d = qt_asciiToDouble(s00, len, nonNullOk, processed, TrailingJunkAllowed);
511 if (se)
512 *se = s00 + processed;
513 if (ok)
514 *ok = nonNullOk;
515 return d;
516}
517
518QString qdtoa(qreal d, int *decpt, int *sign)
519{
520 bool nonNullSign = false;
521 int nonNullDecpt = 0;
522 int length = 0;
523
524 // Some versions of libdouble-conversion like an extra digit, probably for '\0'
525 constexpr int digits = std::numeric_limits<double>::max_digits10 + 1;
526 char result[digits];
527 qt_doubleToAscii(d, QLocaleData::DFSignificantDigits, QLocale::FloatingPointShortest,
528 result, digits, nonNullSign, length, nonNullDecpt);
529
530 if (sign)
531 *sign = nonNullSign ? 1 : 0;
532 if (decpt)
533 *decpt = nonNullDecpt;
534
535 return QLatin1String(result, length);
536}
537
538QT_END_NAMESPACE
539