0
|
1 |
/****************************************************************************
|
|
2 |
**
|
|
3 |
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
4 |
** All rights reserved.
|
|
5 |
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
6 |
**
|
|
7 |
** This file is part of the QtCore module of the Qt Toolkit.
|
|
8 |
**
|
|
9 |
** $QT_BEGIN_LICENSE:LGPL$
|
|
10 |
** No Commercial Usage
|
|
11 |
** This file contains pre-release code and may not be distributed.
|
|
12 |
** You may use this file in accordance with the terms and conditions
|
|
13 |
** contained in the Technology Preview License Agreement accompanying
|
|
14 |
** this package.
|
|
15 |
**
|
|
16 |
** GNU Lesser General Public License Usage
|
|
17 |
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
18 |
** General Public License version 2.1 as published by the Free Software
|
|
19 |
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
20 |
** packaging of this file. Please review the following information to
|
|
21 |
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
22 |
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
23 |
**
|
|
24 |
** In addition, as a special exception, Nokia gives you certain additional
|
|
25 |
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
26 |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
27 |
**
|
|
28 |
** If you have questions regarding the use of this file, please contact
|
|
29 |
** Nokia at qt-info@nokia.com.
|
|
30 |
**
|
|
31 |
**
|
|
32 |
**
|
|
33 |
**
|
|
34 |
**
|
|
35 |
**
|
|
36 |
**
|
|
37 |
**
|
|
38 |
** $QT_END_LICENSE$
|
|
39 |
**
|
|
40 |
****************************************************************************/
|
|
41 |
|
|
42 |
#include "qglobal.h"
|
|
43 |
|
|
44 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
45 |
QT_BEGIN_NAMESPACE
|
|
46 |
class QSystemLocale;
|
|
47 |
static QSystemLocale *QSystemLocale_globalSystemLocale();
|
|
48 |
QT_END_NAMESPACE
|
|
49 |
#endif
|
|
50 |
|
|
51 |
#include "qplatformdefs.h"
|
|
52 |
|
|
53 |
#include "qdatastream.h"
|
|
54 |
#include "qstring.h"
|
|
55 |
#include "qlocale.h"
|
|
56 |
#include "qlocale_p.h"
|
|
57 |
#include "qdatetime_p.h"
|
|
58 |
#include "qnamespace.h"
|
|
59 |
#include "qdatetime.h"
|
|
60 |
#include "qstringlist.h"
|
|
61 |
#include "qvariant.h"
|
|
62 |
#if defined(Q_WS_WIN)
|
|
63 |
# include "qt_windows.h"
|
|
64 |
# include <time.h>
|
|
65 |
#endif
|
|
66 |
#if !defined(QWS) && defined(Q_OS_MAC)
|
|
67 |
# include "private/qcore_mac_p.h"
|
|
68 |
# include <CoreFoundation/CoreFoundation.h>
|
|
69 |
#endif
|
|
70 |
#include "private/qnumeric_p.h"
|
|
71 |
|
|
72 |
#include <ctype.h>
|
|
73 |
#include <float.h>
|
|
74 |
#include <limits.h>
|
|
75 |
#include <math.h>
|
|
76 |
#include <stdlib.h>
|
|
77 |
#include <qdebug.h>
|
|
78 |
#include <time.h>
|
|
79 |
|
|
80 |
#if defined(Q_OS_LINUX) && !defined(__UCLIBC__)
|
|
81 |
# include <fenv.h>
|
|
82 |
#endif
|
|
83 |
|
|
84 |
#if !defined(QT_QLOCALE_NEEDS_VOLATILE)
|
|
85 |
# if defined(Q_CC_GNU)
|
|
86 |
# if __GNUC__ == 4
|
|
87 |
# define QT_QLOCALE_NEEDS_VOLATILE
|
|
88 |
# elif defined(Q_OS_WIN)
|
|
89 |
# define QT_QLOCALE_NEEDS_VOLATILE
|
|
90 |
# endif
|
|
91 |
# endif
|
|
92 |
#endif
|
|
93 |
|
|
94 |
#if defined(QT_QLOCALE_NEEDS_VOLATILE)
|
|
95 |
# define NEEDS_VOLATILE volatile
|
|
96 |
#else
|
|
97 |
# define NEEDS_VOLATILE
|
|
98 |
#endif
|
|
99 |
|
|
100 |
// Sizes as defined by the ISO C99 standard - fallback
|
|
101 |
#ifndef LLONG_MAX
|
|
102 |
# define LLONG_MAX Q_INT64_C(0x7fffffffffffffff)
|
|
103 |
#endif
|
|
104 |
#ifndef LLONG_MIN
|
|
105 |
# define LLONG_MIN (-LLONG_MAX - Q_INT64_C(1))
|
|
106 |
#endif
|
|
107 |
#ifndef ULLONG_MAX
|
|
108 |
# define ULLONG_MAX Q_UINT64_C(0xffffffffffffffff)
|
|
109 |
#endif
|
|
110 |
|
|
111 |
#define CONVERSION_BUFF_SIZE 255
|
|
112 |
|
|
113 |
QT_BEGIN_NAMESPACE
|
|
114 |
|
|
115 |
#ifndef QT_QLOCALE_USES_FCVT
|
|
116 |
static char *_qdtoa( NEEDS_VOLATILE double d, int mode, int ndigits, int *decpt,
|
|
117 |
int *sign, char **rve, char **digits_str);
|
|
118 |
#endif
|
|
119 |
Q_CORE_EXPORT char *qdtoa(double d, int mode, int ndigits, int *decpt,
|
|
120 |
int *sign, char **rve, char **digits_str);
|
|
121 |
Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
|
|
122 |
static qlonglong qstrtoll(const char *nptr, const char **endptr, register int base, bool *ok);
|
|
123 |
static qulonglong qstrtoull(const char *nptr, const char **endptr, register int base, bool *ok);
|
|
124 |
|
|
125 |
#if defined(Q_CC_MWERKS) && defined(Q_OS_WIN32)
|
|
126 |
inline bool isascii(int c)
|
|
127 |
{
|
|
128 |
return (c >= 0 && c <=127);
|
|
129 |
}
|
|
130 |
#endif
|
|
131 |
|
|
132 |
/******************************************************************************
|
|
133 |
** Helpers for accessing Qt locale database
|
|
134 |
*/
|
|
135 |
|
|
136 |
QT_BEGIN_INCLUDE_NAMESPACE
|
|
137 |
#include "qlocale_data_p.h"
|
|
138 |
QT_END_INCLUDE_NAMESPACE
|
|
139 |
|
|
140 |
QLocale::MeasurementSystem QLocalePrivate::measurementSystem() const
|
|
141 |
{
|
|
142 |
for (int i = 0; i < ImperialMeasurementSystemsCount; ++i) {
|
|
143 |
if (ImperialMeasurementSystems[i].languageId == m_language_id
|
|
144 |
&& ImperialMeasurementSystems[i].countryId == m_country_id) {
|
|
145 |
return QLocale::ImperialSystem;
|
|
146 |
}
|
|
147 |
}
|
|
148 |
return QLocale::MetricSystem;
|
|
149 |
}
|
|
150 |
|
|
151 |
// Assumes that code is a
|
|
152 |
// QChar code[3];
|
|
153 |
// If the code is two-digit the third digit must be 0
|
|
154 |
static QLocale::Language codeToLanguage(const QChar *code)
|
|
155 |
{
|
|
156 |
ushort uc1 = code[0].unicode();
|
|
157 |
ushort uc2 = code[1].unicode();
|
|
158 |
ushort uc3 = code[2].unicode();
|
|
159 |
|
|
160 |
if (uc1 == 'n' && uc2 == 'o' && uc3 == 0)
|
|
161 |
uc2 = 'b';
|
|
162 |
|
|
163 |
const unsigned char *c = language_code_list;
|
|
164 |
for (; *c != 0; c += 3) {
|
|
165 |
if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2])
|
|
166 |
return QLocale::Language((c - language_code_list)/3);
|
|
167 |
}
|
|
168 |
|
|
169 |
return QLocale::C;
|
|
170 |
}
|
|
171 |
|
|
172 |
// Assumes that code is a
|
|
173 |
// QChar code[2];
|
|
174 |
static QLocale::Country codeToCountry(const QChar *code)
|
|
175 |
{
|
|
176 |
ushort uc1 = code[0].unicode();
|
|
177 |
ushort uc2 = code[1].unicode();
|
|
178 |
|
|
179 |
const unsigned char *c = country_code_list;
|
|
180 |
for (; *c != 0; c += 2) {
|
|
181 |
if (uc1 == c[0] && uc2 == c[1])
|
|
182 |
return QLocale::Country((c - country_code_list)/2);
|
|
183 |
}
|
|
184 |
|
|
185 |
return QLocale::AnyCountry;
|
|
186 |
}
|
|
187 |
|
|
188 |
static QString languageToCode(QLocale::Language language)
|
|
189 |
{
|
|
190 |
if (language == QLocale::C)
|
|
191 |
return QLatin1String("C");
|
|
192 |
|
|
193 |
const unsigned char *c = language_code_list + 3*(uint(language));
|
|
194 |
|
|
195 |
QString code(c[2] == 0 ? 2 : 3, Qt::Uninitialized);
|
|
196 |
|
|
197 |
code[0] = ushort(c[0]);
|
|
198 |
code[1] = ushort(c[1]);
|
|
199 |
if (c[2] != 0)
|
|
200 |
code[2] = ushort(c[2]);
|
|
201 |
|
|
202 |
return code;
|
|
203 |
}
|
|
204 |
|
|
205 |
static QString countryToCode(QLocale::Country country)
|
|
206 |
{
|
|
207 |
if (country == QLocale::AnyCountry)
|
|
208 |
return QString();
|
|
209 |
|
|
210 |
QString code(2, Qt::Uninitialized);
|
|
211 |
const unsigned char *c = country_code_list + 2*(uint(country));
|
|
212 |
code[0] = ushort(c[0]);
|
|
213 |
code[1] = ushort(c[1]);
|
|
214 |
return code;
|
|
215 |
}
|
|
216 |
|
|
217 |
static const QLocalePrivate *findLocale(QLocale::Language language, QLocale::Country country)
|
|
218 |
{
|
|
219 |
unsigned language_id = language;
|
|
220 |
unsigned country_id = country;
|
|
221 |
|
|
222 |
uint idx = locale_index[language_id];
|
|
223 |
|
|
224 |
const QLocalePrivate *d = locale_data + idx;
|
|
225 |
|
|
226 |
if (idx == 0) // default language has no associated country
|
|
227 |
return d;
|
|
228 |
|
|
229 |
if (country == QLocale::AnyCountry)
|
|
230 |
return d;
|
|
231 |
|
|
232 |
Q_ASSERT(d->languageId() == language_id);
|
|
233 |
|
|
234 |
while (d->languageId() == language_id
|
|
235 |
&& d->countryId() != country_id)
|
|
236 |
++d;
|
|
237 |
|
|
238 |
if (d->countryId() == country_id
|
|
239 |
&& d->languageId() == language_id)
|
|
240 |
return d;
|
|
241 |
|
|
242 |
return locale_data + idx;
|
|
243 |
}
|
|
244 |
|
|
245 |
static bool splitLocaleName(const QString &name, QChar *lang_begin, QChar *cntry_begin)
|
|
246 |
{
|
|
247 |
for (int i = 0; i < 3; ++i)
|
|
248 |
lang_begin[i] = 0;
|
|
249 |
for (int i = 0; i < 2; ++i)
|
|
250 |
cntry_begin[i] = 0;
|
|
251 |
|
|
252 |
int l = name.length();
|
|
253 |
|
|
254 |
QChar *lang = lang_begin;
|
|
255 |
QChar *cntry = cntry_begin;
|
|
256 |
|
|
257 |
int state = 0;
|
|
258 |
const QChar *uc = name.unicode();
|
|
259 |
for (int i = 0; i < l; ++i) {
|
|
260 |
if (uc->unicode() == '.' || uc->unicode() == '@')
|
|
261 |
break;
|
|
262 |
|
|
263 |
switch (state) {
|
|
264 |
case 0:
|
|
265 |
// parsing language
|
|
266 |
if (uc->unicode() == '_') {
|
|
267 |
state = 1;
|
|
268 |
break;
|
|
269 |
}
|
|
270 |
if (lang - lang_begin == 3)
|
|
271 |
return false;
|
|
272 |
if (uc->unicode() < 'a' || uc->unicode() > 'z')
|
|
273 |
return false;
|
|
274 |
|
|
275 |
*lang = *uc;
|
|
276 |
++lang;
|
|
277 |
break;
|
|
278 |
case 1:
|
|
279 |
// parsing country
|
|
280 |
if (cntry - cntry_begin == 2) {
|
|
281 |
cntry_begin[0] = 0;
|
|
282 |
break;
|
|
283 |
}
|
|
284 |
|
|
285 |
*cntry = *uc;
|
|
286 |
++cntry;
|
|
287 |
break;
|
|
288 |
}
|
|
289 |
|
|
290 |
++uc;
|
|
291 |
}
|
|
292 |
|
|
293 |
int lang_len = lang - lang_begin;
|
|
294 |
|
|
295 |
return lang_len == 2 || lang_len == 3;
|
|
296 |
}
|
|
297 |
|
|
298 |
void getLangAndCountry(const QString &name, QLocale::Language &lang, QLocale::Country &cntry)
|
|
299 |
{
|
|
300 |
lang = QLocale::C;
|
|
301 |
cntry = QLocale::AnyCountry;
|
|
302 |
|
|
303 |
QChar lang_code[3];
|
|
304 |
QChar cntry_code[2];
|
|
305 |
if (!splitLocaleName(name, lang_code, cntry_code))
|
|
306 |
return;
|
|
307 |
|
|
308 |
lang = codeToLanguage(lang_code);
|
|
309 |
if (lang == QLocale::C)
|
|
310 |
return;
|
|
311 |
|
|
312 |
if (cntry_code[0].unicode() != 0)
|
|
313 |
cntry = codeToCountry(cntry_code);
|
|
314 |
}
|
|
315 |
|
|
316 |
static const QLocalePrivate *findLocale(const QString &name)
|
|
317 |
{
|
|
318 |
QLocale::Language lang;
|
|
319 |
QLocale::Country cntry;
|
|
320 |
getLangAndCountry(name, lang, cntry);
|
|
321 |
|
|
322 |
return findLocale(lang, cntry);
|
|
323 |
}
|
|
324 |
static QString readEscapedFormatString(const QString &format, int *idx)
|
|
325 |
{
|
|
326 |
int &i = *idx;
|
|
327 |
|
|
328 |
Q_ASSERT(format.at(i) == QLatin1Char('\''));
|
|
329 |
++i;
|
|
330 |
if (i == format.size())
|
|
331 |
return QString();
|
|
332 |
if (format.at(i).unicode() == '\'') { // "''" outside of a quoted stirng
|
|
333 |
++i;
|
|
334 |
return QLatin1String("'");
|
|
335 |
}
|
|
336 |
|
|
337 |
QString result;
|
|
338 |
|
|
339 |
while (i < format.size()) {
|
|
340 |
if (format.at(i).unicode() == '\'') {
|
|
341 |
if (i + 1 < format.size() && format.at(i + 1).unicode() == '\'') {
|
|
342 |
// "''" inside of a quoted string
|
|
343 |
result.append(QLatin1Char('\''));
|
|
344 |
i += 2;
|
|
345 |
} else {
|
|
346 |
break;
|
|
347 |
}
|
|
348 |
} else {
|
|
349 |
result.append(format.at(i++));
|
|
350 |
}
|
|
351 |
}
|
|
352 |
if (i < format.size())
|
|
353 |
++i;
|
|
354 |
|
|
355 |
return result;
|
|
356 |
}
|
|
357 |
|
|
358 |
static int repeatCount(const QString &s, int i)
|
|
359 |
{
|
|
360 |
QChar c = s.at(i);
|
|
361 |
int j = i + 1;
|
|
362 |
while (j < s.size() && s.at(j) == c)
|
|
363 |
++j;
|
|
364 |
return j - i;
|
|
365 |
}
|
|
366 |
|
|
367 |
static const QLocalePrivate *default_lp = 0;
|
|
368 |
static uint default_number_options = 0;
|
|
369 |
|
|
370 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
371 |
static QByteArray envVarLocale()
|
|
372 |
{
|
|
373 |
static QByteArray lang = 0;
|
|
374 |
#ifdef Q_OS_UNIX
|
|
375 |
lang = qgetenv("LC_ALL");
|
|
376 |
if (lang.isNull())
|
|
377 |
lang = qgetenv("LC_NUMERIC");
|
|
378 |
if (lang.isNull())
|
|
379 |
#endif
|
|
380 |
lang = qgetenv("LANG");
|
|
381 |
return lang;
|
|
382 |
}
|
|
383 |
|
|
384 |
|
|
385 |
#if defined(Q_OS_WIN)
|
|
386 |
/******************************************************************************
|
|
387 |
** Wrappers for Windows locale system functions
|
|
388 |
*/
|
|
389 |
|
|
390 |
static const char *winLangCodeToIsoName(int code);
|
|
391 |
static QString winIso639LangName(LCID id = LOCALE_USER_DEFAULT);
|
|
392 |
static QString winIso3116CtryName(LCID id = LOCALE_USER_DEFAULT);
|
|
393 |
|
|
394 |
static QString getWinLocaleInfo(LCTYPE type)
|
|
395 |
{
|
|
396 |
LCID id = GetUserDefaultLCID();
|
|
397 |
int cnt = GetLocaleInfo(id, type, 0, 0) * 2;
|
|
398 |
|
|
399 |
if (cnt == 0) {
|
|
400 |
qWarning("QLocale: empty windows locale info (%d)", (int)type);
|
|
401 |
return QString();
|
|
402 |
}
|
|
403 |
|
|
404 |
QByteArray buff(cnt, 0);
|
|
405 |
|
|
406 |
cnt = GetLocaleInfo(id, type, reinterpret_cast<wchar_t*>(buff.data()), buff.size() / 2);
|
|
407 |
|
|
408 |
if (cnt == 0) {
|
|
409 |
qWarning("QLocale: empty windows locale info (%d)", (int)type);
|
|
410 |
return QString();
|
|
411 |
}
|
|
412 |
|
|
413 |
return QString::fromWCharArray(reinterpret_cast<const wchar_t *>(buff.data()));
|
|
414 |
}
|
|
415 |
|
|
416 |
QByteArray getWinLocaleName(LCID id = LOCALE_USER_DEFAULT)
|
|
417 |
{
|
|
418 |
QByteArray result;
|
|
419 |
if (id == LOCALE_USER_DEFAULT) {
|
|
420 |
result = envVarLocale();
|
|
421 |
QChar lang[3];
|
|
422 |
QChar cntry[2];
|
|
423 |
if ( result == "C" || (!result.isEmpty()
|
|
424 |
&& splitLocaleName(QString::fromLocal8Bit(result), lang, cntry)) ) {
|
|
425 |
long id = 0;
|
|
426 |
bool ok = false;
|
|
427 |
id = qstrtoll(result.data(), 0, 0, &ok);
|
|
428 |
if ( !ok || id == 0 || id < INT_MIN || id > INT_MAX )
|
|
429 |
return result;
|
|
430 |
else
|
|
431 |
return winLangCodeToIsoName( (int)id );
|
|
432 |
}
|
|
433 |
}
|
|
434 |
|
|
435 |
#if defined(Q_OS_WINCE)
|
|
436 |
result = winLangCodeToIsoName(id != LOCALE_USER_DEFAULT ? id : GetUserDefaultLCID());
|
|
437 |
#else
|
|
438 |
if (id == LOCALE_USER_DEFAULT)
|
|
439 |
id = GetUserDefaultLCID();
|
|
440 |
QString resultuage = winIso639LangName(id);
|
|
441 |
QString country = winIso3116CtryName(id);
|
|
442 |
result = resultuage.toLatin1();
|
|
443 |
if (!country.isEmpty()) {
|
|
444 |
result += '_';
|
|
445 |
result += country.toLatin1();
|
|
446 |
}
|
|
447 |
#endif
|
|
448 |
|
|
449 |
return result;
|
|
450 |
}
|
|
451 |
|
|
452 |
Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id)
|
|
453 |
{
|
|
454 |
return QLocale(QString::fromLatin1(getWinLocaleName(id)));
|
|
455 |
}
|
|
456 |
|
|
457 |
static QString winToQtFormat(const QString &sys_fmt)
|
|
458 |
{
|
|
459 |
QString result;
|
|
460 |
int i = 0;
|
|
461 |
|
|
462 |
while (i < sys_fmt.size()) {
|
|
463 |
if (sys_fmt.at(i).unicode() == QLatin1Char('\'')) {
|
|
464 |
QString text = readEscapedFormatString(sys_fmt, &i);
|
|
465 |
if (text == QLatin1String("'"))
|
|
466 |
result += QLatin1String("''");
|
|
467 |
else
|
|
468 |
result += QLatin1Char('\'') + text + QLatin1Char('\'');
|
|
469 |
continue;
|
|
470 |
}
|
|
471 |
|
|
472 |
QChar c = sys_fmt.at(i);
|
|
473 |
int repeat = repeatCount(sys_fmt, i);
|
|
474 |
|
|
475 |
switch (c.unicode()) {
|
|
476 |
// Date
|
|
477 |
case 'y':
|
|
478 |
if (repeat > 5)
|
|
479 |
repeat = 5;
|
|
480 |
else if (repeat == 3)
|
|
481 |
repeat = 2;
|
|
482 |
switch (repeat) {
|
|
483 |
case 1:
|
|
484 |
result += QLatin1String("yy"); // "y" unsupported by Qt, use "yy"
|
|
485 |
break;
|
|
486 |
case 5:
|
|
487 |
result += QLatin1String("yyyy"); // "yyyyy" same as "yyyy" on Windows
|
|
488 |
break;
|
|
489 |
default:
|
|
490 |
result += QString(repeat, QLatin1Char('y'));
|
|
491 |
break;
|
|
492 |
}
|
|
493 |
break;
|
|
494 |
case 'g':
|
|
495 |
if (repeat > 2)
|
|
496 |
repeat = 2;
|
|
497 |
switch (repeat) {
|
|
498 |
case 2:
|
|
499 |
break; // no equivalent of "gg" in Qt
|
|
500 |
default:
|
|
501 |
result += QLatin1Char('g');
|
|
502 |
break;
|
|
503 |
}
|
|
504 |
break;
|
|
505 |
case 't':
|
|
506 |
if (repeat > 2)
|
|
507 |
repeat = 2;
|
|
508 |
result += QLatin1String("AP"); // "t" unsupported, use "AP"
|
|
509 |
break;
|
|
510 |
default:
|
|
511 |
result += QString(repeat, c);
|
|
512 |
break;
|
|
513 |
}
|
|
514 |
|
|
515 |
i += repeat;
|
|
516 |
}
|
|
517 |
|
|
518 |
return result;
|
|
519 |
}
|
|
520 |
|
|
521 |
|
|
522 |
|
|
523 |
static QString winDateToString(const QDate &date, DWORD flags)
|
|
524 |
{
|
|
525 |
SYSTEMTIME st;
|
|
526 |
memset(&st, 0, sizeof(SYSTEMTIME));
|
|
527 |
st.wYear = date.year();
|
|
528 |
st.wMonth = date.month();
|
|
529 |
st.wDay = date.day();
|
|
530 |
|
|
531 |
LCID id = GetUserDefaultLCID();
|
|
532 |
|
|
533 |
wchar_t buf[255];
|
|
534 |
if (GetDateFormat(id, flags, &st, 0, buf, 255))
|
|
535 |
return QString::fromWCharArray(buf);
|
|
536 |
|
|
537 |
return QString();
|
|
538 |
}
|
|
539 |
|
|
540 |
static QString winTimeToString(const QTime &time)
|
|
541 |
{
|
|
542 |
SYSTEMTIME st;
|
|
543 |
memset(&st, 0, sizeof(SYSTEMTIME));
|
|
544 |
st.wHour = time.hour();
|
|
545 |
st.wMinute = time.minute();
|
|
546 |
st.wSecond = time.second();
|
|
547 |
st.wMilliseconds = 0;
|
|
548 |
|
|
549 |
DWORD flags = 0;
|
|
550 |
LCID id = GetUserDefaultLCID();
|
|
551 |
|
|
552 |
wchar_t buf[255];
|
|
553 |
if (GetTimeFormat(id, flags, &st, 0, buf, 255))
|
|
554 |
return QString::fromWCharArray(buf);
|
|
555 |
|
|
556 |
return QString();
|
|
557 |
}
|
|
558 |
|
|
559 |
static QString winDayName(int day, bool short_format)
|
|
560 |
{
|
|
561 |
static const LCTYPE short_day_map[]
|
|
562 |
= { LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2,
|
|
563 |
LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5,
|
|
564 |
LOCALE_SABBREVDAYNAME6, LOCALE_SABBREVDAYNAME7 };
|
|
565 |
|
|
566 |
static const LCTYPE long_day_map[]
|
|
567 |
= { LOCALE_SDAYNAME1, LOCALE_SDAYNAME2,
|
|
568 |
LOCALE_SDAYNAME3, LOCALE_SDAYNAME4, LOCALE_SDAYNAME5,
|
|
569 |
LOCALE_SDAYNAME6, LOCALE_SDAYNAME7 };
|
|
570 |
|
|
571 |
day -= 1;
|
|
572 |
|
|
573 |
LCTYPE type = short_format
|
|
574 |
? short_day_map[day] : long_day_map[day];
|
|
575 |
return getWinLocaleInfo(type);
|
|
576 |
}
|
|
577 |
|
|
578 |
static QString winMonthName(int month, bool short_format)
|
|
579 |
{
|
|
580 |
static const LCTYPE short_month_map[]
|
|
581 |
= { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
|
|
582 |
LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
|
|
583 |
LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
|
|
584 |
LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
|
|
585 |
|
|
586 |
static const LCTYPE long_month_map[]
|
|
587 |
= { LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3,
|
|
588 |
LOCALE_SMONTHNAME4, LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6,
|
|
589 |
LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8, LOCALE_SMONTHNAME9,
|
|
590 |
LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12 };
|
|
591 |
|
|
592 |
month -= 1;
|
|
593 |
if (month < 0 || month > 11)
|
|
594 |
return QString();
|
|
595 |
|
|
596 |
LCTYPE type = short_format ? short_month_map[month] : long_month_map[month];
|
|
597 |
return getWinLocaleInfo(type);
|
|
598 |
}
|
|
599 |
|
|
600 |
static QLocale::MeasurementSystem winSystemMeasurementSystem()
|
|
601 |
{
|
|
602 |
LCID id = GetUserDefaultLCID();
|
|
603 |
wchar_t output[2];
|
|
604 |
|
|
605 |
if (GetLocaleInfo(id, LOCALE_IMEASURE, output, 2)) {
|
|
606 |
QString iMeasure = QString::fromWCharArray(output);
|
|
607 |
if (iMeasure == QLatin1String("1")) {
|
|
608 |
return QLocale::ImperialSystem;
|
|
609 |
}
|
|
610 |
}
|
|
611 |
|
|
612 |
return QLocale::MetricSystem;
|
|
613 |
}
|
|
614 |
|
|
615 |
static QString winSystemAMText()
|
|
616 |
{
|
|
617 |
LCID id = GetUserDefaultLCID();
|
|
618 |
wchar_t output[15]; // maximum length including terminating zero character for Win2003+
|
|
619 |
|
|
620 |
if (GetLocaleInfo(id, LOCALE_S1159, output, 15)) {
|
|
621 |
return QString::fromWCharArray(output);
|
|
622 |
}
|
|
623 |
|
|
624 |
return QString();
|
|
625 |
}
|
|
626 |
|
|
627 |
static QString winSystemPMText()
|
|
628 |
{
|
|
629 |
LCID id = GetUserDefaultLCID();
|
|
630 |
wchar_t output[15]; // maximum length including terminating zero character for Win2003+
|
|
631 |
|
|
632 |
if (GetLocaleInfo(id, LOCALE_S2359, output, 15)) {
|
|
633 |
return QString::fromWCharArray(output);
|
|
634 |
}
|
|
635 |
|
|
636 |
return QString();
|
|
637 |
}
|
|
638 |
|
|
639 |
/*!
|
|
640 |
\since 4.6
|
|
641 |
Returns the fallback locale obtained from the system.
|
|
642 |
*/
|
|
643 |
QLocale QSystemLocale::fallbackLocale() const
|
|
644 |
{
|
|
645 |
return QLocale(QString::fromLatin1(getWinLocaleName()));
|
|
646 |
}
|
|
647 |
|
|
648 |
QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
|
|
649 |
{
|
|
650 |
LCTYPE locale_info = 0;
|
|
651 |
bool format_string = false;
|
|
652 |
|
|
653 |
switch(type) {
|
|
654 |
// case Name:
|
|
655 |
// return getWinLocaleName();
|
|
656 |
case DecimalPoint:
|
|
657 |
locale_info = LOCALE_SDECIMAL;
|
|
658 |
break;
|
|
659 |
case GroupSeparator:
|
|
660 |
locale_info = LOCALE_STHOUSAND;
|
|
661 |
break;
|
|
662 |
case NegativeSign:
|
|
663 |
locale_info = LOCALE_SNEGATIVESIGN;
|
|
664 |
break;
|
|
665 |
case PositiveSign:
|
|
666 |
locale_info = LOCALE_SPOSITIVESIGN;
|
|
667 |
break;
|
|
668 |
case DateFormatLong:
|
|
669 |
locale_info = LOCALE_SLONGDATE;
|
|
670 |
format_string = true;
|
|
671 |
break;
|
|
672 |
case DateFormatShort:
|
|
673 |
locale_info = LOCALE_SSHORTDATE;
|
|
674 |
format_string = true;
|
|
675 |
break;
|
|
676 |
case TimeFormatLong:
|
|
677 |
case TimeFormatShort:
|
|
678 |
locale_info = LOCALE_STIMEFORMAT;
|
|
679 |
format_string = true;
|
|
680 |
break;
|
|
681 |
|
|
682 |
case DateTimeFormatLong:
|
|
683 |
case DateTimeFormatShort:
|
|
684 |
return query(type == DateTimeFormatLong ? DateFormatLong : DateFormatShort).toString()
|
|
685 |
+ QLatin1Char(' ') + query(type == DateTimeFormatLong ? TimeFormatLong : TimeFormatShort).toString();
|
|
686 |
case DayNameLong:
|
|
687 |
case DayNameShort:
|
|
688 |
return winDayName(in.toInt(), (type == DayNameShort));
|
|
689 |
case MonthNameLong:
|
|
690 |
case MonthNameShort:
|
|
691 |
return winMonthName(in.toInt(), (type == MonthNameShort));
|
|
692 |
case DateToStringShort:
|
|
693 |
case DateToStringLong:
|
|
694 |
return winDateToString(in.toDate(), type == DateToStringShort ? DATE_SHORTDATE : DATE_LONGDATE);
|
|
695 |
case TimeToStringShort:
|
|
696 |
case TimeToStringLong:
|
|
697 |
return winTimeToString(in.toTime());
|
|
698 |
case DateTimeToStringShort:
|
|
699 |
case DateTimeToStringLong: {
|
|
700 |
const QDateTime dt = in.toDateTime();
|
|
701 |
return winDateToString(dt.date(), type == DateTimeToStringShort ? DATE_SHORTDATE : DATE_LONGDATE)
|
|
702 |
+ QLatin1Char(' ') + winTimeToString(dt.time()); }
|
|
703 |
|
|
704 |
case ZeroDigit:
|
|
705 |
locale_info = LOCALE_SNATIVEDIGITS;
|
|
706 |
break;
|
|
707 |
|
|
708 |
case LanguageId:
|
|
709 |
case CountryId: {
|
|
710 |
QString locale = QString::fromLatin1(getWinLocaleName());
|
|
711 |
QLocale::Language lang;
|
|
712 |
QLocale::Country cntry;
|
|
713 |
getLangAndCountry(locale, lang, cntry);
|
|
714 |
if (type == LanguageId)
|
|
715 |
return lang;
|
|
716 |
if (cntry == QLocale::AnyCountry)
|
|
717 |
return fallbackLocale().country();
|
|
718 |
return cntry;
|
|
719 |
}
|
|
720 |
|
|
721 |
case MeasurementSystem:
|
|
722 |
return QVariant(static_cast<int>(winSystemMeasurementSystem()));
|
|
723 |
|
|
724 |
case AMText:
|
|
725 |
return QVariant(winSystemAMText());
|
|
726 |
case PMText:
|
|
727 |
return QVariant(winSystemPMText());
|
|
728 |
default:
|
|
729 |
break;
|
|
730 |
}
|
|
731 |
if (locale_info) {
|
|
732 |
QString result = getWinLocaleInfo(locale_info);
|
|
733 |
if (format_string)
|
|
734 |
result = winToQtFormat(result);
|
|
735 |
if (!result.isEmpty())
|
|
736 |
return result;
|
|
737 |
}
|
|
738 |
return QVariant();
|
|
739 |
}
|
|
740 |
|
|
741 |
struct WindowsToISOListElt {
|
|
742 |
ushort windows_code;
|
|
743 |
char iso_name[6];
|
|
744 |
};
|
|
745 |
|
|
746 |
static const WindowsToISOListElt windows_to_iso_list[] = {
|
|
747 |
{ 0x0401, "ar_SA" },
|
|
748 |
{ 0x0402, "bg\0 " },
|
|
749 |
{ 0x0403, "ca\0 " },
|
|
750 |
{ 0x0404, "zh_TW" },
|
|
751 |
{ 0x0405, "cs\0 " },
|
|
752 |
{ 0x0406, "da\0 " },
|
|
753 |
{ 0x0407, "de\0 " },
|
|
754 |
{ 0x0408, "el\0 " },
|
|
755 |
{ 0x0409, "en_US" },
|
|
756 |
{ 0x040a, "es\0 " },
|
|
757 |
{ 0x040b, "fi\0 " },
|
|
758 |
{ 0x040c, "fr\0 " },
|
|
759 |
{ 0x040d, "he\0 " },
|
|
760 |
{ 0x040e, "hu\0 " },
|
|
761 |
{ 0x040f, "is\0 " },
|
|
762 |
{ 0x0410, "it\0 " },
|
|
763 |
{ 0x0411, "ja\0 " },
|
|
764 |
{ 0x0412, "ko\0 " },
|
|
765 |
{ 0x0413, "nl\0 " },
|
|
766 |
{ 0x0414, "no\0 " },
|
|
767 |
{ 0x0415, "pl\0 " },
|
|
768 |
{ 0x0416, "pt_BR" },
|
|
769 |
{ 0x0418, "ro\0 " },
|
|
770 |
{ 0x0419, "ru\0 " },
|
|
771 |
{ 0x041a, "hr\0 " },
|
|
772 |
{ 0x041c, "sq\0 " },
|
|
773 |
{ 0x041d, "sv\0 " },
|
|
774 |
{ 0x041e, "th\0 " },
|
|
775 |
{ 0x041f, "tr\0 " },
|
|
776 |
{ 0x0420, "ur\0 " },
|
|
777 |
{ 0x0421, "in\0 " },
|
|
778 |
{ 0x0422, "uk\0 " },
|
|
779 |
{ 0x0423, "be\0 " },
|
|
780 |
{ 0x0425, "et\0 " },
|
|
781 |
{ 0x0426, "lv\0 " },
|
|
782 |
{ 0x0427, "lt\0 " },
|
|
783 |
{ 0x0429, "fa\0 " },
|
|
784 |
{ 0x042a, "vi\0 " },
|
|
785 |
{ 0x042d, "eu\0 " },
|
|
786 |
{ 0x042f, "mk\0 " },
|
|
787 |
{ 0x0436, "af\0 " },
|
|
788 |
{ 0x0438, "fo\0 " },
|
|
789 |
{ 0x0439, "hi\0 " },
|
|
790 |
{ 0x043e, "ms\0 " },
|
|
791 |
{ 0x0458, "mt\0 " },
|
|
792 |
{ 0x0801, "ar_IQ" },
|
|
793 |
{ 0x0804, "zh_CN" },
|
|
794 |
{ 0x0807, "de_CH" },
|
|
795 |
{ 0x0809, "en_GB" },
|
|
796 |
{ 0x080a, "es_MX" },
|
|
797 |
{ 0x080c, "fr_BE" },
|
|
798 |
{ 0x0810, "it_CH" },
|
|
799 |
{ 0x0812, "ko\0 " },
|
|
800 |
{ 0x0813, "nl_BE" },
|
|
801 |
{ 0x0814, "no\0 " },
|
|
802 |
{ 0x0816, "pt\0 " },
|
|
803 |
{ 0x081a, "sr\0 " },
|
|
804 |
{ 0x081d, "sv_FI" },
|
|
805 |
{ 0x0c01, "ar_EG" },
|
|
806 |
{ 0x0c04, "zh_HK" },
|
|
807 |
{ 0x0c07, "de_AT" },
|
|
808 |
{ 0x0c09, "en_AU" },
|
|
809 |
{ 0x0c0a, "es\0 " },
|
|
810 |
{ 0x0c0c, "fr_CA" },
|
|
811 |
{ 0x0c1a, "sr\0 " },
|
|
812 |
{ 0x1001, "ar_LY" },
|
|
813 |
{ 0x1004, "zh_SG" },
|
|
814 |
{ 0x1007, "de_LU" },
|
|
815 |
{ 0x1009, "en_CA" },
|
|
816 |
{ 0x100a, "es_GT" },
|
|
817 |
{ 0x100c, "fr_CH" },
|
|
818 |
{ 0x1401, "ar_DZ" },
|
|
819 |
{ 0x1407, "de_LI" },
|
|
820 |
{ 0x1409, "en_NZ" },
|
|
821 |
{ 0x140a, "es_CR" },
|
|
822 |
{ 0x140c, "fr_LU" },
|
|
823 |
{ 0x1801, "ar_MA" },
|
|
824 |
{ 0x1809, "en_IE" },
|
|
825 |
{ 0x180a, "es_PA" },
|
|
826 |
{ 0x1c01, "ar_TN" },
|
|
827 |
{ 0x1c09, "en_ZA" },
|
|
828 |
{ 0x1c0a, "es_DO" },
|
|
829 |
{ 0x2001, "ar_OM" },
|
|
830 |
{ 0x2009, "en_JM" },
|
|
831 |
{ 0x200a, "es_VE" },
|
|
832 |
{ 0x2401, "ar_YE" },
|
|
833 |
{ 0x2409, "en\0 " },
|
|
834 |
{ 0x240a, "es_CO" },
|
|
835 |
{ 0x2801, "ar_SY" },
|
|
836 |
{ 0x2809, "en_BZ" },
|
|
837 |
{ 0x280a, "es_PE" },
|
|
838 |
{ 0x2c01, "ar_JO" },
|
|
839 |
{ 0x2c09, "en_TT" },
|
|
840 |
{ 0x2c0a, "es_AR" },
|
|
841 |
{ 0x3001, "ar_LB" },
|
|
842 |
{ 0x300a, "es_EC" },
|
|
843 |
{ 0x3401, "ar_KW" },
|
|
844 |
{ 0x340a, "es_CL" },
|
|
845 |
{ 0x3801, "ar_AE" },
|
|
846 |
{ 0x380a, "es_UY" },
|
|
847 |
{ 0x3c01, "ar_BH" },
|
|
848 |
{ 0x3c0a, "es_PY" },
|
|
849 |
{ 0x4001, "ar_QA" },
|
|
850 |
{ 0x400a, "es_BO" },
|
|
851 |
{ 0x440a, "es_SV" },
|
|
852 |
{ 0x480a, "es_HN" },
|
|
853 |
{ 0x4c0a, "es_NI" },
|
|
854 |
{ 0x500a, "es_PR" }
|
|
855 |
};
|
|
856 |
|
|
857 |
static const int windows_to_iso_count
|
|
858 |
= sizeof(windows_to_iso_list)/sizeof(WindowsToISOListElt);
|
|
859 |
|
|
860 |
static const char *winLangCodeToIsoName(int code)
|
|
861 |
{
|
|
862 |
int cmp = code - windows_to_iso_list[0].windows_code;
|
|
863 |
if (cmp < 0)
|
|
864 |
return 0;
|
|
865 |
|
|
866 |
if (cmp == 0)
|
|
867 |
return windows_to_iso_list[0].iso_name;
|
|
868 |
|
|
869 |
int begin = 0;
|
|
870 |
int end = windows_to_iso_count;
|
|
871 |
|
|
872 |
while (end - begin > 1) {
|
|
873 |
uint mid = (begin + end)/2;
|
|
874 |
|
|
875 |
const WindowsToISOListElt *elt = windows_to_iso_list + mid;
|
|
876 |
int cmp = code - elt->windows_code;
|
|
877 |
if (cmp < 0)
|
|
878 |
end = mid;
|
|
879 |
else if (cmp > 0)
|
|
880 |
begin = mid;
|
|
881 |
else
|
|
882 |
return elt->iso_name;
|
|
883 |
}
|
|
884 |
|
|
885 |
return 0;
|
|
886 |
|
|
887 |
}
|
|
888 |
|
|
889 |
static QString winIso639LangName(LCID id)
|
|
890 |
{
|
|
891 |
QString result;
|
|
892 |
|
|
893 |
// Windows returns the wrong ISO639 for some languages, we need to detect them here using
|
|
894 |
// the language code
|
|
895 |
QString lang_code;
|
|
896 |
wchar_t out[256];
|
|
897 |
if (GetLocaleInfo(id, LOCALE_ILANGUAGE, out, 255))
|
|
898 |
lang_code = QString::fromWCharArray(out);
|
|
899 |
|
|
900 |
if (!lang_code.isEmpty()) {
|
|
901 |
const char *endptr;
|
|
902 |
bool ok;
|
|
903 |
QByteArray latin1_lang_code = lang_code.toLatin1();
|
|
904 |
int i = qstrtoull(latin1_lang_code, &endptr, 16, &ok);
|
|
905 |
if (ok && *endptr == '\0') {
|
|
906 |
switch (i) {
|
|
907 |
case 0x814:
|
|
908 |
result = QLatin1String("nn"); // Nynorsk
|
|
909 |
break;
|
|
910 |
default:
|
|
911 |
break;
|
|
912 |
}
|
|
913 |
}
|
|
914 |
}
|
|
915 |
|
|
916 |
if (!result.isEmpty())
|
|
917 |
return result;
|
|
918 |
|
|
919 |
// not one of the problematic languages - do the usual lookup
|
|
920 |
if (GetLocaleInfo(id, LOCALE_SISO639LANGNAME , out, 255))
|
|
921 |
result = QString::fromWCharArray(out);
|
|
922 |
|
|
923 |
return result;
|
|
924 |
}
|
|
925 |
|
|
926 |
static QString winIso3116CtryName(LCID id)
|
|
927 |
{
|
|
928 |
QString result;
|
|
929 |
|
|
930 |
wchar_t out[256];
|
|
931 |
if (GetLocaleInfo(id, LOCALE_SISO3166CTRYNAME, out, 255))
|
|
932 |
result = QString::fromWCharArray(out);
|
|
933 |
|
|
934 |
return result;
|
|
935 |
}
|
|
936 |
|
|
937 |
|
|
938 |
#elif defined(Q_OS_MAC)
|
|
939 |
/******************************************************************************
|
|
940 |
** Wrappers for Mac locale system functions
|
|
941 |
*/
|
|
942 |
|
|
943 |
static QByteArray getMacLocaleName()
|
|
944 |
{
|
|
945 |
QByteArray result = envVarLocale();
|
|
946 |
|
|
947 |
QChar lang[3];
|
|
948 |
QChar cntry[2];
|
|
949 |
if (result.isEmpty() || result != "C"
|
|
950 |
&& !splitLocaleName(QString::fromLocal8Bit(result), lang, cntry)) {
|
|
951 |
QCFType<CFLocaleRef> l = CFLocaleCopyCurrent();
|
|
952 |
CFStringRef locale = CFLocaleGetIdentifier(l);
|
|
953 |
result = QCFString::toQString(locale).toUtf8();
|
|
954 |
}
|
|
955 |
return result;
|
|
956 |
}
|
|
957 |
|
|
958 |
static QString macMonthName(int month, bool short_format)
|
|
959 |
{
|
|
960 |
month -= 1;
|
|
961 |
if (month < 0 || month > 11)
|
|
962 |
return QString();
|
|
963 |
|
|
964 |
QCFType<CFDateFormatterRef> formatter
|
|
965 |
= CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()),
|
|
966 |
kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
|
|
967 |
QCFType<CFArrayRef> values
|
|
968 |
= static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter,
|
|
969 |
short_format ? kCFDateFormatterShortMonthSymbols
|
|
970 |
: kCFDateFormatterMonthSymbols));
|
|
971 |
if (values != 0) {
|
|
972 |
CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, month));
|
|
973 |
return QCFString::toQString(cfstring);
|
|
974 |
}
|
|
975 |
return QString();
|
|
976 |
}
|
|
977 |
|
|
978 |
|
|
979 |
static QString macDayName(int day, bool short_format)
|
|
980 |
{
|
|
981 |
if (day < 1 || day > 7)
|
|
982 |
return QString();
|
|
983 |
|
|
984 |
QCFType<CFDateFormatterRef> formatter
|
|
985 |
= CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()),
|
|
986 |
kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
|
|
987 |
QCFType<CFArrayRef> values = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter,
|
|
988 |
short_format ? kCFDateFormatterShortWeekdaySymbols
|
|
989 |
: kCFDateFormatterWeekdaySymbols));
|
|
990 |
if (values != 0) {
|
|
991 |
CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, day % 7));
|
|
992 |
return QCFString::toQString(cfstring);
|
|
993 |
}
|
|
994 |
return QString();
|
|
995 |
}
|
|
996 |
|
|
997 |
static QString macDateToString(const QDate &date, bool short_format)
|
|
998 |
{
|
|
999 |
CFGregorianDate macGDate;
|
|
1000 |
macGDate.year = date.year();
|
|
1001 |
macGDate.month = date.month();
|
|
1002 |
macGDate.day = date.day();
|
|
1003 |
macGDate.hour = 0;
|
|
1004 |
macGDate.minute = 0;
|
|
1005 |
macGDate.second = 0.0;
|
|
1006 |
QCFType<CFDateRef> myDate
|
|
1007 |
= CFDateCreate(0, CFGregorianDateGetAbsoluteTime(macGDate,
|
|
1008 |
QCFType<CFTimeZoneRef>(CFTimeZoneCopyDefault())));
|
|
1009 |
QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
|
|
1010 |
CFDateFormatterStyle style = short_format ? kCFDateFormatterShortStyle : kCFDateFormatterLongStyle;
|
|
1011 |
QCFType<CFDateFormatterRef> myFormatter
|
|
1012 |
= CFDateFormatterCreate(kCFAllocatorDefault,
|
|
1013 |
mylocale, style,
|
|
1014 |
kCFDateFormatterNoStyle);
|
|
1015 |
return QCFString(CFDateFormatterCreateStringWithDate(0, myFormatter, myDate));
|
|
1016 |
}
|
|
1017 |
|
|
1018 |
static QString macTimeToString(const QTime &time, bool short_format)
|
|
1019 |
{
|
|
1020 |
CFGregorianDate macGDate;
|
|
1021 |
// Assume this is local time and the current date
|
|
1022 |
QDate dt = QDate::currentDate();
|
|
1023 |
macGDate.year = dt.year();
|
|
1024 |
macGDate.month = dt.month();
|
|
1025 |
macGDate.day = dt.day();
|
|
1026 |
macGDate.hour = time.hour();
|
|
1027 |
macGDate.minute = time.minute();
|
|
1028 |
macGDate.second = time.second();
|
|
1029 |
QCFType<CFDateRef> myDate
|
|
1030 |
= CFDateCreate(0, CFGregorianDateGetAbsoluteTime(macGDate,
|
|
1031 |
QCFType<CFTimeZoneRef>(CFTimeZoneCopyDefault())));
|
|
1032 |
|
|
1033 |
QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
|
|
1034 |
CFDateFormatterStyle style = short_format ? kCFDateFormatterShortStyle : kCFDateFormatterLongStyle;
|
|
1035 |
QCFType<CFDateFormatterRef> myFormatter = CFDateFormatterCreate(kCFAllocatorDefault,
|
|
1036 |
mylocale,
|
|
1037 |
kCFDateFormatterNoStyle,
|
|
1038 |
style);
|
|
1039 |
return QCFString(CFDateFormatterCreateStringWithDate(0, myFormatter, myDate));
|
|
1040 |
}
|
|
1041 |
|
|
1042 |
static QString macToQtFormat(const QString &sys_fmt)
|
|
1043 |
{
|
|
1044 |
QString result;
|
|
1045 |
int i = 0;
|
|
1046 |
|
|
1047 |
while (i < sys_fmt.size()) {
|
|
1048 |
if (sys_fmt.at(i).unicode() == '\'') {
|
|
1049 |
QString text = readEscapedFormatString(sys_fmt, &i);
|
|
1050 |
if (text == QLatin1String("'"))
|
|
1051 |
result += QLatin1String("''");
|
|
1052 |
else
|
|
1053 |
result += QLatin1Char('\'') + text + QLatin1Char('\'');
|
|
1054 |
continue;
|
|
1055 |
}
|
|
1056 |
|
|
1057 |
QChar c = sys_fmt.at(i);
|
|
1058 |
int repeat = repeatCount(sys_fmt, i);
|
|
1059 |
|
|
1060 |
switch (c.unicode()) {
|
|
1061 |
case 'G': // Qt doesn't support these :(
|
|
1062 |
case 'Y':
|
|
1063 |
case 'D':
|
|
1064 |
case 'F':
|
|
1065 |
case 'w':
|
|
1066 |
case 'W':
|
|
1067 |
case 'g':
|
|
1068 |
break;
|
|
1069 |
|
|
1070 |
case 'u': // extended year - use 'y'
|
|
1071 |
if (repeat < 4)
|
|
1072 |
result += QLatin1String("yy");
|
|
1073 |
else
|
|
1074 |
result += QLatin1String("yyyy");
|
|
1075 |
break;
|
|
1076 |
case 'S': // fractional second
|
|
1077 |
if (repeat < 3)
|
|
1078 |
result += QLatin1Char('z');
|
|
1079 |
else
|
|
1080 |
result += QLatin1String("zzz");
|
|
1081 |
break;
|
|
1082 |
case 'E':
|
|
1083 |
if (repeat <= 3)
|
|
1084 |
result += QLatin1String("ddd");
|
|
1085 |
else
|
|
1086 |
result += QLatin1String("dddd");
|
|
1087 |
break;
|
|
1088 |
case 'e':
|
|
1089 |
if (repeat >= 2)
|
|
1090 |
result += QLatin1String("dd");
|
|
1091 |
else
|
|
1092 |
result += QLatin1Char('d');
|
|
1093 |
break;
|
|
1094 |
case 'a':
|
|
1095 |
result += QLatin1String("AP");
|
|
1096 |
break;
|
|
1097 |
case 'k':
|
|
1098 |
result += QString(repeat, QLatin1Char('H'));
|
|
1099 |
break;
|
|
1100 |
case 'K':
|
|
1101 |
result += QString(repeat, QLatin1Char('h'));
|
|
1102 |
break;
|
|
1103 |
case 'z':
|
|
1104 |
case 'Z':
|
|
1105 |
case 'v':
|
|
1106 |
result += QLatin1Char('t');
|
|
1107 |
break;
|
|
1108 |
default:
|
|
1109 |
result += QString(repeat, c);
|
|
1110 |
break;
|
|
1111 |
}
|
|
1112 |
|
|
1113 |
i += repeat;
|
|
1114 |
}
|
|
1115 |
|
|
1116 |
return result;
|
|
1117 |
}
|
|
1118 |
|
|
1119 |
QString getMacDateFormat(CFDateFormatterStyle style)
|
|
1120 |
{
|
|
1121 |
QCFType<CFLocaleRef> l = CFLocaleCopyCurrent();
|
|
1122 |
QCFType<CFDateFormatterRef> formatter = CFDateFormatterCreate(kCFAllocatorDefault,
|
|
1123 |
l, style, kCFDateFormatterNoStyle);
|
|
1124 |
return macToQtFormat(QCFString::toQString(CFDateFormatterGetFormat(formatter)));
|
|
1125 |
}
|
|
1126 |
|
|
1127 |
static QString getMacTimeFormat(CFDateFormatterStyle style)
|
|
1128 |
{
|
|
1129 |
QCFType<CFLocaleRef> l = CFLocaleCopyCurrent();
|
|
1130 |
QCFType<CFDateFormatterRef> formatter = CFDateFormatterCreate(kCFAllocatorDefault,
|
|
1131 |
l, kCFDateFormatterNoStyle, style);
|
|
1132 |
return macToQtFormat(QCFString::toQString(CFDateFormatterGetFormat(formatter)));
|
|
1133 |
}
|
|
1134 |
|
|
1135 |
static QString getCFLocaleValue(CFStringRef key)
|
|
1136 |
{
|
|
1137 |
QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
|
|
1138 |
CFTypeRef value = CFLocaleGetValue(locale, key);
|
|
1139 |
return QCFString::toQString(CFStringRef(static_cast<CFTypeRef>(value)));
|
|
1140 |
}
|
|
1141 |
|
|
1142 |
static QLocale::MeasurementSystem macMeasurementSystem()
|
|
1143 |
{
|
|
1144 |
QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
|
|
1145 |
CFStringRef system = static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleMeasurementSystem));
|
|
1146 |
if (QCFString::toQString(system) == QLatin1String("Metric")) {
|
|
1147 |
return QLocale::MetricSystem;
|
|
1148 |
} else {
|
|
1149 |
return QLocale::ImperialSystem;
|
|
1150 |
}
|
|
1151 |
}
|
|
1152 |
|
|
1153 |
static void getMacPreferredLanguageAndCountry(QString *language, QString *country)
|
|
1154 |
{
|
|
1155 |
QCFType<CFArrayRef> languages = (CFArrayRef)CFPreferencesCopyValue(
|
|
1156 |
CFSTR("AppleLanguages"),
|
|
1157 |
kCFPreferencesAnyApplication,
|
|
1158 |
kCFPreferencesCurrentUser,
|
|
1159 |
kCFPreferencesAnyHost);
|
|
1160 |
if (languages && CFArrayGetCount(languages) > 0) {
|
|
1161 |
QCFType<CFLocaleRef> locale = CFLocaleCreate(kCFAllocatorDefault,
|
|
1162 |
CFStringRef(CFArrayGetValueAtIndex(languages, 0)));
|
|
1163 |
if (language)
|
|
1164 |
*language = QCFString::toQString(CFStringRef(CFLocaleGetValue(locale, kCFLocaleLanguageCode)));
|
|
1165 |
if (country)
|
|
1166 |
*country = QCFString::toQString(CFStringRef(CFLocaleGetValue(locale, kCFLocaleCountryCode)));
|
|
1167 |
}
|
|
1168 |
}
|
|
1169 |
|
|
1170 |
QLocale QSystemLocale::fallbackLocale() const
|
|
1171 |
{
|
|
1172 |
return QLocale(QString::fromUtf8(getMacLocaleName().constData()));
|
|
1173 |
}
|
|
1174 |
|
|
1175 |
QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
|
|
1176 |
{
|
|
1177 |
switch(type) {
|
|
1178 |
// case Name:
|
|
1179 |
// return getMacLocaleName();
|
|
1180 |
case DecimalPoint: {
|
|
1181 |
QString value = getCFLocaleValue(kCFLocaleDecimalSeparator);
|
|
1182 |
return value.isEmpty() ? QVariant() : value;
|
|
1183 |
}
|
|
1184 |
case GroupSeparator: {
|
|
1185 |
QString value = getCFLocaleValue(kCFLocaleGroupingSeparator);
|
|
1186 |
return value.isEmpty() ? QVariant() : value;
|
|
1187 |
}
|
|
1188 |
case DateFormatLong:
|
|
1189 |
case DateFormatShort:
|
|
1190 |
return macToQtFormat(getMacDateFormat(type == DateFormatShort
|
|
1191 |
? kCFDateFormatterShortStyle
|
|
1192 |
: kCFDateFormatterLongStyle));
|
|
1193 |
case TimeFormatLong:
|
|
1194 |
case TimeFormatShort:
|
|
1195 |
return macToQtFormat(getMacTimeFormat(type == TimeFormatShort
|
|
1196 |
? kCFDateFormatterShortStyle
|
|
1197 |
: kCFDateFormatterLongStyle));
|
|
1198 |
case DayNameLong:
|
|
1199 |
case DayNameShort:
|
|
1200 |
return macDayName(in.toInt(), (type == DayNameShort));
|
|
1201 |
case MonthNameLong:
|
|
1202 |
case MonthNameShort:
|
|
1203 |
return macMonthName(in.toInt(), (type == MonthNameShort));
|
|
1204 |
case DateToStringShort:
|
|
1205 |
case DateToStringLong:
|
|
1206 |
return macDateToString(in.toDate(), (type == DateToStringShort));
|
|
1207 |
case TimeToStringShort:
|
|
1208 |
case TimeToStringLong:
|
|
1209 |
return macTimeToString(in.toTime(), (type == TimeToStringShort));
|
|
1210 |
|
|
1211 |
case NegativeSign:
|
|
1212 |
case PositiveSign:
|
|
1213 |
case ZeroDigit:
|
|
1214 |
break;
|
|
1215 |
case LanguageId:
|
|
1216 |
case CountryId: {
|
|
1217 |
QString preferredLanguage;
|
|
1218 |
QString preferredCountry;
|
|
1219 |
getMacPreferredLanguageAndCountry(&preferredLanguage, &preferredCountry);
|
|
1220 |
QLocale::Language languageCode = (preferredLanguage.isEmpty() ? QLocale::C : codeToLanguage(preferredLanguage.data()));
|
|
1221 |
QLocale::Country countryCode = (preferredCountry.isEmpty() ? QLocale::AnyCountry : codeToCountry(preferredCountry.data()));
|
|
1222 |
const QLocalePrivate *d = findLocale(languageCode, countryCode);
|
|
1223 |
if (type == LanguageId)
|
|
1224 |
return (QLocale::Language)d->languageId();
|
|
1225 |
return (QLocale::Country)d->countryId();
|
|
1226 |
}
|
|
1227 |
|
|
1228 |
case MeasurementSystem:
|
|
1229 |
return QVariant(static_cast<int>(macMeasurementSystem()));
|
|
1230 |
|
|
1231 |
case AMText:
|
|
1232 |
case PMText:
|
|
1233 |
break;
|
|
1234 |
default:
|
|
1235 |
break;
|
|
1236 |
}
|
|
1237 |
return QVariant();
|
|
1238 |
}
|
|
1239 |
|
|
1240 |
#elif defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
|
|
1241 |
|
|
1242 |
static uint unixGetSystemMeasurementSystem()
|
|
1243 |
{
|
|
1244 |
QString meas_locale = QString::fromLocal8Bit(qgetenv("LC_ALL"));
|
|
1245 |
if (meas_locale.isEmpty()) {
|
|
1246 |
meas_locale = QString::fromLocal8Bit(qgetenv("LC_MEASUREMENT"));
|
|
1247 |
}
|
|
1248 |
if (meas_locale.isEmpty()) {
|
|
1249 |
meas_locale = QString::fromLocal8Bit(qgetenv("LANG"));
|
|
1250 |
}
|
|
1251 |
if (meas_locale.isEmpty()) {
|
|
1252 |
meas_locale = QString::fromLocal8Bit("C");
|
|
1253 |
}
|
|
1254 |
|
|
1255 |
if (meas_locale.compare(QString::fromLocal8Bit("Metric"), Qt::CaseInsensitive) == 0)
|
|
1256 |
return 0;
|
|
1257 |
if (meas_locale.compare(QString::fromLocal8Bit("Other"), Qt::CaseInsensitive) == 0)
|
|
1258 |
return 0;
|
|
1259 |
|
|
1260 |
const QLocalePrivate* locale = findLocale(meas_locale);
|
|
1261 |
return locale->measurementSystem();
|
|
1262 |
}
|
|
1263 |
|
|
1264 |
/*!
|
|
1265 |
\internal
|
|
1266 |
*/
|
|
1267 |
QLocale QSystemLocale::fallbackLocale() const
|
|
1268 |
{
|
|
1269 |
return QLocale(QLatin1String(envVarLocale()));
|
|
1270 |
}
|
|
1271 |
|
|
1272 |
/*!
|
|
1273 |
\internal
|
|
1274 |
*/
|
|
1275 |
QVariant QSystemLocale::query(QueryType type, QVariant /* in */) const
|
|
1276 |
{
|
|
1277 |
if (type == MeasurementSystem) {
|
|
1278 |
return QVariant(unixGetSystemMeasurementSystem());
|
|
1279 |
} else {
|
|
1280 |
return QVariant();
|
|
1281 |
}
|
|
1282 |
}
|
|
1283 |
|
|
1284 |
#elif !defined(Q_OS_SYMBIAN)
|
|
1285 |
|
|
1286 |
/*!
|
|
1287 |
\since 4.6
|
|
1288 |
|
|
1289 |
Returns a fallback locale, that will get used for everything that
|
|
1290 |
is not explicitly overridden by the system locale.
|
|
1291 |
*/
|
|
1292 |
QLocale QSystemLocale::fallbackLocale() const
|
|
1293 |
{
|
|
1294 |
return QLocale(QLatin1String(envVarLocale()));
|
|
1295 |
}
|
|
1296 |
|
|
1297 |
/*!
|
|
1298 |
Performs a query of the given \a type in the system locale for
|
|
1299 |
customized values or conversion. If the method returns a null
|
|
1300 |
QVariant, the conversion of the fallbackLocale() will be used.
|
|
1301 |
|
|
1302 |
\a in is unused for some of the query types.
|
|
1303 |
|
|
1304 |
\sa QSystemLocale::QueryType
|
|
1305 |
*/
|
|
1306 |
QVariant QSystemLocale::query(QueryType /* type */, QVariant /* in */) const
|
|
1307 |
{
|
|
1308 |
return QVariant();
|
|
1309 |
}
|
|
1310 |
|
|
1311 |
#endif
|
|
1312 |
|
|
1313 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
1314 |
static QSystemLocale *_systemLocale = 0;
|
|
1315 |
Q_GLOBAL_STATIC_WITH_ARGS(QSystemLocale, QSystemLocale_globalSystemLocale, (true))
|
|
1316 |
static QLocalePrivate *system_lp = 0;
|
|
1317 |
Q_GLOBAL_STATIC(QLocalePrivate, globalLocalePrivate)
|
|
1318 |
#endif
|
|
1319 |
|
|
1320 |
/******************************************************************************
|
|
1321 |
** Default system locale behavior
|
|
1322 |
*/
|
|
1323 |
|
|
1324 |
/*!
|
|
1325 |
\class QSystemLocale
|
|
1326 |
\brief The QSystemLocale class can be used to finetune the system locale
|
|
1327 |
of the user.
|
|
1328 |
\since 4.2
|
|
1329 |
|
|
1330 |
\ingroup i18n
|
|
1331 |
|
|
1332 |
\warning This class is only useful in very rare cases. Usually QLocale offers
|
|
1333 |
all the functionality required for application development.
|
|
1334 |
|
|
1335 |
QSystemLocale allows to override the values provided by the system
|
|
1336 |
locale (QLocale::system()).
|
|
1337 |
|
|
1338 |
\sa QLocale
|
|
1339 |
*/
|
|
1340 |
|
|
1341 |
/*!
|
|
1342 |
\enum QSystemLocale::QueryType
|
|
1343 |
|
|
1344 |
Specifies the type of information queried by query(). For each value
|
|
1345 |
the type of information to return from the query() method is listed.
|
|
1346 |
|
|
1347 |
\value LanguageId a uint specifying the language.
|
|
1348 |
\value CountryId a uint specifying the country.
|
|
1349 |
\value DecimalPoint a QString specifying the decimal point.
|
|
1350 |
\value GroupSeparator a QString specifying the group separator.
|
|
1351 |
\value ZeroDigit a QString specifying the zero digit.
|
|
1352 |
\value NegativeSign a QString specifying the minus sign.
|
|
1353 |
\value PositiveSign a QString specifying the plus sign.
|
|
1354 |
\value DateFormatLong a QString specifying the long date format
|
|
1355 |
\value DateFormatShort a QString specifying the short date format
|
|
1356 |
\value TimeFormatLong a QString specifying the long time format
|
|
1357 |
\value TimeFormatShort a QString specifying the short time format
|
|
1358 |
\value DayNameLong a QString specifying the name of a weekday. the in variant contains an integer between 1 and 7 (Monday - Sunday)
|
|
1359 |
\value DayNameShort a QString specifying the short name of a weekday. the in variant contains an integer between 1 and 7 (Monday - Sunday)
|
|
1360 |
\value MonthNameLong a QString specifying the name of a month. the in variant contains an integer between 1 and 12
|
|
1361 |
\value MonthNameShort a QString specifying the short name of a month. the in variant contains an integer between 1 and 12
|
|
1362 |
\value DateToStringLong converts the QDate stored in the in variant to a QString using the long date format
|
|
1363 |
\value DateToStringShort converts the QDate stored in the in variant to a QString using the short date format
|
|
1364 |
\value TimeToStringLong converts the QTime stored in the in variant to a QString using the long time format
|
|
1365 |
\value TimeToStringShort converts the QTime stored in the in variant to a QString using the short time format
|
|
1366 |
\value DateTimeFormatLong a QString specifying the long date time format
|
|
1367 |
\value DateTimeFormatShort a QString specifying the short date time format
|
|
1368 |
\value DateTimeToStringLong converts the QDateTime in the in variant to a QString using the long datetime format
|
|
1369 |
\value DateTimeToStringShort converts the QDateTime in the in variant to a QString using the short datetime format
|
|
1370 |
\value MeasurementSystem a QLocale::MeasurementSystem enum specifying the measurement system
|
|
1371 |
\value AMText a string that represents the system AM designator associated with a 12-hour clock.
|
|
1372 |
\value PMText a string that represents the system PM designator associated with a 12-hour clock.
|
|
1373 |
*/
|
|
1374 |
|
|
1375 |
/*!
|
|
1376 |
Constructs a QSystemLocale object. The constructor will automatically
|
|
1377 |
install this object as the system locale and remove any earlier installed
|
|
1378 |
system locales.
|
|
1379 |
*/
|
|
1380 |
QSystemLocale::QSystemLocale()
|
|
1381 |
{
|
|
1382 |
delete _systemLocale;
|
|
1383 |
_systemLocale = this;
|
|
1384 |
|
|
1385 |
if (system_lp)
|
|
1386 |
system_lp->m_language_id = 0;
|
|
1387 |
}
|
|
1388 |
|
|
1389 |
/*! \internal */
|
|
1390 |
QSystemLocale::QSystemLocale(bool)
|
|
1391 |
{ }
|
|
1392 |
|
|
1393 |
/*!
|
|
1394 |
Deletes the object.
|
|
1395 |
*/
|
|
1396 |
QSystemLocale::~QSystemLocale()
|
|
1397 |
{
|
|
1398 |
if (_systemLocale == this) {
|
|
1399 |
_systemLocale = 0;
|
|
1400 |
|
|
1401 |
if (system_lp)
|
|
1402 |
system_lp->m_language_id = 0;
|
|
1403 |
}
|
|
1404 |
}
|
|
1405 |
|
|
1406 |
static const QSystemLocale *systemLocale()
|
|
1407 |
{
|
|
1408 |
if (_systemLocale)
|
|
1409 |
return _systemLocale;
|
|
1410 |
return QSystemLocale_globalSystemLocale();
|
|
1411 |
}
|
|
1412 |
|
|
1413 |
void QLocalePrivate::updateSystemPrivate()
|
|
1414 |
{
|
|
1415 |
const QSystemLocale *sys_locale = systemLocale();
|
|
1416 |
if (!system_lp)
|
|
1417 |
system_lp = globalLocalePrivate();
|
|
1418 |
*system_lp = *sys_locale->fallbackLocale().d();
|
|
1419 |
|
|
1420 |
QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant());
|
|
1421 |
if (!res.isNull())
|
|
1422 |
system_lp->m_language_id = res.toInt();
|
|
1423 |
res = sys_locale->query(QSystemLocale::CountryId, QVariant());
|
|
1424 |
if (!res.isNull())
|
|
1425 |
system_lp->m_country_id = res.toInt();
|
|
1426 |
|
|
1427 |
res = sys_locale->query(QSystemLocale::DecimalPoint, QVariant());
|
|
1428 |
if (!res.isNull())
|
|
1429 |
system_lp->m_decimal = res.toString().at(0).unicode();
|
|
1430 |
|
|
1431 |
res = sys_locale->query(QSystemLocale::GroupSeparator, QVariant());
|
|
1432 |
if (!res.isNull())
|
|
1433 |
system_lp->m_group = res.toString().at(0).unicode();
|
|
1434 |
|
|
1435 |
res = sys_locale->query(QSystemLocale::ZeroDigit, QVariant());
|
|
1436 |
if (!res.isNull())
|
|
1437 |
system_lp->m_zero = res.toString().at(0).unicode();
|
|
1438 |
|
|
1439 |
res = sys_locale->query(QSystemLocale::NegativeSign, QVariant());
|
|
1440 |
if (!res.isNull())
|
|
1441 |
system_lp->m_minus = res.toString().at(0).unicode();
|
|
1442 |
|
|
1443 |
res = sys_locale->query(QSystemLocale::PositiveSign, QVariant());
|
|
1444 |
if (!res.isNull())
|
|
1445 |
system_lp->m_plus = res.toString().at(0).unicode();
|
|
1446 |
}
|
|
1447 |
#endif
|
|
1448 |
|
|
1449 |
static const QLocalePrivate *systemPrivate()
|
|
1450 |
{
|
|
1451 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
1452 |
// copy over the information from the fallback locale and modify
|
|
1453 |
if (!system_lp || system_lp->m_language_id == 0)
|
|
1454 |
QLocalePrivate::updateSystemPrivate();
|
|
1455 |
|
|
1456 |
return system_lp;
|
|
1457 |
#else
|
|
1458 |
return locale_data;
|
|
1459 |
#endif
|
|
1460 |
}
|
|
1461 |
|
|
1462 |
static const QLocalePrivate *defaultPrivate()
|
|
1463 |
{
|
|
1464 |
if (!default_lp)
|
|
1465 |
default_lp = systemPrivate();
|
|
1466 |
return default_lp;
|
|
1467 |
}
|
|
1468 |
|
|
1469 |
static QString getLocaleListData(const ushort *data, int size, int index)
|
|
1470 |
{
|
|
1471 |
static const ushort separator = ';';
|
|
1472 |
while (index && size > 0) {
|
|
1473 |
while (*data != separator)
|
|
1474 |
++data, --size;
|
|
1475 |
--index;
|
|
1476 |
++data;
|
|
1477 |
--size;
|
|
1478 |
}
|
|
1479 |
const ushort *end = data;
|
|
1480 |
while (size > 0 && *end != separator)
|
|
1481 |
++end, --size;
|
|
1482 |
return QString::fromRawData(reinterpret_cast<const QChar*>(data), end-data);
|
|
1483 |
}
|
|
1484 |
|
|
1485 |
static inline QString getLocaleData(const ushort *data, int size)
|
|
1486 |
{
|
|
1487 |
return QString::fromRawData(reinterpret_cast<const QChar*>(data), size);
|
|
1488 |
}
|
|
1489 |
|
|
1490 |
|
|
1491 |
#ifndef QT_NO_DATASTREAM
|
|
1492 |
QDataStream &operator<<(QDataStream &ds, const QLocale &l)
|
|
1493 |
{
|
|
1494 |
ds << l.name();
|
|
1495 |
return ds;
|
|
1496 |
}
|
|
1497 |
|
|
1498 |
QDataStream &operator>>(QDataStream &ds, QLocale &l)
|
|
1499 |
{
|
|
1500 |
QString s;
|
|
1501 |
ds >> s;
|
|
1502 |
l = QLocale(s);
|
|
1503 |
return ds;
|
|
1504 |
}
|
|
1505 |
#endif // QT_NO_DATASTREAM
|
|
1506 |
|
|
1507 |
|
|
1508 |
/*!
|
|
1509 |
\class QLocale
|
|
1510 |
\brief The QLocale class converts between numbers and their
|
|
1511 |
string representations in various languages.
|
|
1512 |
|
|
1513 |
\reentrant
|
|
1514 |
\ingroup i18n
|
|
1515 |
\ingroup string-processing
|
|
1516 |
\ingroup shared
|
|
1517 |
|
|
1518 |
|
|
1519 |
QLocale is initialized with a language/country pair in its
|
|
1520 |
constructor and offers number-to-string and string-to-number
|
|
1521 |
conversion functions similar to those in QString.
|
|
1522 |
|
|
1523 |
Example:
|
|
1524 |
|
|
1525 |
\snippet doc/src/snippets/code/src_corelib_tools_qlocale.cpp 0
|
|
1526 |
|
|
1527 |
QLocale supports the concept of a default locale, which is
|
|
1528 |
determined from the system's locale settings at application
|
|
1529 |
startup. The default locale can be changed by calling the
|
|
1530 |
static member setDefault(). Setting the default locale has the
|
|
1531 |
following effects:
|
|
1532 |
|
|
1533 |
\list
|
|
1534 |
\i If a QLocale object is constructed with the default constructor,
|
|
1535 |
it will use the default locale's settings.
|
|
1536 |
\i QString::toInt(), QString::toDouble(), etc., interpret the
|
|
1537 |
string according to the default locale. If this fails, it
|
|
1538 |
falls back on the "C" locale.
|
|
1539 |
\i QString::arg() uses the default locale to format a number when
|
|
1540 |
its position specifier in the format string contains an 'L',
|
|
1541 |
e.g. "%L1".
|
|
1542 |
\endlist
|
|
1543 |
|
|
1544 |
The following example illustrates how to use QLocale directly:
|
|
1545 |
|
|
1546 |
\snippet doc/src/snippets/code/src_corelib_tools_qlocale.cpp 1
|
|
1547 |
|
|
1548 |
When a language/country pair is specified in the constructor, one
|
|
1549 |
of three things can happen:
|
|
1550 |
|
|
1551 |
\list
|
|
1552 |
\i If the language/country pair is found in the database, it is used.
|
|
1553 |
\i If the language is found but the country is not, or if the country
|
|
1554 |
is \c AnyCountry, the language is used with the most
|
|
1555 |
appropriate available country (for example, Germany for German),
|
|
1556 |
\i If neither the language nor the country are found, QLocale
|
|
1557 |
defaults to the default locale (see setDefault()).
|
|
1558 |
\endlist
|
|
1559 |
|
|
1560 |
The "C" locale is identical in behavior to \l{English}/\l{UnitedStates}.
|
|
1561 |
|
|
1562 |
Use language() and country() to determine the actual language and
|
|
1563 |
country values used.
|
|
1564 |
|
|
1565 |
An alternative method for constructing a QLocale object is by
|
|
1566 |
specifying the locale name.
|
|
1567 |
|
|
1568 |
\snippet doc/src/snippets/code/src_corelib_tools_qlocale.cpp 2
|
|
1569 |
|
|
1570 |
This constructor converts the locale name to a language/country
|
|
1571 |
pair; it does not use the system locale database.
|
|
1572 |
|
|
1573 |
QLocale's data is based on Common Locale Data Repository v1.6.1.
|
|
1574 |
|
|
1575 |
The double-to-string and string-to-double conversion functions are
|
|
1576 |
covered by the following licenses:
|
|
1577 |
|
|
1578 |
\legalese
|
|
1579 |
Copyright (c) 1991 by AT&T.
|
|
1580 |
|
|
1581 |
Permission to use, copy, modify, and distribute this software for any
|
|
1582 |
purpose without fee is hereby granted, provided that this entire notice
|
|
1583 |
is included in all copies of any software which is or includes a copy
|
|
1584 |
or modification of this software and in all copies of the supporting
|
|
1585 |
documentation for such software.
|
|
1586 |
|
|
1587 |
THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
|
1588 |
WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
|
|
1589 |
REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
|
1590 |
OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
|
1591 |
|
|
1592 |
This product includes software developed by the University of
|
|
1593 |
California, Berkeley and its contributors.
|
|
1594 |
|
|
1595 |
\sa QString::arg(), QString::toInt(), QString::toDouble()
|
|
1596 |
*/
|
|
1597 |
|
|
1598 |
/*!
|
|
1599 |
\enum QLocale::Language
|
|
1600 |
|
|
1601 |
This enumerated type is used to specify a language.
|
|
1602 |
|
|
1603 |
\value C The "C" locale is identical in behavior to English/UnitedStates.
|
|
1604 |
\value Abkhazian
|
|
1605 |
\value Afan
|
|
1606 |
\value Afar
|
|
1607 |
\value Afrikaans
|
|
1608 |
\value Albanian
|
|
1609 |
\value Amharic
|
|
1610 |
\value Arabic
|
|
1611 |
\value Armenian
|
|
1612 |
\value Assamese
|
|
1613 |
\value Aymara
|
|
1614 |
\value Azerbaijani
|
|
1615 |
\value Bashkir
|
|
1616 |
\value Basque
|
|
1617 |
\value Bengali
|
|
1618 |
\value Bhutani
|
|
1619 |
\value Bihari
|
|
1620 |
\value Bislama
|
|
1621 |
\value Bosnian
|
|
1622 |
\value Breton
|
|
1623 |
\value Bulgarian
|
|
1624 |
\value Burmese
|
|
1625 |
\value Byelorussian
|
|
1626 |
\value Cambodian
|
|
1627 |
\value Catalan
|
|
1628 |
\value Chinese
|
|
1629 |
\value Cornish
|
|
1630 |
\value Corsican
|
|
1631 |
\value Croatian
|
|
1632 |
\value Czech
|
|
1633 |
\value Danish
|
|
1634 |
\value Divehi
|
|
1635 |
\value Dutch
|
|
1636 |
\value English
|
|
1637 |
\value Esperanto
|
|
1638 |
\value Estonian
|
|
1639 |
\value Faroese
|
|
1640 |
\value FijiLanguage
|
|
1641 |
\value Finnish
|
|
1642 |
\value French
|
|
1643 |
\value Frisian
|
|
1644 |
\value Gaelic
|
|
1645 |
\value Galician
|
|
1646 |
\value Georgian
|
|
1647 |
\value German
|
|
1648 |
\value Greek
|
|
1649 |
\value Greenlandic
|
|
1650 |
\value Guarani
|
|
1651 |
\value Gujarati
|
|
1652 |
\value Hausa
|
|
1653 |
\value Hebrew
|
|
1654 |
\value Hindi
|
|
1655 |
\value Hungarian
|
|
1656 |
\value Icelandic
|
|
1657 |
\value Indonesian
|
|
1658 |
\value Interlingua
|
|
1659 |
\value Interlingue
|
|
1660 |
\value Inuktitut
|
|
1661 |
\value Inupiak
|
|
1662 |
\value Irish
|
|
1663 |
\value Italian
|
|
1664 |
\value Japanese
|
|
1665 |
\value Javanese
|
|
1666 |
\value Kannada
|
|
1667 |
\value Kashmiri
|
|
1668 |
\value Kazakh
|
|
1669 |
\value Kinyarwanda
|
|
1670 |
\value Kirghiz
|
|
1671 |
\value Korean
|
|
1672 |
\value Kurdish
|
|
1673 |
\value Kurundi
|
|
1674 |
\value Laothian
|
|
1675 |
\value Latin
|
|
1676 |
\value Latvian
|
|
1677 |
\value Lingala
|
|
1678 |
\value Lithuanian
|
|
1679 |
\value Macedonian
|
|
1680 |
\value Malagasy
|
|
1681 |
\value Malay
|
|
1682 |
\value Malayalam
|
|
1683 |
\value Maltese
|
|
1684 |
\value Manx
|
|
1685 |
\value Maori
|
|
1686 |
\value Marathi
|
|
1687 |
\value Moldavian
|
|
1688 |
\value Mongolian
|
|
1689 |
\value NauruLanguage
|
|
1690 |
\value Nepali
|
|
1691 |
\value Norwegian
|
|
1692 |
\value NorwegianBokmal
|
|
1693 |
\value Nynorsk Obsolete, please use NorwegianNynorsk
|
|
1694 |
\value NorwegianNynorsk
|
|
1695 |
\value Occitan
|
|
1696 |
\value Oriya
|
|
1697 |
\value Pashto
|
|
1698 |
\value Persian
|
|
1699 |
\value Polish
|
|
1700 |
\value Portuguese
|
|
1701 |
\value Punjabi
|
|
1702 |
\value Quechua
|
|
1703 |
\value RhaetoRomance
|
|
1704 |
\value Romanian
|
|
1705 |
\value Russian
|
|
1706 |
\value Samoan
|
|
1707 |
\value Sangho
|
|
1708 |
\value Sanskrit
|
|
1709 |
\value Serbian
|
|
1710 |
\value SerboCroatian
|
|
1711 |
\value Sesotho
|
|
1712 |
\value Setswana
|
|
1713 |
\value Shona
|
|
1714 |
\value Sindhi
|
|
1715 |
\value Singhalese
|
|
1716 |
\value Siswati
|
|
1717 |
\value Slovak
|
|
1718 |
\value Slovenian
|
|
1719 |
\value Somali
|
|
1720 |
\value Spanish
|
|
1721 |
\value Sundanese
|
|
1722 |
\value Swahili
|
|
1723 |
\value Swedish
|
|
1724 |
\value Tagalog
|
|
1725 |
\value Tajik
|
|
1726 |
\value Tamil
|
|
1727 |
\value Tatar
|
|
1728 |
\value Telugu
|
|
1729 |
\value Thai
|
|
1730 |
\value Tibetan
|
|
1731 |
\value Tigrinya
|
|
1732 |
\value TongaLanguage
|
|
1733 |
\value Tsonga
|
|
1734 |
\value Turkish
|
|
1735 |
\value Turkmen
|
|
1736 |
\value Twi
|
|
1737 |
\value Uigur
|
|
1738 |
\value Ukrainian
|
|
1739 |
\value Urdu
|
|
1740 |
\value Uzbek
|
|
1741 |
\value Vietnamese
|
|
1742 |
\value Volapuk
|
|
1743 |
\value Welsh
|
|
1744 |
\value Wolof
|
|
1745 |
\value Xhosa
|
|
1746 |
\value Yiddish
|
|
1747 |
\value Yoruba
|
|
1748 |
\value Zhuang
|
|
1749 |
\value Zulu
|
|
1750 |
\value Bosnian
|
|
1751 |
\value Divehi
|
|
1752 |
\value Manx
|
|
1753 |
\value Cornish
|
|
1754 |
\value Akan
|
|
1755 |
\value Konkani
|
|
1756 |
\value Ga
|
|
1757 |
\value Igbo
|
|
1758 |
\value Kamba
|
|
1759 |
\value Syriac
|
|
1760 |
\value Blin
|
|
1761 |
\value Geez
|
|
1762 |
\value Koro
|
|
1763 |
\value Sidamo
|
|
1764 |
\value Atsam
|
|
1765 |
\value Tigre
|
|
1766 |
\value Jju
|
|
1767 |
\value Friulian
|
|
1768 |
\value Venda
|
|
1769 |
\value Ewe
|
|
1770 |
\value Walamo
|
|
1771 |
\value Hawaiian
|
|
1772 |
\value Tyap
|
|
1773 |
\value Chewa
|
|
1774 |
\omitvalue LastLanguage
|
|
1775 |
|
|
1776 |
\sa language()
|
|
1777 |
*/
|
|
1778 |
|
|
1779 |
/*!
|
|
1780 |
\enum QLocale::Country
|
|
1781 |
|
|
1782 |
This enumerated type is used to specify a country.
|
|
1783 |
|
|
1784 |
\value AnyCountry
|
|
1785 |
\value Afghanistan
|
|
1786 |
\value Albania
|
|
1787 |
\value Algeria
|
|
1788 |
\value AmericanSamoa
|
|
1789 |
\value Andorra
|
|
1790 |
\value Angola
|
|
1791 |
\value Anguilla
|
|
1792 |
\value Antarctica
|
|
1793 |
\value AntiguaAndBarbuda
|
|
1794 |
\value Argentina
|
|
1795 |
\value Armenia
|
|
1796 |
\value Aruba
|
|
1797 |
\value Australia
|
|
1798 |
\value Austria
|
|
1799 |
\value Azerbaijan
|
|
1800 |
\value Bahamas
|
|
1801 |
\value Bahrain
|
|
1802 |
\value Bangladesh
|
|
1803 |
\value Barbados
|
|
1804 |
\value Belarus
|
|
1805 |
\value Belgium
|
|
1806 |
\value Belize
|
|
1807 |
\value Benin
|
|
1808 |
\value Bermuda
|
|
1809 |
\value Bhutan
|
|
1810 |
\value Bolivia
|
|
1811 |
\value BosniaAndHerzegowina
|
|
1812 |
\value Botswana
|
|
1813 |
\value BouvetIsland
|
|
1814 |
\value Brazil
|
|
1815 |
\value BritishIndianOceanTerritory
|
|
1816 |
\value BruneiDarussalam
|
|
1817 |
\value Bulgaria
|
|
1818 |
\value BurkinaFaso
|
|
1819 |
\value Burundi
|
|
1820 |
\value Cambodia
|
|
1821 |
\value Cameroon
|
|
1822 |
\value Canada
|
|
1823 |
\value CapeVerde
|
|
1824 |
\value CaymanIslands
|
|
1825 |
\value CentralAfricanRepublic
|
|
1826 |
\value Chad
|
|
1827 |
\value Chile
|
|
1828 |
\value China
|
|
1829 |
\value ChristmasIsland
|
|
1830 |
\value CocosIslands
|
|
1831 |
\value Colombia
|
|
1832 |
\value Comoros
|
|
1833 |
\value DemocraticRepublicOfCongo
|
|
1834 |
\value PeoplesRepublicOfCongo
|
|
1835 |
\value CookIslands
|
|
1836 |
\value CostaRica
|
|
1837 |
\value IvoryCoast
|
|
1838 |
\value Croatia
|
|
1839 |
\value Cuba
|
|
1840 |
\value Cyprus
|
|
1841 |
\value CzechRepublic
|
|
1842 |
\value Denmark
|
|
1843 |
\value Djibouti
|
|
1844 |
\value Dominica
|
|
1845 |
\value DominicanRepublic
|
|
1846 |
\value EastTimor
|
|
1847 |
\value Ecuador
|
|
1848 |
\value Egypt
|
|
1849 |
\value ElSalvador
|
|
1850 |
\value EquatorialGuinea
|
|
1851 |
\value Eritrea
|
|
1852 |
\value Estonia
|
|
1853 |
\value Ethiopia
|
|
1854 |
\value FalklandIslands
|
|
1855 |
\value FaroeIslands
|
|
1856 |
\value FijiCountry
|
|
1857 |
\value Finland
|
|
1858 |
\value France
|
|
1859 |
\value MetropolitanFrance
|
|
1860 |
\value FrenchGuiana
|
|
1861 |
\value FrenchPolynesia
|
|
1862 |
\value FrenchSouthernTerritories
|
|
1863 |
\value Gabon
|
|
1864 |
\value Gambia
|
|
1865 |
\value Georgia
|
|
1866 |
\value Germany
|
|
1867 |
\value Ghana
|
|
1868 |
\value Gibraltar
|
|
1869 |
\value Greece
|
|
1870 |
\value Greenland
|
|
1871 |
\value Grenada
|
|
1872 |
\value Guadeloupe
|
|
1873 |
\value Guam
|
|
1874 |
\value Guatemala
|
|
1875 |
\value Guinea
|
|
1876 |
\value GuineaBissau
|
|
1877 |
\value Guyana
|
|
1878 |
\value Haiti
|
|
1879 |
\value HeardAndMcDonaldIslands
|
|
1880 |
\value Honduras
|
|
1881 |
\value HongKong
|
|
1882 |
\value Hungary
|
|
1883 |
\value Iceland
|
|
1884 |
\value India
|
|
1885 |
\value Indonesia
|
|
1886 |
\value Iran
|
|
1887 |
\value Iraq
|
|
1888 |
\value Ireland
|
|
1889 |
\value Israel
|
|
1890 |
\value Italy
|
|
1891 |
\value Jamaica
|
|
1892 |
\value Japan
|
|
1893 |
\value Jordan
|
|
1894 |
\value Kazakhstan
|
|
1895 |
\value Kenya
|
|
1896 |
\value Kiribati
|
|
1897 |
\value DemocraticRepublicOfKorea
|
|
1898 |
\value RepublicOfKorea
|
|
1899 |
\value Kuwait
|
|
1900 |
\value Kyrgyzstan
|
|
1901 |
\value Lao
|
|
1902 |
\value Latvia
|
|
1903 |
\value Lebanon
|
|
1904 |
\value Lesotho
|
|
1905 |
\value Liberia
|
|
1906 |
\value LibyanArabJamahiriya
|
|
1907 |
\value Liechtenstein
|
|
1908 |
\value Lithuania
|
|
1909 |
\value Luxembourg
|
|
1910 |
\value Macau
|
|
1911 |
\value Macedonia
|
|
1912 |
\value Madagascar
|
|
1913 |
\value Malawi
|
|
1914 |
\value Malaysia
|
|
1915 |
\value Maldives
|
|
1916 |
\value Mali
|
|
1917 |
\value Malta
|
|
1918 |
\value MarshallIslands
|
|
1919 |
\value Martinique
|
|
1920 |
\value Mauritania
|
|
1921 |
\value Mauritius
|
|
1922 |
\value Mayotte
|
|
1923 |
\value Mexico
|
|
1924 |
\value Micronesia
|
|
1925 |
\value Moldova
|
|
1926 |
\value Monaco
|
|
1927 |
\value Mongolia
|
|
1928 |
\value Montserrat
|
|
1929 |
\value Morocco
|
|
1930 |
\value Mozambique
|
|
1931 |
\value Myanmar
|
|
1932 |
\value Namibia
|
|
1933 |
\value NauruCountry
|
|
1934 |
\value Nepal
|
|
1935 |
\value Netherlands
|
|
1936 |
\value NetherlandsAntilles
|
|
1937 |
\value NewCaledonia
|
|
1938 |
\value NewZealand
|
|
1939 |
\value Nicaragua
|
|
1940 |
\value Niger
|
|
1941 |
\value Nigeria
|
|
1942 |
\value Niue
|
|
1943 |
\value NorfolkIsland
|
|
1944 |
\value NorthernMarianaIslands
|
|
1945 |
\value Norway
|
|
1946 |
\value Oman
|
|
1947 |
\value Pakistan
|
|
1948 |
\value Palau
|
|
1949 |
\value PalestinianTerritory
|
|
1950 |
\value Panama
|
|
1951 |
\value PapuaNewGuinea
|
|
1952 |
\value Paraguay
|
|
1953 |
\value Peru
|
|
1954 |
\value Philippines
|
|
1955 |
\value Pitcairn
|
|
1956 |
\value Poland
|
|
1957 |
\value Portugal
|
|
1958 |
\value PuertoRico
|
|
1959 |
\value Qatar
|
|
1960 |
\value Reunion
|
|
1961 |
\value Romania
|
|
1962 |
\value RussianFederation
|
|
1963 |
\value Rwanda
|
|
1964 |
\value SaintKittsAndNevis
|
|
1965 |
\value StLucia
|
|
1966 |
\value StVincentAndTheGrenadines
|
|
1967 |
\value Samoa
|
|
1968 |
\value SanMarino
|
|
1969 |
\value SaoTomeAndPrincipe
|
|
1970 |
\value SaudiArabia
|
|
1971 |
\value Senegal
|
|
1972 |
\value SerbiaAndMontenegro
|
|
1973 |
\value Seychelles
|
|
1974 |
\value SierraLeone
|
|
1975 |
\value Singapore
|
|
1976 |
\value Slovakia
|
|
1977 |
\value Slovenia
|
|
1978 |
\value SolomonIslands
|
|
1979 |
\value Somalia
|
|
1980 |
\value SouthAfrica
|
|
1981 |
\value SouthGeorgiaAndTheSouthSandwichIslands
|
|
1982 |
\value Spain
|
|
1983 |
\value SriLanka
|
|
1984 |
\value StHelena
|
|
1985 |
\value StPierreAndMiquelon
|
|
1986 |
\value Sudan
|
|
1987 |
\value Suriname
|
|
1988 |
\value SvalbardAndJanMayenIslands
|
|
1989 |
\value Swaziland
|
|
1990 |
\value Sweden
|
|
1991 |
\value Switzerland
|
|
1992 |
\value SyrianArabRepublic
|
|
1993 |
\value Taiwan
|
|
1994 |
\value Tajikistan
|
|
1995 |
\value Tanzania
|
|
1996 |
\value Thailand
|
|
1997 |
\value Togo
|
|
1998 |
\value Tokelau
|
|
1999 |
\value TongaCountry
|
|
2000 |
\value TrinidadAndTobago
|
|
2001 |
\value Tunisia
|
|
2002 |
\value Turkey
|
|
2003 |
\value Turkmenistan
|
|
2004 |
\value TurksAndCaicosIslands
|
|
2005 |
\value Tuvalu
|
|
2006 |
\value Uganda
|
|
2007 |
\value Ukraine
|
|
2008 |
\value UnitedArabEmirates
|
|
2009 |
\value UnitedKingdom
|
|
2010 |
\value UnitedStates
|
|
2011 |
\value UnitedStatesMinorOutlyingIslands
|
|
2012 |
\value Uruguay
|
|
2013 |
\value Uzbekistan
|
|
2014 |
\value Vanuatu
|
|
2015 |
\value VaticanCityState
|
|
2016 |
\value Venezuela
|
|
2017 |
\value VietNam
|
|
2018 |
\value BritishVirginIslands
|
|
2019 |
\value USVirginIslands
|
|
2020 |
\value WallisAndFutunaIslands
|
|
2021 |
\value WesternSahara
|
|
2022 |
\value Yemen
|
|
2023 |
\value Yugoslavia
|
|
2024 |
\value Zambia
|
|
2025 |
\value Zimbabwe
|
|
2026 |
\omitvalue LastCountry
|
|
2027 |
|
|
2028 |
\sa country()
|
|
2029 |
*/
|
|
2030 |
|
|
2031 |
/*!
|
|
2032 |
\enum QLocale::FormatType
|
|
2033 |
|
|
2034 |
This enum describes the types of format that can be used when
|
|
2035 |
converting QDate and QTime objects to strings.
|
|
2036 |
|
|
2037 |
\value LongFormat The long version of day and month names; for
|
|
2038 |
example, returning "January" as a month name.
|
|
2039 |
|
|
2040 |
\value ShortFormat The short version of day and month names; for
|
|
2041 |
example, returning "Jan" as a month name.
|
|
2042 |
|
|
2043 |
\value NarrowFormat A special version of day and month names for
|
|
2044 |
use when space is limited; for example, returning "J" as a month
|
|
2045 |
name. Note that the narrow format might contain the same text for
|
|
2046 |
different months and days or it can even be an empty string if the
|
|
2047 |
locale doesn't support narrow names, so you should avoid using it
|
|
2048 |
for date formatting. Also, for the system locale this format is
|
|
2049 |
the same as ShortFormat.
|
|
2050 |
*/
|
|
2051 |
|
|
2052 |
/*!
|
|
2053 |
\enum QLocale::NumberOption
|
|
2054 |
|
|
2055 |
This enum defines a set of options for number-to-string and string-to-number
|
|
2056 |
conversions. They can be retrieved with numberOptions() and set with
|
|
2057 |
setNumberOptions().
|
|
2058 |
|
|
2059 |
\value OmitGroupSeparator If this option is set, the number-to-string functions
|
|
2060 |
will not insert group separators in their return values. The default
|
|
2061 |
is to insert group separators.
|
|
2062 |
\value RejectGroupSeparator If this option is set, the string-to-number functions
|
|
2063 |
will fail if they encounter group separators in their input. The default
|
|
2064 |
is to accept numbers containing correctly placed group separators.
|
|
2065 |
|
|
2066 |
\sa setNumberOptions() numberOptions()
|
|
2067 |
*/
|
|
2068 |
|
|
2069 |
/*!
|
|
2070 |
\enum QLocale::MeasurementSystem
|
|
2071 |
|
|
2072 |
This enum defines which units are used for measurement.
|
|
2073 |
|
|
2074 |
\value MetricSystem This value indicates metric units, such as meters,
|
|
2075 |
centimeters and millimeters.
|
|
2076 |
\value ImperialSystem This value indicates imperial units, such as inches and
|
|
2077 |
miles. There are several distinct imperial systems in the world; this
|
|
2078 |
value stands for the official United States imperial units.
|
|
2079 |
|
|
2080 |
\since 4.4
|
|
2081 |
*/
|
|
2082 |
|
|
2083 |
|
|
2084 |
/*!
|
|
2085 |
\fn bool QLocale::operator==(const QLocale &other) const
|
|
2086 |
|
|
2087 |
Returns true if the QLocale object is the same as the \a other
|
|
2088 |
locale specified; otherwise returns false.
|
|
2089 |
*/
|
|
2090 |
|
|
2091 |
/*!
|
|
2092 |
\fn bool QLocale::operator!=(const QLocale &other) const
|
|
2093 |
|
|
2094 |
Returns true if the QLocale object is not the same as the \a other
|
|
2095 |
locale specified; otherwise returns false.
|
|
2096 |
*/
|
|
2097 |
|
|
2098 |
static const int locale_data_size = sizeof(locale_data)/sizeof(QLocalePrivate) - 1;
|
|
2099 |
|
|
2100 |
static const QLocalePrivate *dataPointerHelper(quint16 index)
|
|
2101 |
{
|
|
2102 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
2103 |
Q_ASSERT(index <= locale_data_size);
|
|
2104 |
if (index == locale_data_size)
|
|
2105 |
return system_lp;
|
|
2106 |
#else
|
|
2107 |
Q_ASSERT(index < locale_data_size);
|
|
2108 |
#endif
|
|
2109 |
|
|
2110 |
return &locale_data[index];
|
|
2111 |
}
|
|
2112 |
|
|
2113 |
static quint16 localePrivateIndex(const QLocalePrivate *p)
|
|
2114 |
{
|
|
2115 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
2116 |
Q_ASSERT((p >= locale_data && p - locale_data < locale_data_size)
|
|
2117 |
|| (p != 0 && p == system_lp));
|
|
2118 |
quint16 index = p == system_lp ? locale_data_size : p - locale_data;
|
|
2119 |
#else
|
|
2120 |
Q_ASSERT(p >= locale_data && p - locale_data < locale_data_size);
|
|
2121 |
quint16 index = p - locale_data;
|
|
2122 |
#endif
|
|
2123 |
|
|
2124 |
return index;
|
|
2125 |
}
|
|
2126 |
|
|
2127 |
/*!
|
|
2128 |
Constructs a QLocale object with the specified \a name,
|
|
2129 |
which has the format
|
|
2130 |
"language[_country][.codeset][@modifier]" or "C", where:
|
|
2131 |
|
|
2132 |
\list
|
|
2133 |
\i language is a lowercase, two-letter, ISO 639 language code,
|
|
2134 |
\i territory is an uppercase, two-letter, ISO 3166 country code,
|
|
2135 |
\i and codeset and modifier are ignored.
|
|
2136 |
\endlist
|
|
2137 |
|
|
2138 |
If the string violates the locale format, or language is not
|
|
2139 |
a valid ISO 369 code, the "C" locale is used instead. If country
|
|
2140 |
is not present, or is not a valid ISO 3166 code, the most
|
|
2141 |
appropriate country is chosen for the specified language.
|
|
2142 |
|
|
2143 |
The language and country codes are converted to their respective
|
|
2144 |
\c Language and \c Country enums. After this conversion is
|
|
2145 |
performed the constructor behaves exactly like QLocale(Country,
|
|
2146 |
Language).
|
|
2147 |
|
|
2148 |
This constructor is much slower than QLocale(Country, Language).
|
|
2149 |
|
|
2150 |
\sa name()
|
|
2151 |
*/
|
|
2152 |
|
|
2153 |
QLocale::QLocale(const QString &name)
|
|
2154 |
: v(0)
|
|
2155 |
{
|
|
2156 |
p.numberOptions = 0;
|
|
2157 |
p.index = localePrivateIndex(findLocale(name));
|
|
2158 |
}
|
|
2159 |
|
|
2160 |
/*!
|
|
2161 |
Constructs a QLocale object initialized with the default locale. If
|
|
2162 |
no default locale was set using setDefaultLocale(), this locale will
|
|
2163 |
be the same as the one returned by system().
|
|
2164 |
|
|
2165 |
\sa setDefault()
|
|
2166 |
*/
|
|
2167 |
|
|
2168 |
QLocale::QLocale()
|
|
2169 |
: v(0)
|
|
2170 |
{
|
|
2171 |
p.numberOptions = default_number_options;
|
|
2172 |
p.index = localePrivateIndex(defaultPrivate());
|
|
2173 |
}
|
|
2174 |
|
|
2175 |
/*!
|
|
2176 |
Constructs a QLocale object with the specified \a language and \a
|
|
2177 |
country.
|
|
2178 |
|
|
2179 |
\list
|
|
2180 |
\i If the language/country pair is found in the database, it is used.
|
|
2181 |
\i If the language is found but the country is not, or if the country
|
|
2182 |
is \c AnyCountry, the language is used with the most
|
|
2183 |
appropriate available country (for example, Germany for German),
|
|
2184 |
\i If neither the language nor the country are found, QLocale
|
|
2185 |
defaults to the default locale (see setDefault()).
|
|
2186 |
\endlist
|
|
2187 |
|
|
2188 |
The language and country that are actually used can be queried
|
|
2189 |
using language() and country().
|
|
2190 |
|
|
2191 |
\sa setDefault() language() country()
|
|
2192 |
*/
|
|
2193 |
|
|
2194 |
QLocale::QLocale(Language language, Country country)
|
|
2195 |
: v(0)
|
|
2196 |
{
|
|
2197 |
const QLocalePrivate *d = findLocale(language, country);
|
|
2198 |
|
|
2199 |
// If not found, should default to system
|
|
2200 |
if (d->languageId() == QLocale::C && language != QLocale::C) {
|
|
2201 |
p.numberOptions = default_number_options;
|
|
2202 |
p.index = localePrivateIndex(defaultPrivate());
|
|
2203 |
} else {
|
|
2204 |
p.numberOptions = 0;
|
|
2205 |
p.index = localePrivateIndex(d);
|
|
2206 |
}
|
|
2207 |
}
|
|
2208 |
|
|
2209 |
/*!
|
|
2210 |
Constructs a QLocale object as a copy of \a other.
|
|
2211 |
*/
|
|
2212 |
|
|
2213 |
QLocale::QLocale(const QLocale &other)
|
|
2214 |
{
|
|
2215 |
v = other.v;
|
|
2216 |
}
|
|
2217 |
|
|
2218 |
const QLocalePrivate *QLocale::d() const
|
|
2219 |
{
|
|
2220 |
return dataPointerHelper(p.index);
|
|
2221 |
}
|
|
2222 |
|
|
2223 |
/*!
|
|
2224 |
Assigns \a other to this QLocale object and returns a reference
|
|
2225 |
to this QLocale object.
|
|
2226 |
*/
|
|
2227 |
|
|
2228 |
QLocale &QLocale::operator=(const QLocale &other)
|
|
2229 |
{
|
|
2230 |
v = other.v;
|
|
2231 |
return *this;
|
|
2232 |
}
|
|
2233 |
|
|
2234 |
/*!
|
|
2235 |
\since 4.2
|
|
2236 |
|
|
2237 |
Sets the \a options related to number conversions for this
|
|
2238 |
QLocale instance.
|
|
2239 |
*/
|
|
2240 |
void QLocale::setNumberOptions(NumberOptions options)
|
|
2241 |
{
|
|
2242 |
p.numberOptions = options;
|
|
2243 |
}
|
|
2244 |
|
|
2245 |
/*!
|
|
2246 |
\since 4.2
|
|
2247 |
|
|
2248 |
Returns the options related to number conversions for this
|
|
2249 |
QLocale instance.
|
|
2250 |
|
|
2251 |
By default, no options are set for the standard locales.
|
|
2252 |
*/
|
|
2253 |
QLocale::NumberOptions QLocale::numberOptions() const
|
|
2254 |
{
|
|
2255 |
return static_cast<NumberOption>(p.numberOptions);
|
|
2256 |
}
|
|
2257 |
|
|
2258 |
/*!
|
|
2259 |
\nonreentrant
|
|
2260 |
|
|
2261 |
Sets the global default locale to \a locale. These
|
|
2262 |
values are used when a QLocale object is constructed with
|
|
2263 |
no arguments. If this function is not called, the system's
|
|
2264 |
locale is used.
|
|
2265 |
|
|
2266 |
\warning In a multithreaded application, the default locale
|
|
2267 |
should be set at application startup, before any non-GUI threads
|
|
2268 |
are created.
|
|
2269 |
|
|
2270 |
\sa system() c()
|
|
2271 |
*/
|
|
2272 |
|
|
2273 |
void QLocale::setDefault(const QLocale &locale)
|
|
2274 |
{
|
|
2275 |
default_lp = locale.d();
|
|
2276 |
default_number_options = locale.numberOptions();
|
|
2277 |
}
|
|
2278 |
|
|
2279 |
/*!
|
|
2280 |
Returns the language of this locale.
|
|
2281 |
|
|
2282 |
\sa country(), languageToString(), name()
|
|
2283 |
*/
|
|
2284 |
QLocale::Language QLocale::language() const
|
|
2285 |
{
|
|
2286 |
return Language(d()->languageId());
|
|
2287 |
}
|
|
2288 |
|
|
2289 |
/*!
|
|
2290 |
Returns the country of this locale.
|
|
2291 |
|
|
2292 |
\sa language(), countryToString(), name()
|
|
2293 |
*/
|
|
2294 |
QLocale::Country QLocale::country() const
|
|
2295 |
{
|
|
2296 |
return Country(d()->countryId());
|
|
2297 |
}
|
|
2298 |
|
|
2299 |
/*!
|
|
2300 |
Returns the language and country of this locale as a
|
|
2301 |
string of the form "language_country", where
|
|
2302 |
language is a lowercase, two-letter ISO 639 language code,
|
|
2303 |
and country is an uppercase, two-letter ISO 3166 country code.
|
|
2304 |
|
|
2305 |
\sa language(), country()
|
|
2306 |
*/
|
|
2307 |
|
|
2308 |
QString QLocale::name() const
|
|
2309 |
{
|
|
2310 |
Language l = language();
|
|
2311 |
|
|
2312 |
QString result = languageToCode(l);
|
|
2313 |
|
|
2314 |
if (l == C)
|
|
2315 |
return result;
|
|
2316 |
|
|
2317 |
Country c = country();
|
|
2318 |
if (c == AnyCountry)
|
|
2319 |
return result;
|
|
2320 |
|
|
2321 |
result.append(QLatin1Char('_'));
|
|
2322 |
result.append(countryToCode(c));
|
|
2323 |
|
|
2324 |
return result;
|
|
2325 |
}
|
|
2326 |
|
|
2327 |
/*!
|
|
2328 |
Returns a QString containing the name of \a language.
|
|
2329 |
|
|
2330 |
\sa countryToString(), name()
|
|
2331 |
*/
|
|
2332 |
|
|
2333 |
QString QLocale::languageToString(Language language)
|
|
2334 |
{
|
|
2335 |
if (uint(language) > uint(QLocale::LastLanguage))
|
|
2336 |
return QLatin1String("Unknown");
|
|
2337 |
return QLatin1String(language_name_list + language_name_index[language]);
|
|
2338 |
}
|
|
2339 |
|
|
2340 |
/*!
|
|
2341 |
Returns a QString containing the name of \a country.
|
|
2342 |
|
|
2343 |
\sa country(), name()
|
|
2344 |
*/
|
|
2345 |
|
|
2346 |
QString QLocale::countryToString(Country country)
|
|
2347 |
{
|
|
2348 |
if (uint(country) > uint(QLocale::LastCountry))
|
|
2349 |
return QLatin1String("Unknown");
|
|
2350 |
return QLatin1String(country_name_list + country_name_index[country]);
|
|
2351 |
}
|
|
2352 |
|
|
2353 |
/*!
|
|
2354 |
Returns the short int represented by the localized string \a s,
|
|
2355 |
using base \a base. If \a base is 0 the base is determined
|
|
2356 |
automatically using the following rules: If the string begins with
|
|
2357 |
"0x", it is assumed to be hexadecimal; if it begins with "0", it
|
|
2358 |
is assumed to be octal; otherwise it is assumed to be decimal.
|
|
2359 |
|
|
2360 |
If the conversion fails the function returns 0.
|
|
2361 |
|
|
2362 |
If \a ok is not 0, failure is reported by setting *ok to false, and
|
|
2363 |
success by setting *ok to true.
|
|
2364 |
|
|
2365 |
This function ignores leading and trailing whitespace.
|
|
2366 |
|
|
2367 |
\sa toUShort(), toString()
|
|
2368 |
*/
|
|
2369 |
|
|
2370 |
short QLocale::toShort(const QString &s, bool *ok, int base) const
|
|
2371 |
{
|
|
2372 |
qlonglong i = toLongLong(s, ok, base);
|
|
2373 |
if (i < SHRT_MIN || i > SHRT_MAX) {
|
|
2374 |
if (ok != 0)
|
|
2375 |
*ok = false;
|
|
2376 |
return 0;
|
|
2377 |
}
|
|
2378 |
return short(i);
|
|
2379 |
}
|
|
2380 |
|
|
2381 |
/*!
|
|
2382 |
Returns the unsigned short int represented by the localized string
|
|
2383 |
\a s, using base \a base. If \a base is 0 the base is determined
|
|
2384 |
automatically using the following rules: If the string begins with
|
|
2385 |
"0x", it is assumed to be hexadecimal; if it begins with "0", it
|
|
2386 |
is assumed to be octal; otherwise it is assumed to be decimal.
|
|
2387 |
|
|
2388 |
If the conversion fails the function returns 0.
|
|
2389 |
|
|
2390 |
If \a ok is not 0, failure is reported by setting *ok to false, and
|
|
2391 |
success by setting *ok to true.
|
|
2392 |
|
|
2393 |
This function ignores leading and trailing whitespace.
|
|
2394 |
|
|
2395 |
\sa toShort(), toString()
|
|
2396 |
*/
|
|
2397 |
|
|
2398 |
ushort QLocale::toUShort(const QString &s, bool *ok, int base) const
|
|
2399 |
{
|
|
2400 |
qulonglong i = toULongLong(s, ok, base);
|
|
2401 |
if (i > USHRT_MAX) {
|
|
2402 |
if (ok != 0)
|
|
2403 |
*ok = false;
|
|
2404 |
return 0;
|
|
2405 |
}
|
|
2406 |
return ushort(i);
|
|
2407 |
}
|
|
2408 |
|
|
2409 |
/*!
|
|
2410 |
Returns the int represented by the localized string \a s, using
|
|
2411 |
base \a base. If \a base is 0 the base is determined automatically
|
|
2412 |
using the following rules: If the string begins with "0x", it is
|
|
2413 |
assumed to be hexadecimal; if it begins with "0", it is assumed to
|
|
2414 |
be octal; otherwise it is assumed to be decimal.
|
|
2415 |
|
|
2416 |
If the conversion fails the function returns 0.
|
|
2417 |
|
|
2418 |
If \a ok is not 0, failure is reported by setting *ok to false, and
|
|
2419 |
success by setting *ok to true.
|
|
2420 |
|
|
2421 |
This function ignores leading and trailing whitespace.
|
|
2422 |
|
|
2423 |
\sa toUInt(), toString()
|
|
2424 |
*/
|
|
2425 |
|
|
2426 |
int QLocale::toInt(const QString &s, bool *ok, int base) const
|
|
2427 |
{
|
|
2428 |
qlonglong i = toLongLong(s, ok, base);
|
|
2429 |
if (i < INT_MIN || i > INT_MAX) {
|
|
2430 |
if (ok != 0)
|
|
2431 |
*ok = false;
|
|
2432 |
return 0;
|
|
2433 |
}
|
|
2434 |
return int(i);
|
|
2435 |
}
|
|
2436 |
|
|
2437 |
/*!
|
|
2438 |
Returns the unsigned int represented by the localized string \a s,
|
|
2439 |
using base \a base. If \a base is 0 the base is determined
|
|
2440 |
automatically using the following rules: If the string begins with
|
|
2441 |
"0x", it is assumed to be hexadecimal; if it begins with "0", it
|
|
2442 |
is assumed to be octal; otherwise it is assumed to be decimal.
|
|
2443 |
|
|
2444 |
If the conversion fails the function returns 0.
|
|
2445 |
|
|
2446 |
If \a ok is not 0, failure is reported by setting *ok to false, and
|
|
2447 |
success by setting *ok to true.
|
|
2448 |
|
|
2449 |
This function ignores leading and trailing whitespace.
|
|
2450 |
|
|
2451 |
\sa toInt(), toString()
|
|
2452 |
*/
|
|
2453 |
|
|
2454 |
uint QLocale::toUInt(const QString &s, bool *ok, int base) const
|
|
2455 |
{
|
|
2456 |
qulonglong i = toULongLong(s, ok, base);
|
|
2457 |
if (i > UINT_MAX) {
|
|
2458 |
if (ok != 0)
|
|
2459 |
*ok = false;
|
|
2460 |
return 0;
|
|
2461 |
}
|
|
2462 |
return uint(i);
|
|
2463 |
}
|
|
2464 |
|
|
2465 |
/*!
|
|
2466 |
Returns the long long int represented by the localized string \a
|
|
2467 |
s, using base \a base. If \a base is 0 the base is determined
|
|
2468 |
automatically using the following rules: If the string begins with
|
|
2469 |
"0x", it is assumed to be hexadecimal; if it begins with "0", it
|
|
2470 |
is assumed to be octal; otherwise it is assumed to be decimal.
|
|
2471 |
|
|
2472 |
If the conversion fails the function returns 0.
|
|
2473 |
|
|
2474 |
If \a ok is not 0, failure is reported by setting *ok to false, and
|
|
2475 |
success by setting *ok to true.
|
|
2476 |
|
|
2477 |
This function ignores leading and trailing whitespace.
|
|
2478 |
|
|
2479 |
\sa toInt(), toULongLong(), toDouble(), toString()
|
|
2480 |
*/
|
|
2481 |
|
|
2482 |
|
|
2483 |
qlonglong QLocale::toLongLong(const QString &s, bool *ok, int base) const
|
|
2484 |
{
|
|
2485 |
QLocalePrivate::GroupSeparatorMode mode
|
|
2486 |
= p.numberOptions & RejectGroupSeparator
|
|
2487 |
? QLocalePrivate::FailOnGroupSeparators
|
|
2488 |
: QLocalePrivate::ParseGroupSeparators;
|
|
2489 |
|
|
2490 |
return d()->stringToLongLong(s, base, ok, mode);
|
|
2491 |
}
|
|
2492 |
|
|
2493 |
// ### Qt5: make the return type for toULongLong() qulonglong.
|
|
2494 |
|
|
2495 |
/*!
|
|
2496 |
Returns the unsigned long long int represented by the localized
|
|
2497 |
string \a s, using base \a base. If \a base is 0 the base is
|
|
2498 |
determined automatically using the following rules: If the string
|
|
2499 |
begins with "0x", it is assumed to be hexadecimal; if it begins
|
|
2500 |
with "0", it is assumed to be octal; otherwise it is assumed to be
|
|
2501 |
decimal.
|
|
2502 |
|
|
2503 |
If the conversion fails the function returns 0.
|
|
2504 |
|
|
2505 |
If \a ok is not 0, failure is reported by setting *ok to false, and
|
|
2506 |
success by setting *ok to true.
|
|
2507 |
|
|
2508 |
This function ignores leading and trailing whitespace.
|
|
2509 |
|
|
2510 |
\sa toLongLong(), toInt(), toDouble(), toString()
|
|
2511 |
*/
|
|
2512 |
|
|
2513 |
qlonglong QLocale::toULongLong(const QString &s, bool *ok, int base) const
|
|
2514 |
{
|
|
2515 |
QLocalePrivate::GroupSeparatorMode mode
|
|
2516 |
= p.numberOptions & RejectGroupSeparator
|
|
2517 |
? QLocalePrivate::FailOnGroupSeparators
|
|
2518 |
: QLocalePrivate::ParseGroupSeparators;
|
|
2519 |
|
|
2520 |
return d()->stringToUnsLongLong(s, base, ok, mode);
|
|
2521 |
}
|
|
2522 |
|
|
2523 |
/*!
|
|
2524 |
Returns the float represented by the localized string \a s, or 0.0
|
|
2525 |
if the conversion failed.
|
|
2526 |
|
|
2527 |
If \a ok is not 0, reports failure by setting
|
|
2528 |
*ok to false and success by setting *ok to true.
|
|
2529 |
|
|
2530 |
This function ignores leading and trailing whitespace.
|
|
2531 |
|
|
2532 |
\sa toDouble(), toInt(), toString()
|
|
2533 |
*/
|
|
2534 |
|
|
2535 |
#define QT_MAX_FLOAT 3.4028234663852886e+38
|
|
2536 |
|
|
2537 |
float QLocale::toFloat(const QString &s, bool *ok) const
|
|
2538 |
{
|
|
2539 |
bool myOk;
|
|
2540 |
double d = toDouble(s, &myOk);
|
|
2541 |
if (!myOk || d > QT_MAX_FLOAT || d < -QT_MAX_FLOAT) {
|
|
2542 |
if (ok != 0)
|
|
2543 |
*ok = false;
|
|
2544 |
return 0.0;
|
|
2545 |
}
|
|
2546 |
if (ok != 0)
|
|
2547 |
*ok = true;
|
|
2548 |
return float(d);
|
|
2549 |
}
|
|
2550 |
|
|
2551 |
/*!
|
|
2552 |
Returns the double represented by the localized string \a s, or
|
|
2553 |
0.0 if the conversion failed.
|
|
2554 |
|
|
2555 |
If \a ok is not 0, reports failure by setting
|
|
2556 |
*ok to false and success by setting *ok to true.
|
|
2557 |
|
|
2558 |
Unlike QString::toDouble(), this function does not fall back to
|
|
2559 |
the "C" locale if the string cannot be interpreted in this
|
|
2560 |
locale.
|
|
2561 |
|
|
2562 |
\snippet doc/src/snippets/code/src_corelib_tools_qlocale.cpp 3
|
|
2563 |
|
|
2564 |
Notice that the last conversion returns 1234.0, because '.' is the
|
|
2565 |
thousands group separator in the German locale.
|
|
2566 |
|
|
2567 |
This function ignores leading and trailing whitespace.
|
|
2568 |
|
|
2569 |
\sa toFloat(), toInt(), toString()
|
|
2570 |
*/
|
|
2571 |
|
|
2572 |
double QLocale::toDouble(const QString &s, bool *ok) const
|
|
2573 |
{
|
|
2574 |
QLocalePrivate::GroupSeparatorMode mode
|
|
2575 |
= p.numberOptions & RejectGroupSeparator
|
|
2576 |
? QLocalePrivate::FailOnGroupSeparators
|
|
2577 |
: QLocalePrivate::ParseGroupSeparators;
|
|
2578 |
|
|
2579 |
return d()->stringToDouble(s, ok, mode);
|
|
2580 |
}
|
|
2581 |
|
|
2582 |
/*!
|
|
2583 |
Returns a localized string representation of \a i.
|
|
2584 |
|
|
2585 |
\sa toLongLong()
|
|
2586 |
*/
|
|
2587 |
|
|
2588 |
QString QLocale::toString(qlonglong i) const
|
|
2589 |
{
|
|
2590 |
int flags = p.numberOptions & OmitGroupSeparator
|
|
2591 |
? 0
|
|
2592 |
: QLocalePrivate::ThousandsGroup;
|
|
2593 |
|
|
2594 |
return d()->longLongToString(i, -1, 10, -1, flags);
|
|
2595 |
}
|
|
2596 |
|
|
2597 |
/*!
|
|
2598 |
\overload
|
|
2599 |
|
|
2600 |
\sa toULongLong()
|
|
2601 |
*/
|
|
2602 |
|
|
2603 |
QString QLocale::toString(qulonglong i) const
|
|
2604 |
{
|
|
2605 |
int flags = p.numberOptions & OmitGroupSeparator
|
|
2606 |
? 0
|
|
2607 |
: QLocalePrivate::ThousandsGroup;
|
|
2608 |
|
|
2609 |
return d()->unsLongLongToString(i, -1, 10, -1, flags);
|
|
2610 |
}
|
|
2611 |
|
|
2612 |
/*!
|
|
2613 |
Returns a localized string representation of the given \a date in the
|
|
2614 |
specified \a format.
|
|
2615 |
If \a format is an empty string, an empty string is returned.
|
|
2616 |
*/
|
|
2617 |
|
|
2618 |
QString QLocale::toString(const QDate &date, const QString &format) const
|
|
2619 |
{
|
|
2620 |
return d()->dateTimeToString(format, &date, 0, this);
|
|
2621 |
}
|
|
2622 |
|
|
2623 |
/*!
|
|
2624 |
Returns a localized string representation of the given \a date according
|
|
2625 |
to the specified \a format.
|
|
2626 |
*/
|
|
2627 |
|
|
2628 |
QString QLocale::toString(const QDate &date, FormatType format) const
|
|
2629 |
{
|
|
2630 |
if (!date.isValid())
|
|
2631 |
return QString();
|
|
2632 |
|
|
2633 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
2634 |
if (d() == systemPrivate()) {
|
|
2635 |
QVariant res = systemLocale()->query(format == LongFormat
|
|
2636 |
? QSystemLocale::DateToStringLong : QSystemLocale::DateToStringShort,
|
|
2637 |
date);
|
|
2638 |
if (!res.isNull())
|
|
2639 |
return res.toString();
|
|
2640 |
}
|
|
2641 |
#endif
|
|
2642 |
|
|
2643 |
QString format_str = dateFormat(format);
|
|
2644 |
return toString(date, format_str);
|
|
2645 |
}
|
|
2646 |
|
|
2647 |
static bool timeFormatContainsAP(const QString &format)
|
|
2648 |
{
|
|
2649 |
int i = 0;
|
|
2650 |
while (i < format.size()) {
|
|
2651 |
if (format.at(i).unicode() == '\'') {
|
|
2652 |
readEscapedFormatString(format, &i);
|
|
2653 |
continue;
|
|
2654 |
}
|
|
2655 |
|
|
2656 |
if (format.at(i).toLower().unicode() == 'a')
|
|
2657 |
return true;
|
|
2658 |
|
|
2659 |
++i;
|
|
2660 |
}
|
|
2661 |
return false;
|
|
2662 |
}
|
|
2663 |
|
|
2664 |
static QString timeZone()
|
|
2665 |
{
|
|
2666 |
#if defined(Q_OS_WINCE)
|
|
2667 |
TIME_ZONE_INFORMATION info;
|
|
2668 |
DWORD res = GetTimeZoneInformation(&info);
|
|
2669 |
if (res == TIME_ZONE_ID_UNKNOWN)
|
|
2670 |
return QString();
|
|
2671 |
return QString::fromWCharArray(info.StandardName);
|
|
2672 |
#elif defined(Q_OS_WIN)
|
|
2673 |
_tzset();
|
|
2674 |
# if defined(_MSC_VER) && _MSC_VER >= 1400
|
|
2675 |
size_t returnSize = 0;
|
|
2676 |
char timeZoneName[512];
|
|
2677 |
if (_get_tzname(&returnSize, timeZoneName, 512, 1))
|
|
2678 |
return QString();
|
|
2679 |
return QString::fromLocal8Bit(timeZoneName);
|
|
2680 |
# else
|
|
2681 |
return QString::fromLocal8Bit(_tzname[1]);
|
|
2682 |
# endif
|
|
2683 |
#elif defined(Q_OS_VXWORKS)
|
|
2684 |
return QString();
|
|
2685 |
#else
|
|
2686 |
tzset();
|
|
2687 |
return QString::fromLocal8Bit(tzname[1]);
|
|
2688 |
#endif
|
|
2689 |
}
|
|
2690 |
|
|
2691 |
/*!
|
|
2692 |
Returns a localized string representation of the given \a time according
|
|
2693 |
to the specified \a format.
|
|
2694 |
If \a format is an empty string, an empty string is returned.
|
|
2695 |
*/
|
|
2696 |
QString QLocale::toString(const QTime &time, const QString &format) const
|
|
2697 |
{
|
|
2698 |
return d()->dateTimeToString(format, 0, &time, this);
|
|
2699 |
}
|
|
2700 |
|
|
2701 |
/*!
|
|
2702 |
\since 4.4
|
|
2703 |
|
|
2704 |
Returns a localized string representation of the given \a dateTime according
|
|
2705 |
to the specified \a format.
|
|
2706 |
If \a format is an empty string, an empty string is returned.
|
|
2707 |
*/
|
|
2708 |
|
|
2709 |
QString QLocale::toString(const QDateTime &dateTime, const QString &format) const
|
|
2710 |
{
|
|
2711 |
const QDate dt = dateTime.date();
|
|
2712 |
const QTime tm = dateTime.time();
|
|
2713 |
return d()->dateTimeToString(format, &dt, &tm, this);
|
|
2714 |
}
|
|
2715 |
|
|
2716 |
/*!
|
|
2717 |
\since 4.4
|
|
2718 |
|
|
2719 |
Returns a localized string representation of the given \a dateTime according
|
|
2720 |
to the specified \a format.
|
|
2721 |
*/
|
|
2722 |
|
|
2723 |
QString QLocale::toString(const QDateTime &dateTime, FormatType format) const
|
|
2724 |
{
|
|
2725 |
if (!dateTime.isValid())
|
|
2726 |
return QString();
|
|
2727 |
|
|
2728 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
2729 |
if (d() == systemPrivate()) {
|
|
2730 |
QVariant res = systemLocale()->query(format == LongFormat
|
|
2731 |
? QSystemLocale::DateTimeToStringLong
|
|
2732 |
: QSystemLocale::DateTimeToStringShort,
|
|
2733 |
dateTime);
|
|
2734 |
if (!res.isNull())
|
|
2735 |
return res.toString();
|
|
2736 |
}
|
|
2737 |
#endif
|
|
2738 |
|
|
2739 |
const QString format_str = dateTimeFormat(format);
|
|
2740 |
return toString(dateTime, format_str);
|
|
2741 |
}
|
|
2742 |
|
|
2743 |
|
|
2744 |
/*!
|
|
2745 |
Returns a localized string representation of the given \a time in the
|
|
2746 |
specified \a format.
|
|
2747 |
*/
|
|
2748 |
|
|
2749 |
QString QLocale::toString(const QTime &time, FormatType format) const
|
|
2750 |
{
|
|
2751 |
if (!time.isValid())
|
|
2752 |
return QString();
|
|
2753 |
|
|
2754 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
2755 |
if (d() == systemPrivate()) {
|
|
2756 |
QVariant res = systemLocale()->query(format == LongFormat
|
|
2757 |
? QSystemLocale::TimeToStringLong : QSystemLocale::TimeToStringShort,
|
|
2758 |
time);
|
|
2759 |
if (!res.isNull())
|
|
2760 |
return res.toString();
|
|
2761 |
}
|
|
2762 |
#endif
|
|
2763 |
|
|
2764 |
QString format_str = timeFormat(format);
|
|
2765 |
return toString(time, format_str);
|
|
2766 |
}
|
|
2767 |
|
|
2768 |
/*!
|
|
2769 |
\since 4.1
|
|
2770 |
|
|
2771 |
Returns the date format used for the current locale.
|
|
2772 |
|
|
2773 |
If \a format is LongFormat the format will be a long version.
|
|
2774 |
Otherwise it uses a shorter version.
|
|
2775 |
|
|
2776 |
\sa QDate::toString(), QDate::fromString()
|
|
2777 |
*/
|
|
2778 |
|
|
2779 |
QString QLocale::dateFormat(FormatType format) const
|
|
2780 |
{
|
|
2781 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
2782 |
if (d() == systemPrivate()) {
|
|
2783 |
QVariant res = systemLocale()->query(format == LongFormat
|
|
2784 |
? QSystemLocale::DateFormatLong : QSystemLocale::DateFormatShort,
|
|
2785 |
QVariant());
|
|
2786 |
if (!res.isNull())
|
|
2787 |
return res.toString();
|
|
2788 |
}
|
|
2789 |
#endif
|
|
2790 |
|
|
2791 |
quint32 idx, size;
|
|
2792 |
switch (format) {
|
|
2793 |
case LongFormat:
|
|
2794 |
idx = d()->m_long_date_format_idx;
|
|
2795 |
size = d()->m_long_date_format_size;
|
|
2796 |
break;
|
|
2797 |
default:
|
|
2798 |
idx = d()->m_short_date_format_idx;
|
|
2799 |
size = d()->m_short_date_format_size;
|
|
2800 |
break;
|
|
2801 |
}
|
|
2802 |
return getLocaleData(date_format_data + idx, size);
|
|
2803 |
}
|
|
2804 |
|
|
2805 |
/*!
|
|
2806 |
\since 4.1
|
|
2807 |
|
|
2808 |
Returns the time format used for the current locale.
|
|
2809 |
|
|
2810 |
If \a format is LongFormat the format will be a long version.
|
|
2811 |
Otherwise it uses a shorter version.
|
|
2812 |
|
|
2813 |
\sa QTime::toString(), QTime::fromString()
|
|
2814 |
*/
|
|
2815 |
|
|
2816 |
QString QLocale::timeFormat(FormatType format) const
|
|
2817 |
{
|
|
2818 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
2819 |
if (d() == systemPrivate()) {
|
|
2820 |
QVariant res = systemLocale()->query(format == LongFormat
|
|
2821 |
? QSystemLocale::TimeFormatLong : QSystemLocale::TimeFormatShort,
|
|
2822 |
QVariant());
|
|
2823 |
if (!res.isNull())
|
|
2824 |
return res.toString();
|
|
2825 |
}
|
|
2826 |
#endif
|
|
2827 |
|
|
2828 |
quint32 idx, size;
|
|
2829 |
switch (format) {
|
|
2830 |
case LongFormat:
|
|
2831 |
idx = d()->m_long_time_format_idx;
|
|
2832 |
size = d()->m_long_time_format_size;
|
|
2833 |
break;
|
|
2834 |
default:
|
|
2835 |
idx = d()->m_short_time_format_idx;
|
|
2836 |
size = d()->m_short_time_format_size;
|
|
2837 |
break;
|
|
2838 |
}
|
|
2839 |
return getLocaleData(time_format_data + idx, size);
|
|
2840 |
}
|
|
2841 |
|
|
2842 |
/*!
|
|
2843 |
\since 4.4
|
|
2844 |
|
|
2845 |
Returns the date time format used for the current locale.
|
|
2846 |
|
|
2847 |
If \a format is ShortFormat the format will be a short version.
|
|
2848 |
Otherwise it uses a longer version.
|
|
2849 |
|
|
2850 |
\sa QDateTime::toString(), QDateTime::fromString()
|
|
2851 |
*/
|
|
2852 |
|
|
2853 |
QString QLocale::dateTimeFormat(FormatType format) const
|
|
2854 |
{
|
|
2855 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
2856 |
if (d() == systemPrivate()) {
|
|
2857 |
QVariant res = systemLocale()->query(format == LongFormat
|
|
2858 |
? QSystemLocale::DateTimeFormatLong
|
|
2859 |
: QSystemLocale::DateTimeFormatShort,
|
|
2860 |
QVariant());
|
|
2861 |
if (!res.isNull()) {
|
|
2862 |
return res.toString();
|
|
2863 |
}
|
|
2864 |
}
|
|
2865 |
#endif
|
|
2866 |
return dateFormat(format) + QLatin1Char(' ') + timeFormat(format);
|
|
2867 |
}
|
|
2868 |
|
|
2869 |
/*!
|
|
2870 |
\since 4.4
|
|
2871 |
|
|
2872 |
Parses the time string given in \a string and returns the
|
|
2873 |
time. The format of the time string is chosen according to the
|
|
2874 |
\a format parameter (see timeFormat()).
|
|
2875 |
|
|
2876 |
If the time could not be parsed, returns an invalid time.
|
|
2877 |
|
|
2878 |
\sa timeFormat(), toDate(), toDateTime(), QTime::fromString()
|
|
2879 |
*/
|
|
2880 |
#ifndef QT_NO_DATESTRING
|
|
2881 |
QTime QLocale::toTime(const QString &string, FormatType format) const
|
|
2882 |
{
|
|
2883 |
return toTime(string, timeFormat(format));
|
|
2884 |
}
|
|
2885 |
#endif
|
|
2886 |
|
|
2887 |
/*!
|
|
2888 |
\since 4.4
|
|
2889 |
|
|
2890 |
Parses the date string given in \a string and returns the
|
|
2891 |
date. The format of the date string is chosen according to the
|
|
2892 |
\a format parameter (see dateFormat()).
|
|
2893 |
|
|
2894 |
If the date could not be parsed, returns an invalid date.
|
|
2895 |
|
|
2896 |
\sa dateFormat(), toTime(), toDateTime(), QDate::fromString()
|
|
2897 |
*/
|
|
2898 |
#ifndef QT_NO_DATESTRING
|
|
2899 |
QDate QLocale::toDate(const QString &string, FormatType format) const
|
|
2900 |
{
|
|
2901 |
return toDate(string, dateFormat(format));
|
|
2902 |
}
|
|
2903 |
#endif
|
|
2904 |
|
|
2905 |
/*!
|
|
2906 |
\since 4.4
|
|
2907 |
|
|
2908 |
Parses the date/time string given in \a string and returns the
|
|
2909 |
time. The format of the date/time string is chosen according to the
|
|
2910 |
\a format parameter (see dateTimeFormat()).
|
|
2911 |
|
|
2912 |
If the string could not be parsed, returns an invalid QDateTime.
|
|
2913 |
|
|
2914 |
\sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString()
|
|
2915 |
*/
|
|
2916 |
|
|
2917 |
#ifndef QT_NO_DATESTRING
|
|
2918 |
QDateTime QLocale::toDateTime(const QString &string, FormatType format) const
|
|
2919 |
{
|
|
2920 |
return toDateTime(string, dateFormat(format));
|
|
2921 |
}
|
|
2922 |
#endif
|
|
2923 |
|
|
2924 |
/*!
|
|
2925 |
\since 4.4
|
|
2926 |
|
|
2927 |
Parses the time string given in \a string and returns the
|
|
2928 |
time. See QTime::fromString() for information on what is a valid
|
|
2929 |
format string.
|
|
2930 |
|
|
2931 |
If the time could not be parsed, returns an invalid time.
|
|
2932 |
|
|
2933 |
\sa timeFormat(), toDate(), toDateTime(), QTime::fromString()
|
|
2934 |
*/
|
|
2935 |
#ifndef QT_NO_DATESTRING
|
|
2936 |
QTime QLocale::toTime(const QString &string, const QString &format) const
|
|
2937 |
{
|
|
2938 |
QTime time;
|
|
2939 |
#ifndef QT_BOOTSTRAPPED
|
|
2940 |
QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString);
|
|
2941 |
dt.defaultLocale = *this;
|
|
2942 |
if (dt.parseFormat(format))
|
|
2943 |
dt.fromString(string, 0, &time);
|
|
2944 |
#else
|
|
2945 |
Q_UNUSED(string);
|
|
2946 |
Q_UNUSED(format);
|
|
2947 |
#endif
|
|
2948 |
return time;
|
|
2949 |
}
|
|
2950 |
#endif
|
|
2951 |
|
|
2952 |
/*!
|
|
2953 |
\since 4.4
|
|
2954 |
|
|
2955 |
Parses the date string given in \a string and returns the
|
|
2956 |
date. See QDate::fromString() for information on the expressions
|
|
2957 |
that can be used with this function.
|
|
2958 |
|
|
2959 |
This function searches month names and the names of the days of
|
|
2960 |
the week in the current locale.
|
|
2961 |
|
|
2962 |
If the date could not be parsed, returns an invalid date.
|
|
2963 |
|
|
2964 |
\sa dateFormat(), toTime(), toDateTime(), QDate::fromString()
|
|
2965 |
*/
|
|
2966 |
#ifndef QT_NO_DATESTRING
|
|
2967 |
QDate QLocale::toDate(const QString &string, const QString &format) const
|
|
2968 |
{
|
|
2969 |
QDate date;
|
|
2970 |
#ifndef QT_BOOTSTRAPPED
|
|
2971 |
QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString);
|
|
2972 |
dt.defaultLocale = *this;
|
|
2973 |
if (dt.parseFormat(format))
|
|
2974 |
dt.fromString(string, &date, 0);
|
|
2975 |
#else
|
|
2976 |
Q_UNUSED(string);
|
|
2977 |
Q_UNUSED(format);
|
|
2978 |
#endif
|
|
2979 |
return date;
|
|
2980 |
}
|
|
2981 |
#endif
|
|
2982 |
|
|
2983 |
/*!
|
|
2984 |
\since 4.4
|
|
2985 |
|
|
2986 |
Parses the date/time string given in \a string and returns the
|
|
2987 |
time. See QDateTime::fromString() for information on the expressions
|
|
2988 |
that can be used with this function.
|
|
2989 |
|
|
2990 |
\note The month and day names used must be given in the user's local
|
|
2991 |
language.
|
|
2992 |
|
|
2993 |
If the string could not be parsed, returns an invalid QDateTime.
|
|
2994 |
|
|
2995 |
\sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString()
|
|
2996 |
*/
|
|
2997 |
#ifndef QT_NO_DATESTRING
|
|
2998 |
QDateTime QLocale::toDateTime(const QString &string, const QString &format) const
|
|
2999 |
{
|
|
3000 |
#ifndef QT_BOOTSTRAPPED
|
|
3001 |
QTime time;
|
|
3002 |
QDate date;
|
|
3003 |
|
|
3004 |
QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString);
|
|
3005 |
dt.defaultLocale = *this;
|
|
3006 |
if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
|
|
3007 |
return QDateTime(date, time);
|
|
3008 |
#else
|
|
3009 |
Q_UNUSED(string);
|
|
3010 |
Q_UNUSED(format);
|
|
3011 |
#endif
|
|
3012 |
return QDateTime(QDate(), QTime(-1, -1, -1));
|
|
3013 |
}
|
|
3014 |
#endif
|
|
3015 |
|
|
3016 |
|
|
3017 |
/*!
|
|
3018 |
\since 4.1
|
|
3019 |
|
|
3020 |
Returns the decimal point character of this locale.
|
|
3021 |
*/
|
|
3022 |
QChar QLocale::decimalPoint() const
|
|
3023 |
{
|
|
3024 |
return d()->decimal();
|
|
3025 |
}
|
|
3026 |
|
|
3027 |
/*!
|
|
3028 |
\since 4.1
|
|
3029 |
|
|
3030 |
Returns the group separator character of this locale.
|
|
3031 |
*/
|
|
3032 |
QChar QLocale::groupSeparator() const
|
|
3033 |
{
|
|
3034 |
return d()->group();
|
|
3035 |
}
|
|
3036 |
|
|
3037 |
/*!
|
|
3038 |
\since 4.1
|
|
3039 |
|
|
3040 |
Returns the percent character of this locale.
|
|
3041 |
*/
|
|
3042 |
QChar QLocale::percent() const
|
|
3043 |
{
|
|
3044 |
return d()->percent();
|
|
3045 |
}
|
|
3046 |
|
|
3047 |
/*!
|
|
3048 |
\since 4.1
|
|
3049 |
|
|
3050 |
Returns the zero digit character of this locale.
|
|
3051 |
*/
|
|
3052 |
QChar QLocale::zeroDigit() const
|
|
3053 |
{
|
|
3054 |
return d()->zero();
|
|
3055 |
}
|
|
3056 |
|
|
3057 |
/*!
|
|
3058 |
\since 4.1
|
|
3059 |
|
|
3060 |
Returns the negative sign character of this locale.
|
|
3061 |
*/
|
|
3062 |
QChar QLocale::negativeSign() const
|
|
3063 |
{
|
|
3064 |
return d()->minus();
|
|
3065 |
}
|
|
3066 |
|
|
3067 |
/*!
|
|
3068 |
\since 4.5
|
|
3069 |
|
|
3070 |
Returns the positive sign character of this locale.
|
|
3071 |
*/
|
|
3072 |
QChar QLocale::positiveSign() const
|
|
3073 |
{
|
|
3074 |
return d()->plus();
|
|
3075 |
}
|
|
3076 |
|
|
3077 |
/*!
|
|
3078 |
\since 4.1
|
|
3079 |
|
|
3080 |
Returns the exponential character of this locale.
|
|
3081 |
*/
|
|
3082 |
QChar QLocale::exponential() const
|
|
3083 |
{
|
|
3084 |
return d()->exponential();
|
|
3085 |
}
|
|
3086 |
|
|
3087 |
static bool qIsUpper(char c)
|
|
3088 |
{
|
|
3089 |
return c >= 'A' && c <= 'Z';
|
|
3090 |
}
|
|
3091 |
|
|
3092 |
static char qToLower(char c)
|
|
3093 |
{
|
|
3094 |
if (c >= 'A' && c <= 'Z')
|
|
3095 |
return c - 'A' + 'a';
|
|
3096 |
else
|
|
3097 |
return c;
|
|
3098 |
}
|
|
3099 |
|
|
3100 |
/*!
|
|
3101 |
\overload
|
|
3102 |
|
|
3103 |
\a f and \a prec have the same meaning as in QString::number(double, char, int).
|
|
3104 |
|
|
3105 |
\sa toDouble()
|
|
3106 |
*/
|
|
3107 |
|
|
3108 |
QString QLocale::toString(double i, char f, int prec) const
|
|
3109 |
{
|
|
3110 |
QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal;
|
|
3111 |
uint flags = 0;
|
|
3112 |
|
|
3113 |
if (qIsUpper(f))
|
|
3114 |
flags = QLocalePrivate::CapitalEorX;
|
|
3115 |
f = qToLower(f);
|
|
3116 |
|
|
3117 |
switch (f) {
|
|
3118 |
case 'f':
|
|
3119 |
form = QLocalePrivate::DFDecimal;
|
|
3120 |
break;
|
|
3121 |
case 'e':
|
|
3122 |
form = QLocalePrivate::DFExponent;
|
|
3123 |
break;
|
|
3124 |
case 'g':
|
|
3125 |
form = QLocalePrivate::DFSignificantDigits;
|
|
3126 |
break;
|
|
3127 |
default:
|
|
3128 |
break;
|
|
3129 |
}
|
|
3130 |
|
|
3131 |
if (!(p.numberOptions & OmitGroupSeparator))
|
|
3132 |
flags |= QLocalePrivate::ThousandsGroup;
|
|
3133 |
return d()->doubleToString(i, prec, form, -1, flags);
|
|
3134 |
}
|
|
3135 |
|
|
3136 |
/*!
|
|
3137 |
\fn QLocale QLocale::c()
|
|
3138 |
|
|
3139 |
Returns a QLocale object initialized to the "C" locale.
|
|
3140 |
|
|
3141 |
\sa system()
|
|
3142 |
*/
|
|
3143 |
|
|
3144 |
/*!
|
|
3145 |
Returns a QLocale object initialized to the system locale.
|
|
3146 |
|
|
3147 |
On Windows and Mac, this locale will use the decimal/grouping characters and date/time
|
|
3148 |
formats specified in the system configuration panel.
|
|
3149 |
|
|
3150 |
\sa QTextCodec::locale() c()
|
|
3151 |
*/
|
|
3152 |
|
|
3153 |
QLocale QLocale::system()
|
|
3154 |
{
|
|
3155 |
QLocale result(C);
|
|
3156 |
result.p.index = localePrivateIndex(systemPrivate());
|
|
3157 |
return result;
|
|
3158 |
}
|
|
3159 |
|
|
3160 |
/*!
|
|
3161 |
\since 4.3
|
|
3162 |
|
|
3163 |
Returns the list of countries that have entires for \a language in Qt's locale
|
|
3164 |
database. If the result is an empty list, then \a language is not represented in
|
|
3165 |
Qt's locale database.
|
|
3166 |
*/
|
|
3167 |
QList<QLocale::Country> QLocale::countriesForLanguage(Language language)
|
|
3168 |
{
|
|
3169 |
QList<Country> result;
|
|
3170 |
|
|
3171 |
unsigned language_id = language;
|
|
3172 |
uint idx = locale_index[language_id];
|
|
3173 |
|
|
3174 |
if (language == C) {
|
|
3175 |
result << AnyCountry;
|
|
3176 |
return result;
|
|
3177 |
}
|
|
3178 |
|
|
3179 |
const QLocalePrivate *d = locale_data + idx;
|
|
3180 |
|
|
3181 |
while (d->languageId() == language_id) {
|
|
3182 |
result << static_cast<Country>(d->countryId());
|
|
3183 |
++d;
|
|
3184 |
}
|
|
3185 |
|
|
3186 |
return result;
|
|
3187 |
}
|
|
3188 |
|
|
3189 |
/*!
|
|
3190 |
\since 4.2
|
|
3191 |
|
|
3192 |
Returns the localized name of \a month, in the format specified
|
|
3193 |
by \a type.
|
|
3194 |
|
|
3195 |
\sa dayName(), standaloneMonthName()
|
|
3196 |
*/
|
|
3197 |
QString QLocale::monthName(int month, FormatType type) const
|
|
3198 |
{
|
|
3199 |
if (month < 1 || month > 12)
|
|
3200 |
return QString();
|
|
3201 |
|
|
3202 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
3203 |
if (d() == systemPrivate()) {
|
|
3204 |
QVariant res = systemLocale()->query(type == LongFormat
|
|
3205 |
? QSystemLocale::MonthNameLong : QSystemLocale::MonthNameShort,
|
|
3206 |
month);
|
|
3207 |
if (!res.isNull())
|
|
3208 |
return res.toString();
|
|
3209 |
}
|
|
3210 |
#endif
|
|
3211 |
|
|
3212 |
quint32 idx, size;
|
|
3213 |
switch (type) {
|
|
3214 |
case QLocale::LongFormat:
|
|
3215 |
idx = d()->m_long_month_names_idx;
|
|
3216 |
size = d()->m_long_month_names_size;
|
|
3217 |
break;
|
|
3218 |
case QLocale::ShortFormat:
|
|
3219 |
idx = d()->m_short_month_names_idx;
|
|
3220 |
size = d()->m_short_month_names_size;
|
|
3221 |
break;
|
|
3222 |
case QLocale::NarrowFormat:
|
|
3223 |
idx = d()->m_narrow_month_names_idx;
|
|
3224 |
size = d()->m_narrow_month_names_size;
|
|
3225 |
break;
|
|
3226 |
default:
|
|
3227 |
return QString();
|
|
3228 |
}
|
|
3229 |
return getLocaleListData(months_data + idx, size, month - 1);
|
|
3230 |
}
|
|
3231 |
|
|
3232 |
/*!
|
|
3233 |
\since 4.5
|
|
3234 |
|
|
3235 |
Returns the localized name of \a month that is used as a
|
|
3236 |
standalone text, in the format specified by \a type.
|
|
3237 |
|
|
3238 |
If the locale information doesn't specify the standalone month
|
|
3239 |
name then return value is the same as in monthName().
|
|
3240 |
|
|
3241 |
\sa monthName(), standaloneDayName()
|
|
3242 |
*/
|
|
3243 |
QString QLocale::standaloneMonthName(int month, FormatType type) const
|
|
3244 |
{
|
|
3245 |
if (month < 1 || month > 12)
|
|
3246 |
return QString();
|
|
3247 |
|
|
3248 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
3249 |
if (d() == systemPrivate()) {
|
|
3250 |
QVariant res = systemLocale()->query(type == LongFormat
|
|
3251 |
? QSystemLocale::MonthNameLong : QSystemLocale::MonthNameShort,
|
|
3252 |
month);
|
|
3253 |
if (!res.isNull())
|
|
3254 |
return res.toString();
|
|
3255 |
}
|
|
3256 |
#endif
|
|
3257 |
|
|
3258 |
quint32 idx, size;
|
|
3259 |
switch (type) {
|
|
3260 |
case QLocale::LongFormat:
|
|
3261 |
idx = d()->m_standalone_long_month_names_idx;
|
|
3262 |
size = d()->m_standalone_long_month_names_size;
|
|
3263 |
break;
|
|
3264 |
case QLocale::ShortFormat:
|
|
3265 |
idx = d()->m_standalone_short_month_names_idx;
|
|
3266 |
size = d()->m_standalone_short_month_names_size;
|
|
3267 |
break;
|
|
3268 |
case QLocale::NarrowFormat:
|
|
3269 |
idx = d()->m_standalone_narrow_month_names_idx;
|
|
3270 |
size = d()->m_standalone_narrow_month_names_size;
|
|
3271 |
break;
|
|
3272 |
default:
|
|
3273 |
return QString();
|
|
3274 |
}
|
|
3275 |
QString name = getLocaleListData(standalone_months_data + idx, size, month - 1);
|
|
3276 |
if (name.isEmpty())
|
|
3277 |
return monthName(month, type);
|
|
3278 |
return name;
|
|
3279 |
}
|
|
3280 |
|
|
3281 |
/*!
|
|
3282 |
\since 4.2
|
|
3283 |
|
|
3284 |
Returns the localized name of the \a day (where 1 represents
|
|
3285 |
Monday, 2 represents Tuesday and so on), in the format specified
|
|
3286 |
by \a type.
|
|
3287 |
|
|
3288 |
\sa monthName(), standaloneDayName()
|
|
3289 |
*/
|
|
3290 |
QString QLocale::dayName(int day, FormatType type) const
|
|
3291 |
{
|
|
3292 |
if (day < 1 || day > 7)
|
|
3293 |
return QString();
|
|
3294 |
|
|
3295 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
3296 |
if (d() == systemPrivate()) {
|
|
3297 |
QVariant res = systemLocale()->query(type == LongFormat
|
|
3298 |
? QSystemLocale::DayNameLong : QSystemLocale::DayNameShort,
|
|
3299 |
day);
|
|
3300 |
if (!res.isNull())
|
|
3301 |
return res.toString();
|
|
3302 |
}
|
|
3303 |
#endif
|
|
3304 |
if (day == 7)
|
|
3305 |
day = 0;
|
|
3306 |
|
|
3307 |
quint32 idx, size;
|
|
3308 |
switch (type) {
|
|
3309 |
case QLocale::LongFormat:
|
|
3310 |
idx = d()->m_long_day_names_idx;
|
|
3311 |
size = d()->m_long_day_names_size;
|
|
3312 |
break;
|
|
3313 |
case QLocale::ShortFormat:
|
|
3314 |
idx = d()->m_short_day_names_idx;
|
|
3315 |
size = d()->m_short_day_names_size;
|
|
3316 |
break;
|
|
3317 |
case QLocale::NarrowFormat:
|
|
3318 |
idx = d()->m_narrow_day_names_idx;
|
|
3319 |
size = d()->m_narrow_day_names_size;
|
|
3320 |
break;
|
|
3321 |
default:
|
|
3322 |
return QString();
|
|
3323 |
}
|
|
3324 |
return getLocaleListData(days_data + idx, size, day);
|
|
3325 |
}
|
|
3326 |
|
|
3327 |
/*!
|
|
3328 |
\since 4.5
|
|
3329 |
|
|
3330 |
Returns the localized name of the \a day (where 1 represents
|
|
3331 |
Monday, 2 represents Tuesday and so on) that is used as a
|
|
3332 |
standalone text, in the format specified by \a type.
|
|
3333 |
|
|
3334 |
If the locale information does not specify the standalone day
|
|
3335 |
name then return value is the same as in dayName().
|
|
3336 |
|
|
3337 |
\sa dayName(), standaloneMonthName()
|
|
3338 |
*/
|
|
3339 |
QString QLocale::standaloneDayName(int day, FormatType type) const
|
|
3340 |
{
|
|
3341 |
if (day < 1 || day > 7)
|
|
3342 |
return QString();
|
|
3343 |
|
|
3344 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
3345 |
if (d() == systemPrivate()) {
|
|
3346 |
QVariant res = systemLocale()->query(type == LongFormat
|
|
3347 |
? QSystemLocale::DayNameLong : QSystemLocale::DayNameShort,
|
|
3348 |
day);
|
|
3349 |
if (!res.isNull())
|
|
3350 |
return res.toString();
|
|
3351 |
}
|
|
3352 |
#endif
|
|
3353 |
if (day == 7)
|
|
3354 |
day = 0;
|
|
3355 |
|
|
3356 |
quint32 idx, size;
|
|
3357 |
switch (type) {
|
|
3358 |
case QLocale::LongFormat:
|
|
3359 |
idx = d()->m_standalone_long_day_names_idx;
|
|
3360 |
size = d()->m_standalone_long_day_names_size;
|
|
3361 |
break;
|
|
3362 |
case QLocale::ShortFormat:
|
|
3363 |
idx = d()->m_standalone_short_day_names_idx;
|
|
3364 |
size = d()->m_standalone_short_day_names_size;
|
|
3365 |
break;
|
|
3366 |
case QLocale::NarrowFormat:
|
|
3367 |
idx = d()->m_standalone_narrow_day_names_idx;
|
|
3368 |
size = d()->m_standalone_narrow_day_names_size;
|
|
3369 |
break;
|
|
3370 |
default:
|
|
3371 |
return QString();
|
|
3372 |
}
|
|
3373 |
QString name = getLocaleListData(days_data + idx, size, day);
|
|
3374 |
if (name.isEmpty())
|
|
3375 |
return dayName(day == 0 ? 7 : day, type);
|
|
3376 |
return name;
|
|
3377 |
}
|
|
3378 |
|
|
3379 |
/*!
|
|
3380 |
\since 4.4
|
|
3381 |
|
|
3382 |
Returns the measurement system for the locale.
|
|
3383 |
*/
|
|
3384 |
QLocale::MeasurementSystem QLocale::measurementSystem() const
|
|
3385 |
{
|
|
3386 |
MeasurementSystem meas = MetricSystem;
|
|
3387 |
bool found = false;
|
|
3388 |
|
|
3389 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
3390 |
if (d() == systemPrivate()) {
|
|
3391 |
QVariant res = systemLocale()->query(QSystemLocale::MeasurementSystem, QVariant());
|
|
3392 |
if (!res.isNull()) {
|
|
3393 |
meas = MeasurementSystem(res.toInt());
|
|
3394 |
found = true;
|
|
3395 |
}
|
|
3396 |
}
|
|
3397 |
#endif
|
|
3398 |
|
|
3399 |
if (!found) {
|
|
3400 |
meas = d()->measurementSystem();
|
|
3401 |
found = true;
|
|
3402 |
}
|
|
3403 |
|
|
3404 |
return meas;
|
|
3405 |
}
|
|
3406 |
|
|
3407 |
/*!
|
|
3408 |
\since 4.5
|
|
3409 |
|
|
3410 |
Returns the localized name of the "AM" suffix for times specified using
|
|
3411 |
the conventions of the 12-hour clock.
|
|
3412 |
|
|
3413 |
\sa pmText()
|
|
3414 |
*/
|
|
3415 |
QString QLocale::amText() const
|
|
3416 |
{
|
|
3417 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
3418 |
if (d() == systemPrivate()) {
|
|
3419 |
QVariant res = systemLocale()->query(QSystemLocale::AMText, QVariant());
|
|
3420 |
if (!res.isNull())
|
|
3421 |
return res.toString();
|
|
3422 |
}
|
|
3423 |
#endif
|
|
3424 |
return getLocaleData(am_data + d()->m_am_idx, d()->m_am_size);
|
|
3425 |
}
|
|
3426 |
|
|
3427 |
/*!
|
|
3428 |
\since 4.5
|
|
3429 |
|
|
3430 |
Returns the localized name of the "PM" suffix for times specified using
|
|
3431 |
the conventions of the 12-hour clock.
|
|
3432 |
|
|
3433 |
\sa amText()
|
|
3434 |
*/
|
|
3435 |
QString QLocale::pmText() const
|
|
3436 |
{
|
|
3437 |
#ifndef QT_NO_SYSTEMLOCALE
|
|
3438 |
if (d() == systemPrivate()) {
|
|
3439 |
QVariant res = systemLocale()->query(QSystemLocale::PMText, QVariant());
|
|
3440 |
if (!res.isNull())
|
|
3441 |
return res.toString();
|
|
3442 |
}
|
|
3443 |
#endif
|
|
3444 |
return getLocaleData(pm_data + d()->m_pm_idx, d()->m_pm_size);
|
|
3445 |
}
|
|
3446 |
|
|
3447 |
|
|
3448 |
/*!
|
|
3449 |
\fn QString QLocale::toString(short i) const
|
|
3450 |
|
|
3451 |
\overload
|
|
3452 |
|
|
3453 |
\sa toShort()
|
|
3454 |
*/
|
|
3455 |
|
|
3456 |
/*!
|
|
3457 |
\fn QString QLocale::toString(ushort i) const
|
|
3458 |
|
|
3459 |
\overload
|
|
3460 |
|
|
3461 |
\sa toUShort()
|
|
3462 |
*/
|
|
3463 |
|
|
3464 |
/*!
|
|
3465 |
\fn QString QLocale::toString(int i) const
|
|
3466 |
|
|
3467 |
\overload
|
|
3468 |
|
|
3469 |
\sa toInt()
|
|
3470 |
*/
|
|
3471 |
|
|
3472 |
/*!
|
|
3473 |
\fn QString QLocale::toString(uint i) const
|
|
3474 |
|
|
3475 |
\overload
|
|
3476 |
|
|
3477 |
\sa toUInt()
|
|
3478 |
*/
|
|
3479 |
|
|
3480 |
/*
|
|
3481 |
\fn QString QLocale::toString(long i) const
|
|
3482 |
|
|
3483 |
\overload
|
|
3484 |
|
|
3485 |
\sa toLong()
|
|
3486 |
*/
|
|
3487 |
|
|
3488 |
/*
|
|
3489 |
\fn QString QLocale::toString(ulong i) const
|
|
3490 |
|
|
3491 |
\overload
|
|
3492 |
|
|
3493 |
\sa toULong()
|
|
3494 |
*/
|
|
3495 |
|
|
3496 |
/*!
|
|
3497 |
\fn QString QLocale::toString(float i, char f = 'g', int prec = 6) const
|
|
3498 |
|
|
3499 |
\overload
|
|
3500 |
|
|
3501 |
\a f and \a prec have the same meaning as in QString::number(double, char, int).
|
|
3502 |
|
|
3503 |
\sa toDouble()
|
|
3504 |
*/
|
|
3505 |
|
|
3506 |
|
|
3507 |
static QString qulltoa(qulonglong l, int base, const QLocalePrivate &locale)
|
|
3508 |
{
|
|
3509 |
ushort buff[65]; // length of MAX_ULLONG in base 2
|
|
3510 |
ushort *p = buff + 65;
|
|
3511 |
const QChar _zero = locale.zero();
|
|
3512 |
|
|
3513 |
if (base != 10 || _zero.unicode() == '0') {
|
|
3514 |
while (l != 0) {
|
|
3515 |
int c = l % base;
|
|
3516 |
|
|
3517 |
--p;
|
|
3518 |
|
|
3519 |
if (c < 10)
|
|
3520 |
*p = '0' + c;
|
|
3521 |
else
|
|
3522 |
*p = c - 10 + 'a';
|
|
3523 |
|
|
3524 |
l /= base;
|
|
3525 |
}
|
|
3526 |
}
|
|
3527 |
else {
|
|
3528 |
while (l != 0) {
|
|
3529 |
int c = l % base;
|
|
3530 |
|
|
3531 |
*(--p) = _zero.unicode() + c;
|
|
3532 |
|
|
3533 |
l /= base;
|
|
3534 |
}
|
|
3535 |
}
|
|
3536 |
|
|
3537 |
return QString(reinterpret_cast<QChar *>(p), 65 - (p - buff));
|
|
3538 |
}
|
|
3539 |
|
|
3540 |
static QString qlltoa(qlonglong l, int base, const QLocalePrivate &locale)
|
|
3541 |
{
|
|
3542 |
return qulltoa(l < 0 ? -l : l, base, locale);
|
|
3543 |
}
|
|
3544 |
|
|
3545 |
enum PrecisionMode {
|
|
3546 |
PMDecimalDigits = 0x01,
|
|
3547 |
PMSignificantDigits = 0x02,
|
|
3548 |
PMChopTrailingZeros = 0x03
|
|
3549 |
};
|
|
3550 |
|
|
3551 |
static QString &decimalForm(QString &digits, int decpt, uint precision,
|
|
3552 |
PrecisionMode pm,
|
|
3553 |
bool always_show_decpt,
|
|
3554 |
bool thousands_group,
|
|
3555 |
const QLocalePrivate &locale)
|
|
3556 |
{
|
|
3557 |
if (decpt < 0) {
|
|
3558 |
for (int i = 0; i < -decpt; ++i)
|
|
3559 |
digits.prepend(locale.zero());
|
|
3560 |
decpt = 0;
|
|
3561 |
}
|
|
3562 |
else if (decpt > digits.length()) {
|
|
3563 |
for (int i = digits.length(); i < decpt; ++i)
|
|
3564 |
digits.append(locale.zero());
|
|
3565 |
}
|
|
3566 |
|
|
3567 |
if (pm == PMDecimalDigits) {
|
|
3568 |
uint decimal_digits = digits.length() - decpt;
|
|
3569 |
for (uint i = decimal_digits; i < precision; ++i)
|
|
3570 |
digits.append(locale.zero());
|
|
3571 |
}
|
|
3572 |
else if (pm == PMSignificantDigits) {
|
|
3573 |
for (uint i = digits.length(); i < precision; ++i)
|
|
3574 |
digits.append(locale.zero());
|
|
3575 |
}
|
|
3576 |
else { // pm == PMChopTrailingZeros
|
|
3577 |
}
|
|
3578 |
|
|
3579 |
if (always_show_decpt || decpt < digits.length())
|
|
3580 |
digits.insert(decpt, locale.decimal());
|
|
3581 |
|
|
3582 |
if (thousands_group) {
|
|
3583 |
for (int i = decpt - 3; i > 0; i -= 3)
|
|
3584 |
digits.insert(i, locale.group());
|
|
3585 |
}
|
|
3586 |
|
|
3587 |
if (decpt == 0)
|
|
3588 |
digits.prepend(locale.zero());
|
|
3589 |
|
|
3590 |
return digits;
|
|
3591 |
}
|
|
3592 |
|
|
3593 |
static QString &exponentForm(QString &digits, int decpt, uint precision,
|
|
3594 |
PrecisionMode pm,
|
|
3595 |
bool always_show_decpt,
|
|
3596 |
const QLocalePrivate &locale)
|
|
3597 |
{
|
|
3598 |
int exp = decpt - 1;
|
|
3599 |
|
|
3600 |
if (pm == PMDecimalDigits) {
|
|
3601 |
for (uint i = digits.length(); i < precision + 1; ++i)
|
|
3602 |
digits.append(locale.zero());
|
|
3603 |
}
|
|
3604 |
else if (pm == PMSignificantDigits) {
|
|
3605 |
for (uint i = digits.length(); i < precision; ++i)
|
|
3606 |
digits.append(locale.zero());
|
|
3607 |
}
|
|
3608 |
else { // pm == PMChopTrailingZeros
|
|
3609 |
}
|
|
3610 |
|
|
3611 |
if (always_show_decpt || digits.length() > 1)
|
|
3612 |
digits.insert(1, locale.decimal());
|
|
3613 |
|
|
3614 |
digits.append(locale.exponential());
|
|
3615 |
digits.append(locale.longLongToString(exp, 2, 10,
|
|
3616 |
-1, QLocalePrivate::AlwaysShowSign));
|
|
3617 |
|
|
3618 |
return digits;
|
|
3619 |
}
|
|
3620 |
|
|
3621 |
static bool isZero(double d)
|
|
3622 |
{
|
|
3623 |
uchar *ch = (uchar *)&d;
|
|
3624 |
#ifdef QT_ARMFPA
|
|
3625 |
return !(ch[3] & 0x7F || ch[2] || ch[1] || ch[0] || ch[7] || ch[6] || ch[5] || ch[4]);
|
|
3626 |
#else
|
|
3627 |
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
|
|
3628 |
return !(ch[0] & 0x7F || ch[1] || ch[2] || ch[3] || ch[4] || ch[5] || ch[6] || ch[7]);
|
|
3629 |
} else {
|
|
3630 |
return !(ch[7] & 0x7F || ch[6] || ch[5] || ch[4] || ch[3] || ch[2] || ch[1] || ch[0]);
|
|
3631 |
}
|
|
3632 |
#endif
|
|
3633 |
}
|
|
3634 |
|
|
3635 |
QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *date, const QTime *time,
|
|
3636 |
const QLocale *q) const
|
|
3637 |
{
|
|
3638 |
Q_ASSERT(date || time);
|
|
3639 |
if ((date && !date->isValid()) || (time && !time->isValid()))
|
|
3640 |
return QString();
|
|
3641 |
const bool format_am_pm = time && timeFormatContainsAP(format);
|
|
3642 |
|
|
3643 |
enum { AM, PM } am_pm = AM;
|
|
3644 |
int hour12 = time ? time->hour() : -1;
|
|
3645 |
if (time) {
|
|
3646 |
if (hour12 == 0) {
|
|
3647 |
am_pm = AM;
|
|
3648 |
hour12 = 12;
|
|
3649 |
} else if (hour12 < 12) {
|
|
3650 |
am_pm = AM;
|
|
3651 |
} else if (hour12 == 12) {
|
|
3652 |
am_pm = PM;
|
|
3653 |
} else {
|
|
3654 |
am_pm = PM;
|
|
3655 |
hour12 -= 12;
|
|
3656 |
}
|
|
3657 |
}
|
|
3658 |
|
|
3659 |
QString result;
|
|
3660 |
|
|
3661 |
int i = 0;
|
|
3662 |
while (i < format.size()) {
|
|
3663 |
if (format.at(i).unicode() == '\'') {
|
|
3664 |
result.append(readEscapedFormatString(format, &i));
|
|
3665 |
continue;
|
|
3666 |
}
|
|
3667 |
|
|
3668 |
const QChar c = format.at(i);
|
|
3669 |
int repeat = repeatCount(format, i);
|
|
3670 |
bool used = false;
|
|
3671 |
if (date) {
|
|
3672 |
switch (c.unicode()) {
|
|
3673 |
case 'y':
|
|
3674 |
used = true;
|
|
3675 |
if (repeat >= 4)
|
|
3676 |
repeat = 4;
|
|
3677 |
else if (repeat >= 2)
|
|
3678 |
repeat = 2;
|
|
3679 |
|
|
3680 |
switch (repeat) {
|
|
3681 |
case 4:
|
|
3682 |
result.append(longLongToString(date->year()));
|
|
3683 |
break;
|
|
3684 |
case 2:
|
|
3685 |
result.append(longLongToString(date->year() % 100, -1, 10, 2,
|
|
3686 |
QLocalePrivate::ZeroPadded));
|
|
3687 |
break;
|
|
3688 |
default:
|
|
3689 |
repeat = 1;
|
|
3690 |
result.append(c);
|
|
3691 |
break;
|
|
3692 |
}
|
|
3693 |
break;
|
|
3694 |
|
|
3695 |
case 'M':
|
|
3696 |
used = true;
|
|
3697 |
repeat = qMin(repeat, 4);
|
|
3698 |
switch (repeat) {
|
|
3699 |
case 1:
|
|
3700 |
result.append(longLongToString(date->month()));
|
|
3701 |
break;
|
|
3702 |
case 2:
|
|
3703 |
result.append(longLongToString(date->month(), -1, 10, 2, QLocalePrivate::ZeroPadded));
|
|
3704 |
break;
|
|
3705 |
case 3:
|
|
3706 |
result.append(q->monthName(date->month(), QLocale::ShortFormat));
|
|
3707 |
break;
|
|
3708 |
case 4:
|
|
3709 |
result.append(q->monthName(date->month(), QLocale::LongFormat));
|
|
3710 |
break;
|
|
3711 |
}
|
|
3712 |
break;
|
|
3713 |
|
|
3714 |
case 'd':
|
|
3715 |
used = true;
|
|
3716 |
repeat = qMin(repeat, 4);
|
|
3717 |
switch (repeat) {
|
|
3718 |
case 1:
|
|
3719 |
result.append(longLongToString(date->day()));
|
|
3720 |
break;
|
|
3721 |
case 2:
|
|
3722 |
result.append(longLongToString(date->day(), -1, 10, 2, QLocalePrivate::ZeroPadded));
|
|
3723 |
break;
|
|
3724 |
case 3:
|
|
3725 |
result.append(q->dayName(date->dayOfWeek(), QLocale::ShortFormat));
|
|
3726 |
break;
|
|
3727 |
case 4:
|
|
3728 |
result.append(q->dayName(date->dayOfWeek(), QLocale::LongFormat));
|
|
3729 |
break;
|
|
3730 |
}
|
|
3731 |
break;
|
|
3732 |
|
|
3733 |
default:
|
|
3734 |
break;
|
|
3735 |
}
|
|
3736 |
}
|
|
3737 |
if (!used && time) {
|
|
3738 |
switch (c.unicode()) {
|
|
3739 |
case 'h': {
|
|
3740 |
used = true;
|
|
3741 |
repeat = qMin(repeat, 2);
|
|
3742 |
const int hour = format_am_pm ? hour12 : time->hour();
|
|
3743 |
|
|
3744 |
switch (repeat) {
|
|
3745 |
case 1:
|
|
3746 |
result.append(longLongToString(hour));
|
|
3747 |
break;
|
|
3748 |
case 2:
|
|
3749 |
result.append(longLongToString(hour, -1, 10, 2, QLocalePrivate::ZeroPadded));
|
|
3750 |
break;
|
|
3751 |
}
|
|
3752 |
break;
|
|
3753 |
}
|
|
3754 |
case 'H':
|
|
3755 |
used = true;
|
|
3756 |
repeat = qMin(repeat, 2);
|
|
3757 |
switch (repeat) {
|
|
3758 |
case 1:
|
|
3759 |
result.append(longLongToString(time->hour()));
|
|
3760 |
break;
|
|
3761 |
case 2:
|
|
3762 |
result.append(longLongToString(time->hour(), -1, 10, 2, QLocalePrivate::ZeroPadded));
|
|
3763 |
break;
|
|
3764 |
}
|
|
3765 |
break;
|
|
3766 |
|
|
3767 |
case 'm':
|
|
3768 |
used = true;
|
|
3769 |
repeat = qMin(repeat, 2);
|
|
3770 |
switch (repeat) {
|
|
3771 |
case 1:
|
|
3772 |
result.append(longLongToString(time->minute()));
|
|
3773 |
break;
|
|
3774 |
case 2:
|
|
3775 |
result.append(longLongToString(time->minute(), -1, 10, 2, QLocalePrivate::ZeroPadded));
|
|
3776 |
break;
|
|
3777 |
}
|
|
3778 |
break;
|
|
3779 |
|
|
3780 |
case 's':
|
|
3781 |
used = true;
|
|
3782 |
repeat = qMin(repeat, 2);
|
|
3783 |
switch (repeat) {
|
|
3784 |
case 1:
|
|
3785 |
result.append(longLongToString(time->second()));
|
|
3786 |
break;
|
|
3787 |
case 2:
|
|
3788 |
result.append(longLongToString(time->second(), -1, 10, 2, QLocalePrivate::ZeroPadded));
|
|
3789 |
break;
|
|
3790 |
}
|
|
3791 |
break;
|
|
3792 |
|
|
3793 |
case 'a':
|
|
3794 |
used = true;
|
|
3795 |
if (i + 1 < format.length() && format.at(i + 1).unicode() == 'p') {
|
|
3796 |
repeat = 2;
|
|
3797 |
} else {
|
|
3798 |
repeat = 1;
|
|
3799 |
}
|
|
3800 |
result.append(am_pm == AM ? QLatin1String("am") : QLatin1String("pm"));
|
|
3801 |
break;
|
|
3802 |
|
|
3803 |
case 'A':
|
|
3804 |
used = true;
|
|
3805 |
if (i + 1 < format.length() && format.at(i + 1).unicode() == 'P') {
|
|
3806 |
repeat = 2;
|
|
3807 |
} else {
|
|
3808 |
repeat = 1;
|
|
3809 |
}
|
|
3810 |
result.append(am_pm == AM ? QLatin1String("AM") : QLatin1String("PM"));
|
|
3811 |
break;
|
|
3812 |
|
|
3813 |
case 'z':
|
|
3814 |
used = true;
|
|
3815 |
if (repeat >= 3) {
|
|
3816 |
repeat = 3;
|
|
3817 |
} else {
|
|
3818 |
repeat = 1;
|
|
3819 |
}
|
|
3820 |
switch (repeat) {
|
|
3821 |
case 1:
|
|
3822 |
result.append(longLongToString(time->msec()));
|
|
3823 |
break;
|
|
3824 |
case 3:
|
|
3825 |
result.append(longLongToString(time->msec(), -1, 10, 3, QLocalePrivate::ZeroPadded));
|
|
3826 |
break;
|
|
3827 |
}
|
|
3828 |
break;
|
|
3829 |
|
|
3830 |
case 't':
|
|
3831 |
used = true;
|
|
3832 |
repeat = 1;
|
|
3833 |
result.append(timeZone());
|
|
3834 |
break;
|
|
3835 |
default:
|
|
3836 |
break;
|
|
3837 |
}
|
|
3838 |
}
|
|
3839 |
if (!used) {
|
|
3840 |
result.append(QString(repeat, c));
|
|
3841 |
}
|
|
3842 |
i += repeat;
|
|
3843 |
}
|
|
3844 |
|
|
3845 |
return result;
|
|
3846 |
}
|
|
3847 |
|
|
3848 |
QString QLocalePrivate::doubleToString(double d,
|
|
3849 |
int precision,
|
|
3850 |
DoubleForm form,
|
|
3851 |
int width,
|
|
3852 |
unsigned flags) const
|
|
3853 |
{
|
|
3854 |
if (precision == -1)
|
|
3855 |
precision = 6;
|
|
3856 |
if (width == -1)
|
|
3857 |
width = 0;
|
|
3858 |
|
|
3859 |
bool negative = false;
|
|
3860 |
bool special_number = false; // nan, +/-inf
|
|
3861 |
QString num_str;
|
|
3862 |
|
|
3863 |
// Detect special numbers (nan, +/-inf)
|
|
3864 |
if (qt_is_inf(d)) {
|
|
3865 |
num_str = QString::fromLatin1("inf");
|
|
3866 |
special_number = true;
|
|
3867 |
negative = d < 0;
|
|
3868 |
} else if (qt_is_nan(d)) {
|
|
3869 |
num_str = QString::fromLatin1("nan");
|
|
3870 |
special_number = true;
|
|
3871 |
}
|
|
3872 |
|
|
3873 |
// Handle normal numbers
|
|
3874 |
if (!special_number) {
|
|
3875 |
int decpt, sign;
|
|
3876 |
QString digits;
|
|
3877 |
|
|
3878 |
#ifdef QT_QLOCALE_USES_FCVT
|
|
3879 |
// NOT thread safe!
|
|
3880 |
if (form == DFDecimal) {
|
|
3881 |
digits = QLatin1String(fcvt(d, precision, &decpt, &sign));
|
|
3882 |
} else {
|
|
3883 |
int pr = precision;
|
|
3884 |
if (form == DFExponent)
|
|
3885 |
++pr;
|
|
3886 |
else if (form == DFSignificantDigits && pr == 0)
|
|
3887 |
pr = 1;
|
|
3888 |
digits = QLatin1String(ecvt(d, pr, &decpt, &sign));
|
|
3889 |
|
|
3890 |
// Chop trailing zeros
|
|
3891 |
if (digits.length() > 0) {
|
|
3892 |
int last_nonzero_idx = digits.length() - 1;
|
|
3893 |
while (last_nonzero_idx > 0
|
|
3894 |
&& digits.unicode()[last_nonzero_idx] == QLatin1Char('0'))
|
|
3895 |
--last_nonzero_idx;
|
|
3896 |
digits.truncate(last_nonzero_idx + 1);
|
|
3897 |
}
|
|
3898 |
|
|
3899 |
}
|
|
3900 |
|
|
3901 |
#else
|
|
3902 |
int mode;
|
|
3903 |
if (form == DFDecimal)
|
|
3904 |
mode = 3;
|
|
3905 |
else
|
|
3906 |
mode = 2;
|
|
3907 |
|
|
3908 |
/* This next bit is a bit quirky. In DFExponent form, the precision
|
|
3909 |
is the number of digits after decpt. So that would suggest using
|
|
3910 |
mode=3 for qdtoa. But qdtoa behaves strangely when mode=3 and
|
|
3911 |
precision=0. So we get around this by using mode=2 and reasoning
|
|
3912 |
that we want precision+1 significant digits, since the decimal
|
|
3913 |
point in this mode is always after the first digit. */
|
|
3914 |
int pr = precision;
|
|
3915 |
if (form == DFExponent)
|
|
3916 |
++pr;
|
|
3917 |
|
|
3918 |
char *rve = 0;
|
|
3919 |
char *buff = 0;
|
|
3920 |
QT_TRY {
|
|
3921 |
digits = QLatin1String(qdtoa(d, mode, pr, &decpt, &sign, &rve, &buff));
|
|
3922 |
} QT_CATCH(...) {
|
|
3923 |
if (buff != 0)
|
|
3924 |
free(buff);
|
|
3925 |
QT_RETHROW;
|
|
3926 |
}
|
|
3927 |
if (buff != 0)
|
|
3928 |
free(buff);
|
|
3929 |
#endif // QT_QLOCALE_USES_FCVT
|
|
3930 |
|
|
3931 |
const QChar _zero = zero();
|
|
3932 |
|
|
3933 |
if (_zero.unicode() != '0') {
|
|
3934 |
ushort z = _zero.unicode() - '0';
|
|
3935 |
for (int i = 0; i < digits.length(); ++i)
|
|
3936 |
reinterpret_cast<ushort *>(digits.data())[i] += z;
|
|
3937 |
}
|
|
3938 |
|
|
3939 |
bool always_show_decpt = (flags & Alternate || flags & ForcePoint);
|
|
3940 |
switch (form) {
|
|
3941 |
case DFExponent: {
|
|
3942 |
num_str = exponentForm(digits, decpt, precision, PMDecimalDigits,
|
|
3943 |
always_show_decpt, *this);
|
|
3944 |
break;
|
|
3945 |
}
|
|
3946 |
case DFDecimal: {
|
|
3947 |
num_str = decimalForm(digits, decpt, precision, PMDecimalDigits,
|
|
3948 |
always_show_decpt, flags & ThousandsGroup,
|
|
3949 |
*this);
|
|
3950 |
break;
|
|
3951 |
}
|
|
3952 |
case DFSignificantDigits: {
|
|
3953 |
PrecisionMode mode = (flags & Alternate) ?
|
|
3954 |
PMSignificantDigits : PMChopTrailingZeros;
|
|
3955 |
|
|
3956 |
if (decpt != digits.length() && (decpt <= -4 || decpt > precision))
|
|
3957 |
num_str = exponentForm(digits, decpt, precision, mode,
|
|
3958 |
always_show_decpt, *this);
|
|
3959 |
else
|
|
3960 |
num_str = decimalForm(digits, decpt, precision, mode,
|
|
3961 |
always_show_decpt, flags & ThousandsGroup,
|
|
3962 |
*this);
|
|
3963 |
break;
|
|
3964 |
}
|
|
3965 |
}
|
|
3966 |
|
|
3967 |
negative = sign != 0 && !isZero(d);
|
|
3968 |
}
|
|
3969 |
|
|
3970 |
// pad with zeros. LeftAdjusted overrides this flag). Also, we don't
|
|
3971 |
// pad special numbers
|
|
3972 |
if (flags & QLocalePrivate::ZeroPadded
|
|
3973 |
&& !(flags & QLocalePrivate::LeftAdjusted)
|
|
3974 |
&& !special_number) {
|
|
3975 |
int num_pad_chars = width - num_str.length();
|
|
3976 |
// leave space for the sign
|
|
3977 |
if (negative
|
|
3978 |
|| flags & QLocalePrivate::AlwaysShowSign
|
|
3979 |
|| flags & QLocalePrivate::BlankBeforePositive)
|
|
3980 |
--num_pad_chars;
|
|
3981 |
|
|
3982 |
for (int i = 0; i < num_pad_chars; ++i)
|
|
3983 |
num_str.prepend(zero());
|
|
3984 |
}
|
|
3985 |
|
|
3986 |
// add sign
|
|
3987 |
if (negative)
|
|
3988 |
num_str.prepend(minus());
|
|
3989 |
else if (flags & QLocalePrivate::AlwaysShowSign)
|
|
3990 |
num_str.prepend(plus());
|
|
3991 |
else if (flags & QLocalePrivate::BlankBeforePositive)
|
|
3992 |
num_str.prepend(QLatin1Char(' '));
|
|
3993 |
|
|
3994 |
if (flags & QLocalePrivate::CapitalEorX)
|
|
3995 |
num_str = num_str.toUpper();
|
|
3996 |
|
|
3997 |
return num_str;
|
|
3998 |
}
|
|
3999 |
|
|
4000 |
QString QLocalePrivate::longLongToString(qlonglong l, int precision,
|
|
4001 |
int base, int width,
|
|
4002 |
unsigned flags) const
|
|
4003 |
{
|
|
4004 |
bool precision_not_specified = false;
|
|
4005 |
if (precision == -1) {
|
|
4006 |
precision_not_specified = true;
|
|
4007 |
precision = 1;
|
|
4008 |
}
|
|
4009 |
|
|
4010 |
bool negative = l < 0;
|
|
4011 |
if (base != 10) {
|
|
4012 |
// these are not supported by sprintf for octal and hex
|
|
4013 |
flags &= ~AlwaysShowSign;
|
|
4014 |
flags &= ~BlankBeforePositive;
|
|
4015 |
negative = false; // neither are negative numbers
|
|
4016 |
}
|
|
4017 |
|
|
4018 |
QString num_str;
|
|
4019 |
if (base == 10)
|
|
4020 |
num_str = qlltoa(l, base, *this);
|
|
4021 |
else
|
|
4022 |
num_str = qulltoa(l, base, *this);
|
|
4023 |
|
|
4024 |
uint cnt_thousand_sep = 0;
|
|
4025 |
if (flags & ThousandsGroup && base == 10) {
|
|
4026 |
for (int i = num_str.length() - 3; i > 0; i -= 3) {
|
|
4027 |
num_str.insert(i, group());
|
|
4028 |
++cnt_thousand_sep;
|
|
4029 |
}
|
|
4030 |
}
|
|
4031 |
|
|
4032 |
for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i)
|
|
4033 |
num_str.prepend(base == 10 ? zero() : QChar::fromLatin1('0'));
|
|
4034 |
|
|
4035 |
if ((flags & Alternate || flags & ShowBase)
|
|
4036 |
&& base == 8
|
|
4037 |
&& (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0')))
|
|
4038 |
num_str.prepend(QLatin1Char('0'));
|
|
4039 |
|
|
4040 |
// LeftAdjusted overrides this flag ZeroPadded. sprintf only padds
|
|
4041 |
// when precision is not specified in the format string
|
|
4042 |
bool zero_padded = flags & ZeroPadded
|
|
4043 |
&& !(flags & LeftAdjusted)
|
|
4044 |
&& precision_not_specified;
|
|
4045 |
|
|
4046 |
if (zero_padded) {
|
|
4047 |
int num_pad_chars = width - num_str.length();
|
|
4048 |
|
|
4049 |
// leave space for the sign
|
|
4050 |
if (negative
|
|
4051 |
|| flags & AlwaysShowSign
|
|
4052 |
|| flags & BlankBeforePositive)
|
|
4053 |
--num_pad_chars;
|
|
4054 |
|
|
4055 |
// leave space for optional '0x' in hex form
|
|
4056 |
if (base == 16 && (flags & Alternate || flags & ShowBase))
|
|
4057 |
num_pad_chars -= 2;
|
|
4058 |
// leave space for optional '0b' in binary form
|
|
4059 |
else if (base == 2 && (flags & Alternate || flags & ShowBase))
|
|
4060 |
num_pad_chars -= 2;
|
|
4061 |
|
|
4062 |
for (int i = 0; i < num_pad_chars; ++i)
|
|
4063 |
num_str.prepend(base == 10 ? zero() : QChar::fromLatin1('0'));
|
|
4064 |
}
|
|
4065 |
|
|
4066 |
if (flags & CapitalEorX)
|
|
4067 |
num_str = num_str.toUpper();
|
|
4068 |
|
|
4069 |
if (base == 16 && (flags & Alternate || flags & ShowBase))
|
|
4070 |
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
|
|
4071 |
if (base == 2 && (flags & Alternate || flags & ShowBase))
|
|
4072 |
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
|
|
4073 |
|
|
4074 |
// add sign
|
|
4075 |
if (negative)
|
|
4076 |
num_str.prepend(minus());
|
|
4077 |
else if (flags & AlwaysShowSign)
|
|
4078 |
num_str.prepend(plus());
|
|
4079 |
else if (flags & BlankBeforePositive)
|
|
4080 |
num_str.prepend(QLatin1Char(' '));
|
|
4081 |
|
|
4082 |
return num_str;
|
|
4083 |
}
|
|
4084 |
|
|
4085 |
QString QLocalePrivate::unsLongLongToString(qulonglong l, int precision,
|
|
4086 |
int base, int width,
|
|
4087 |
unsigned flags) const
|
|
4088 |
{
|
|
4089 |
bool precision_not_specified = false;
|
|
4090 |
if (precision == -1) {
|
|
4091 |
precision_not_specified = true;
|
|
4092 |
precision = 1;
|
|
4093 |
}
|
|
4094 |
|
|
4095 |
QString num_str = qulltoa(l, base, *this);
|
|
4096 |
|
|
4097 |
uint cnt_thousand_sep = 0;
|
|
4098 |
if (flags & ThousandsGroup && base == 10) {
|
|
4099 |
for (int i = num_str.length() - 3; i > 0; i -=3) {
|
|
4100 |
num_str.insert(i, group());
|
|
4101 |
++cnt_thousand_sep;
|
|
4102 |
}
|
|
4103 |
}
|
|
4104 |
|
|
4105 |
for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i)
|
|
4106 |
num_str.prepend(base == 10 ? zero() : QChar::fromLatin1('0'));
|
|
4107 |
|
|
4108 |
if ((flags & Alternate || flags & ShowBase)
|
|
4109 |
&& base == 8
|
|
4110 |
&& (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0')))
|
|
4111 |
num_str.prepend(QLatin1Char('0'));
|
|
4112 |
|
|
4113 |
// LeftAdjusted overrides this flag ZeroPadded. sprintf only padds
|
|
4114 |
// when precision is not specified in the format string
|
|
4115 |
bool zero_padded = flags & ZeroPadded
|
|
4116 |
&& !(flags & LeftAdjusted)
|
|
4117 |
&& precision_not_specified;
|
|
4118 |
|
|
4119 |
if (zero_padded) {
|
|
4120 |
int num_pad_chars = width - num_str.length();
|
|
4121 |
|
|
4122 |
// leave space for optional '0x' in hex form
|
|
4123 |
if (base == 16 && flags & Alternate)
|
|
4124 |
num_pad_chars -= 2;
|
|
4125 |
// leave space for optional '0b' in binary form
|
|
4126 |
else if (base == 2 && flags & Alternate)
|
|
4127 |
num_pad_chars -= 2;
|
|
4128 |
|
|
4129 |
for (int i = 0; i < num_pad_chars; ++i)
|
|
4130 |
num_str.prepend(base == 10 ? zero() : QChar::fromLatin1('0'));
|
|
4131 |
}
|
|
4132 |
|
|
4133 |
if (flags & CapitalEorX)
|
|
4134 |
num_str = num_str.toUpper();
|
|
4135 |
|
|
4136 |
if (base == 16 && (flags & Alternate || flags & ShowBase))
|
|
4137 |
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x"));
|
|
4138 |
else if (base == 2 && (flags & Alternate || flags & ShowBase))
|
|
4139 |
num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b"));
|
|
4140 |
|
|
4141 |
// add sign
|
|
4142 |
if (flags & AlwaysShowSign)
|
|
4143 |
num_str.prepend(plus());
|
|
4144 |
else if (flags & BlankBeforePositive)
|
|
4145 |
num_str.prepend(QLatin1Char(' '));
|
|
4146 |
|
|
4147 |
return num_str;
|
|
4148 |
}
|
|
4149 |
|
|
4150 |
// Removes thousand-group separators in "C" locale.
|
|
4151 |
static bool removeGroupSeparators(QLocalePrivate::CharBuff *num)
|
|
4152 |
{
|
|
4153 |
int group_cnt = 0; // counts number of group chars
|
|
4154 |
int decpt_idx = -1;
|
|
4155 |
|
|
4156 |
char *data = num->data();
|
|
4157 |
int l = qstrlen(data);
|
|
4158 |
|
|
4159 |
// Find the decimal point and check if there are any group chars
|
|
4160 |
int i = 0;
|
|
4161 |
for (; i < l; ++i) {
|
|
4162 |
char c = data[i];
|
|
4163 |
|
|
4164 |
if (c == ',') {
|
|
4165 |
if (i == 0 || data[i - 1] < '0' || data[i - 1] > '9')
|
|
4166 |
return false;
|
|
4167 |
if (i == l - 1 || data[i + 1] < '0' || data[i + 1] > '9')
|
|
4168 |
return false;
|
|
4169 |
++group_cnt;
|
|
4170 |
}
|
|
4171 |
else if (c == '.') {
|
|
4172 |
// Fail if more than one decimal points
|
|
4173 |
if (decpt_idx != -1)
|
|
4174 |
return false;
|
|
4175 |
decpt_idx = i;
|
|
4176 |
} else if (c == 'e' || c == 'E') {
|
|
4177 |
// an 'e' or 'E' - if we have not encountered a decimal
|
|
4178 |
// point, this is where it "is".
|
|
4179 |
if (decpt_idx == -1)
|
|
4180 |
decpt_idx = i;
|
|
4181 |
}
|
|
4182 |
}
|
|
4183 |
|
|
4184 |
// If no group chars, we're done
|
|
4185 |
if (group_cnt == 0)
|
|
4186 |
return true;
|
|
4187 |
|
|
4188 |
// No decimal point means that it "is" at the end of the string
|
|
4189 |
if (decpt_idx == -1)
|
|
4190 |
decpt_idx = l;
|
|
4191 |
|
|
4192 |
i = 0;
|
|
4193 |
while (i < l && group_cnt > 0) {
|
|
4194 |
char c = data[i];
|
|
4195 |
|
|
4196 |
if (c == ',') {
|
|
4197 |
// Don't allow group chars after the decimal point
|
|
4198 |
if (i > decpt_idx)
|
|
4199 |
return false;
|
|
4200 |
|
|
4201 |
// Check that it is placed correctly relative to the decpt
|
|
4202 |
if ((decpt_idx - i) % 4 != 0)
|
|
4203 |
return false;
|
|
4204 |
|
|
4205 |
// Remove it
|
|
4206 |
memmove(data + i, data + i + 1, l - i - 1);
|
|
4207 |
data[--l] = '\0';
|
|
4208 |
|
|
4209 |
--group_cnt;
|
|
4210 |
--decpt_idx;
|
|
4211 |
} else {
|
|
4212 |
// Check that we are not missing a separator
|
|
4213 |
if (i < decpt_idx
|
|
4214 |
&& (decpt_idx - i) % 4 == 0
|
|
4215 |
&& !(i == 0 && c == '-')) // check for negative sign at start of string
|
|
4216 |
return false;
|
|
4217 |
++i;
|
|
4218 |
}
|
|
4219 |
}
|
|
4220 |
|
|
4221 |
return true;
|
|
4222 |
}
|
|
4223 |
|
|
4224 |
/*
|
|
4225 |
Converts a number in locale to its representation in the C locale.
|
|
4226 |
Only has to guarantee that a string that is a correct representation of
|
|
4227 |
a number will be converted. If junk is passed in, junk will be passed
|
|
4228 |
out and the error will be detected during the actual conversion to a
|
|
4229 |
number. We can't detect junk here, since we don't even know the base
|
|
4230 |
of the number.
|
|
4231 |
*/
|
|
4232 |
bool QLocalePrivate::numberToCLocale(const QString &num,
|
|
4233 |
GroupSeparatorMode group_sep_mode,
|
|
4234 |
CharBuff *result) const
|
|
4235 |
{
|
|
4236 |
const QChar *uc = num.unicode();
|
|
4237 |
int l = num.length();
|
|
4238 |
int idx = 0;
|
|
4239 |
|
|
4240 |
// Skip whitespace
|
|
4241 |
while (idx < l && uc[idx].isSpace())
|
|
4242 |
++idx;
|
|
4243 |
if (idx == l)
|
|
4244 |
return false;
|
|
4245 |
|
|
4246 |
const QChar _group = group();
|
|
4247 |
|
|
4248 |
while (idx < l) {
|
|
4249 |
const QChar &in = uc[idx];
|
|
4250 |
|
|
4251 |
char out = digitToCLocale(in);
|
|
4252 |
if (out == 0) {
|
|
4253 |
if (in == list())
|
|
4254 |
out = ';';
|
|
4255 |
else if (in == percent())
|
|
4256 |
out = '%';
|
|
4257 |
// for handling base-x numbers
|
|
4258 |
else if (in.unicode() >= 'A' && in.unicode() <= 'Z')
|
|
4259 |
out = in.toLower().toLatin1();
|
|
4260 |
else if (in.unicode() >= 'a' && in.unicode() <= 'z')
|
|
4261 |
out = in.toLatin1();
|
|
4262 |
else
|
|
4263 |
break;
|
|
4264 |
}
|
|
4265 |
|
|
4266 |
result->append(out);
|
|
4267 |
|
|
4268 |
++idx;
|
|
4269 |
}
|
|
4270 |
|
|
4271 |
// Check trailing whitespace
|
|
4272 |
for (; idx < l; ++idx) {
|
|
4273 |
if (!uc[idx].isSpace())
|
|
4274 |
return false;
|
|
4275 |
}
|
|
4276 |
|
|
4277 |
result->append('\0');
|
|
4278 |
|
|
4279 |
// Check separators
|
|
4280 |
if (group_sep_mode == ParseGroupSeparators
|
|
4281 |
&& !removeGroupSeparators(result))
|
|
4282 |
return false;
|
|
4283 |
|
|
4284 |
|
|
4285 |
return true;
|
|
4286 |
}
|
|
4287 |
|
|
4288 |
bool QLocalePrivate::validateChars(const QString &str, NumberMode numMode, QByteArray *buff,
|
|
4289 |
int decDigits) const
|
|
4290 |
{
|
|
4291 |
buff->clear();
|
|
4292 |
buff->reserve(str.length());
|
|
4293 |
|
|
4294 |
const bool scientific = numMode == DoubleScientificMode;
|
|
4295 |
bool lastWasE = false;
|
|
4296 |
int eCnt = 0;
|
|
4297 |
int decPointCnt = 0;
|
|
4298 |
bool dec = false;
|
|
4299 |
int decDigitCnt = 0;
|
|
4300 |
|
|
4301 |
for (int i = 0; i < str.length(); ++i) {
|
|
4302 |
char c = digitToCLocale(str.at(i));
|
|
4303 |
|
|
4304 |
if (c >= '0' && c <= '9') {
|
|
4305 |
if (numMode != IntegerMode) {
|
|
4306 |
// If a double has too many digits after decpt, it shall be Invalid.
|
|
4307 |
if (dec && decDigits != -1 && decDigits < ++decDigitCnt)
|
|
4308 |
return false;
|
|
4309 |
}
|
|
4310 |
} else {
|
|
4311 |
switch (c) {
|
|
4312 |
case '.':
|
|
4313 |
if (numMode == IntegerMode) {
|
|
4314 |
// If an integer has a decimal point, it shall be Invalid.
|
|
4315 |
return false;
|
|
4316 |
} else {
|
|
4317 |
// If a double has more than one decimal point, it shall be Invalid.
|
|
4318 |
if (++decPointCnt > 1)
|
|
4319 |
return false;
|
|
4320 |
#if 0
|
|
4321 |
// If a double with no decimal digits has a decimal point, it shall be
|
|
4322 |
// Invalid.
|
|
4323 |
if (decDigits == 0)
|
|
4324 |
return false;
|
|
4325 |
#endif // On second thoughts, it shall be Valid.
|
|
4326 |
|
|
4327 |
dec = true;
|
|
4328 |
}
|
|
4329 |
break;
|
|
4330 |
|
|
4331 |
case '+':
|
|
4332 |
case '-':
|
|
4333 |
if (scientific) {
|
|
4334 |
// If a scientific has a sign that's not at the beginning or after
|
|
4335 |
// an 'e', it shall be Invalid.
|
|
4336 |
if (i != 0 && !lastWasE)
|
|
4337 |
return false;
|
|
4338 |
} else {
|
|
4339 |
// If a non-scientific has a sign that's not at the beginning,
|
|
4340 |
// it shall be Invalid.
|
|
4341 |
if (i != 0)
|
|
4342 |
return false;
|
|
4343 |
}
|
|
4344 |
break;
|
|
4345 |
|
|
4346 |
case ',':
|
|
4347 |
return false;
|
|
4348 |
|
|
4349 |
case 'e':
|
|
4350 |
if (scientific) {
|
|
4351 |
// If a scientific has more than one 'e', it shall be Invalid.
|
|
4352 |
if (++eCnt > 1)
|
|
4353 |
return false;
|
|
4354 |
dec = false;
|
|
4355 |
} else {
|
|
4356 |
// If a non-scientific has an 'e', it shall be Invalid.
|
|
4357 |
return false;
|
|
4358 |
}
|
|
4359 |
break;
|
|
4360 |
|
|
4361 |
default:
|
|
4362 |
// If it's not a valid digit, it shall be Invalid.
|
|
4363 |
return false;
|
|
4364 |
}
|
|
4365 |
}
|
|
4366 |
|
|
4367 |
lastWasE = c == 'e';
|
|
4368 |
buff->append(c);
|
|
4369 |
}
|
|
4370 |
|
|
4371 |
return true;
|
|
4372 |
}
|
|
4373 |
|
|
4374 |
double QLocalePrivate::stringToDouble(const QString &number, bool *ok,
|
|
4375 |
GroupSeparatorMode group_sep_mode) const
|
|
4376 |
{
|
|
4377 |
CharBuff buff;
|
|
4378 |
if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmed() : number,
|
|
4379 |
group_sep_mode, &buff)) {
|
|
4380 |
if (ok != 0)
|
|
4381 |
*ok = false;
|
|
4382 |
return 0.0;
|
|
4383 |
}
|
|
4384 |
return bytearrayToDouble(buff.constData(), ok);
|
|
4385 |
}
|
|
4386 |
|
|
4387 |
qlonglong QLocalePrivate::stringToLongLong(const QString &number, int base,
|
|
4388 |
bool *ok, GroupSeparatorMode group_sep_mode) const
|
|
4389 |
{
|
|
4390 |
CharBuff buff;
|
|
4391 |
if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmed() : number,
|
|
4392 |
group_sep_mode, &buff)) {
|
|
4393 |
if (ok != 0)
|
|
4394 |
*ok = false;
|
|
4395 |
return 0;
|
|
4396 |
}
|
|
4397 |
|
|
4398 |
return bytearrayToLongLong(buff.constData(), base, ok);
|
|
4399 |
}
|
|
4400 |
|
|
4401 |
qulonglong QLocalePrivate::stringToUnsLongLong(const QString &number, int base,
|
|
4402 |
bool *ok, GroupSeparatorMode group_sep_mode) const
|
|
4403 |
{
|
|
4404 |
CharBuff buff;
|
|
4405 |
if (!numberToCLocale(group().unicode() == 0xa0 ? number.trimmed() : number,
|
|
4406 |
group_sep_mode, &buff)) {
|
|
4407 |
if (ok != 0)
|
|
4408 |
*ok = false;
|
|
4409 |
return 0;
|
|
4410 |
}
|
|
4411 |
|
|
4412 |
return bytearrayToUnsLongLong(buff.constData(), base, ok);
|
|
4413 |
}
|
|
4414 |
|
|
4415 |
|
|
4416 |
double QLocalePrivate::bytearrayToDouble(const char *num, bool *ok, bool *overflow)
|
|
4417 |
{
|
|
4418 |
if (ok != 0)
|
|
4419 |
*ok = true;
|
|
4420 |
if (overflow != 0)
|
|
4421 |
*overflow = false;
|
|
4422 |
|
|
4423 |
if (*num == '\0') {
|
|
4424 |
if (ok != 0)
|
|
4425 |
*ok = false;
|
|
4426 |
return 0.0;
|
|
4427 |
}
|
|
4428 |
|
|
4429 |
if (qstrcmp(num, "nan") == 0)
|
|
4430 |
return qt_snan();
|
|
4431 |
|
|
4432 |
if (qstrcmp(num, "+inf") == 0 || qstrcmp(num, "inf") == 0)
|
|
4433 |
return qt_inf();
|
|
4434 |
|
|
4435 |
if (qstrcmp(num, "-inf") == 0)
|
|
4436 |
return -qt_inf();
|
|
4437 |
|
|
4438 |
bool _ok;
|
|
4439 |
const char *endptr;
|
|
4440 |
double d = qstrtod(num, &endptr, &_ok);
|
|
4441 |
|
|
4442 |
if (!_ok) {
|
|
4443 |
// the only way strtod can fail with *endptr != '\0' on a non-empty
|
|
4444 |
// input string is overflow
|
|
4445 |
if (ok != 0)
|
|
4446 |
*ok = false;
|
|
4447 |
if (overflow != 0)
|
|
4448 |
*overflow = *endptr != '\0';
|
|
4449 |
return 0.0;
|
|
4450 |
}
|
|
4451 |
|
|
4452 |
if (*endptr != '\0') {
|
|
4453 |
// we stopped at a non-digit character after converting some digits
|
|
4454 |
if (ok != 0)
|
|
4455 |
*ok = false;
|
|
4456 |
if (overflow != 0)
|
|
4457 |
*overflow = false;
|
|
4458 |
return 0.0;
|
|
4459 |
}
|
|
4460 |
|
|
4461 |
if (ok != 0)
|
|
4462 |
*ok = true;
|
|
4463 |
if (overflow != 0)
|
|
4464 |
*overflow = false;
|
|
4465 |
return d;
|
|
4466 |
}
|
|
4467 |
|
|
4468 |
qlonglong QLocalePrivate::bytearrayToLongLong(const char *num, int base, bool *ok, bool *overflow)
|
|
4469 |
{
|
|
4470 |
bool _ok;
|
|
4471 |
const char *endptr;
|
|
4472 |
|
|
4473 |
if (*num == '\0') {
|
|
4474 |
if (ok != 0)
|
|
4475 |
*ok = false;
|
|
4476 |
if (overflow != 0)
|
|
4477 |
*overflow = false;
|
|
4478 |
return 0;
|
|
4479 |
}
|
|
4480 |
|
|
4481 |
qlonglong l = qstrtoll(num, &endptr, base, &_ok);
|
|
4482 |
|
|
4483 |
if (!_ok) {
|
|
4484 |
if (ok != 0)
|
|
4485 |
*ok = false;
|
|
4486 |
if (overflow != 0) {
|
|
4487 |
// the only way qstrtoll can fail with *endptr != '\0' on a non-empty
|
|
4488 |
// input string is overflow
|
|
4489 |
*overflow = *endptr != '\0';
|
|
4490 |
}
|
|
4491 |
return 0;
|
|
4492 |
}
|
|
4493 |
|
|
4494 |
if (*endptr != '\0') {
|
|
4495 |
// we stopped at a non-digit character after converting some digits
|
|
4496 |
if (ok != 0)
|
|
4497 |
*ok = false;
|
|
4498 |
if (overflow != 0)
|
|
4499 |
*overflow = false;
|
|
4500 |
return 0;
|
|
4501 |
}
|
|
4502 |
|
|
4503 |
if (ok != 0)
|
|
4504 |
*ok = true;
|
|
4505 |
if (overflow != 0)
|
|
4506 |
*overflow = false;
|
|
4507 |
return l;
|
|
4508 |
}
|
|
4509 |
|
|
4510 |
qulonglong QLocalePrivate::bytearrayToUnsLongLong(const char *num, int base, bool *ok)
|
|
4511 |
{
|
|
4512 |
bool _ok;
|
|
4513 |
const char *endptr;
|
|
4514 |
qulonglong l = qstrtoull(num, &endptr, base, &_ok);
|
|
4515 |
|
|
4516 |
if (!_ok || *endptr != '\0') {
|
|
4517 |
if (ok != 0)
|
|
4518 |
*ok = false;
|
|
4519 |
return 0;
|
|
4520 |
}
|
|
4521 |
|
|
4522 |
if (ok != 0)
|
|
4523 |
*ok = true;
|
|
4524 |
return l;
|
|
4525 |
}
|
|
4526 |
|
|
4527 |
/*-
|
|
4528 |
* Copyright (c) 1992, 1993
|
|
4529 |
* The Regents of the University of California. All rights reserved.
|
|
4530 |
*
|
|
4531 |
* Redistribution and use in source and binary forms, with or without
|
|
4532 |
* modification, are permitted provided that the following conditions
|
|
4533 |
* are met:
|
|
4534 |
* 1. Redistributions of source code must retain the above copyright
|
|
4535 |
* notice, this list of conditions and the following disclaimer.
|
|
4536 |
* 2. Redistributions in binary form must reproduce the above copyright
|
|
4537 |
* notice, this list of conditions and the following disclaimer in the
|
|
4538 |
* documentation and/or other materials provided with the distribution.
|
|
4539 |
* 3. All advertising materials mentioning features or use of this software
|
|
4540 |
* must display the following acknowledgment:
|
|
4541 |
* This product includes software developed by the University of
|
|
4542 |
* California, Berkeley and its contributors.
|
|
4543 |
* 4. Neither the name of the University nor the names of its contributors
|
|
4544 |
* may be used to endorse or promote products derived from this software
|
|
4545 |
* without specific prior written permission.
|
|
4546 |
*
|
|
4547 |
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
4548 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
4549 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
4550 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
4551 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
4552 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
4553 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
4554 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
4555 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
4556 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
4557 |
* SUCH DAMAGE.
|
|
4558 |
*/
|
|
4559 |
|
|
4560 |
// static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
|
|
4561 |
// "$FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.5.2.1 2001/03/02 09:45:20 obrien Exp $";
|
|
4562 |
|
|
4563 |
/*
|
|
4564 |
* Convert a string to an unsigned long long integer.
|
|
4565 |
*
|
|
4566 |
* Ignores `locale' stuff. Assumes that the upper and lower case
|
|
4567 |
* alphabets and digits are each contiguous.
|
|
4568 |
*/
|
|
4569 |
static qulonglong qstrtoull(const char *nptr, const char **endptr, register int base, bool *ok)
|
|
4570 |
{
|
|
4571 |
register const char *s = nptr;
|
|
4572 |
register qulonglong acc;
|
|
4573 |
register unsigned char c;
|
|
4574 |
register qulonglong qbase, cutoff;
|
|
4575 |
register int any, cutlim;
|
|
4576 |
|
|
4577 |
if (ok != 0)
|
|
4578 |
*ok = true;
|
|
4579 |
|
|
4580 |
/*
|
|
4581 |
* See strtoq for comments as to the logic used.
|
|
4582 |
*/
|
|
4583 |
s = nptr;
|
|
4584 |
do {
|
|
4585 |
c = *s++;
|
|
4586 |
} while (isspace(c));
|
|
4587 |
if (c == '-') {
|
|
4588 |
if (ok != 0)
|
|
4589 |
*ok = false;
|
|
4590 |
if (endptr != 0)
|
|
4591 |
*endptr = s - 1;
|
|
4592 |
return 0;
|
|
4593 |
} else {
|
|
4594 |
if (c == '+')
|
|
4595 |
c = *s++;
|
|
4596 |
}
|
|
4597 |
if ((base == 0 || base == 16) &&
|
|
4598 |
c == '0' && (*s == 'x' || *s == 'X')) {
|
|
4599 |
c = s[1];
|
|
4600 |
s += 2;
|
|
4601 |
base = 16;
|
|
4602 |
}
|
|
4603 |
if (base == 0)
|
|
4604 |
base = c == '0' ? 8 : 10;
|
|
4605 |
qbase = unsigned(base);
|
|
4606 |
cutoff = qulonglong(ULLONG_MAX) / qbase;
|
|
4607 |
cutlim = qulonglong(ULLONG_MAX) % qbase;
|
|
4608 |
for (acc = 0, any = 0;; c = *s++) {
|
|
4609 |
if (!isascii(c))
|
|
4610 |
break;
|
|
4611 |
if (isdigit(c))
|
|
4612 |
c -= '0';
|
|
4613 |
else if (isalpha(c))
|
|
4614 |
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
|
|
4615 |
else
|
|
4616 |
break;
|
|
4617 |
if (c >= base)
|
|
4618 |
break;
|
|
4619 |
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
|
|
4620 |
any = -1;
|
|
4621 |
else {
|
|
4622 |
any = 1;
|
|
4623 |
acc *= qbase;
|
|
4624 |
acc += c;
|
|
4625 |
}
|
|
4626 |
}
|
|
4627 |
if (any == 0) {
|
|
4628 |
if (ok != 0)
|
|
4629 |
*ok = false;
|
|
4630 |
} else if (any < 0) {
|
|
4631 |
acc = ULLONG_MAX;
|
|
4632 |
if (ok != 0)
|
|
4633 |
*ok = false;
|
|
4634 |
}
|
|
4635 |
if (endptr != 0)
|
|
4636 |
*endptr = (any ? s - 1 : nptr);
|
|
4637 |
return acc;
|
|
4638 |
}
|
|
4639 |
|
|
4640 |
|
|
4641 |
// "$FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.5.2.1 2001/03/02 09:45:20 obrien Exp $";
|
|
4642 |
|
|
4643 |
|
|
4644 |
/*
|
|
4645 |
* Convert a string to a long long integer.
|
|
4646 |
*
|
|
4647 |
* Ignores `locale' stuff. Assumes that the upper and lower case
|
|
4648 |
* alphabets and digits are each contiguous.
|
|
4649 |
*/
|
|
4650 |
static qlonglong qstrtoll(const char *nptr, const char **endptr, register int base, bool *ok)
|
|
4651 |
{
|
|
4652 |
register const char *s;
|
|
4653 |
register qulonglong acc;
|
|
4654 |
register unsigned char c;
|
|
4655 |
register qulonglong qbase, cutoff;
|
|
4656 |
register int neg, any, cutlim;
|
|
4657 |
|
|
4658 |
/*
|
|
4659 |
* Skip white space and pick up leading +/- sign if any.
|
|
4660 |
* If base is 0, allow 0x for hex and 0 for octal, else
|
|
4661 |
* assume decimal; if base is already 16, allow 0x.
|
|
4662 |
*/
|
|
4663 |
s = nptr;
|
|
4664 |
do {
|
|
4665 |
c = *s++;
|
|
4666 |
} while (isspace(c));
|
|
4667 |
if (c == '-') {
|
|
4668 |
neg = 1;
|
|
4669 |
c = *s++;
|
|
4670 |
} else {
|
|
4671 |
neg = 0;
|
|
4672 |
if (c == '+')
|
|
4673 |
c = *s++;
|
|
4674 |
}
|
|
4675 |
if ((base == 0 || base == 16) &&
|
|
4676 |
c == '0' && (*s == 'x' || *s == 'X')) {
|
|
4677 |
c = s[1];
|
|
4678 |
s += 2;
|
|
4679 |
base = 16;
|
|
4680 |
}
|
|
4681 |
if (base == 0)
|
|
4682 |
base = c == '0' ? 8 : 10;
|
|
4683 |
|
|
4684 |
/*
|
|
4685 |
* Compute the cutoff value between legal numbers and illegal
|
|
4686 |
* numbers. That is the largest legal value, divided by the
|
|
4687 |
* base. An input number that is greater than this value, if
|
|
4688 |
* followed by a legal input character, is too big. One that
|
|
4689 |
* is equal to this value may be valid or not; the limit
|
|
4690 |
* between valid and invalid numbers is then based on the last
|
|
4691 |
* digit. For instance, if the range for quads is
|
|
4692 |
* [-9223372036854775808..9223372036854775807] and the input base
|
|
4693 |
* is 10, cutoff will be set to 922337203685477580 and cutlim to
|
|
4694 |
* either 7 (neg==0) or 8 (neg==1), meaning that if we have
|
|
4695 |
* accumulated a value > 922337203685477580, or equal but the
|
|
4696 |
* next digit is > 7 (or 8), the number is too big, and we will
|
|
4697 |
* return a range error.
|
|
4698 |
*
|
|
4699 |
* Set any if any `digits' consumed; make it negative to indicate
|
|
4700 |
* overflow.
|
|
4701 |
*/
|
|
4702 |
qbase = unsigned(base);
|
|
4703 |
cutoff = neg ? qulonglong(0-(LLONG_MIN + LLONG_MAX)) + LLONG_MAX : LLONG_MAX;
|
|
4704 |
cutlim = cutoff % qbase;
|
|
4705 |
cutoff /= qbase;
|
|
4706 |
for (acc = 0, any = 0;; c = *s++) {
|
|
4707 |
if (!isascii(c))
|
|
4708 |
break;
|
|
4709 |
if (isdigit(c))
|
|
4710 |
c -= '0';
|
|
4711 |
else if (isalpha(c))
|
|
4712 |
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
|
|
4713 |
else
|
|
4714 |
break;
|
|
4715 |
if (c >= base)
|
|
4716 |
break;
|
|
4717 |
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
|
|
4718 |
any = -1;
|
|
4719 |
else {
|
|
4720 |
any = 1;
|
|
4721 |
acc *= qbase;
|
|
4722 |
acc += c;
|
|
4723 |
}
|
|
4724 |
}
|
|
4725 |
if (any < 0) {
|
|
4726 |
acc = neg ? LLONG_MIN : LLONG_MAX;
|
|
4727 |
if (ok != 0)
|
|
4728 |
*ok = false;
|
|
4729 |
} else if (neg) {
|
|
4730 |
acc = (~acc) + 1;
|
|
4731 |
}
|
|
4732 |
if (endptr != 0)
|
|
4733 |
*endptr = (any >= 0 ? s - 1 : nptr);
|
|
4734 |
|
|
4735 |
if (ok != 0)
|
|
4736 |
*ok = any > 0;
|
|
4737 |
|
|
4738 |
return acc;
|
|
4739 |
}
|
|
4740 |
|
|
4741 |
#ifndef QT_QLOCALE_USES_FCVT
|
|
4742 |
|
|
4743 |
/* From: NetBSD: strtod.c,v 1.26 1998/02/03 18:44:21 perry Exp */
|
|
4744 |
/* $FreeBSD: src/lib/libc/stdlib/netbsd_strtod.c,v 1.2.2.2 2001/03/02 17:14:15 tegge Exp $ */
|
|
4745 |
|
|
4746 |
/* Please send bug reports to
|
|
4747 |
David M. Gay
|
|
4748 |
AT&T Bell Laboratories, Room 2C-463
|
|
4749 |
600 Mountain Avenue
|
|
4750 |
Murray Hill, NJ 07974-2070
|
|
4751 |
U.S.A.
|
|
4752 |
dmg@research.att.com or research!dmg
|
|
4753 |
*/
|
|
4754 |
|
|
4755 |
/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
|
|
4756 |
*
|
|
4757 |
* This strtod returns a nearest machine number to the input decimal
|
|
4758 |
* string (or sets errno to ERANGE). With IEEE arithmetic, ties are
|
|
4759 |
* broken by the IEEE round-even rule. Otherwise ties are broken by
|
|
4760 |
* biased rounding (add half and chop).
|
|
4761 |
*
|
|
4762 |
* Inspired loosely by William D. Clinger's paper "How to Read Floating
|
|
4763 |
* Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
|
|
4764 |
*
|
|
4765 |
* Modifications:
|
|
4766 |
*
|
|
4767 |
* 1. We only require IEEE, IBM, or VAX double-precision
|
|
4768 |
* arithmetic (not IEEE double-extended).
|
|
4769 |
* 2. We get by with floating-point arithmetic in a case that
|
|
4770 |
* Clinger missed -- when we're computing d * 10^n
|
|
4771 |
* for a small integer d and the integer n is not too
|
|
4772 |
* much larger than 22 (the maximum integer k for which
|
|
4773 |
* we can represent 10^k exactly), we may be able to
|
|
4774 |
* compute (d*10^k) * 10^(e-k) with just one roundoff.
|
|
4775 |
* 3. Rather than a bit-at-a-time adjustment of the binary
|
|
4776 |
* result in the hard case, we use floating-point
|
|
4777 |
* arithmetic to determine the adjustment to within
|
|
4778 |
* one bit; only in really hard cases do we need to
|
|
4779 |
* compute a second residual.
|
|
4780 |
* 4. Because of 3., we don't need a large table of powers of 10
|
|
4781 |
* for ten-to-e (just some small tables, e.g. of 10^k
|
|
4782 |
* for 0 <= k <= 22).
|
|
4783 |
*/
|
|
4784 |
|
|
4785 |
/*
|
|
4786 |
* #define IEEE_LITTLE_ENDIAN for IEEE-arithmetic machines where the least
|
|
4787 |
* significant byte has the lowest address.
|
|
4788 |
* #define IEEE_BIG_ENDIAN for IEEE-arithmetic machines where the most
|
|
4789 |
* significant byte has the lowest address.
|
|
4790 |
* #define Long int on machines with 32-bit ints and 64-bit longs.
|
|
4791 |
* #define Sudden_Underflow for IEEE-format machines without gradual
|
|
4792 |
* underflow (i.e., that flush to zero on underflow).
|
|
4793 |
* #define IBM for IBM mainframe-style floating-point arithmetic.
|
|
4794 |
* #define VAX for VAX-style floating-point arithmetic.
|
|
4795 |
* #define Unsigned_Shifts if >> does treats its left operand as unsigned.
|
|
4796 |
* #define No_leftright to omit left-right logic in fast floating-point
|
|
4797 |
* computation of dtoa.
|
|
4798 |
* #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3.
|
|
4799 |
* #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
|
|
4800 |
* that use extended-precision instructions to compute rounded
|
|
4801 |
* products and quotients) with IBM.
|
|
4802 |
* #define ROUND_BIASED for IEEE-format with biased rounding.
|
|
4803 |
* #define Inaccurate_Divide for IEEE-format with correctly rounded
|
|
4804 |
* products but inaccurate quotients, e.g., for Intel i860.
|
|
4805 |
* #define Just_16 to store 16 bits per 32-bit Long when doing high-precision
|
|
4806 |
* integer arithmetic. Whether this speeds things up or slows things
|
|
4807 |
* down depends on the machine and the number being converted.
|
|
4808 |
* #define KR_headers for old-style C function headers.
|
|
4809 |
* #define Bad_float_h if your system lacks a float.h or if it does not
|
|
4810 |
* define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
|
|
4811 |
* FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
|
|
4812 |
* #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
|
|
4813 |
* if memory is available and otherwise does something you deem
|
|
4814 |
* appropriate. If MALLOC is undefined, malloc will be invoked
|
|
4815 |
* directly -- and assumed always to succeed.
|
|
4816 |
*/
|
|
4817 |
|
|
4818 |
#if defined(LIBC_SCCS) && !defined(lint)
|
|
4819 |
__RCSID("$NetBSD: strtod.c,v 1.26 1998/02/03 18:44:21 perry Exp $");
|
|
4820 |
#endif /* LIBC_SCCS and not lint */
|
|
4821 |
|
|
4822 |
/*
|
|
4823 |
#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
|
|
4824 |
defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
|
|
4825 |
defined(__powerpc__) || defined(Q_OS_WIN) || defined(Q_OS_DARWIN) || defined(Q_OS_MAC) || \
|
|
4826 |
defined(mips) || defined(Q_OS_AIX) || defined(Q_OS_SOLARIS)
|
|
4827 |
# define IEEE_BIG_OR_LITTLE_ENDIAN 1
|
|
4828 |
#endif
|
|
4829 |
*/
|
|
4830 |
|
|
4831 |
// *All* of our architectures have IEEE arithmetic, don't they?
|
|
4832 |
#define IEEE_BIG_OR_LITTLE_ENDIAN 1
|
|
4833 |
|
|
4834 |
#ifdef __arm32__
|
|
4835 |
/*
|
|
4836 |
* Although the CPU is little endian the FP has different
|
|
4837 |
* byte and word endianness. The byte order is still little endian
|
|
4838 |
* but the word order is big endian.
|
|
4839 |
*/
|
|
4840 |
#define IEEE_BIG_OR_LITTLE_ENDIAN
|
|
4841 |
#endif
|
|
4842 |
|
|
4843 |
#ifdef vax
|
|
4844 |
#define VAX
|
|
4845 |
#endif
|
|
4846 |
|
|
4847 |
#define Long qint32
|
|
4848 |
#define ULong quint32
|
|
4849 |
|
|
4850 |
#define MALLOC malloc
|
|
4851 |
|
|
4852 |
#ifdef BSD_QDTOA_DEBUG
|
|
4853 |
QT_BEGIN_INCLUDE_NAMESPACE
|
|
4854 |
#include <stdio.h>
|
|
4855 |
QT_END_INCLUDE_NAMESPACE
|
|
4856 |
|
|
4857 |
#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
|
|
4858 |
#endif
|
|
4859 |
|
|
4860 |
#ifdef Unsigned_Shifts
|
|
4861 |
#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000;
|
|
4862 |
#else
|
|
4863 |
#define Sign_Extend(a,b) /*no-op*/
|
|
4864 |
#endif
|
|
4865 |
|
|
4866 |
#if (defined(IEEE_BIG_OR_LITTLE_ENDIAN) + defined(VAX) + defined(IBM)) != 1
|
|
4867 |
#error Exactly one of IEEE_BIG_OR_LITTLE_ENDIAN, VAX, or IBM should be defined.
|
|
4868 |
#endif
|
|
4869 |
|
|
4870 |
static inline ULong _getWord0(const NEEDS_VOLATILE double x)
|
|
4871 |
{
|
|
4872 |
const NEEDS_VOLATILE uchar *ptr = reinterpret_cast<const NEEDS_VOLATILE uchar *>(&x);
|
|
4873 |
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
|
|
4874 |
return (ptr[0]<<24) + (ptr[1]<<16) + (ptr[2]<<8) + ptr[3];
|
|
4875 |
} else {
|
|
4876 |
return (ptr[7]<<24) + (ptr[6]<<16) + (ptr[5]<<8) + ptr[4];
|
|
4877 |
}
|
|
4878 |
}
|
|
4879 |
|
|
4880 |
static inline void _setWord0(NEEDS_VOLATILE double *x, ULong l)
|
|
4881 |
{
|
|
4882 |
NEEDS_VOLATILE uchar *ptr = reinterpret_cast<NEEDS_VOLATILE uchar *>(x);
|
|
4883 |
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
|
|
4884 |
ptr[0] = uchar(l>>24);
|
|
4885 |
ptr[1] = uchar(l>>16);
|
|
4886 |
ptr[2] = uchar(l>>8);
|
|
4887 |
ptr[3] = uchar(l);
|
|
4888 |
} else {
|
|
4889 |
ptr[7] = uchar(l>>24);
|
|
4890 |
ptr[6] = uchar(l>>16);
|
|
4891 |
ptr[5] = uchar(l>>8);
|
|
4892 |
ptr[4] = uchar(l);
|
|
4893 |
}
|
|
4894 |
}
|
|
4895 |
|
|
4896 |
static inline ULong _getWord1(const NEEDS_VOLATILE double x)
|
|
4897 |
{
|
|
4898 |
const NEEDS_VOLATILE uchar *ptr = reinterpret_cast<const NEEDS_VOLATILE uchar *>(&x);
|
|
4899 |
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
|
|
4900 |
return (ptr[4]<<24) + (ptr[5]<<16) + (ptr[6]<<8) + ptr[7];
|
|
4901 |
} else {
|
|
4902 |
return (ptr[3]<<24) + (ptr[2]<<16) + (ptr[1]<<8) + ptr[0];
|
|
4903 |
}
|
|
4904 |
}
|
|
4905 |
static inline void _setWord1(NEEDS_VOLATILE double *x, ULong l)
|
|
4906 |
{
|
|
4907 |
NEEDS_VOLATILE uchar *ptr = reinterpret_cast<uchar NEEDS_VOLATILE *>(x);
|
|
4908 |
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
|
|
4909 |
ptr[4] = uchar(l>>24);
|
|
4910 |
ptr[5] = uchar(l>>16);
|
|
4911 |
ptr[6] = uchar(l>>8);
|
|
4912 |
ptr[7] = uchar(l);
|
|
4913 |
} else {
|
|
4914 |
ptr[3] = uchar(l>>24);
|
|
4915 |
ptr[2] = uchar(l>>16);
|
|
4916 |
ptr[1] = uchar(l>>8);
|
|
4917 |
ptr[0] = uchar(l);
|
|
4918 |
}
|
|
4919 |
}
|
|
4920 |
|
|
4921 |
static inline ULong getWord0(const NEEDS_VOLATILE double x)
|
|
4922 |
{
|
|
4923 |
#ifdef QT_ARMFPA
|
|
4924 |
return _getWord1(x);
|
|
4925 |
#else
|
|
4926 |
return _getWord0(x);
|
|
4927 |
#endif
|
|
4928 |
}
|
|
4929 |
|
|
4930 |
static inline void setWord0(NEEDS_VOLATILE double *x, ULong l)
|
|
4931 |
{
|
|
4932 |
#ifdef QT_ARMFPA
|
|
4933 |
_setWord1(x, l);
|
|
4934 |
#else
|
|
4935 |
_setWord0(x, l);
|
|
4936 |
#endif
|
|
4937 |
}
|
|
4938 |
|
|
4939 |
static inline ULong getWord1(const NEEDS_VOLATILE double x)
|
|
4940 |
{
|
|
4941 |
#ifdef QT_ARMFPA
|
|
4942 |
return _getWord0(x);
|
|
4943 |
#else
|
|
4944 |
return _getWord1(x);
|
|
4945 |
#endif
|
|
4946 |
}
|
|
4947 |
|
|
4948 |
static inline void setWord1(NEEDS_VOLATILE double *x, ULong l)
|
|
4949 |
{
|
|
4950 |
#ifdef QT_ARMFPA
|
|
4951 |
_setWord0(x, l);
|
|
4952 |
#else
|
|
4953 |
_setWord1(x, l);
|
|
4954 |
#endif
|
|
4955 |
}
|
|
4956 |
|
|
4957 |
static inline void Storeinc(ULong *&a, const ULong &b, const ULong &c)
|
|
4958 |
{
|
|
4959 |
|
|
4960 |
*a = (ushort(b) << 16) | ushort(c);
|
|
4961 |
++a;
|
|
4962 |
}
|
|
4963 |
|
|
4964 |
/* #define P DBL_MANT_DIG */
|
|
4965 |
/* Ten_pmax = floor(P*log(2)/log(5)) */
|
|
4966 |
/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
|
|
4967 |
/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
|
|
4968 |
/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
|
|
4969 |
|
|
4970 |
#if defined(IEEE_BIG_OR_LITTLE_ENDIAN)
|
|
4971 |
#define Exp_shift 20
|
|
4972 |
#define Exp_shift1 20
|
|
4973 |
#define Exp_msk1 0x100000
|
|
4974 |
#define Exp_msk11 0x100000
|
|
4975 |
#define Exp_mask 0x7ff00000
|
|
4976 |
#define P 53
|
|
4977 |
#define Bias 1023
|
|
4978 |
#define IEEE_Arith
|
|
4979 |
#define Emin (-1022)
|
|
4980 |
#define Exp_1 0x3ff00000
|
|
4981 |
#define Exp_11 0x3ff00000
|
|
4982 |
#define Ebits 11
|
|
4983 |
#define Frac_mask 0xfffff
|
|
4984 |
#define Frac_mask1 0xfffff
|
|
4985 |
#define Ten_pmax 22
|
|
4986 |
#define Bletch 0x10
|
|
4987 |
#define Bndry_mask 0xfffff
|
|
4988 |
#define Bndry_mask1 0xfffff
|
|
4989 |
#if defined(LSB) && defined(Q_OS_VXWORKS)
|
|
4990 |
#undef LSB
|
|
4991 |
#endif
|
|
4992 |
#define LSB 1
|
|
4993 |
#define Sign_bit 0x80000000
|
|
4994 |
#define Log2P 1
|
|
4995 |
#define Tiny0 0
|
|
4996 |
#define Tiny1 1
|
|
4997 |
#define Quick_max 14
|
|
4998 |
#define Int_max 14
|
|
4999 |
#define Infinite(x) (getWord0(x) == 0x7ff00000) /* sufficient test for here */
|
|
5000 |
#else
|
|
5001 |
#undef Sudden_Underflow
|
|
5002 |
#define Sudden_Underflow
|
|
5003 |
#ifdef IBM
|
|
5004 |
#define Exp_shift 24
|
|
5005 |
#define Exp_shift1 24
|
|
5006 |
#define Exp_msk1 0x1000000
|
|
5007 |
#define Exp_msk11 0x1000000
|
|
5008 |
#define Exp_mask 0x7f000000
|
|
5009 |
#define P 14
|
|
5010 |
#define Bias 65
|
|
5011 |
#define Exp_1 0x41000000
|
|
5012 |
#define Exp_11 0x41000000
|
|
5013 |
#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
|
|
5014 |
#define Frac_mask 0xffffff
|
|
5015 |
#define Frac_mask1 0xffffff
|
|
5016 |
#define Bletch 4
|
|
5017 |
#define Ten_pmax 22
|
|
5018 |
#define Bndry_mask 0xefffff
|
|
5019 |
#define Bndry_mask1 0xffffff
|
|
5020 |
#define LSB 1
|
|
5021 |
#define Sign_bit 0x80000000
|
|
5022 |
#define Log2P 4
|
|
5023 |
#define Tiny0 0x100000
|
|
5024 |
#define Tiny1 0
|
|
5025 |
#define Quick_max 14
|
|
5026 |
#define Int_max 15
|
|
5027 |
#else /* VAX */
|
|
5028 |
#define Exp_shift 23
|
|
5029 |
#define Exp_shift1 7
|
|
5030 |
#define Exp_msk1 0x80
|
|
5031 |
#define Exp_msk11 0x800000
|
|
5032 |
#define Exp_mask 0x7f80
|
|
5033 |
#define P 56
|
|
5034 |
#define Bias 129
|
|
5035 |
#define Exp_1 0x40800000
|
|
5036 |
#define Exp_11 0x4080
|
|
5037 |
#define Ebits 8
|
|
5038 |
#define Frac_mask 0x7fffff
|
|
5039 |
#define Frac_mask1 0xffff007f
|
|
5040 |
#define Ten_pmax 24
|
|
5041 |
#define Bletch 2
|
|
5042 |
#define Bndry_mask 0xffff007f
|
|
5043 |
#define Bndry_mask1 0xffff007f
|
|
5044 |
#define LSB 0x10000
|
|
5045 |
#define Sign_bit 0x8000
|
|
5046 |
#define Log2P 1
|
|
5047 |
#define Tiny0 0x80
|
|
5048 |
#define Tiny1 0
|
|
5049 |
#define Quick_max 15
|
|
5050 |
#define Int_max 15
|
|
5051 |
#endif
|
|
5052 |
#endif
|
|
5053 |
|
|
5054 |
#ifndef IEEE_Arith
|
|
5055 |
#define ROUND_BIASED
|
|
5056 |
#endif
|
|
5057 |
|
|
5058 |
#ifdef RND_PRODQUOT
|
|
5059 |
#define rounded_product(a,b) a = rnd_prod(a, b)
|
|
5060 |
#define rounded_quotient(a,b) a = rnd_quot(a, b)
|
|
5061 |
extern double rnd_prod(double, double), rnd_quot(double, double);
|
|
5062 |
#else
|
|
5063 |
#define rounded_product(a,b) a *= b
|
|
5064 |
#define rounded_quotient(a,b) a /= b
|
|
5065 |
#endif
|
|
5066 |
|
|
5067 |
#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
|
|
5068 |
#define Big1 0xffffffff
|
|
5069 |
|
|
5070 |
#ifndef Just_16
|
|
5071 |
/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
|
|
5072 |
* This makes some inner loops simpler and sometimes saves work
|
|
5073 |
* during multiplications, but it often seems to make things slightly
|
|
5074 |
* slower. Hence the default is now to store 32 bits per Long.
|
|
5075 |
*/
|
|
5076 |
#ifndef Pack_32
|
|
5077 |
#define Pack_32
|
|
5078 |
#endif
|
|
5079 |
#endif
|
|
5080 |
|
|
5081 |
#define Kmax 15
|
|
5082 |
|
|
5083 |
struct
|
|
5084 |
Bigint {
|
|
5085 |
struct Bigint *next;
|
|
5086 |
int k, maxwds, sign, wds;
|
|
5087 |
ULong x[1];
|
|
5088 |
};
|
|
5089 |
|
|
5090 |
typedef struct Bigint Bigint;
|
|
5091 |
|
|
5092 |
static Bigint *Balloc(int k)
|
|
5093 |
{
|
|
5094 |
int x;
|
|
5095 |
Bigint *rv;
|
|
5096 |
|
|
5097 |
x = 1 << k;
|
|
5098 |
rv = static_cast<Bigint *>(MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long)));
|
|
5099 |
Q_CHECK_PTR(rv);
|
|
5100 |
rv->k = k;
|
|
5101 |
rv->maxwds = x;
|
|
5102 |
rv->sign = rv->wds = 0;
|
|
5103 |
return rv;
|
|
5104 |
}
|
|
5105 |
|
|
5106 |
static void Bfree(Bigint *v)
|
|
5107 |
{
|
|
5108 |
free(v);
|
|
5109 |
}
|
|
5110 |
|
|
5111 |
#define Bcopy(x,y) memcpy(reinterpret_cast<char *>(&x->sign), reinterpret_cast<char *>(&y->sign), \
|
|
5112 |
y->wds*sizeof(Long) + 2*sizeof(int))
|
|
5113 |
|
|
5114 |
/* multiply by m and add a */
|
|
5115 |
static Bigint *multadd(Bigint *b, int m, int a)
|
|
5116 |
{
|
|
5117 |
int i, wds;
|
|
5118 |
ULong *x, y;
|
|
5119 |
#ifdef Pack_32
|
|
5120 |
ULong xi, z;
|
|
5121 |
#endif
|
|
5122 |
Bigint *b1;
|
|
5123 |
|
|
5124 |
wds = b->wds;
|
|
5125 |
x = b->x;
|
|
5126 |
i = 0;
|
|
5127 |
do {
|
|
5128 |
#ifdef Pack_32
|
|
5129 |
xi = *x;
|
|
5130 |
y = (xi & 0xffff) * m + a;
|
|
5131 |
z = (xi >> 16) * m + (y >> 16);
|
|
5132 |
a = (z >> 16);
|
|
5133 |
*x++ = (z << 16) + (y & 0xffff);
|
|
5134 |
#else
|
|
5135 |
y = *x * m + a;
|
|
5136 |
a = (y >> 16);
|
|
5137 |
*x++ = y & 0xffff;
|
|
5138 |
#endif
|
|
5139 |
}
|
|
5140 |
while(++i < wds);
|
|
5141 |
if (a) {
|
|
5142 |
if (wds >= b->maxwds) {
|
|
5143 |
b1 = Balloc(b->k+1);
|
|
5144 |
Bcopy(b1, b);
|
|
5145 |
Bfree(b);
|
|
5146 |
b = b1;
|
|
5147 |
}
|
|
5148 |
b->x[wds++] = a;
|
|
5149 |
b->wds = wds;
|
|
5150 |
}
|
|
5151 |
return b;
|
|
5152 |
}
|
|
5153 |
|
|
5154 |
static Bigint *s2b(const char *s, int nd0, int nd, ULong y9)
|
|
5155 |
{
|
|
5156 |
Bigint *b;
|
|
5157 |
int i, k;
|
|
5158 |
Long x, y;
|
|
5159 |
|
|
5160 |
x = (nd + 8) / 9;
|
|
5161 |
for(k = 0, y = 1; x > y; y <<= 1, k++) ;
|
|
5162 |
#ifdef Pack_32
|
|
5163 |
b = Balloc(k);
|
|
5164 |
b->x[0] = y9;
|
|
5165 |
b->wds = 1;
|
|
5166 |
#else
|
|
5167 |
b = Balloc(k+1);
|
|
5168 |
b->x[0] = y9 & 0xffff;
|
|
5169 |
b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
|
|
5170 |
#endif
|
|
5171 |
|
|
5172 |
i = 9;
|
|
5173 |
if (9 < nd0) {
|
|
5174 |
s += 9;
|
|
5175 |
do b = multadd(b, 10, *s++ - '0');
|
|
5176 |
while(++i < nd0);
|
|
5177 |
s++;
|
|
5178 |
}
|
|
5179 |
else
|
|
5180 |
s += 10;
|
|
5181 |
for(; i < nd; i++)
|
|
5182 |
b = multadd(b, 10, *s++ - '0');
|
|
5183 |
return b;
|
|
5184 |
}
|
|
5185 |
|
|
5186 |
static int hi0bits(ULong x)
|
|
5187 |
{
|
|
5188 |
int k = 0;
|
|
5189 |
|
|
5190 |
if (!(x & 0xffff0000)) {
|
|
5191 |
k = 16;
|
|
5192 |
x <<= 16;
|
|
5193 |
}
|
|
5194 |
if (!(x & 0xff000000)) {
|
|
5195 |
k += 8;
|
|
5196 |
x <<= 8;
|
|
5197 |
}
|
|
5198 |
if (!(x & 0xf0000000)) {
|
|
5199 |
k += 4;
|
|
5200 |
x <<= 4;
|
|
5201 |
}
|
|
5202 |
if (!(x & 0xc0000000)) {
|
|
5203 |
k += 2;
|
|
5204 |
x <<= 2;
|
|
5205 |
}
|
|
5206 |
if (!(x & 0x80000000)) {
|
|
5207 |
k++;
|
|
5208 |
if (!(x & 0x40000000))
|
|
5209 |
return 32;
|
|
5210 |
}
|
|
5211 |
return k;
|
|
5212 |
}
|
|
5213 |
|
|
5214 |
static int lo0bits(ULong *y)
|
|
5215 |
{
|
|
5216 |
int k;
|
|
5217 |
ULong x = *y;
|
|
5218 |
|
|
5219 |
if (x & 7) {
|
|
5220 |
if (x & 1)
|
|
5221 |
return 0;
|
|
5222 |
if (x & 2) {
|
|
5223 |
*y = x >> 1;
|
|
5224 |
return 1;
|
|
5225 |
}
|
|
5226 |
*y = x >> 2;
|
|
5227 |
return 2;
|
|
5228 |
}
|
|
5229 |
k = 0;
|
|
5230 |
if (!(x & 0xffff)) {
|
|
5231 |
k = 16;
|
|
5232 |
x >>= 16;
|
|
5233 |
}
|
|
5234 |
if (!(x & 0xff)) {
|
|
5235 |
k += 8;
|
|
5236 |
x >>= 8;
|
|
5237 |
}
|
|
5238 |
if (!(x & 0xf)) {
|
|
5239 |
k += 4;
|
|
5240 |
x >>= 4;
|
|
5241 |
}
|
|
5242 |
if (!(x & 0x3)) {
|
|
5243 |
k += 2;
|
|
5244 |
x >>= 2;
|
|
5245 |
}
|
|
5246 |
if (!(x & 1)) {
|
|
5247 |
k++;
|
|
5248 |
x >>= 1;
|
|
5249 |
if (!x & 1)
|
|
5250 |
return 32;
|
|
5251 |
}
|
|
5252 |
*y = x;
|
|
5253 |
return k;
|
|
5254 |
}
|
|
5255 |
|
|
5256 |
static Bigint *i2b(int i)
|
|
5257 |
{
|
|
5258 |
Bigint *b;
|
|
5259 |
|
|
5260 |
b = Balloc(1);
|
|
5261 |
b->x[0] = i;
|
|
5262 |
b->wds = 1;
|
|
5263 |
return b;
|
|
5264 |
}
|
|
5265 |
|
|
5266 |
static Bigint *mult(Bigint *a, Bigint *b)
|
|
5267 |
{
|
|
5268 |
Bigint *c;
|
|
5269 |
int k, wa, wb, wc;
|
|
5270 |
ULong carry, y, z;
|
|
5271 |
ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
|
|
5272 |
#ifdef Pack_32
|
|
5273 |
ULong z2;
|
|
5274 |
#endif
|
|
5275 |
|
|
5276 |
if (a->wds < b->wds) {
|
|
5277 |
c = a;
|
|
5278 |
a = b;
|
|
5279 |
b = c;
|
|
5280 |
}
|
|
5281 |
k = a->k;
|
|
5282 |
wa = a->wds;
|
|
5283 |
wb = b->wds;
|
|
5284 |
wc = wa + wb;
|
|
5285 |
if (wc > a->maxwds)
|
|
5286 |
k++;
|
|
5287 |
c = Balloc(k);
|
|
5288 |
for(x = c->x, xa = x + wc; x < xa; x++)
|
|
5289 |
*x = 0;
|
|
5290 |
xa = a->x;
|
|
5291 |
xae = xa + wa;
|
|
5292 |
xb = b->x;
|
|
5293 |
xbe = xb + wb;
|
|
5294 |
xc0 = c->x;
|
|
5295 |
#ifdef Pack_32
|
|
5296 |
for(; xb < xbe; xb++, xc0++) {
|
|
5297 |
if ((y = *xb & 0xffff) != 0) {
|
|
5298 |
x = xa;
|
|
5299 |
xc = xc0;
|
|
5300 |
carry = 0;
|
|
5301 |
do {
|
|
5302 |
z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
|
|
5303 |
carry = z >> 16;
|
|
5304 |
z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
|
|
5305 |
carry = z2 >> 16;
|
|
5306 |
Storeinc(xc, z2, z);
|
|
5307 |
}
|
|
5308 |
while(x < xae);
|
|
5309 |
*xc = carry;
|
|
5310 |
}
|
|
5311 |
if ((y = *xb >> 16) != 0) {
|
|
5312 |
x = xa;
|
|
5313 |
xc = xc0;
|
|
5314 |
carry = 0;
|
|
5315 |
z2 = *xc;
|
|
5316 |
do {
|
|
5317 |
z = (*x & 0xffff) * y + (*xc >> 16) + carry;
|
|
5318 |
carry = z >> 16;
|
|
5319 |
Storeinc(xc, z, z2);
|
|
5320 |
z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
|
|
5321 |
carry = z2 >> 16;
|
|
5322 |
}
|
|
5323 |
while(x < xae);
|
|
5324 |
*xc = z2;
|
|
5325 |
}
|
|
5326 |
}
|
|
5327 |
#else
|
|
5328 |
for(; xb < xbe; xc0++) {
|
|
5329 |
if (y = *xb++) {
|
|
5330 |
x = xa;
|
|
5331 |
xc = xc0;
|
|
5332 |
carry = 0;
|
|
5333 |
do {
|
|
5334 |
z = *x++ * y + *xc + carry;
|
|
5335 |
carry = z >> 16;
|
|
5336 |
*xc++ = z & 0xffff;
|
|
5337 |
}
|
|
5338 |
while(x < xae);
|
|
5339 |
*xc = carry;
|
|
5340 |
}
|
|
5341 |
}
|
|
5342 |
#endif
|
|
5343 |
for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
|
|
5344 |
c->wds = wc;
|
|
5345 |
return c;
|
|
5346 |
}
|
|
5347 |
|
|
5348 |
static Bigint *p5s;
|
|
5349 |
|
|
5350 |
struct p5s_deleter
|
|
5351 |
{
|
|
5352 |
~p5s_deleter()
|
|
5353 |
{
|
|
5354 |
while (p5s) {
|
|
5355 |
Bigint *next = p5s->next;
|
|
5356 |
Bfree(p5s);
|
|
5357 |
p5s = next;
|
|
5358 |
}
|
|
5359 |
}
|
|
5360 |
};
|
|
5361 |
|
|
5362 |
static Bigint *pow5mult(Bigint *b, int k)
|
|
5363 |
{
|
|
5364 |
Bigint *b1, *p5, *p51;
|
|
5365 |
int i;
|
|
5366 |
static const int p05[3] = { 5, 25, 125 };
|
|
5367 |
|
|
5368 |
if ((i = k & 3) != 0)
|
|
5369 |
#if defined(Q_OS_IRIX) && defined(Q_CC_GNU)
|
|
5370 |
{
|
|
5371 |
// work around a bug on 64 bit IRIX gcc
|
|
5372 |
int *p = (int *) p05;
|
|
5373 |
b = multadd(b, p[i-1], 0);
|
|
5374 |
}
|
|
5375 |
#else
|
|
5376 |
b = multadd(b, p05[i-1], 0);
|
|
5377 |
#endif
|
|
5378 |
|
|
5379 |
if (!(k >>= 2))
|
|
5380 |
return b;
|
|
5381 |
if (!(p5 = p5s)) {
|
|
5382 |
/* first time */
|
|
5383 |
static p5s_deleter deleter;
|
|
5384 |
p5 = p5s = i2b(625);
|
|
5385 |
p5->next = 0;
|
|
5386 |
}
|
|
5387 |
for(;;) {
|
|
5388 |
if (k & 1) {
|
|
5389 |
b1 = mult(b, p5);
|
|
5390 |
Bfree(b);
|
|
5391 |
b = b1;
|
|
5392 |
}
|
|
5393 |
if (!(k >>= 1))
|
|
5394 |
break;
|
|
5395 |
if (!(p51 = p5->next)) {
|
|
5396 |
p51 = p5->next = mult(p5,p5);
|
|
5397 |
p51->next = 0;
|
|
5398 |
}
|
|
5399 |
p5 = p51;
|
|
5400 |
}
|
|
5401 |
return b;
|
|
5402 |
}
|
|
5403 |
|
|
5404 |
static Bigint *lshift(Bigint *b, int k)
|
|
5405 |
{
|
|
5406 |
int i, k1, n, n1;
|
|
5407 |
Bigint *b1;
|
|
5408 |
ULong *x, *x1, *xe, z;
|
|
5409 |
|
|
5410 |
#ifdef Pack_32
|
|
5411 |
n = k >> 5;
|
|
5412 |
#else
|
|
5413 |
n = k >> 4;
|
|
5414 |
#endif
|
|
5415 |
k1 = b->k;
|
|
5416 |
n1 = n + b->wds + 1;
|
|
5417 |
for(i = b->maxwds; n1 > i; i <<= 1)
|
|
5418 |
k1++;
|
|
5419 |
b1 = Balloc(k1);
|
|
5420 |
x1 = b1->x;
|
|
5421 |
for(i = 0; i < n; i++)
|
|
5422 |
*x1++ = 0;
|
|
5423 |
x = b->x;
|
|
5424 |
xe = x + b->wds;
|
|
5425 |
#ifdef Pack_32
|
|
5426 |
if (k &= 0x1f) {
|
|
5427 |
k1 = 32 - k;
|
|
5428 |
z = 0;
|
|
5429 |
do {
|
|
5430 |
*x1++ = *x << k | z;
|
|
5431 |
z = *x++ >> k1;
|
|
5432 |
}
|
|
5433 |
while(x < xe);
|
|
5434 |
if ((*x1 = z) != 0)
|
|
5435 |
++n1;
|
|
5436 |
}
|
|
5437 |
#else
|
|
5438 |
if (k &= 0xf) {
|
|
5439 |
k1 = 16 - k;
|
|
5440 |
z = 0;
|
|
5441 |
do {
|
|
5442 |
*x1++ = *x << k & 0xffff | z;
|
|
5443 |
z = *x++ >> k1;
|
|
5444 |
}
|
|
5445 |
while(x < xe);
|
|
5446 |
if (*x1 = z)
|
|
5447 |
++n1;
|
|
5448 |
}
|
|
5449 |
#endif
|
|
5450 |
else do
|
|
5451 |
*x1++ = *x++;
|
|
5452 |
while(x < xe);
|
|
5453 |
b1->wds = n1 - 1;
|
|
5454 |
Bfree(b);
|
|
5455 |
return b1;
|
|
5456 |
}
|
|
5457 |
|
|
5458 |
static int cmp(Bigint *a, Bigint *b)
|
|
5459 |
{
|
|
5460 |
ULong *xa, *xa0, *xb, *xb0;
|
|
5461 |
int i, j;
|
|
5462 |
|
|
5463 |
i = a->wds;
|
|
5464 |
j = b->wds;
|
|
5465 |
#ifdef BSD_QDTOA_DEBUG
|
|
5466 |
if (i > 1 && !a->x[i-1])
|
|
5467 |
Bug("cmp called with a->x[a->wds-1] == 0");
|
|
5468 |
if (j > 1 && !b->x[j-1])
|
|
5469 |
Bug("cmp called with b->x[b->wds-1] == 0");
|
|
5470 |
#endif
|
|
5471 |
if (i -= j)
|
|
5472 |
return i;
|
|
5473 |
xa0 = a->x;
|
|
5474 |
xa = xa0 + j;
|
|
5475 |
xb0 = b->x;
|
|
5476 |
xb = xb0 + j;
|
|
5477 |
for(;;) {
|
|
5478 |
if (*--xa != *--xb)
|
|
5479 |
return *xa < *xb ? -1 : 1;
|
|
5480 |
if (xa <= xa0)
|
|
5481 |
break;
|
|
5482 |
}
|
|
5483 |
return 0;
|
|
5484 |
}
|
|
5485 |
|
|
5486 |
static Bigint *diff(Bigint *a, Bigint *b)
|
|
5487 |
{
|
|
5488 |
Bigint *c;
|
|
5489 |
int i, wa, wb;
|
|
5490 |
Long borrow, y; /* We need signed shifts here. */
|
|
5491 |
ULong *xa, *xae, *xb, *xbe, *xc;
|
|
5492 |
#ifdef Pack_32
|
|
5493 |
Long z;
|
|
5494 |
#endif
|
|
5495 |
|
|
5496 |
i = cmp(a,b);
|
|
5497 |
if (!i) {
|
|
5498 |
c = Balloc(0);
|
|
5499 |
c->wds = 1;
|
|
5500 |
c->x[0] = 0;
|
|
5501 |
return c;
|
|
5502 |
}
|
|
5503 |
if (i < 0) {
|
|
5504 |
c = a;
|
|
5505 |
a = b;
|
|
5506 |
b = c;
|
|
5507 |
i = 1;
|
|
5508 |
}
|
|
5509 |
else
|
|
5510 |
i = 0;
|
|
5511 |
c = Balloc(a->k);
|
|
5512 |
c->sign = i;
|
|
5513 |
wa = a->wds;
|
|
5514 |
xa = a->x;
|
|
5515 |
xae = xa + wa;
|
|
5516 |
wb = b->wds;
|
|
5517 |
xb = b->x;
|
|
5518 |
xbe = xb + wb;
|
|
5519 |
xc = c->x;
|
|
5520 |
borrow = 0;
|
|
5521 |
#ifdef Pack_32
|
|
5522 |
do {
|
|
5523 |
y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
|
|
5524 |
borrow = y >> 16;
|
|
5525 |
Sign_Extend(borrow, y);
|
|
5526 |
z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
|
|
5527 |
borrow = z >> 16;
|
|
5528 |
Sign_Extend(borrow, z);
|
|
5529 |
Storeinc(xc, z, y);
|
|
5530 |
}
|
|
5531 |
while(xb < xbe);
|
|
5532 |
while(xa < xae) {
|
|
5533 |
y = (*xa & 0xffff) + borrow;
|
|
5534 |
borrow = y >> 16;
|
|
5535 |
Sign_Extend(borrow, y);
|
|
5536 |
z = (*xa++ >> 16) + borrow;
|
|
5537 |
borrow = z >> 16;
|
|
5538 |
Sign_Extend(borrow, z);
|
|
5539 |
Storeinc(xc, z, y);
|
|
5540 |
}
|
|
5541 |
#else
|
|
5542 |
do {
|
|
5543 |
y = *xa++ - *xb++ + borrow;
|
|
5544 |
borrow = y >> 16;
|
|
5545 |
Sign_Extend(borrow, y);
|
|
5546 |
*xc++ = y & 0xffff;
|
|
5547 |
}
|
|
5548 |
while(xb < xbe);
|
|
5549 |
while(xa < xae) {
|
|
5550 |
y = *xa++ + borrow;
|
|
5551 |
borrow = y >> 16;
|
|
5552 |
Sign_Extend(borrow, y);
|
|
5553 |
*xc++ = y & 0xffff;
|
|
5554 |
}
|
|
5555 |
#endif
|
|
5556 |
while(!*--xc)
|
|
5557 |
wa--;
|
|
5558 |
c->wds = wa;
|
|
5559 |
return c;
|
|
5560 |
}
|
|
5561 |
|
|
5562 |
static double ulp(double x)
|
|
5563 |
{
|
|
5564 |
Long L;
|
|
5565 |
double a;
|
|
5566 |
|
|
5567 |
L = (getWord0(x) & Exp_mask) - (P-1)*Exp_msk1;
|
|
5568 |
#ifndef Sudden_Underflow
|
|
5569 |
if (L > 0) {
|
|
5570 |
#endif
|
|
5571 |
#ifdef IBM
|
|
5572 |
L |= Exp_msk1 >> 4;
|
|
5573 |
#endif
|
|
5574 |
setWord0(&a, L);
|
|
5575 |
setWord1(&a, 0);
|
|
5576 |
#ifndef Sudden_Underflow
|
|
5577 |
}
|
|
5578 |
else {
|
|
5579 |
L = -L >> Exp_shift;
|
|
5580 |
if (L < Exp_shift) {
|
|
5581 |
setWord0(&a, 0x80000 >> L);
|
|
5582 |
setWord1(&a, 0);
|
|
5583 |
}
|
|
5584 |
else {
|
|
5585 |
setWord0(&a, 0);
|
|
5586 |
L -= Exp_shift;
|
|
5587 |
setWord1(&a, L >= 31 ? 1U : 1U << (31 - L));
|
|
5588 |
}
|
|
5589 |
}
|
|
5590 |
#endif
|
|
5591 |
return a;
|
|
5592 |
}
|
|
5593 |
|
|
5594 |
static double b2d(Bigint *a, int *e)
|
|
5595 |
{
|
|
5596 |
ULong *xa, *xa0, w, y, z;
|
|
5597 |
int k;
|
|
5598 |
double d;
|
|
5599 |
|
|
5600 |
xa0 = a->x;
|
|
5601 |
xa = xa0 + a->wds;
|
|
5602 |
y = *--xa;
|
|
5603 |
#ifdef BSD_QDTOA_DEBUG
|
|
5604 |
if (!y) Bug("zero y in b2d");
|
|
5605 |
#endif
|
|
5606 |
k = hi0bits(y);
|
|
5607 |
*e = 32 - k;
|
|
5608 |
#ifdef Pack_32
|
|
5609 |
if (k < Ebits) {
|
|
5610 |
setWord0(&d, Exp_1 | y >> (Ebits - k));
|
|
5611 |
w = xa > xa0 ? *--xa : 0;
|
|
5612 |
setWord1(&d, y << ((32-Ebits) + k) | w >> (Ebits - k));
|
|
5613 |
goto ret_d;
|
|
5614 |
}
|
|
5615 |
z = xa > xa0 ? *--xa : 0;
|
|
5616 |
if (k -= Ebits) {
|
|
5617 |
setWord0(&d, Exp_1 | y << k | z >> (32 - k));
|
|
5618 |
y = xa > xa0 ? *--xa : 0;
|
|
5619 |
setWord1(&d, z << k | y >> (32 - k));
|
|
5620 |
}
|
|
5621 |
else {
|
|
5622 |
setWord0(&d, Exp_1 | y);
|
|
5623 |
setWord1(&d, z);
|
|
5624 |
}
|
|
5625 |
#else
|
|
5626 |
if (k < Ebits + 16) {
|
|
5627 |
z = xa > xa0 ? *--xa : 0;
|
|
5628 |
setWord0(&d, Exp_1 | y << k - Ebits | z >> Ebits + 16 - k);
|
|
5629 |
w = xa > xa0 ? *--xa : 0;
|
|
5630 |
y = xa > xa0 ? *--xa : 0;
|
|
5631 |
setWord1(&d, z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k);
|
|
5632 |
goto ret_d;
|
|
5633 |
}
|
|
5634 |
z = xa > xa0 ? *--xa : 0;
|
|
5635 |
w = xa > xa0 ? *--xa : 0;
|
|
5636 |
k -= Ebits + 16;
|
|
5637 |
setWord0(&d, Exp_1 | y << k + 16 | z << k | w >> 16 - k);
|
|
5638 |
y = xa > xa0 ? *--xa : 0;
|
|
5639 |
setWord1(&d, w << k + 16 | y << k);
|
|
5640 |
#endif
|
|
5641 |
ret_d:
|
|
5642 |
return d;
|
|
5643 |
}
|
|
5644 |
|
|
5645 |
static Bigint *d2b(double d, int *e, int *bits)
|
|
5646 |
{
|
|
5647 |
Bigint *b;
|
|
5648 |
int de, i, k;
|
|
5649 |
ULong *x, y, z;
|
|
5650 |
|
|
5651 |
#ifdef Pack_32
|
|
5652 |
b = Balloc(1);
|
|
5653 |
#else
|
|
5654 |
b = Balloc(2);
|
|
5655 |
#endif
|
|
5656 |
x = b->x;
|
|
5657 |
|
|
5658 |
z = getWord0(d) & Frac_mask;
|
|
5659 |
setWord0(&d, getWord0(d) & 0x7fffffff); /* clear sign bit, which we ignore */
|
|
5660 |
#ifdef Sudden_Underflow
|
|
5661 |
de = (int)(getWord0(d) >> Exp_shift);
|
|
5662 |
#ifndef IBM
|
|
5663 |
z |= Exp_msk11;
|
|
5664 |
#endif
|
|
5665 |
#else
|
|
5666 |
if ((de = int(getWord0(d) >> Exp_shift)) != 0)
|
|
5667 |
z |= Exp_msk1;
|
|
5668 |
#endif
|
|
5669 |
#ifdef Pack_32
|
|
5670 |
if ((y = getWord1(d)) != 0) {
|
|
5671 |
if ((k = lo0bits(&y)) != 0) {
|
|
5672 |
x[0] = y | z << (32 - k);
|
|
5673 |
z >>= k;
|
|
5674 |
}
|
|
5675 |
else
|
|
5676 |
x[0] = y;
|
|
5677 |
i = b->wds = (x[1] = z) ? 2 : 1;
|
|
5678 |
}
|
|
5679 |
else {
|
|
5680 |
#ifdef BSD_QDTOA_DEBUG
|
|
5681 |
if (!z)
|
|
5682 |
Bug("Zero passed to d2b");
|
|
5683 |
#endif
|
|
5684 |
k = lo0bits(&z);
|
|
5685 |
x[0] = z;
|
|
5686 |
i = b->wds = 1;
|
|
5687 |
k += 32;
|
|
5688 |
}
|
|
5689 |
#else
|
|
5690 |
if (y = getWord1(d)) {
|
|
5691 |
if (k = lo0bits(&y))
|
|
5692 |
if (k >= 16) {
|
|
5693 |
x[0] = y | z << 32 - k & 0xffff;
|
|
5694 |
x[1] = z >> k - 16 & 0xffff;
|
|
5695 |
x[2] = z >> k;
|
|
5696 |
i = 2;
|
|
5697 |
}
|
|
5698 |
else {
|
|
5699 |
x[0] = y & 0xffff;
|
|
5700 |
x[1] = y >> 16 | z << 16 - k & 0xffff;
|
|
5701 |
x[2] = z >> k & 0xffff;
|
|
5702 |
x[3] = z >> k+16;
|
|
5703 |
i = 3;
|
|
5704 |
}
|
|
5705 |
else {
|
|
5706 |
x[0] = y & 0xffff;
|
|
5707 |
x[1] = y >> 16;
|
|
5708 |
x[2] = z & 0xffff;
|
|
5709 |
x[3] = z >> 16;
|
|
5710 |
i = 3;
|
|
5711 |
}
|
|
5712 |
}
|
|
5713 |
else {
|
|
5714 |
#ifdef BSD_QDTOA_DEBUG
|
|
5715 |
if (!z)
|
|
5716 |
Bug("Zero passed to d2b");
|
|
5717 |
#endif
|
|
5718 |
k = lo0bits(&z);
|
|
5719 |
if (k >= 16) {
|
|
5720 |
x[0] = z;
|
|
5721 |
i = 0;
|
|
5722 |
}
|
|
5723 |
else {
|
|
5724 |
x[0] = z & 0xffff;
|
|
5725 |
x[1] = z >> 16;
|
|
5726 |
i = 1;
|
|
5727 |
}
|
|
5728 |
k += 32;
|
|
5729 |
}
|
|
5730 |
while(!x[i])
|
|
5731 |
--i;
|
|
5732 |
b->wds = i + 1;
|
|
5733 |
#endif
|
|
5734 |
#ifndef Sudden_Underflow
|
|
5735 |
if (de) {
|
|
5736 |
#endif
|
|
5737 |
#ifdef IBM
|
|
5738 |
*e = (de - Bias - (P-1) << 2) + k;
|
|
5739 |
*bits = 4*P + 8 - k - hi0bits(getWord0(d) & Frac_mask);
|
|
5740 |
#else
|
|
5741 |
*e = de - Bias - (P-1) + k;
|
|
5742 |
*bits = P - k;
|
|
5743 |
#endif
|
|
5744 |
#ifndef Sudden_Underflow
|
|
5745 |
}
|
|
5746 |
else {
|
|
5747 |
*e = de - Bias - (P-1) + 1 + k;
|
|
5748 |
#ifdef Pack_32
|
|
5749 |
*bits = 32*i - hi0bits(x[i-1]);
|
|
5750 |
#else
|
|
5751 |
*bits = (i+2)*16 - hi0bits(x[i]);
|
|
5752 |
#endif
|
|
5753 |
}
|
|
5754 |
#endif
|
|
5755 |
return b;
|
|
5756 |
}
|
|
5757 |
|
|
5758 |
static double ratio(Bigint *a, Bigint *b)
|
|
5759 |
{
|
|
5760 |
double da, db;
|
|
5761 |
int k, ka, kb;
|
|
5762 |
|
|
5763 |
da = b2d(a, &ka);
|
|
5764 |
db = b2d(b, &kb);
|
|
5765 |
#ifdef Pack_32
|
|
5766 |
k = ka - kb + 32*(a->wds - b->wds);
|
|
5767 |
#else
|
|
5768 |
k = ka - kb + 16*(a->wds - b->wds);
|
|
5769 |
#endif
|
|
5770 |
#ifdef IBM
|
|
5771 |
if (k > 0) {
|
|
5772 |
setWord0(&da, getWord0(da) + (k >> 2)*Exp_msk1);
|
|
5773 |
if (k &= 3)
|
|
5774 |
da *= 1 << k;
|
|
5775 |
}
|
|
5776 |
else {
|
|
5777 |
k = -k;
|
|
5778 |
setWord0(&db, getWord0(db) + (k >> 2)*Exp_msk1);
|
|
5779 |
if (k &= 3)
|
|
5780 |
db *= 1 << k;
|
|
5781 |
}
|
|
5782 |
#else
|
|
5783 |
if (k > 0)
|
|
5784 |
setWord0(&da, getWord0(da) + k*Exp_msk1);
|
|
5785 |
else {
|
|
5786 |
k = -k;
|
|
5787 |
setWord0(&db, getWord0(db) + k*Exp_msk1);
|
|
5788 |
}
|
|
5789 |
#endif
|
|
5790 |
return da / db;
|
|
5791 |
}
|
|
5792 |
|
|
5793 |
static const double tens[] = {
|
|
5794 |
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
|
|
5795 |
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
|
|
5796 |
1e20, 1e21, 1e22
|
|
5797 |
#ifdef VAX
|
|
5798 |
, 1e23, 1e24
|
|
5799 |
#endif
|
|
5800 |
};
|
|
5801 |
|
|
5802 |
#ifdef IEEE_Arith
|
|
5803 |
static const double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
|
|
5804 |
static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
|
|
5805 |
#define n_bigtens 5
|
|
5806 |
#else
|
|
5807 |
#ifdef IBM
|
|
5808 |
static const double bigtens[] = { 1e16, 1e32, 1e64 };
|
|
5809 |
static const double tinytens[] = { 1e-16, 1e-32, 1e-64 };
|
|
5810 |
#define n_bigtens 3
|
|
5811 |
#else
|
|
5812 |
static const double bigtens[] = { 1e16, 1e32 };
|
|
5813 |
static const double tinytens[] = { 1e-16, 1e-32 };
|
|
5814 |
#define n_bigtens 2
|
|
5815 |
#endif
|
|
5816 |
#endif
|
|
5817 |
|
|
5818 |
/*
|
|
5819 |
The pre-release gcc3.3 shipped with SuSE 8.2 has a bug which causes
|
|
5820 |
the comparison 1e-100 == 0.0 to return true. As a workaround, we
|
|
5821 |
compare it to a global variable containing 0.0, which produces
|
|
5822 |
correct assembler output.
|
|
5823 |
|
|
5824 |
### consider detecting the broken compilers and using the static
|
|
5825 |
### double for these, and use a #define for all working compilers
|
|
5826 |
*/
|
|
5827 |
static double g_double_zero = 0.0;
|
|
5828 |
|
|
5829 |
Q_CORE_EXPORT double qstrtod(const char *s00, const char **se, bool *ok)
|
|
5830 |
{
|
|
5831 |
int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
|
|
5832 |
e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
|
|
5833 |
const char *s, *s0, *s1;
|
|
5834 |
double aadj, aadj1, adj, rv, rv0;
|
|
5835 |
Long L;
|
|
5836 |
ULong y, z;
|
|
5837 |
Bigint *bb1, *bd0;
|
|
5838 |
Bigint *bb = NULL, *bd = NULL, *bs = NULL, *delta = NULL;/* pacify gcc */
|
|
5839 |
|
|
5840 |
/*
|
|
5841 |
#ifndef KR_headers
|
|
5842 |
const char decimal_point = localeconv()->decimal_point[0];
|
|
5843 |
#else
|
|
5844 |
const char decimal_point = '.';
|
|
5845 |
#endif */
|
|
5846 |
if (ok != 0)
|
|
5847 |
*ok = true;
|
|
5848 |
|
|
5849 |
const char decimal_point = '.';
|
|
5850 |
|
|
5851 |
sign = nz0 = nz = 0;
|
|
5852 |
rv = 0.;
|
|
5853 |
|
|
5854 |
|
|
5855 |
for(s = s00; isspace(uchar(*s)); s++)
|
|
5856 |
;
|
|
5857 |
|
|
5858 |
if (*s == '-') {
|
|
5859 |
sign = 1;
|
|
5860 |
s++;
|
|
5861 |
} else if (*s == '+') {
|
|
5862 |
s++;
|
|
5863 |
}
|
|
5864 |
|
|
5865 |
if (*s == '\0') {
|
|
5866 |
s = s00;
|
|
5867 |
goto ret;
|
|
5868 |
}
|
|
5869 |
|
|
5870 |
if (*s == '0') {
|
|
5871 |
nz0 = 1;
|
|
5872 |
while(*++s == '0') ;
|
|
5873 |
if (!*s)
|
|
5874 |
goto ret;
|
|
5875 |
}
|
|
5876 |
s0 = s;
|
|
5877 |
y = z = 0;
|
|
5878 |
for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
|
|
5879 |
if (nd < 9)
|
|
5880 |
y = 10*y + c - '0';
|
|
5881 |
else if (nd < 16)
|
|
5882 |
z = 10*z + c - '0';
|
|
5883 |
nd0 = nd;
|
|
5884 |
if (c == decimal_point) {
|
|
5885 |
c = *++s;
|
|
5886 |
if (!nd) {
|
|
5887 |
for(; c == '0'; c = *++s)
|
|
5888 |
nz++;
|
|
5889 |
if (c > '0' && c <= '9') {
|
|
5890 |
s0 = s;
|
|
5891 |
nf += nz;
|
|
5892 |
nz = 0;
|
|
5893 |
goto have_dig;
|
|
5894 |
}
|
|
5895 |
goto dig_done;
|
|
5896 |
}
|
|
5897 |
for(; c >= '0' && c <= '9'; c = *++s) {
|
|
5898 |
have_dig:
|
|
5899 |
nz++;
|
|
5900 |
if (c -= '0') {
|
|
5901 |
nf += nz;
|
|
5902 |
for(i = 1; i < nz; i++)
|
|
5903 |
if (nd++ < 9)
|
|
5904 |
y *= 10;
|
|
5905 |
else if (nd <= DBL_DIG + 1)
|
|
5906 |
z *= 10;
|
|
5907 |
if (nd++ < 9)
|
|
5908 |
y = 10*y + c;
|
|
5909 |
else if (nd <= DBL_DIG + 1)
|
|
5910 |
z = 10*z + c;
|
|
5911 |
nz = 0;
|
|
5912 |
}
|
|
5913 |
}
|
|
5914 |
}
|
|
5915 |
dig_done:
|
|
5916 |
e = 0;
|
|
5917 |
if (c == 'e' || c == 'E') {
|
|
5918 |
if (!nd && !nz && !nz0) {
|
|
5919 |
s = s00;
|
|
5920 |
goto ret;
|
|
5921 |
}
|
|
5922 |
s00 = s;
|
|
5923 |
esign = 0;
|
|
5924 |
switch(c = *++s) {
|
|
5925 |
case '-':
|
|
5926 |
esign = 1;
|
|
5927 |
case '+':
|
|
5928 |
c = *++s;
|
|
5929 |
}
|
|
5930 |
if (c >= '0' && c <= '9') {
|
|
5931 |
while(c == '0')
|
|
5932 |
c = *++s;
|
|
5933 |
if (c > '0' && c <= '9') {
|
|
5934 |
L = c - '0';
|
|
5935 |
s1 = s;
|
|
5936 |
while((c = *++s) >= '0' && c <= '9')
|
|
5937 |
L = 10*L + c - '0';
|
|
5938 |
if (s - s1 > 8 || L > 19999)
|
|
5939 |
/* Avoid confusion from exponents
|
|
5940 |
* so large that e might overflow.
|
|
5941 |
*/
|
|
5942 |
e = 19999; /* safe for 16 bit ints */
|
|
5943 |
else
|
|
5944 |
e = int(L);
|
|
5945 |
if (esign)
|
|
5946 |
e = -e;
|
|
5947 |
}
|
|
5948 |
else
|
|
5949 |
e = 0;
|
|
5950 |
}
|
|
5951 |
else
|
|
5952 |
s = s00;
|
|
5953 |
}
|
|
5954 |
if (!nd) {
|
|
5955 |
if (!nz && !nz0)
|
|
5956 |
s = s00;
|
|
5957 |
goto ret;
|
|
5958 |
}
|
|
5959 |
e1 = e -= nf;
|
|
5960 |
|
|
5961 |
/* Now we have nd0 digits, starting at s0, followed by a
|
|
5962 |
* decimal point, followed by nd-nd0 digits. The number we're
|
|
5963 |
* after is the integer represented by those digits times
|
|
5964 |
* 10**e */
|
|
5965 |
|
|
5966 |
if (!nd0)
|
|
5967 |
nd0 = nd;
|
|
5968 |
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
|
|
5969 |
rv = y;
|
|
5970 |
if (k > 9)
|
|
5971 |
#if defined(Q_OS_IRIX) && defined(Q_CC_GNU)
|
|
5972 |
{
|
|
5973 |
// work around a bug on 64 bit IRIX gcc
|
|
5974 |
double *t = (double *) tens;
|
|
5975 |
rv = t[k - 9] * rv + z;
|
|
5976 |
}
|
|
5977 |
#else
|
|
5978 |
rv = tens[k - 9] * rv + z;
|
|
5979 |
#endif
|
|
5980 |
|
|
5981 |
bd0 = 0;
|
|
5982 |
if (nd <= DBL_DIG
|
|
5983 |
#ifndef RND_PRODQUOT
|
|
5984 |
&& FLT_ROUNDS == 1
|
|
5985 |
#endif
|
|
5986 |
) {
|
|
5987 |
if (!e)
|
|
5988 |
goto ret;
|
|
5989 |
if (e > 0) {
|
|
5990 |
if (e <= Ten_pmax) {
|
|
5991 |
#ifdef VAX
|
|
5992 |
goto vax_ovfl_check;
|
|
5993 |
#else
|
|
5994 |
/* rv = */ rounded_product(rv, tens[e]);
|
|
5995 |
goto ret;
|
|
5996 |
#endif
|
|
5997 |
}
|
|
5998 |
i = DBL_DIG - nd;
|
|
5999 |
if (e <= Ten_pmax + i) {
|
|
6000 |
/* A fancier test would sometimes let us do
|
|
6001 |
* this for larger i values.
|
|
6002 |
*/
|
|
6003 |
e -= i;
|
|
6004 |
rv *= tens[i];
|
|
6005 |
#ifdef VAX
|
|
6006 |
/* VAX exponent range is so narrow we must
|
|
6007 |
* worry about overflow here...
|
|
6008 |
*/
|
|
6009 |
vax_ovfl_check:
|
|
6010 |
setWord0(&rv, getWord0(rv) - P*Exp_msk1);
|
|
6011 |
/* rv = */ rounded_product(rv, tens[e]);
|
|
6012 |
if ((getWord0(rv) & Exp_mask)
|
|
6013 |
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
|
|
6014 |
goto ovfl;
|
|
6015 |
setWord0(&rv, getWord0(rv) + P*Exp_msk1);
|
|
6016 |
#else
|
|
6017 |
/* rv = */ rounded_product(rv, tens[e]);
|
|
6018 |
#endif
|
|
6019 |
goto ret;
|
|
6020 |
}
|
|
6021 |
}
|
|
6022 |
#ifndef Inaccurate_Divide
|
|
6023 |
else if (e >= -Ten_pmax) {
|
|
6024 |
/* rv = */ rounded_quotient(rv, tens[-e]);
|
|
6025 |
goto ret;
|
|
6026 |
}
|
|
6027 |
#endif
|
|
6028 |
}
|
|
6029 |
e1 += nd - k;
|
|
6030 |
|
|
6031 |
/* Get starting approximation = rv * 10**e1 */
|
|
6032 |
|
|
6033 |
if (e1 > 0) {
|
|
6034 |
if ((i = e1 & 15) != 0)
|
|
6035 |
rv *= tens[i];
|
|
6036 |
if (e1 &= ~15) {
|
|
6037 |
if (e1 > DBL_MAX_10_EXP) {
|
|
6038 |
ovfl:
|
|
6039 |
// errno = ERANGE;
|
|
6040 |
if (ok != 0)
|
|
6041 |
*ok = false;
|
|
6042 |
#ifdef __STDC__
|
|
6043 |
rv = HUGE_VAL;
|
|
6044 |
#else
|
|
6045 |
/* Can't trust HUGE_VAL */
|
|
6046 |
#ifdef IEEE_Arith
|
|
6047 |
setWord0(&rv, Exp_mask);
|
|
6048 |
setWord1(&rv, 0);
|
|
6049 |
#else
|
|
6050 |
setWord0(&rv, Big0);
|
|
6051 |
setWord1(&rv, Big1);
|
|
6052 |
#endif
|
|
6053 |
#endif
|
|
6054 |
if (bd0)
|
|
6055 |
goto retfree;
|
|
6056 |
goto ret;
|
|
6057 |
}
|
|
6058 |
if (e1 >>= 4) {
|
|
6059 |
for(j = 0; e1 > 1; j++, e1 >>= 1)
|
|
6060 |
if (e1 & 1)
|
|
6061 |
rv *= bigtens[j];
|
|
6062 |
/* The last multiplication could overflow. */
|
|
6063 |
setWord0(&rv, getWord0(rv) - P*Exp_msk1);
|
|
6064 |
rv *= bigtens[j];
|
|
6065 |
if ((z = getWord0(rv) & Exp_mask)
|
|
6066 |
> Exp_msk1*(DBL_MAX_EXP+Bias-P))
|
|
6067 |
goto ovfl;
|
|
6068 |
if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
|
|
6069 |
/* set to largest number */
|
|
6070 |
/* (Can't trust DBL_MAX) */
|
|
6071 |
setWord0(&rv, Big0);
|
|
6072 |
setWord1(&rv, Big1);
|
|
6073 |
}
|
|
6074 |
else
|
|
6075 |
setWord0(&rv, getWord0(rv) + P*Exp_msk1);
|
|
6076 |
}
|
|
6077 |
|
|
6078 |
}
|
|
6079 |
}
|
|
6080 |
else if (e1 < 0) {
|
|
6081 |
e1 = -e1;
|
|
6082 |
if ((i = e1 & 15) != 0)
|
|
6083 |
rv /= tens[i];
|
|
6084 |
if (e1 &= ~15) {
|
|
6085 |
e1 >>= 4;
|
|
6086 |
if (e1 >= 1 << n_bigtens)
|
|
6087 |
goto undfl;
|
|
6088 |
for(j = 0; e1 > 1; j++, e1 >>= 1)
|
|
6089 |
if (e1 & 1)
|
|
6090 |
rv *= tinytens[j];
|
|
6091 |
/* The last multiplication could underflow. */
|
|
6092 |
rv0 = rv;
|
|
6093 |
rv *= tinytens[j];
|
|
6094 |
if (rv == g_double_zero)
|
|
6095 |
{
|
|
6096 |
rv = 2.*rv0;
|
|
6097 |
rv *= tinytens[j];
|
|
6098 |
if (rv == g_double_zero)
|
|
6099 |
{
|
|
6100 |
undfl:
|
|
6101 |
rv = 0.;
|
|
6102 |
// errno = ERANGE;
|
|
6103 |
if (ok != 0)
|
|
6104 |
*ok = false;
|
|
6105 |
if (bd0)
|
|
6106 |
goto retfree;
|
|
6107 |
goto ret;
|
|
6108 |
}
|
|
6109 |
setWord0(&rv, Tiny0);
|
|
6110 |
setWord1(&rv, Tiny1);
|
|
6111 |
/* The refinement below will clean
|
|
6112 |
* this approximation up.
|
|
6113 |
*/
|
|
6114 |
}
|
|
6115 |
}
|
|
6116 |
}
|
|
6117 |
|
|
6118 |
/* Now the hard part -- adjusting rv to the correct value.*/
|
|
6119 |
|
|
6120 |
/* Put digits into bd: true value = bd * 10^e */
|
|
6121 |
|
|
6122 |
bd0 = s2b(s0, nd0, nd, y);
|
|
6123 |
|
|
6124 |
for(;;) {
|
|
6125 |
bd = Balloc(bd0->k);
|
|
6126 |
Bcopy(bd, bd0);
|
|
6127 |
bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */
|
|
6128 |
bs = i2b(1);
|
|
6129 |
|
|
6130 |
if (e >= 0) {
|
|
6131 |
bb2 = bb5 = 0;
|
|
6132 |
bd2 = bd5 = e;
|
|
6133 |
}
|
|
6134 |
else {
|
|
6135 |
bb2 = bb5 = -e;
|
|
6136 |
bd2 = bd5 = 0;
|
|
6137 |
}
|
|
6138 |
if (bbe >= 0)
|
|
6139 |
bb2 += bbe;
|
|
6140 |
else
|
|
6141 |
bd2 -= bbe;
|
|
6142 |
bs2 = bb2;
|
|
6143 |
#ifdef Sudden_Underflow
|
|
6144 |
#ifdef IBM
|
|
6145 |
j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
|
|
6146 |
#else
|
|
6147 |
j = P + 1 - bbbits;
|
|
6148 |
#endif
|
|
6149 |
#else
|
|
6150 |
i = bbe + bbbits - 1; /* logb(rv) */
|
|
6151 |
if (i < Emin) /* denormal */
|
|
6152 |
j = bbe + (P-Emin);
|
|
6153 |
else
|
|
6154 |
j = P + 1 - bbbits;
|
|
6155 |
#endif
|
|
6156 |
bb2 += j;
|
|
6157 |
bd2 += j;
|
|
6158 |
i = bb2 < bd2 ? bb2 : bd2;
|
|
6159 |
if (i > bs2)
|
|
6160 |
i = bs2;
|
|
6161 |
if (i > 0) {
|
|
6162 |
bb2 -= i;
|
|
6163 |
bd2 -= i;
|
|
6164 |
bs2 -= i;
|
|
6165 |
}
|
|
6166 |
if (bb5 > 0) {
|
|
6167 |
bs = pow5mult(bs, bb5);
|
|
6168 |
bb1 = mult(bs, bb);
|
|
6169 |
Bfree(bb);
|
|
6170 |
bb = bb1;
|
|
6171 |
}
|
|
6172 |
if (bb2 > 0)
|
|
6173 |
bb = lshift(bb, bb2);
|
|
6174 |
if (bd5 > 0)
|
|
6175 |
bd = pow5mult(bd, bd5);
|
|
6176 |
if (bd2 > 0)
|
|
6177 |
bd = lshift(bd, bd2);
|
|
6178 |
if (bs2 > 0)
|
|
6179 |
bs = lshift(bs, bs2);
|
|
6180 |
delta = diff(bb, bd);
|
|
6181 |
dsign = delta->sign;
|
|
6182 |
delta->sign = 0;
|
|
6183 |
i = cmp(delta, bs);
|
|
6184 |
if (i < 0) {
|
|
6185 |
/* Error is less than half an ulp -- check for
|
|
6186 |
* special case of mantissa a power of two.
|
|
6187 |
*/
|
|
6188 |
if (dsign || getWord1(rv) || getWord0(rv) & Bndry_mask)
|
|
6189 |
break;
|
|
6190 |
delta = lshift(delta,Log2P);
|
|
6191 |
if (cmp(delta, bs) > 0)
|
|
6192 |
goto drop_down;
|
|
6193 |
break;
|
|
6194 |
}
|
|
6195 |
if (i == 0) {
|
|
6196 |
/* exactly half-way between */
|
|
6197 |
if (dsign) {
|
|
6198 |
if ((getWord0(rv) & Bndry_mask1) == Bndry_mask1
|
|
6199 |
&& getWord1(rv) == 0xffffffff) {
|
|
6200 |
/*boundary case -- increment exponent*/
|
|
6201 |
setWord0(&rv, (getWord0(rv) & Exp_mask)
|
|
6202 |
+ Exp_msk1
|
|
6203 |
#ifdef IBM
|
|
6204 |
| Exp_msk1 >> 4
|
|
6205 |
#endif
|
|
6206 |
);
|
|
6207 |
setWord1(&rv, 0);
|
|
6208 |
break;
|
|
6209 |
}
|
|
6210 |
}
|
|
6211 |
else if (!(getWord0(rv) & Bndry_mask) && !getWord1(rv)) {
|
|
6212 |
drop_down:
|
|
6213 |
/* boundary case -- decrement exponent */
|
|
6214 |
#ifdef Sudden_Underflow
|
|
6215 |
L = getWord0(rv) & Exp_mask;
|
|
6216 |
#ifdef IBM
|
|
6217 |
if (L < Exp_msk1)
|
|
6218 |
#else
|
|
6219 |
if (L <= Exp_msk1)
|
|
6220 |
#endif
|
|
6221 |
goto undfl;
|
|
6222 |
L -= Exp_msk1;
|
|
6223 |
#else
|
|
6224 |
L = (getWord0(rv) & Exp_mask) - Exp_msk1;
|
|
6225 |
#endif
|
|
6226 |
setWord0(&rv, L | Bndry_mask1);
|
|
6227 |
setWord1(&rv, 0xffffffff);
|
|
6228 |
#ifdef IBM
|
|
6229 |
goto cont;
|
|
6230 |
#else
|
|
6231 |
break;
|
|
6232 |
#endif
|
|
6233 |
}
|
|
6234 |
#ifndef ROUND_BIASED
|
|
6235 |
if (!(getWord1(rv) & LSB))
|
|
6236 |
break;
|
|
6237 |
#endif
|
|
6238 |
if (dsign)
|
|
6239 |
rv += ulp(rv);
|
|
6240 |
#ifndef ROUND_BIASED
|
|
6241 |
else {
|
|
6242 |
rv -= ulp(rv);
|
|
6243 |
#ifndef Sudden_Underflow
|
|
6244 |
if (rv == g_double_zero)
|
|
6245 |
goto undfl;
|
|
6246 |
#endif
|
|
6247 |
}
|
|
6248 |
#endif
|
|
6249 |
break;
|
|
6250 |
}
|
|
6251 |
if ((aadj = ratio(delta, bs)) <= 2.) {
|
|
6252 |
if (dsign)
|
|
6253 |
aadj = aadj1 = 1.;
|
|
6254 |
else if (getWord1(rv) || getWord0(rv) & Bndry_mask) {
|
|
6255 |
#ifndef Sudden_Underflow
|
|
6256 |
if (getWord1(rv) == Tiny1 && !getWord0(rv))
|
|
6257 |
goto undfl;
|
|
6258 |
#endif
|
|
6259 |
aadj = 1.;
|
|
6260 |
aadj1 = -1.;
|
|
6261 |
}
|
|
6262 |
else {
|
|
6263 |
/* special case -- power of FLT_RADIX to be */
|
|
6264 |
/* rounded down... */
|
|
6265 |
|
|
6266 |
if (aadj < 2./FLT_RADIX)
|
|
6267 |
aadj = 1./FLT_RADIX;
|
|
6268 |
else
|
|
6269 |
aadj *= 0.5;
|
|
6270 |
aadj1 = -aadj;
|
|
6271 |
}
|
|
6272 |
}
|
|
6273 |
else {
|
|
6274 |
aadj *= 0.5;
|
|
6275 |
aadj1 = dsign ? aadj : -aadj;
|
|
6276 |
#ifdef Check_FLT_ROUNDS
|
|
6277 |
switch(FLT_ROUNDS) {
|
|
6278 |
case 2: /* towards +infinity */
|
|
6279 |
aadj1 -= 0.5;
|
|
6280 |
break;
|
|
6281 |
case 0: /* towards 0 */
|
|
6282 |
case 3: /* towards -infinity */
|
|
6283 |
aadj1 += 0.5;
|
|
6284 |
}
|
|
6285 |
#else
|
|
6286 |
if (FLT_ROUNDS == 0)
|
|
6287 |
aadj1 += 0.5;
|
|
6288 |
#endif
|
|
6289 |
}
|
|
6290 |
y = getWord0(rv) & Exp_mask;
|
|
6291 |
|
|
6292 |
/* Check for overflow */
|
|
6293 |
|
|
6294 |
if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
|
|
6295 |
rv0 = rv;
|
|
6296 |
setWord0(&rv, getWord0(rv) - P*Exp_msk1);
|
|
6297 |
adj = aadj1 * ulp(rv);
|
|
6298 |
rv += adj;
|
|
6299 |
if ((getWord0(rv) & Exp_mask) >=
|
|
6300 |
Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
|
|
6301 |
if (getWord0(rv0) == Big0 && getWord1(rv0) == Big1)
|
|
6302 |
goto ovfl;
|
|
6303 |
setWord0(&rv, Big0);
|
|
6304 |
setWord1(&rv, Big1);
|
|
6305 |
goto cont;
|
|
6306 |
}
|
|
6307 |
else
|
|
6308 |
setWord0(&rv, getWord0(rv) + P*Exp_msk1);
|
|
6309 |
}
|
|
6310 |
else {
|
|
6311 |
#ifdef Sudden_Underflow
|
|
6312 |
if ((getWord0(rv) & Exp_mask) <= P*Exp_msk1) {
|
|
6313 |
rv0 = rv;
|
|
6314 |
setWord0(&rv, getWord0(rv) + P*Exp_msk1);
|
|
6315 |
adj = aadj1 * ulp(rv);
|
|
6316 |
rv += adj;
|
|
6317 |
#ifdef IBM
|
|
6318 |
if ((getWord0(rv) & Exp_mask) < P*Exp_msk1)
|
|
6319 |
#else
|
|
6320 |
if ((getWord0(rv) & Exp_mask) <= P*Exp_msk1)
|
|
6321 |
#endif
|
|
6322 |
{
|
|
6323 |
if (getWord0(rv0) == Tiny0
|
|
6324 |
&& getWord1(rv0) == Tiny1)
|
|
6325 |
goto undfl;
|
|
6326 |
setWord0(&rv, Tiny0);
|
|
6327 |
setWord1(&rv, Tiny1);
|
|
6328 |
goto cont;
|
|
6329 |
}
|
|
6330 |
else
|
|
6331 |
setWord0(&rv, getWord0(rv) - P*Exp_msk1);
|
|
6332 |
}
|
|
6333 |
else {
|
|
6334 |
adj = aadj1 * ulp(rv);
|
|
6335 |
rv += adj;
|
|
6336 |
}
|
|
6337 |
#else
|
|
6338 |
/* Compute adj so that the IEEE rounding rules will
|
|
6339 |
* correctly round rv + adj in some half-way cases.
|
|
6340 |
* If rv * ulp(rv) is denormalized (i.e.,
|
|
6341 |
* y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
|
|
6342 |
* trouble from bits lost to denormalization;
|
|
6343 |
* example: 1.2e-307 .
|
|
6344 |
*/
|
|
6345 |
if (y <= (P-1)*Exp_msk1 && aadj >= 1.) {
|
|
6346 |
aadj1 = int(aadj + 0.5);
|
|
6347 |
if (!dsign)
|
|
6348 |
aadj1 = -aadj1;
|
|
6349 |
}
|
|
6350 |
adj = aadj1 * ulp(rv);
|
|
6351 |
rv += adj;
|
|
6352 |
#endif
|
|
6353 |
}
|
|
6354 |
z = getWord0(rv) & Exp_mask;
|
|
6355 |
if (y == z) {
|
|
6356 |
/* Can we stop now? */
|
|
6357 |
L = Long(aadj);
|
|
6358 |
aadj -= L;
|
|
6359 |
/* The tolerances below are conservative. */
|
|
6360 |
if (dsign || getWord1(rv) || getWord0(rv) & Bndry_mask) {
|
|
6361 |
if (aadj < .4999999 || aadj > .5000001)
|
|
6362 |
break;
|
|
6363 |
}
|
|
6364 |
else if (aadj < .4999999/FLT_RADIX)
|
|
6365 |
break;
|
|
6366 |
}
|
|
6367 |
cont:
|
|
6368 |
Bfree(bb);
|
|
6369 |
Bfree(bd);
|
|
6370 |
Bfree(bs);
|
|
6371 |
Bfree(delta);
|
|
6372 |
}
|
|
6373 |
retfree:
|
|
6374 |
Bfree(bb);
|
|
6375 |
Bfree(bd);
|
|
6376 |
Bfree(bs);
|
|
6377 |
Bfree(bd0);
|
|
6378 |
Bfree(delta);
|
|
6379 |
ret:
|
|
6380 |
if (se)
|
|
6381 |
*se = s;
|
|
6382 |
return sign ? -rv : rv;
|
|
6383 |
}
|
|
6384 |
|
|
6385 |
static int quorem(Bigint *b, Bigint *S)
|
|
6386 |
{
|
|
6387 |
int n;
|
|
6388 |
Long borrow, y;
|
|
6389 |
ULong carry, q, ys;
|
|
6390 |
ULong *bx, *bxe, *sx, *sxe;
|
|
6391 |
#ifdef Pack_32
|
|
6392 |
Long z;
|
|
6393 |
ULong si, zs;
|
|
6394 |
#endif
|
|
6395 |
|
|
6396 |
n = S->wds;
|
|
6397 |
#ifdef BSD_QDTOA_DEBUG
|
|
6398 |
/*debug*/ if (b->wds > n)
|
|
6399 |
/*debug*/ Bug("oversize b in quorem");
|
|
6400 |
#endif
|
|
6401 |
if (b->wds < n)
|
|
6402 |
return 0;
|
|
6403 |
sx = S->x;
|
|
6404 |
sxe = sx + --n;
|
|
6405 |
bx = b->x;
|
|
6406 |
bxe = bx + n;
|
|
6407 |
q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
|
|
6408 |
#ifdef BSD_QDTOA_DEBUG
|
|
6409 |
/*debug*/ if (q > 9)
|
|
6410 |
/*debug*/ Bug("oversized quotient in quorem");
|
|
6411 |
#endif
|
|
6412 |
if (q) {
|
|
6413 |
borrow = 0;
|
|
6414 |
carry = 0;
|
|
6415 |
do {
|
|
6416 |
#ifdef Pack_32
|
|
6417 |
si = *sx++;
|
|
6418 |
ys = (si & 0xffff) * q + carry;
|
|
6419 |
zs = (si >> 16) * q + (ys >> 16);
|
|
6420 |
carry = zs >> 16;
|
|
6421 |
y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
|
|
6422 |
borrow = y >> 16;
|
|
6423 |
Sign_Extend(borrow, y);
|
|
6424 |
z = (*bx >> 16) - (zs & 0xffff) + borrow;
|
|
6425 |
borrow = z >> 16;
|
|
6426 |
Sign_Extend(borrow, z);
|
|
6427 |
Storeinc(bx, z, y);
|
|
6428 |
#else
|
|
6429 |
ys = *sx++ * q + carry;
|
|
6430 |
carry = ys >> 16;
|
|
6431 |
y = *bx - (ys & 0xffff) + borrow;
|
|
6432 |
borrow = y >> 16;
|
|
6433 |
Sign_Extend(borrow, y);
|
|
6434 |
*bx++ = y & 0xffff;
|
|
6435 |
#endif
|
|
6436 |
}
|
|
6437 |
while(sx <= sxe);
|
|
6438 |
if (!*bxe) {
|
|
6439 |
bx = b->x;
|
|
6440 |
while(--bxe > bx && !*bxe)
|
|
6441 |
--n;
|
|
6442 |
b->wds = n;
|
|
6443 |
}
|
|
6444 |
}
|
|
6445 |
if (cmp(b, S) >= 0) {
|
|
6446 |
q++;
|
|
6447 |
borrow = 0;
|
|
6448 |
carry = 0;
|
|
6449 |
bx = b->x;
|
|
6450 |
sx = S->x;
|
|
6451 |
do {
|
|
6452 |
#ifdef Pack_32
|
|
6453 |
si = *sx++;
|
|
6454 |
ys = (si & 0xffff) + carry;
|
|
6455 |
zs = (si >> 16) + (ys >> 16);
|
|
6456 |
carry = zs >> 16;
|
|
6457 |
y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
|
|
6458 |
borrow = y >> 16;
|
|
6459 |
Sign_Extend(borrow, y);
|
|
6460 |
z = (*bx >> 16) - (zs & 0xffff) + borrow;
|
|
6461 |
borrow = z >> 16;
|
|
6462 |
Sign_Extend(borrow, z);
|
|
6463 |
Storeinc(bx, z, y);
|
|
6464 |
#else
|
|
6465 |
ys = *sx++ + carry;
|
|
6466 |
carry = ys >> 16;
|
|
6467 |
y = *bx - (ys & 0xffff) + borrow;
|
|
6468 |
borrow = y >> 16;
|
|
6469 |
Sign_Extend(borrow, y);
|
|
6470 |
*bx++ = y & 0xffff;
|
|
6471 |
#endif
|
|
6472 |
}
|
|
6473 |
while(sx <= sxe);
|
|
6474 |
bx = b->x;
|
|
6475 |
bxe = bx + n;
|
|
6476 |
if (!*bxe) {
|
|
6477 |
while(--bxe > bx && !*bxe)
|
|
6478 |
--n;
|
|
6479 |
b->wds = n;
|
|
6480 |
}
|
|
6481 |
}
|
|
6482 |
return q;
|
|
6483 |
}
|
|
6484 |
|
|
6485 |
/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
|
|
6486 |
*
|
|
6487 |
* Inspired by "How to Print Floating-Point Numbers Accurately" by
|
|
6488 |
* Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
|
|
6489 |
*
|
|
6490 |
* Modifications:
|
|
6491 |
* 1. Rather than iterating, we use a simple numeric overestimate
|
|
6492 |
* to determine k = floor(log10(d)). We scale relevant
|
|
6493 |
* quantities using O(log2(k)) rather than O(k) multiplications.
|
|
6494 |
* 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
|
|
6495 |
* try to generate digits strictly left to right. Instead, we
|
|
6496 |
* compute with fewer bits and propagate the carry if necessary
|
|
6497 |
* when rounding the final digit up. This is often faster.
|
|
6498 |
* 3. Under the assumption that input will be rounded nearest,
|
|
6499 |
* mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
|
|
6500 |
* That is, we allow equality in stopping tests when the
|
|
6501 |
* round-nearest rule will give the same floating-point value
|
|
6502 |
* as would satisfaction of the stopping test with strict
|
|
6503 |
* inequality.
|
|
6504 |
* 4. We remove common factors of powers of 2 from relevant
|
|
6505 |
* quantities.
|
|
6506 |
* 5. When converting floating-point integers less than 1e16,
|
|
6507 |
* we use floating-point arithmetic rather than resorting
|
|
6508 |
* to multiple-precision integers.
|
|
6509 |
* 6. When asked to produce fewer than 15 digits, we first try
|
|
6510 |
* to get by with floating-point arithmetic; we resort to
|
|
6511 |
* multiple-precision integer arithmetic only if we cannot
|
|
6512 |
* guarantee that the floating-point calculation has given
|
|
6513 |
* the correctly rounded result. For k requested digits and
|
|
6514 |
* "uniformly" distributed input, the probability is
|
|
6515 |
* something like 10^(k-15) that we must resort to the Long
|
|
6516 |
* calculation.
|
|
6517 |
*/
|
|
6518 |
|
|
6519 |
|
|
6520 |
/* This actually sometimes returns a pointer to a string literal
|
|
6521 |
cast to a char*. Do NOT try to modify the return value. */
|
|
6522 |
|
|
6523 |
Q_CORE_EXPORT char *qdtoa ( double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **resultp)
|
|
6524 |
{
|
|
6525 |
// Some values of the floating-point control word can cause _qdtoa to crash with an underflow.
|
|
6526 |
// We set a safe value here.
|
|
6527 |
#ifdef Q_OS_WIN
|
|
6528 |
_clear87();
|
|
6529 |
unsigned int oldbits = _control87(0, 0);
|
|
6530 |
#ifndef MCW_EM
|
|
6531 |
# ifdef _MCW_EM
|
|
6532 |
# define MCW_EM _MCW_EM
|
|
6533 |
# else
|
|
6534 |
# define MCW_EM 0x0008001F
|
|
6535 |
# endif
|
|
6536 |
#endif
|
|
6537 |
_control87(MCW_EM, MCW_EM);
|
|
6538 |
#endif
|
|
6539 |
|
|
6540 |
#if defined(Q_OS_LINUX) && !defined(__UCLIBC__)
|
|
6541 |
fenv_t envp;
|
|
6542 |
feholdexcept(&envp);
|
|
6543 |
#endif
|
|
6544 |
|
|
6545 |
char *s = _qdtoa(d, mode, ndigits, decpt, sign, rve, resultp);
|
|
6546 |
|
|
6547 |
#ifdef Q_OS_WIN
|
|
6548 |
_clear87();
|
|
6549 |
#ifndef _M_X64
|
|
6550 |
_control87(oldbits, 0xFFFFF);
|
|
6551 |
#else
|
|
6552 |
_control87(oldbits, _MCW_EM|_MCW_DN|_MCW_RC);
|
|
6553 |
#endif //_M_X64
|
|
6554 |
#endif //Q_OS_WIN
|
|
6555 |
|
|
6556 |
#if defined(Q_OS_LINUX) && !defined(__UCLIBC__)
|
|
6557 |
fesetenv(&envp);
|
|
6558 |
#endif
|
|
6559 |
|
|
6560 |
return s;
|
|
6561 |
}
|
|
6562 |
|
|
6563 |
static char *_qdtoa( NEEDS_VOLATILE double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **resultp)
|
|
6564 |
{
|
|
6565 |
/*
|
|
6566 |
Arguments ndigits, decpt, sign are similar to those
|
|
6567 |
of ecvt and fcvt; trailing zeros are suppressed from
|
|
6568 |
the returned string. If not null, *rve is set to point
|
|
6569 |
to the end of the return value. If d is +-Infinity or NaN,
|
|
6570 |
then *decpt is set to 9999.
|
|
6571 |
|
|
6572 |
mode:
|
|
6573 |
0 ==> shortest string that yields d when read in
|
|
6574 |
and rounded to nearest.
|
|
6575 |
1 ==> like 0, but with Steele & White stopping rule;
|
|
6576 |
e.g. with IEEE P754 arithmetic , mode 0 gives
|
|
6577 |
1e23 whereas mode 1 gives 9.999999999999999e22.
|
|
6578 |
2 ==> max(1,ndigits) significant digits. This gives a
|
|
6579 |
return value similar to that of ecvt, except
|
|
6580 |
that trailing zeros are suppressed.
|
|
6581 |
3 ==> through ndigits past the decimal point. This
|
|
6582 |
gives a return value similar to that from fcvt,
|
|
6583 |
except that trailing zeros are suppressed, and
|
|
6584 |
ndigits can be negative.
|
|
6585 |
4-9 should give the same return values as 2-3, i.e.,
|
|
6586 |
4 <= mode <= 9 ==> same return as mode
|
|
6587 |
2 + (mode & 1). These modes are mainly for
|
|
6588 |
debugging; often they run slower but sometimes
|
|
6589 |
faster than modes 2-3.
|
|
6590 |
4,5,8,9 ==> left-to-right digit generation.
|
|
6591 |
6-9 ==> don't try fast floating-point estimate
|
|
6592 |
(if applicable).
|
|
6593 |
|
|
6594 |
Values of mode other than 0-9 are treated as mode 0.
|
|
6595 |
|
|
6596 |
Sufficient space is allocated to the return value
|
|
6597 |
to hold the suppressed trailing zeros.
|
|
6598 |
*/
|
|
6599 |
|
|
6600 |
int bbits, b2, b5, be, dig, i, ieps, ilim0,
|
|
6601 |
j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
|
|
6602 |
try_quick;
|
|
6603 |
int ilim = 0, ilim1 = 0, spec_case = 0; /* pacify gcc */
|
|
6604 |
Long L;
|
|
6605 |
#ifndef Sudden_Underflow
|
|
6606 |
int denorm;
|
|
6607 |
ULong x;
|
|
6608 |
#endif
|
|
6609 |
Bigint *b, *b1, *delta, *mhi, *S;
|
|
6610 |
Bigint *mlo = NULL; /* pacify gcc */
|
|
6611 |
double d2;
|
|
6612 |
double ds, eps;
|
|
6613 |
char *s, *s0;
|
|
6614 |
|
|
6615 |
if (getWord0(d) & Sign_bit) {
|
|
6616 |
/* set sign for everything, including 0's and NaNs */
|
|
6617 |
*sign = 1;
|
|
6618 |
setWord0(&d, getWord0(d) & ~Sign_bit); /* clear sign bit */
|
|
6619 |
}
|
|
6620 |
else
|
|
6621 |
*sign = 0;
|
|
6622 |
|
|
6623 |
#if defined(IEEE_Arith) + defined(VAX)
|
|
6624 |
#ifdef IEEE_Arith
|
|
6625 |
if ((getWord0(d) & Exp_mask) == Exp_mask)
|
|
6626 |
#else
|
|
6627 |
if (getWord0(d) == 0x8000)
|
|
6628 |
#endif
|
|
6629 |
{
|
|
6630 |
/* Infinity or NaN */
|
|
6631 |
*decpt = 9999;
|
|
6632 |
s =
|
|
6633 |
#ifdef IEEE_Arith
|
|
6634 |
!getWord1(d) && !(getWord0(d) & 0xfffff) ? const_cast<char*>("Infinity") :
|
|
6635 |
#endif
|
|
6636 |
const_cast<char*>("NaN");
|
|
6637 |
if (rve)
|
|
6638 |
*rve =
|
|
6639 |
#ifdef IEEE_Arith
|
|
6640 |
s[3] ? s + 8 :
|
|
6641 |
#endif
|
|
6642 |
s + 3;
|
|
6643 |
return s;
|
|
6644 |
}
|
|
6645 |
#endif
|
|
6646 |
#ifdef IBM
|
|
6647 |
d += 0; /* normalize */
|
|
6648 |
#endif
|
|
6649 |
if (d == g_double_zero)
|
|
6650 |
{
|
|
6651 |
*decpt = 1;
|
|
6652 |
s = const_cast<char*>("0");
|
|
6653 |
if (rve)
|
|
6654 |
*rve = s + 1;
|
|
6655 |
return s;
|
|
6656 |
}
|
|
6657 |
|
|
6658 |
b = d2b(d, &be, &bbits);
|
|
6659 |
#ifdef Sudden_Underflow
|
|
6660 |
i = (int)(getWord0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
|
|
6661 |
#else
|
|
6662 |
if ((i = int(getWord0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) {
|
|
6663 |
#endif
|
|
6664 |
d2 = d;
|
|
6665 |
setWord0(&d2, getWord0(d2) & Frac_mask1);
|
|
6666 |
setWord0(&d2, getWord0(d2) | Exp_11);
|
|
6667 |
#ifdef IBM
|
|
6668 |
if (j = 11 - hi0bits(getWord0(d2) & Frac_mask))
|
|
6669 |
d2 /= 1 << j;
|
|
6670 |
#endif
|
|
6671 |
|
|
6672 |
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5
|
|
6673 |
* log10(x) = log(x) / log(10)
|
|
6674 |
* ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
|
|
6675 |
* log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
|
|
6676 |
*
|
|
6677 |
* This suggests computing an approximation k to log10(d) by
|
|
6678 |
*
|
|
6679 |
* k = (i - Bias)*0.301029995663981
|
|
6680 |
* + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
|
|
6681 |
*
|
|
6682 |
* We want k to be too large rather than too small.
|
|
6683 |
* The error in the first-order Taylor series approximation
|
|
6684 |
* is in our favor, so we just round up the constant enough
|
|
6685 |
* to compensate for any error in the multiplication of
|
|
6686 |
* (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
|
|
6687 |
* and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
|
|
6688 |
* adding 1e-13 to the constant term more than suffices.
|
|
6689 |
* Hence we adjust the constant term to 0.1760912590558.
|
|
6690 |
* (We could get a more accurate k by invoking log10,
|
|
6691 |
* but this is probably not worthwhile.)
|
|
6692 |
*/
|
|
6693 |
|
|
6694 |
i -= Bias;
|
|
6695 |
#ifdef IBM
|
|
6696 |
i <<= 2;
|
|
6697 |
i += j;
|
|
6698 |
#endif
|
|
6699 |
#ifndef Sudden_Underflow
|
|
6700 |
denorm = 0;
|
|
6701 |
}
|
|
6702 |
else {
|
|
6703 |
/* d is denormalized */
|
|
6704 |
|
|
6705 |
i = bbits + be + (Bias + (P-1) - 1);
|
|
6706 |
x = i > 32 ? getWord0(d) << (64 - i) | getWord1(d) >> (i - 32)
|
|
6707 |
: getWord1(d) << (32 - i);
|
|
6708 |
d2 = x;
|
|
6709 |
setWord0(&d2, getWord0(d2) - 31*Exp_msk1); /* adjust exponent */
|
|
6710 |
i -= (Bias + (P-1) - 1) + 1;
|
|
6711 |
denorm = 1;
|
|
6712 |
}
|
|
6713 |
#endif
|
|
6714 |
ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
|
|
6715 |
k = int(ds);
|
|
6716 |
if (ds < 0. && ds != k)
|
|
6717 |
k--; /* want k = floor(ds) */
|
|
6718 |
k_check = 1;
|
|
6719 |
if (k >= 0 && k <= Ten_pmax) {
|
|
6720 |
if (d < tens[k])
|
|
6721 |
k--;
|
|
6722 |
k_check = 0;
|
|
6723 |
}
|
|
6724 |
j = bbits - i - 1;
|
|
6725 |
if (j >= 0) {
|
|
6726 |
b2 = 0;
|
|
6727 |
s2 = j;
|
|
6728 |
}
|
|
6729 |
else {
|
|
6730 |
b2 = -j;
|
|
6731 |
s2 = 0;
|
|
6732 |
}
|
|
6733 |
if (k >= 0) {
|
|
6734 |
b5 = 0;
|
|
6735 |
s5 = k;
|
|
6736 |
s2 += k;
|
|
6737 |
}
|
|
6738 |
else {
|
|
6739 |
b2 -= k;
|
|
6740 |
b5 = -k;
|
|
6741 |
s5 = 0;
|
|
6742 |
}
|
|
6743 |
if (mode < 0 || mode > 9)
|
|
6744 |
mode = 0;
|
|
6745 |
try_quick = 1;
|
|
6746 |
if (mode > 5) {
|
|
6747 |
mode -= 4;
|
|
6748 |
try_quick = 0;
|
|
6749 |
}
|
|
6750 |
leftright = 1;
|
|
6751 |
switch(mode) {
|
|
6752 |
case 0:
|
|
6753 |
case 1:
|
|
6754 |
ilim = ilim1 = -1;
|
|
6755 |
i = 18;
|
|
6756 |
ndigits = 0;
|
|
6757 |
break;
|
|
6758 |
case 2:
|
|
6759 |
leftright = 0;
|
|
6760 |
/* no break */
|
|
6761 |
case 4:
|
|
6762 |
if (ndigits <= 0)
|
|
6763 |
ndigits = 1;
|
|
6764 |
ilim = ilim1 = i = ndigits;
|
|
6765 |
break;
|
|
6766 |
case 3:
|
|
6767 |
leftright = 0;
|
|
6768 |
/* no break */
|
|
6769 |
case 5:
|
|
6770 |
i = ndigits + k + 1;
|
|
6771 |
ilim = i;
|
|
6772 |
ilim1 = i - 1;
|
|
6773 |
if (i <= 0)
|
|
6774 |
i = 1;
|
|
6775 |
}
|
|
6776 |
QT_TRY {
|
|
6777 |
*resultp = static_cast<char *>(malloc(i + 1));
|
|
6778 |
Q_CHECK_PTR(*resultp);
|
|
6779 |
} QT_CATCH(...) {
|
|
6780 |
Bfree(b);
|
|
6781 |
QT_RETHROW;
|
|
6782 |
}
|
|
6783 |
s = s0 = *resultp;
|
|
6784 |
|
|
6785 |
if (ilim >= 0 && ilim <= Quick_max && try_quick) {
|
|
6786 |
|
|
6787 |
/* Try to get by with floating-point arithmetic. */
|
|
6788 |
|
|
6789 |
i = 0;
|
|
6790 |
d2 = d;
|
|
6791 |
k0 = k;
|
|
6792 |
ilim0 = ilim;
|
|
6793 |
ieps = 2; /* conservative */
|
|
6794 |
if (k > 0) {
|
|
6795 |
ds = tens[k&0xf];
|
|
6796 |
j = k >> 4;
|
|
6797 |
if (j & Bletch) {
|
|
6798 |
/* prevent overflows */
|
|
6799 |
j &= Bletch - 1;
|
|
6800 |
d /= bigtens[n_bigtens-1];
|
|
6801 |
ieps++;
|
|
6802 |
}
|
|
6803 |
for(; j; j >>= 1, i++)
|
|
6804 |
if (j & 1) {
|
|
6805 |
ieps++;
|
|
6806 |
ds *= bigtens[i];
|
|
6807 |
}
|
|
6808 |
d /= ds;
|
|
6809 |
}
|
|
6810 |
else if ((j1 = -k) != 0) {
|
|
6811 |
d *= tens[j1 & 0xf];
|
|
6812 |
for(j = j1 >> 4; j; j >>= 1, i++)
|
|
6813 |
if (j & 1) {
|
|
6814 |
ieps++;
|
|
6815 |
d *= bigtens[i];
|
|
6816 |
}
|
|
6817 |
}
|
|
6818 |
if (k_check && d < 1. && ilim > 0) {
|
|
6819 |
if (ilim1 <= 0)
|
|
6820 |
goto fast_failed;
|
|
6821 |
ilim = ilim1;
|
|
6822 |
k--;
|
|
6823 |
d *= 10.;
|
|
6824 |
ieps++;
|
|
6825 |
}
|
|
6826 |
eps = ieps*d + 7.;
|
|
6827 |
setWord0(&eps, getWord0(eps) - (P-1)*Exp_msk1);
|
|
6828 |
if (ilim == 0) {
|
|
6829 |
S = mhi = 0;
|
|
6830 |
d -= 5.;
|
|
6831 |
if (d > eps)
|
|
6832 |
goto one_digit;
|
|
6833 |
if (d < -eps)
|
|
6834 |
goto no_digits;
|
|
6835 |
goto fast_failed;
|
|
6836 |
}
|
|
6837 |
#ifndef No_leftright
|
|
6838 |
if (leftright) {
|
|
6839 |
/* Use Steele & White method of only
|
|
6840 |
* generating digits needed.
|
|
6841 |
*/
|
|
6842 |
eps = 0.5/tens[ilim-1] - eps;
|
|
6843 |
for(i = 0;;) {
|
|
6844 |
L = Long(d);
|
|
6845 |
d -= L;
|
|
6846 |
*s++ = '0' + int(L);
|
|
6847 |
if (d < eps)
|
|
6848 |
goto ret1;
|
|
6849 |
if (1. - d < eps)
|
|
6850 |
goto bump_up;
|
|
6851 |
if (++i >= ilim)
|
|
6852 |
break;
|
|
6853 |
eps *= 10.;
|
|
6854 |
d *= 10.;
|
|
6855 |
}
|
|
6856 |
}
|
|
6857 |
else {
|
|
6858 |
#endif
|
|
6859 |
/* Generate ilim digits, then fix them up. */
|
|
6860 |
#if defined(Q_OS_IRIX) && defined(Q_CC_GNU)
|
|
6861 |
// work around a bug on 64 bit IRIX gcc
|
|
6862 |
double *t = (double *) tens;
|
|
6863 |
eps *= t[ilim-1];
|
|
6864 |
#else
|
|
6865 |
eps *= tens[ilim-1];
|
|
6866 |
#endif
|
|
6867 |
for(i = 1;; i++, d *= 10.) {
|
|
6868 |
L = Long(d);
|
|
6869 |
d -= L;
|
|
6870 |
*s++ = '0' + int(L);
|
|
6871 |
if (i == ilim) {
|
|
6872 |
if (d > 0.5 + eps)
|
|
6873 |
goto bump_up;
|
|
6874 |
else if (d < 0.5 - eps) {
|
|
6875 |
while(*--s == '0') {}
|
|
6876 |
s++;
|
|
6877 |
goto ret1;
|
|
6878 |
}
|
|
6879 |
break;
|
|
6880 |
}
|
|
6881 |
}
|
|
6882 |
#ifndef No_leftright
|
|
6883 |
}
|
|
6884 |
#endif
|
|
6885 |
fast_failed:
|
|
6886 |
s = s0;
|
|
6887 |
d = d2;
|
|
6888 |
k = k0;
|
|
6889 |
ilim = ilim0;
|
|
6890 |
}
|
|
6891 |
|
|
6892 |
/* Do we have a "small" integer? */
|
|
6893 |
|
|
6894 |
if (be >= 0 && k <= Int_max) {
|
|
6895 |
/* Yes. */
|
|
6896 |
ds = tens[k];
|
|
6897 |
if (ndigits < 0 && ilim <= 0) {
|
|
6898 |
S = mhi = 0;
|
|
6899 |
if (ilim < 0 || d <= 5*ds)
|
|
6900 |
goto no_digits;
|
|
6901 |
goto one_digit;
|
|
6902 |
}
|
|
6903 |
for(i = 1;; i++) {
|
|
6904 |
L = Long(d / ds);
|
|
6905 |
d -= L*ds;
|
|
6906 |
#ifdef Check_FLT_ROUNDS
|
|
6907 |
/* If FLT_ROUNDS == 2, L will usually be high by 1 */
|
|
6908 |
if (d < 0) {
|
|
6909 |
L--;
|
|
6910 |
d += ds;
|
|
6911 |
}
|
|
6912 |
#endif
|
|
6913 |
*s++ = '0' + int(L);
|
|
6914 |
if (i == ilim) {
|
|
6915 |
d += d;
|
|
6916 |
if (d > ds || (d == ds && L & 1)) {
|
|
6917 |
bump_up:
|
|
6918 |
while(*--s == '9')
|
|
6919 |
if (s == s0) {
|
|
6920 |
k++;
|
|
6921 |
*s = '0';
|
|
6922 |
break;
|
|
6923 |
}
|
|
6924 |
++*s++;
|
|
6925 |
}
|
|
6926 |
break;
|
|
6927 |
}
|
|
6928 |
if ((d *= 10.) == g_double_zero)
|
|
6929 |
break;
|
|
6930 |
}
|
|
6931 |
goto ret1;
|
|
6932 |
}
|
|
6933 |
|
|
6934 |
m2 = b2;
|
|
6935 |
m5 = b5;
|
|
6936 |
mhi = mlo = 0;
|
|
6937 |
if (leftright) {
|
|
6938 |
if (mode < 2) {
|
|
6939 |
i =
|
|
6940 |
#ifndef Sudden_Underflow
|
|
6941 |
denorm ? be + (Bias + (P-1) - 1 + 1) :
|
|
6942 |
#endif
|
|
6943 |
#ifdef IBM
|
|
6944 |
1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
|
|
6945 |
#else
|
|
6946 |
1 + P - bbits;
|
|
6947 |
#endif
|
|
6948 |
}
|
|
6949 |
else {
|
|
6950 |
j = ilim - 1;
|
|
6951 |
if (m5 >= j)
|
|
6952 |
m5 -= j;
|
|
6953 |
else {
|
|
6954 |
s5 += j -= m5;
|
|
6955 |
b5 += j;
|
|
6956 |
m5 = 0;
|
|
6957 |
}
|
|
6958 |
if ((i = ilim) < 0) {
|
|
6959 |
m2 -= i;
|
|
6960 |
i = 0;
|
|
6961 |
}
|
|
6962 |
}
|
|
6963 |
b2 += i;
|
|
6964 |
s2 += i;
|
|
6965 |
mhi = i2b(1);
|
|
6966 |
}
|
|
6967 |
if (m2 > 0 && s2 > 0) {
|
|
6968 |
i = m2 < s2 ? m2 : s2;
|
|
6969 |
b2 -= i;
|
|
6970 |
m2 -= i;
|
|
6971 |
s2 -= i;
|
|
6972 |
}
|
|
6973 |
if (b5 > 0) {
|
|
6974 |
if (leftright) {
|
|
6975 |
if (m5 > 0) {
|
|
6976 |
mhi = pow5mult(mhi, m5);
|
|
6977 |
b1 = mult(mhi, b);
|
|
6978 |
Bfree(b);
|
|
6979 |
b = b1;
|
|
6980 |
}
|
|
6981 |
if ((j = b5 - m5) != 0)
|
|
6982 |
b = pow5mult(b, j);
|
|
6983 |
}
|
|
6984 |
else
|
|
6985 |
b = pow5mult(b, b5);
|
|
6986 |
}
|
|
6987 |
S = i2b(1);
|
|
6988 |
if (s5 > 0)
|
|
6989 |
S = pow5mult(S, s5);
|
|
6990 |
|
|
6991 |
/* Check for special case that d is a normalized power of 2. */
|
|
6992 |
|
|
6993 |
if (mode < 2) {
|
|
6994 |
if (!getWord1(d) && !(getWord0(d) & Bndry_mask)
|
|
6995 |
#ifndef Sudden_Underflow
|
|
6996 |
&& getWord0(d) & Exp_mask
|
|
6997 |
#endif
|
|
6998 |
) {
|
|
6999 |
/* The special case */
|
|
7000 |
b2 += Log2P;
|
|
7001 |
s2 += Log2P;
|
|
7002 |
spec_case = 1;
|
|
7003 |
}
|
|
7004 |
else
|
|
7005 |
spec_case = 0;
|
|
7006 |
}
|
|
7007 |
|
|
7008 |
/* Arrange for convenient computation of quotients:
|
|
7009 |
* shift left if necessary so divisor has 4 leading 0 bits.
|
|
7010 |
*
|
|
7011 |
* Perhaps we should just compute leading 28 bits of S once
|
|
7012 |
* and for all and pass them and a shift to quorem, so it
|
|
7013 |
* can do shifts and ors to compute the numerator for q.
|
|
7014 |
*/
|
|
7015 |
#ifdef Pack_32
|
|
7016 |
if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) != 0)
|
|
7017 |
i = 32 - i;
|
|
7018 |
#else
|
|
7019 |
if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
|
|
7020 |
i = 16 - i;
|
|
7021 |
#endif
|
|
7022 |
if (i > 4) {
|
|
7023 |
i -= 4;
|
|
7024 |
b2 += i;
|
|
7025 |
m2 += i;
|
|
7026 |
s2 += i;
|
|
7027 |
}
|
|
7028 |
else if (i < 4) {
|
|
7029 |
i += 28;
|
|
7030 |
b2 += i;
|
|
7031 |
m2 += i;
|
|
7032 |
s2 += i;
|
|
7033 |
}
|
|
7034 |
if (b2 > 0)
|
|
7035 |
b = lshift(b, b2);
|
|
7036 |
if (s2 > 0)
|
|
7037 |
S = lshift(S, s2);
|
|
7038 |
if (k_check) {
|
|
7039 |
if (cmp(b,S) < 0) {
|
|
7040 |
k--;
|
|
7041 |
b = multadd(b, 10, 0); /* we botched the k estimate */
|
|
7042 |
if (leftright)
|
|
7043 |
mhi = multadd(mhi, 10, 0);
|
|
7044 |
ilim = ilim1;
|
|
7045 |
}
|
|
7046 |
}
|
|
7047 |
if (ilim <= 0 && mode > 2) {
|
|
7048 |
if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
|
|
7049 |
/* no digits, fcvt style */
|
|
7050 |
no_digits:
|
|
7051 |
k = -1 - ndigits;
|
|
7052 |
goto ret;
|
|
7053 |
}
|
|
7054 |
one_digit:
|
|
7055 |
*s++ = '1';
|
|
7056 |
k++;
|
|
7057 |
goto ret;
|
|
7058 |
}
|
|
7059 |
if (leftright) {
|
|
7060 |
if (m2 > 0)
|
|
7061 |
mhi = lshift(mhi, m2);
|
|
7062 |
|
|
7063 |
/* Compute mlo -- check for special case
|
|
7064 |
* that d is a normalized power of 2.
|
|
7065 |
*/
|
|
7066 |
|
|
7067 |
mlo = mhi;
|
|
7068 |
if (spec_case) {
|
|
7069 |
mhi = Balloc(mhi->k);
|
|
7070 |
Bcopy(mhi, mlo);
|
|
7071 |
mhi = lshift(mhi, Log2P);
|
|
7072 |
}
|
|
7073 |
|
|
7074 |
for(i = 1;;i++) {
|
|
7075 |
dig = quorem(b,S) + '0';
|
|
7076 |
/* Do we yet have the shortest decimal string
|
|
7077 |
* that will round to d?
|
|
7078 |
*/
|
|
7079 |
j = cmp(b, mlo);
|
|
7080 |
delta = diff(S, mhi);
|
|
7081 |
j1 = delta->sign ? 1 : cmp(b, delta);
|
|
7082 |
Bfree(delta);
|
|
7083 |
#ifndef ROUND_BIASED
|
|
7084 |
if (j1 == 0 && !mode && !(getWord1(d) & 1)) {
|
|
7085 |
if (dig == '9')
|
|
7086 |
goto round_9_up;
|
|
7087 |
if (j > 0)
|
|
7088 |
dig++;
|
|
7089 |
*s++ = dig;
|
|
7090 |
goto ret;
|
|
7091 |
}
|
|
7092 |
#endif
|
|
7093 |
if (j < 0 || (j == 0 && !mode
|
|
7094 |
#ifndef ROUND_BIASED
|
|
7095 |
&& !(getWord1(d) & 1)
|
|
7096 |
#endif
|
|
7097 |
)) {
|
|
7098 |
if (j1 > 0) {
|
|
7099 |
b = lshift(b, 1);
|
|
7100 |
j1 = cmp(b, S);
|
|
7101 |
if ((j1 > 0 || (j1 == 0 && dig & 1))
|
|
7102 |
&& dig++ == '9')
|
|
7103 |
goto round_9_up;
|
|
7104 |
}
|
|
7105 |
*s++ = dig;
|
|
7106 |
goto ret;
|
|
7107 |
}
|
|
7108 |
if (j1 > 0) {
|
|
7109 |
if (dig == '9') { /* possible if i == 1 */
|
|
7110 |
round_9_up:
|
|
7111 |
*s++ = '9';
|
|
7112 |
goto roundoff;
|
|
7113 |
}
|
|
7114 |
*s++ = dig + 1;
|
|
7115 |
goto ret;
|
|
7116 |
}
|
|
7117 |
*s++ = dig;
|
|
7118 |
if (i == ilim)
|
|
7119 |
break;
|
|
7120 |
b = multadd(b, 10, 0);
|
|
7121 |
if (mlo == mhi)
|
|
7122 |
mlo = mhi = multadd(mhi, 10, 0);
|
|
7123 |
else {
|
|
7124 |
mlo = multadd(mlo, 10, 0);
|
|
7125 |
mhi = multadd(mhi, 10, 0);
|
|
7126 |
}
|
|
7127 |
}
|
|
7128 |
}
|
|
7129 |
else
|
|
7130 |
for(i = 1;; i++) {
|
|
7131 |
*s++ = dig = quorem(b,S) + '0';
|
|
7132 |
if (i >= ilim)
|
|
7133 |
break;
|
|
7134 |
b = multadd(b, 10, 0);
|
|
7135 |
}
|
|
7136 |
|
|
7137 |
/* Round off last digit */
|
|
7138 |
|
|
7139 |
b = lshift(b, 1);
|
|
7140 |
j = cmp(b, S);
|
|
7141 |
if (j > 0 || (j == 0 && dig & 1)) {
|
|
7142 |
roundoff:
|
|
7143 |
while(*--s == '9')
|
|
7144 |
if (s == s0) {
|
|
7145 |
k++;
|
|
7146 |
*s++ = '1';
|
|
7147 |
goto ret;
|
|
7148 |
}
|
|
7149 |
++*s++;
|
|
7150 |
}
|
|
7151 |
else {
|
|
7152 |
while(*--s == '0') {}
|
|
7153 |
s++;
|
|
7154 |
}
|
|
7155 |
ret:
|
|
7156 |
Bfree(S);
|
|
7157 |
if (mhi) {
|
|
7158 |
if (mlo && mlo != mhi)
|
|
7159 |
Bfree(mlo);
|
|
7160 |
Bfree(mhi);
|
|
7161 |
}
|
|
7162 |
ret1:
|
|
7163 |
Bfree(b);
|
|
7164 |
if (s == s0) { /* don't return empty string */
|
|
7165 |
*s++ = '0';
|
|
7166 |
k = 0;
|
|
7167 |
}
|
|
7168 |
*s = 0;
|
|
7169 |
*decpt = k + 1;
|
|
7170 |
if (rve)
|
|
7171 |
*rve = s;
|
|
7172 |
return s0;
|
|
7173 |
}
|
|
7174 |
#else
|
|
7175 |
// NOT thread safe!
|
|
7176 |
|
|
7177 |
#include <errno.h>
|
|
7178 |
|
|
7179 |
Q_CORE_EXPORT char *qdtoa( double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **resultp)
|
|
7180 |
{
|
|
7181 |
if(rve)
|
|
7182 |
*rve = 0;
|
|
7183 |
|
|
7184 |
char *res;
|
|
7185 |
if (mode == 0)
|
|
7186 |
ndigits = 80;
|
|
7187 |
|
|
7188 |
if (mode == 3)
|
|
7189 |
res = fcvt(d, ndigits, decpt, sign);
|
|
7190 |
else
|
|
7191 |
res = ecvt(d, ndigits, decpt, sign);
|
|
7192 |
|
|
7193 |
int n = qstrlen(res);
|
|
7194 |
if (mode == 0) { // remove trailing 0's
|
|
7195 |
const int stop = qMax(1, *decpt);
|
|
7196 |
int i;
|
|
7197 |
for (i = n-1; i >= stop; --i) {
|
|
7198 |
if (res[i] != '0')
|
|
7199 |
break;
|
|
7200 |
}
|
|
7201 |
n = i + 1;
|
|
7202 |
}
|
|
7203 |
*resultp = static_cast<char*>(malloc(n + 1));
|
|
7204 |
Q_CHECK_PTR(resultp);
|
|
7205 |
qstrncpy(*resultp, res, n + 1);
|
|
7206 |
return *resultp;
|
|
7207 |
}
|
|
7208 |
|
|
7209 |
Q_CORE_EXPORT double qstrtod(const char *s00, const char **se, bool *ok)
|
|
7210 |
{
|
|
7211 |
double ret = strtod((char*)s00, (char**)se);
|
|
7212 |
if (ok) {
|
|
7213 |
if((ret == 0.0l && errno == ERANGE)
|
|
7214 |
|| ret == HUGE_VAL || ret == -HUGE_VAL)
|
|
7215 |
*ok = false;
|
|
7216 |
else
|
|
7217 |
*ok = true; // the result will be that we don't report underflow in this case
|
|
7218 |
}
|
|
7219 |
return ret;
|
|
7220 |
}
|
|
7221 |
#endif // QT_QLOCALE_USES_FCVT
|
|
7222 |
|
|
7223 |
QT_END_NAMESPACE
|