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 QDOUBLESCANPRINT_P_H
5#define QDOUBLESCANPRINT_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 <private/qglobal_p.h>
19
20#if defined(Q_CC_MSVC) && (defined(QT_BOOTSTRAPPED) || defined(QT_NO_DOUBLECONVERSION))
21# include <stdio.h>
22# include <locale.h>
23
24QT_BEGIN_NAMESPACE
25
26// We can always use _sscanf_l and _snprintf_l on MSVC as those were introduced in 2005.
27
28// MSVC doesn't document what it will do with a NULL locale passed to _sscanf_l or _snprintf_l.
29// The documentation for _create_locale() does not formally document "C" to be valid, but an example
30// code snippet in the same documentation shows it.
31
32struct QCLocaleT {
33 QCLocaleT() : locale(_create_locale(LC_ALL, "C"))
34 {
35 }
36
37 ~QCLocaleT()
38 {
39 _free_locale(locale);
40 }
41
42 const _locale_t locale;
43};
44
45# define QT_CLOCALE_HOLDER Q_GLOBAL_STATIC(QCLocaleT, cLocaleT)
46# define QT_CLOCALE cLocaleT()->locale
47
48inline int qDoubleSscanf(const char *buf, _locale_t locale, const char *format, double *d,
49 int *processed)
50{
51 return _sscanf_l(buf, format, locale, d, processed);
52}
53
54inline int qDoubleSnprintf(char *buf, size_t buflen, _locale_t locale, const char *format, double d)
55{
56 return _snprintf_l(buf, buflen, format, locale, d);
57}
58
59QT_END_NAMESPACE
60
61#elif defined(QT_BOOTSTRAPPED)
62# include <stdio.h>
63
64QT_BEGIN_NAMESPACE
65
66// When bootstrapping we don't have libdouble-conversion available, yet. We can also not use locale
67// aware snprintf and sscanf variants in the general case because those are only available on select
68// platforms. We can use the regular snprintf and sscanf because we don't do setlocale(3) when
69// bootstrapping and the locale is always "C" then.
70
71# define QT_CLOCALE_HOLDER
72# define QT_CLOCALE 0
73
74inline int qDoubleSscanf(const char *buf, int, const char *format, double *d, int *processed)
75{
76 return sscanf(buf, format, d, processed);
77}
78inline int qDoubleSnprintf(char *buf, size_t buflen, int, const char *format, double d)
79{
80 return snprintf(buf, buflen, format, d);
81}
82
83QT_END_NAMESPACE
84
85#else // !QT_BOOTSTRAPPED && (!Q_CC_MSVC || !QT_NO_DOUBLECONVERSION)
86# ifdef QT_NO_DOUBLECONVERSION
87# include <stdio.h>
88# include <xlocale.h>
89
90QT_BEGIN_NAMESPACE
91
92// OS X and FreeBSD both treat NULL as the "C" locale for snprintf_l and sscanf_l.
93// When other implementations with different behavior show up, we'll have to do newlocale(3) and
94// freelocale(3) here. The arguments to those will depend on what the other implementations will
95// offer. OS X and FreeBSD again interpret a locale name of NULL as "C", but "C" itself is not
96// documented as valid locale name. Mind that the names of the LC_* constants differ between e.g.
97// BSD variants and linux.
98
99# define QT_CLOCALE_HOLDER
100# define QT_CLOCALE NULL
101
102inline int qDoubleSscanf(const char *buf, locale_t locale, const char *format, double *d,
103 int *processed)
104{
105 return sscanf_l(buf, locale, format, d, processed);
106}
107inline int qDoubleSnprintf(char *buf, size_t buflen, locale_t locale, const char *format, double d)
108{
109 return snprintf_l(buf, buflen, locale, format, d);
110}
111
112QT_END_NAMESPACE
113
114# else // !QT_NO_DOUBLECONVERSION
115# include <double-conversion/double-conversion.h>
116# define QT_CLOCALE_HOLDER
117# endif // QT_NO_DOUBLECONVERSION
118#endif // QT_BOOTSTRAPPED
119
120#endif // QDOUBLESCANPRINT_P_H
121

source code of qtbase/src/corelib/text/qdoublescanprint_p.h