diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2014-02-03 18:06:46 -0800 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-14 00:34:25 +0100 |
commit | 3c15118fa38aaec13125ff82f9cfeabfdd57fd21 (patch) | |
tree | 6308526095b08d1f7108c4b8eeb47064ea25dc85 /src | |
parent | ed7458a8a66416c106ad33871a288091058d01ea (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.cpp | 59 | ||||
-rw-r--r-- | src/corelib/tools/qlocale_tools.cpp | 74 | ||||
-rw-r--r-- | src/corelib/tools/qlocale_tools_p.h | 3 |
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); |