summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2014-02-03 18:06:46 -0800
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-14 00:34:25 +0100
commit3c15118fa38aaec13125ff82f9cfeabfdd57fd21 (patch)
tree6308526095b08d1f7108c4b8eeb47064ea25dc85 /src
parented7458a8a66416c106ad33871a288091058d01ea (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/tools/qlocale.cpp59
-rw-r--r--src/corelib/tools/qlocale_tools.cpp74
-rw-r--r--src/corelib/tools/qlocale_tools_p.h3
3 files changed, 52 insertions, 84 deletions
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index ace22272ec..f3c492574e 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -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;
}
- result->append('\0');
-
- // Check separators
- if (group_sep_mode == ParseGroupSeparators
- && !removeGroupSeparators(result))
- return false;
-
+ 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');
return idx == l;
}
diff --git a/src/corelib/tools/qlocale_tools.cpp b/src/corelib/tools/qlocale_tools.cpp
index 8a5c4420dc..c2bae3df9d 100644
--- a/src/corelib/tools/qlocale_tools.cpp
+++ b/src/corelib/tools/qlocale_tools.cpp
@@ -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.
diff --git a/src/corelib/tools/qlocale_tools_p.h b/src/corelib/tools/qlocale_tools_p.h
index ee66b27eb8..41183560b9 100644
--- a/src/corelib/tools/qlocale_tools_p.h
+++ b/src/corelib/tools/qlocale_tools_p.h
@@ -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);