QLocalePrivate: merge removeGroupSeparators into numberToCLocale
This version will parse the string only once and will not do any memmove. This is more efficient. Change-Id: I59026ad0fa61cc3f16146bdcd622fc54cbd8a321 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
parent
ed7458a8a6
commit
3c15118fa3
@ -3111,6 +3111,11 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len,
|
||||
break;
|
||||
}
|
||||
|
||||
int group_cnt = 0; // counts number of group chars
|
||||
int decpt_idx = -1;
|
||||
int last_separator_idx = -1;
|
||||
int start_of_digits_idx = -1;
|
||||
|
||||
while (idx < l) {
|
||||
const QChar in = uc[idx];
|
||||
|
||||
@ -3128,20 +3133,60 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len,
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (group_sep_mode == ParseGroupSeparators) {
|
||||
if (start_of_digits_idx == -1 && out >= '0' && out <= '9') {
|
||||
start_of_digits_idx = idx;
|
||||
} else if (out == ',') {
|
||||
// Don't allow group chars after the decimal point
|
||||
if (decpt_idx != -1)
|
||||
return false;
|
||||
|
||||
// check distance from the last separator or from the beginning of the digits
|
||||
// ### FIXME: Some locales allow other groupings! See https://en.wikipedia.org/wiki/Thousands_separator
|
||||
if (last_separator_idx != -1 && idx - last_separator_idx != 4)
|
||||
return false;
|
||||
if (last_separator_idx == -1 && (start_of_digits_idx == -1 || idx - start_of_digits_idx > 3))
|
||||
return false;
|
||||
|
||||
last_separator_idx = idx;
|
||||
++group_cnt;
|
||||
|
||||
// don't add the group separator
|
||||
++idx;
|
||||
continue;
|
||||
} else if (out == '.' || out == 'e' || out == 'E') {
|
||||
// Fail if more than one decimal point
|
||||
if (out == '.' && decpt_idx != -1)
|
||||
return false;
|
||||
if (decpt_idx == -1)
|
||||
decpt_idx = idx;
|
||||
|
||||
// check distance from the last separator
|
||||
// ### FIXME: Some locales allow other groupings! See https://en.wikipedia.org/wiki/Thousands_separator
|
||||
if (last_separator_idx != -1 && idx - last_separator_idx != 4)
|
||||
return false;
|
||||
|
||||
// stop processing separators
|
||||
last_separator_idx = -1;
|
||||
}
|
||||
}
|
||||
|
||||
result->append(out);
|
||||
|
||||
++idx;
|
||||
}
|
||||
|
||||
if (group_sep_mode == ParseGroupSeparators) {
|
||||
// group separator post-processing
|
||||
// did we end in a separator?
|
||||
if (last_separator_idx + 1 == idx)
|
||||
return false;
|
||||
// were there enough digits since the last separator?
|
||||
if (last_separator_idx != -1 && idx - last_separator_idx != 4)
|
||||
return false;
|
||||
}
|
||||
|
||||
result->append('\0');
|
||||
|
||||
// Check separators
|
||||
if (group_sep_mode == ParseGroupSeparators
|
||||
&& !removeGroupSeparators(result))
|
||||
return false;
|
||||
|
||||
|
||||
return idx == l;
|
||||
}
|
||||
|
||||
|
@ -184,80 +184,6 @@ QString &exponentForm(QChar zero, QChar decimal, QChar exponential,
|
||||
return digits;
|
||||
}
|
||||
|
||||
// Removes thousand-group separators in "C" locale.
|
||||
bool removeGroupSeparators(QLocaleData::CharBuff *num)
|
||||
{
|
||||
int group_cnt = 0; // counts number of group chars
|
||||
int decpt_idx = -1;
|
||||
|
||||
char *data = num->data();
|
||||
int l = qstrlen(data);
|
||||
|
||||
// Find the decimal point and check if there are any group chars
|
||||
int i = 0;
|
||||
for (; i < l; ++i) {
|
||||
char c = data[i];
|
||||
|
||||
if (c == ',') {
|
||||
if (i == 0 || data[i - 1] < '0' || data[i - 1] > '9')
|
||||
return false;
|
||||
if (i == l - 1 || data[i + 1] < '0' || data[i + 1] > '9')
|
||||
return false;
|
||||
++group_cnt;
|
||||
}
|
||||
else if (c == '.') {
|
||||
// Fail if more than one decimal points
|
||||
if (decpt_idx != -1)
|
||||
return false;
|
||||
decpt_idx = i;
|
||||
} else if (c == 'e' || c == 'E') {
|
||||
// an 'e' or 'E' - if we have not encountered a decimal
|
||||
// point, this is where it "is".
|
||||
if (decpt_idx == -1)
|
||||
decpt_idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
// If no group chars, we're done
|
||||
if (group_cnt == 0)
|
||||
return true;
|
||||
|
||||
// No decimal point means that it "is" at the end of the string
|
||||
if (decpt_idx == -1)
|
||||
decpt_idx = l;
|
||||
|
||||
i = 0;
|
||||
while (i < l && group_cnt > 0) {
|
||||
char c = data[i];
|
||||
|
||||
if (c == ',') {
|
||||
// Don't allow group chars after the decimal point
|
||||
if (i > decpt_idx)
|
||||
return false;
|
||||
|
||||
// Check that it is placed correctly relative to the decpt
|
||||
if ((decpt_idx - i) % 4 != 0)
|
||||
return false;
|
||||
|
||||
// Remove it
|
||||
memmove(data + i, data + i + 1, l - i - 1);
|
||||
data[--l] = '\0';
|
||||
|
||||
--group_cnt;
|
||||
--decpt_idx;
|
||||
} else {
|
||||
// Check that we are not missing a separator
|
||||
if (i < decpt_idx
|
||||
&& (decpt_idx - i) % 4 == 0
|
||||
&& !(i == 0 && (c == '-' || c == '+'))) // check for negative or positive sign at start of string
|
||||
return false;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
|
@ -104,9 +104,6 @@ inline bool isZero(double d)
|
||||
}
|
||||
}
|
||||
|
||||
// Removes thousand-group separators in "C" locale.
|
||||
bool removeGroupSeparators(QLocaleData::CharBuff *num);
|
||||
|
||||
Q_CORE_EXPORT char *qdtoa(double d, int mode, int ndigits, int *decpt,
|
||||
int *sign, char **rve, char **digits_str);
|
||||
Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
|
||||
|
Loading…
Reference in New Issue
Block a user