diff options
Diffstat (limited to 'src/corelib/tools')
-rw-r--r-- | src/corelib/tools/qdatetime.cpp | 114 | ||||
-rw-r--r-- | src/corelib/tools/qdatetime.h | 4 | ||||
-rw-r--r-- | src/corelib/tools/qmap.cpp | 18 | ||||
-rw-r--r-- | src/corelib/tools/qmap.h | 12 | ||||
-rw-r--r-- | src/corelib/tools/qregexp.cpp | 3 | ||||
-rw-r--r-- | src/corelib/tools/qvector.h | 6 |
6 files changed, 89 insertions, 68 deletions
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 7d18e93dce..56dc0fade9 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -93,47 +93,67 @@ static inline QDate fixedDate(int y, int m, int d) return result; } -static inline qint64 julianDayFromDate(qint64 year, int month, int day) +static inline qint64 floordiv(qint64 a, qint64 b) { - // Gregorian calendar - // Algorithm from Henry F. Fliegel and Thomas C. Van Flandern + return (a - (a < 0 ? b-1 : 0)) / b; +} +static inline qint64 floordiv(qint64 a, int b) +{ + return (a - (a < 0 ? b-1 : 0)) / b; +} + +static inline int floordiv(int a, int b) +{ + return (a - (a < 0 ? b-1 : 0)) / b; +} + +static inline qint64 julianDayFromDate(int year, int month, int day) +{ + // Adjust for no year 0 if (year < 0) ++year; - return (1461 * (year + 4800 + (month - 14) / 12)) / 4 - + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12 - - (3 * ((year + 4900 + (month - 14) / 12) / 100)) / 4 - + day - 32075; +/* + * Math from The Calendar FAQ at http://www.tondering.dk/claus/cal/julperiod.php + * This formula is correct for all julian days, when using mathematical integer + * division (round to negative infinity), not c++11 integer division (round to zero) + */ + int a = floordiv(14 - month, 12); + qint64 y = (qint64)year + 4800 - a; + int m = month + 12 * a - 3; + return day + floordiv(153 * m + 2, 5) + 365 * y + floordiv(y, 4) - floordiv(y, 100) + floordiv(y, 400) - 32045; } -static void getDateFromJulianDay(qint64 julianDay, int *year, int *month, int *day) +static void getDateFromJulianDay(qint64 julianDay, int *yearp, int *monthp, int *dayp) { - int y, m, d; +/* + * Math from The Calendar FAQ at http://www.tondering.dk/claus/cal/julperiod.php + * This formula is correct for all julian days, when using mathematical integer + * division (round to negative infinity), not c++11 integer division (round to zero) + */ + qint64 a = julianDay + 32044; + qint64 b = floordiv(4 * a + 3, 146097); + int c = a - floordiv(146097 * b, 4); - // Gregorian calendar - // This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern - qint64 ell, n, i, j; //TODO These will need to be bigger to prevent overflow!!! - ell = julianDay + 68569; - n = (4 * ell) / 146097; - ell = ell - (146097 * n + 3) / 4; - i = (4000 * (ell + 1)) / 1461001; - ell = ell - (1461 * i) / 4 + 31; - j = (80 * ell) / 2447; - d = ell - (2447 * j) / 80; - ell = j / 11; - m = j + 2 - (12 * ell); - y = 100 * (n - 49) + i + ell; + int d = floordiv(4 * c + 3, 1461); + int e = c - floordiv(1461 * d, 4); + int m = floordiv(5 * e + 2, 153); - if (y<= 0) - --y; + int day = e - floordiv(153 * m + 2, 5) + 1; + int month = m + 3 - 12 * floordiv(m, 10); + int year = 100 * b + d - 4800 + floordiv(m, 10); - if (year) - *year = y; - if (month) - *month = m; - if (day) - *day = d; + // Adjust for no year 0 + if (year <= 0) + --year ; + + if (yearp) + *yearp = year; + if (monthp) + *monthp = month; + if (dayp) + *dayp = day; } @@ -225,14 +245,8 @@ static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* d QDate::toJulianDay() and can be set using QDate::fromJulianDay(). The range of dates able to be stored by QDate as a Julian Day number is - limited for convenience from std::numeric_limits<qint64>::min() / 2 to - std::numeric_limits<qint64>::max() / 2, which on most platforms means - from around 2.5 quadrillion BCE to around 2.5 quadrillion CE, effectively - covering the full range of astronomical time. The range of Julian Days - able to be accurately converted to and from valid YMD form Dates is - restricted to 1 January 4800 BCE to 31 December 1400000 CE due to - shortcomings in the available conversion formulas. Conversions outside this - range are not guaranteed to be correct. This may change in the future. + for technical reasons limited to between -784350574879 and 784354017364, + which means from before 2 billion BCE to after 2 billion CE. \sa QTime, QDateTime, QDateEdit, QDateTimeEdit, QCalendarWidget */ @@ -859,9 +873,6 @@ QString QDate::toString(const QString& format) const If the specified date is invalid, the QDate object is set to be invalid. - Note that any date before 4800 BCE or after about 1.4 million CE - may not be accurately stored. - \sa isValid() */ bool QDate::setDate(int year, int month, int day) @@ -882,9 +893,6 @@ bool QDate::setDate(int year, int month, int day) Returns 0 if the date is invalid. - Note that any date before 4800 BCE or after about 1.4 million CE - may not be accurately stored. - \sa year(), month(), day(), isValid() */ void QDate::getDate(int *year, int *month, int *day) @@ -2100,14 +2108,8 @@ int QTime::elapsed() const QDate::toJulianDay() and can be set using QDate::fromJulianDay(). The range of dates able to be stored by QDate as a Julian Day number is - limited for convenience from std::numeric_limits<qint64>::min() / 2 to - std::numeric_limits<qint64>::max() / 2, which on most platforms means - from around 2.5 quadrillion BCE to around 2.5 quadrillion CE, effectively - covering the full range of astronomical time. The range of Julian Days - able to be accurately converted to and from valid YMD form Dates is - restricted to 1 January 4800 BCE to 31 December 1400000 CE due to - shortcomings in the available conversion formulas. Conversions outside this - range are not guaranteed to be correct. This may change in the future. + for technical reasons limited to between -784350574879 and 784354017364, + which means from before 2 billion BCE to after 2 billion CE. \section2 Use of System Timezone @@ -2418,7 +2420,7 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs) QDateTimePrivate::Spec oldSpec = d->spec; - int ddays = msecs / MSECS_PER_DAY; + qint64 ddays = msecs / MSECS_PER_DAY; msecs %= MSECS_PER_DAY; if (msecs < 0) { // negative @@ -3391,10 +3393,11 @@ QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f) int year; QStringList timeParts = parts.at(3).split(QLatin1Char(':')); if ((timeParts.count() == 3) || (timeParts.count() == 2)) { + // Year is after time, e.g. "Sun Dec 1 13:02:00 1974" year = parts.at(4).toInt(&ok); if (!ok) return QDateTime(); - } else { + } else { // Year is before time, e.g. "Sun Dec 1 1974 13:02:00" timeParts = parts.at(4).split(QLatin1Char(':')); if ((timeParts.count() != 3) && (timeParts.count() != 2)) return QDateTime(); @@ -3743,7 +3746,8 @@ static bool hasUnquotedAP(const QString &f) for (int i=0; i<max; ++i) { if (f.at(i) == quote) { inquote = !inquote; - } else if (!inquote && f.at(i).toUpper() == QLatin1Char('A')) { + } else if (!inquote && f.at(i).toUpper() == QLatin1Char('A') + && i + 1 < max && f.at(i + 1).toUpper() == QLatin1Char('P')) { return true; } } diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h index ed7d8adb5f..22db5a4830 100644 --- a/src/corelib/tools/qdatetime.h +++ b/src/corelib/tools/qdatetime.h @@ -121,8 +121,8 @@ QT_DEPRECATED inline bool setYMD(int y, int m, int d) private: static inline qint64 nullJd() { return std::numeric_limits<qint64>::min(); } - static inline qint64 minJd() { return std::numeric_limits<qint64>::min() / 2; } - static inline qint64 maxJd() { return (std::numeric_limits<qint64>::max()) / 2; } + static inline qint64 minJd() { return Q_INT64_C(-784350574879); } + static inline qint64 maxJd() { return Q_INT64_C( 784354017364); } qint64 jd; diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp index dea87c6b63..7c33d60750 100644 --- a/src/corelib/tools/qmap.cpp +++ b/src/corelib/tools/qmap.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE -const QMapDataBase QMapDataBase::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, { 0, 0, 0 } }; +const QMapDataBase QMapDataBase::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, { 0, 0, 0 }, 0 }; const QMapNodeBase *QMapNodeBase::nextNode() const { @@ -177,6 +177,12 @@ void QMapDataBase::freeNodeAndRebalance(QMapNodeBase *z) QMapNodeBase *x_parent; if (y->left == 0) { x = y->right; + if (y == mostLeftNode) { + if (x) + mostLeftNode = x; // It cannot have (left) children due the red black invariant. + else + mostLeftNode = y->parent(); + } } else { if (y->right == 0) { x = y->left; @@ -290,6 +296,13 @@ void QMapDataBase::freeNodeAndRebalance(QMapNodeBase *z) --size; } +void QMapDataBase::recalcMostLeftNode() +{ + mostLeftNode = &header; + while (mostLeftNode->left) + mostLeftNode = mostLeftNode->left; +} + static inline int qMapAlignmentThreshold() { // malloc on 32-bit platforms should return pointers that are 8-byte @@ -324,6 +337,8 @@ QMapNodeBase *QMapDataBase::createNode(int alloc, int alignment, QMapNodeBase *p if (parent) { if (left) { parent->left = node; + if (parent == mostLeftNode) + mostLeftNode = node; } else { parent->right = node; } @@ -352,6 +367,7 @@ QMapDataBase *QMapDataBase::createData() d->header.p = 0; d->header.left = 0; d->header.right = 0; + d->mostLeftNode = &(d->header); return d; } diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index 642cf82f08..d44a79473d 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -173,11 +173,13 @@ struct Q_CORE_EXPORT QMapDataBase QtPrivate::RefCount ref; int size; QMapNodeBase header; + QMapNodeBase *mostLeftNode; void rotateLeft(QMapNodeBase *x); void rotateRight(QMapNodeBase *x); void rebalance(QMapNodeBase *x); void freeNodeAndRebalance(QMapNodeBase *z); + void recalcMostLeftNode(); QMapNodeBase *createNode(int size, int alignment, QMapNodeBase *parent, bool left); void freeTree(QMapNodeBase *root, int alignment); @@ -197,8 +199,8 @@ struct QMapData : public QMapDataBase const Node *end() const { return static_cast<const Node *>(&header); } Node *end() { return static_cast<Node *>(&header); } - const Node *begin() const { if (root()) return root()->minimumNode(); return end(); } - Node *begin() { if (root()) return root()->minimumNode(); return end(); } + const Node *begin() const { if (root()) return static_cast<const Node*>(mostLeftNode); return end(); } + Node *begin() { if (root()) return static_cast<Node*>(mostLeftNode); return end(); } void deleteNode(Node *z); Node *findNode(const Key &akey) const; @@ -555,6 +557,7 @@ inline QMap<Key, T>::QMap(const QMap<Key, T> &other) if (other.d->header.left) { d->header.left = static_cast<Node *>(other.d->header.left)->copy(d); d->header.left->setParent(&d->header); + d->recalcMostLeftNode(); } } } @@ -780,6 +783,7 @@ Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::detach_helper() if (!d->ref.deref()) d->destroy(); d = x; + d->recalcMostLeftNode(); } template <class Key, class T> @@ -935,7 +939,7 @@ Q_OUTOFLINE_TEMPLATE QMap<Key, T>::QMap(const std::map<Key, T> &other) typename std::map<Key,T>::const_iterator it = other.end(); while (it != other.begin()) { --it; - insert((*it).first, (*it).second); + d->createNode((*it).first, (*it).second, d->begin(), true); // insert on most left node. } } @@ -946,7 +950,7 @@ Q_OUTOFLINE_TEMPLATE std::map<Key, T> QMap<Key, T>::toStdMap() const const_iterator it = end(); while (it != begin()) { --it; - map.insert(std::pair<Key, T>(it.key(), it.value())); + map.insert(map.begin(), std::pair<Key, T>(it.key(), it.value())); } return map; } diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index e87e5efc1f..7aea083788 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -1324,14 +1324,11 @@ Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &pattern, QRegExp::Pat #ifndef QT_NO_REGEXP_WILDCARD case QRegExp::Wildcard: return wc2rx(pattern, false); - break; case QRegExp::WildcardUnix: return wc2rx(pattern, true); - break; #endif case QRegExp::FixedString: return QRegExp::escape(pattern); - break; case QRegExp::W3CXmlSchema11: default: return pattern; diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 94733f77da..2c688db507 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -252,7 +252,7 @@ void QVector<T>::defaultConstruct(T *from, T *to) new (from++) T(); } } else { - ::memset(from, 0, (to - from) * sizeof(T)); + ::memset(static_cast<void *>(from), 0, (to - from) * sizeof(T)); } } @@ -267,7 +267,7 @@ void QVector<T>::copyConstruct(const T *srcFrom, const T *srcTo, T *dstFrom) while (srcFrom != srcTo) new (dstFrom++) T(*srcFrom++); } else { - ::memcpy(dstFrom, srcFrom, (srcTo - srcFrom) * sizeof(T)); + ::memcpy(static_cast<void *>(dstFrom), static_cast<const void *>(srcFrom), (srcTo - srcFrom) * sizeof(T)); } } @@ -467,7 +467,7 @@ void QVector<T>::reallocData(const int asize, const int aalloc, QArrayData::Allo new (dst++) T(*srcBegin++); } } else { - ::memcpy(static_cast<void *>(dst), srcBegin, (srcEnd - srcBegin) * sizeof(T)); + ::memcpy(static_cast<void *>(dst), static_cast<void *>(srcBegin), (srcEnd - srcBegin) * sizeof(T)); dst += srcEnd - srcBegin; // destruct unused / not moved data |