diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:18:55 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:18:55 (GMT) |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/corelib/tools | |
download | Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2 |
Long live Qt 4.5!
Diffstat (limited to 'src/corelib/tools')
73 files changed, 77103 insertions, 0 deletions
diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h new file mode 100644 index 0000000..3bfa6ad --- /dev/null +++ b/src/corelib/tools/qalgorithms.h @@ -0,0 +1,565 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QALGORITHMS_H +#define QALGORITHMS_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +/* + Warning: The contents of QAlgorithmsPrivate is not a part of the public Qt API + and may be changed from version to version or even be completely removed. +*/ +namespace QAlgorithmsPrivate { + +template <typename RandomAccessIterator, typename T, typename LessThan> +Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan); +template <typename RandomAccessIterator, typename T> +inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy); + +template <typename RandomAccessIterator, typename T, typename LessThan> +Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan); +template <typename RandomAccessIterator, typename T> +inline void qStableSortHelper(RandomAccessIterator, RandomAccessIterator, const T &); + +template <typename RandomAccessIterator, typename T, typename LessThan> +Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); +template <typename RandomAccessIterator, typename T, typename LessThan> +Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); +template <typename RandomAccessIterator, typename T, typename LessThan> +Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan); + +} + +template <typename InputIterator, typename OutputIterator> +inline OutputIterator qCopy(InputIterator begin, InputIterator end, OutputIterator dest) +{ + while (begin != end) + *dest++ = *begin++; + return dest; +} + +template <typename BiIterator1, typename BiIterator2> +inline BiIterator2 qCopyBackward(BiIterator1 begin, BiIterator1 end, BiIterator2 dest) +{ + while (begin != end) + *--dest = *--end; + return dest; +} + +template <typename InputIterator1, typename InputIterator2> +inline bool qEqual(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2) +{ + for (; first1 != last1; ++first1, ++first2) + if (!(*first1 == *first2)) + return false; + return true; +} + +template <typename ForwardIterator, typename T> +inline void qFill(ForwardIterator first, ForwardIterator last, const T &val) +{ + for (; first != last; ++first) + *first = val; +} + +template <typename Container, typename T> +inline void qFill(Container &container, const T &val) +{ + qFill(container.begin(), container.end(), val); +} + +template <typename InputIterator, typename T> +inline InputIterator qFind(InputIterator first, InputIterator last, const T &val) +{ + while (first != last && !(*first == val)) + ++first; + return first; +} + +template <typename Container, typename T> +inline typename Container::const_iterator qFind(const Container &container, const T &val) +{ + return qFind(container.constBegin(), container.constEnd(), val); +} + +template <typename InputIterator, typename T, typename Size> +inline void qCount(InputIterator first, InputIterator last, const T &value, Size &n) +{ + for (; first != last; ++first) + if (*first == value) + ++n; +} + +template <typename Container, typename T, typename Size> +inline void qCount(const Container &container, const T &value, Size &n) +{ + qCount(container.constBegin(), container.constEnd(), value, n); +} + + +#if defined Q_CC_MSVC && _MSC_VER < 1300 +template <typename T> +inline void qSwap(T &value1, T &value2) +{ + qSwap_helper<T>(value1, value2, (T *)0); +} +#else +template <typename T> +inline void qSwap(T &value1, T &value2) +{ + T t = value1; + value1 = value2; + value2 = t; +} +#endif + +#ifdef qdoc +template <typename T> +LessThan qLess() +{ +} + +template <typename T> +LessThan qGreater() +{ +} +#else +template <typename T> +class qLess +{ +public: + inline bool operator()(const T &t1, const T &t2) const + { + return (t1 < t2); + } +}; + +template <typename T> +class qGreater +{ +public: + inline bool operator()(const T &t1, const T &t2) const + { + return (t2 < t1); + } +}; +#endif + +template <typename RandomAccessIterator> +inline void qSort(RandomAccessIterator start, RandomAccessIterator end) +{ + if (start != end) + QAlgorithmsPrivate::qSortHelper(start, end, *start); +} + +template <typename RandomAccessIterator, typename LessThan> +inline void qSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan) +{ + if (start != end) + QAlgorithmsPrivate::qSortHelper(start, end, *start, lessThan); +} + +template<typename Container> +inline void qSort(Container &c) +{ +#ifdef Q_CC_BOR + // Work around Borland 5.5 optimizer bug + c.detach(); +#endif + if (!c.empty()) + QAlgorithmsPrivate::qSortHelper(c.begin(), c.end(), *c.begin()); +} + +template <typename RandomAccessIterator> +inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end) +{ + if (start != end) + QAlgorithmsPrivate::qStableSortHelper(start, end, *start); +} + +template <typename RandomAccessIterator, typename LessThan> +inline void qStableSort(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan) +{ + if (start != end) + QAlgorithmsPrivate::qStableSortHelper(start, end, *start, lessThan); +} + +template<typename Container> +inline void qStableSort(Container &c) +{ +#ifdef Q_CC_BOR + // Work around Borland 5.5 optimizer bug + c.detach(); +#endif + if (!c.empty()) + QAlgorithmsPrivate::qStableSortHelper(c.begin(), c.end(), *c.begin()); +} + +template <typename RandomAccessIterator, typename T> +Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value) +{ + // Implementation is duplicated from QAlgorithmsPrivate to keep existing code + // compiling. We have to allow using *begin and value with different types, + // and then implementing operator< for those types. + RandomAccessIterator middle; + int n = end - begin; + int half; + + while (n > 0) { + half = n >> 1; + middle = begin + half; + if (*middle < value) { + begin = middle + 1; + n -= half + 1; + } else { + n = half; + } + } + return begin; +} + +template <typename RandomAccessIterator, typename T, typename LessThan> +Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +{ + return QAlgorithmsPrivate::qLowerBoundHelper(begin, end, value, lessThan); +} + +template <typename Container, typename T> +Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qLowerBound(const Container &container, const T &value) +{ + return QAlgorithmsPrivate::qLowerBoundHelper(container.constBegin(), container.constEnd(), value, qLess<T>()); +} + +template <typename RandomAccessIterator, typename T> +Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value) +{ + // Implementation is duplicated from QAlgorithmsPrivate. + RandomAccessIterator middle; + int n = end - begin; + int half; + + while (n > 0) { + half = n >> 1; + middle = begin + half; + if (value < *middle) { + n = half; + } else { + begin = middle + 1; + n -= half + 1; + } + } + return begin; +} + +template <typename RandomAccessIterator, typename T, typename LessThan> +Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +{ + return QAlgorithmsPrivate::qUpperBoundHelper(begin, end, value, lessThan); +} + +template <typename Container, typename T> +Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qUpperBound(const Container &container, const T &value) +{ + return QAlgorithmsPrivate::qUpperBoundHelper(container.constBegin(), container.constEnd(), value, qLess<T>()); +} + +template <typename RandomAccessIterator, typename T> +Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value) +{ + // Implementation is duplicated from QAlgorithmsPrivate. + qint64 l = 0; + qint64 r = end - begin - 1; + if (r < 0) + return end; + qint64 i = (l + r + 1) / 2; + + while (r != l) { + if (value < begin[i]) + r = i - 1; + else + l = i; + i = (l + r + 1) / 2; + } + if (begin[i] < value || value < begin[i]) + return end; + else + return begin + i; +} + +template <typename RandomAccessIterator, typename T, typename LessThan> +Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +{ + return QAlgorithmsPrivate::qBinaryFindHelper(begin, end, value, lessThan); +} + +template <typename Container, typename T> +Q_OUTOFLINE_TEMPLATE typename Container::const_iterator qBinaryFind(const Container &container, const T &value) +{ + return QAlgorithmsPrivate::qBinaryFindHelper(container.constBegin(), container.constEnd(), value, qLess<T>()); +} + +template <typename ForwardIterator> +Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end) +{ + while (begin != end) { + delete *begin; + ++begin; + } +} + +template <typename Container> +inline void qDeleteAll(const Container &c) +{ + qDeleteAll(c.begin(), c.end()); +} + +/* + Warning: The contents of QAlgorithmsPrivate is not a part of the public Qt API + and may be changed from version to version or even be completely removed. +*/ +namespace QAlgorithmsPrivate { + +template <typename RandomAccessIterator, typename T, typename LessThan> +Q_OUTOFLINE_TEMPLATE void qSortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan) +{ +top: + int span = end - start; + if (span < 2) + return; + + --end; + RandomAccessIterator low = start, high = end - 1; + RandomAccessIterator pivot = start + span / 2; + + if (lessThan(*end, *start)) + qSwap(*end, *start); + if (span == 2) + return; + + if (lessThan(*pivot, *start)) + qSwap(*pivot, *start); + if (lessThan(*end, *pivot)) + qSwap(*end, *pivot); + if (span == 3) + return; + + qSwap(*pivot, *end); + + while (low < high) { + while (low < high && lessThan(*low, *end)) + ++low; + + while (high > low && lessThan(*end, *high)) + --high; + + if (low < high) { + qSwap(*low, *high); + ++low; + --high; + } else { + break; + } + } + + if (lessThan(*low, *end)) + ++low; + + qSwap(*end, *low); + qSortHelper(start, low, t, lessThan); + + start = low + 1; + ++end; + goto top; +} + +template <typename RandomAccessIterator, typename T> +inline void qSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy) +{ + qSortHelper(begin, end, dummy, qLess<T>()); +} + +template <typename RandomAccessIterator> +Q_OUTOFLINE_TEMPLATE void qReverse(RandomAccessIterator begin, RandomAccessIterator end) +{ + --end; + while (begin < end) + qSwap(*begin++, *end--); +} + +template <typename RandomAccessIterator> +Q_OUTOFLINE_TEMPLATE void qRotate(RandomAccessIterator begin, RandomAccessIterator middle, RandomAccessIterator end) +{ + qReverse(begin, middle); + qReverse(middle, end); + qReverse(begin, end); +} + +template <typename RandomAccessIterator, typename T, typename LessThan> +Q_OUTOFLINE_TEMPLATE void qMerge(RandomAccessIterator begin, RandomAccessIterator pivot, RandomAccessIterator end, T &t, LessThan lessThan) +{ + const int len1 = pivot - begin; + const int len2 = end - pivot; + + if (len1 == 0 || len2 == 0) + return; + + if (len1 + len2 == 2) { + if (lessThan(*(begin + 1), *(begin))) + qSwap(*begin, *(begin + 1)); + return; + } + + RandomAccessIterator firstCut; + RandomAccessIterator secondCut; + int len2Half; + if (len1 > len2) { + const int len1Half = len1 / 2; + firstCut = begin + len1Half; + secondCut = qLowerBound(pivot, end, *firstCut, lessThan); + len2Half = secondCut - pivot; + } else { + len2Half = len2 / 2; + secondCut = pivot + len2Half; + firstCut = qUpperBound(begin, pivot, *secondCut, lessThan); + } + + qRotate(firstCut, pivot, secondCut); + const RandomAccessIterator newPivot = firstCut + len2Half; + qMerge(begin, firstCut, newPivot, t, lessThan); + qMerge(newPivot, secondCut, end, t, lessThan); +} + +template <typename RandomAccessIterator, typename T, typename LessThan> +Q_OUTOFLINE_TEMPLATE void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &t, LessThan lessThan) +{ + const int span = end - begin; + if (span < 2) + return; + + const RandomAccessIterator middle = begin + span / 2; + qStableSortHelper(begin, middle, t, lessThan); + qStableSortHelper(middle, end, t, lessThan); + qMerge(begin, middle, end, t, lessThan); +} + +template <typename RandomAccessIterator, typename T> +inline void qStableSortHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &dummy) +{ + qStableSortHelper(begin, end, dummy, qLess<T>()); +} + +template <typename RandomAccessIterator, typename T, typename LessThan> +Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +{ + RandomAccessIterator middle; + int n = end - begin; + int half; + + while (n > 0) { + half = n >> 1; + middle = begin + half; + if (lessThan(*middle, value)) { + begin = middle + 1; + n -= half + 1; + } else { + n = half; + } + } + return begin; +} + + +template <typename RandomAccessIterator, typename T, typename LessThan> +Q_OUTOFLINE_TEMPLATE RandomAccessIterator qUpperBoundHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +{ + RandomAccessIterator middle; + int n = end - begin; + int half; + + while (n > 0) { + half = n >> 1; + middle = begin + half; + if (lessThan(value, *middle)) { + n = half; + } else { + begin = middle + 1; + n -= half + 1; + } + } + return begin; +} + +template <typename RandomAccessIterator, typename T, typename LessThan> +Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFindHelper(RandomAccessIterator begin, RandomAccessIterator end, const T &value, LessThan lessThan) +{ + qint64 l = 0; + qint64 r = end - begin - 1; + if (r < 0) + return end; + qint64 i = (l + r + 1) / 2; + + while (r != l) { + if (lessThan(value, begin[i])) + r = i - 1; + else + l = i; + i = (l + r + 1) / 2; + } + if (lessThan(begin[i], value) || lessThan(value, begin[i])) + return end; + else + return begin + i; +} + +} //namespace QAlgorithmsPrivate + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QALGORITHMS_H diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp new file mode 100644 index 0000000..a947ab5 --- /dev/null +++ b/src/corelib/tools/qbitarray.cpp @@ -0,0 +1,728 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbitarray.h" +#include <qdatastream.h> +#include <qdebug.h> +#include <string.h> + +QT_BEGIN_NAMESPACE + +/*! + \class QBitArray + \brief The QBitArray class provides an array of bits. + + \ingroup tools + \ingroup shared + \reentrant + + A QBitArray is an array that gives access to individual bits and + provides operators (\link operator&() AND\endlink, \link + operator|() OR\endlink, \link operator^() XOR\endlink, and \link + operator~() NOT\endlink) that work on entire arrays of bits. It + uses \l{implicit sharing} (copy-on-write) to reduce memory usage + and to avoid the needless copying of data. + + The following code constructs a QBitArray containing 200 bits + initialized to false (0): + + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 0 + + To initialize the bits to true, either pass \c true as second + argument to the constructor, or call fill() later on. + + QBitArray uses 0-based indexes, just like C++ arrays. To access + the bit at a particular index position, you can use operator[](). + On non-const bit arrays, operator[]() returns a reference to a + bit that can be used on the left side of an assignment. For + example: + + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 1 + + For technical reasons, it is more efficient to use testBit() and + setBit() to access bits in the array than operator[](). For + example: + + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 2 + + QBitArray supports \c{&} (\link operator&() AND\endlink), \c{|} + (\link operator|() OR\endlink), \c{^} (\link operator^() + XOR\endlink), \c{~} (\link operator~() NOT\endlink), as well as + \c{&=}, \c{|=}, and \c{^=}. These operators work in the same way + as the built-in C++ bitwise operators of the same name. For + example: + + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 3 + + For historical reasons, QBitArray distinguishes between a null + bit array and an empty bit array. A \e null bit array is a bit + array that is initialized using QBitArray's default constructor. + An \e empty bit array is any bit array with size 0. A null bit + array is always empty, but an empty bit array isn't necessarily + null: + + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 4 + + All functions except isNull() treat null bit arrays the same as + empty bit arrays; for example, QBitArray() compares equal to + QBitArray(0). We recommend that you always use isEmpty() and + avoid isNull(). + + \sa QByteArray, QVector +*/ + +/*! \fn QBitArray::QBitArray() + + Constructs an empty bit array. + + \sa isEmpty() +*/ + +/*! + Constructs a bit array containing \a size bits. The bits are + initialized with \a value, which defaults to false (0). +*/ +QBitArray::QBitArray(int size, bool value) +{ + if (!size) { + d.resize(0); + return; + } + d.resize(1 + (size+7)/8); + uchar* c = reinterpret_cast<uchar*>(d.data()); + memset(c, value ? 0xff : 0, d.size()); + *c = d.size()*8 - size; + if (value && size && size % 8) + *(c+1+size/8) &= (1 << (size%8)) - 1; +} + +/*! \fn int QBitArray::size() const + + Returns the number of bits stored in the bit array. + + \sa resize() +*/ + +/*! \fn int QBitArray::count() const + + Same as size(). +*/ + +/*! + If \a on is true, this function returns the number of + 1-bits stored in the bit array; otherwise the number + of 0-bits is returned. +*/ +int QBitArray::count(bool on) const +{ + int numBits = 0; + int len = size(); +#if 0 + for (int i = 0; i < len; ++i) + numBits += testBit(i); +#else + // See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel + const quint8 *bits = reinterpret_cast<const quint8 *>(d.data()) + 1; + while (len >= 32) { + quint32 v = quint32(bits[0]) | (quint32(bits[1]) << 8) | (quint32(bits[2]) << 16) | (quint32(bits[3]) << 24); + quint32 c = ((v & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f; + c += (((v & 0xfff000) >> 12) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f; + c += ((v >> 24) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f; + len -= 32; + bits += 4; + numBits += int(c); + } + while (len >= 24) { + quint32 v = quint32(bits[0]) | (quint32(bits[1]) << 8) | (quint32(bits[2]) << 16); + quint32 c = ((v & 0xfff) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f; + c += (((v & 0xfff000) >> 12) * Q_UINT64_C(0x1001001001001) & Q_UINT64_C(0x84210842108421)) % 0x1f; + len -= 24; + bits += 3; + numBits += int(c); + } + while (len >= 0) { + if (bits[len / 8] & (1 << ((len - 1) & 7))) + ++numBits; + --len; + } +#endif + return on ? numBits : size() - numBits; +} + +/*! + Resizes the bit array to \a size bits. + + If \a size is greater than the current size, the bit array is + extended to make it \a size bits with the extra bits added to the + end. The new bits are initialized to false (0). + + If \a size is less than the current size, bits are removed from + the end. + + \sa size() +*/ +void QBitArray::resize(int size) +{ + if (!size) { + d.resize(0); + } else { + int s = d.size(); + d.resize(1 + (size+7)/8); + uchar* c = reinterpret_cast<uchar*>(d.data()); + if (size > (s << 3)) + memset(c + s, 0, d.size() - s); + *c = d.size()*8 - size; + } +} + +/*! \fn bool QBitArray::isEmpty() const + + Returns true if this bit array has size 0; otherwise returns + false. + + \sa size() +*/ + +/*! \fn bool QBitArray::isNull() const + + Returns true if this bit array is null; otherwise returns false. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 5 + + Qt makes a distinction between null bit arrays and empty bit + arrays for historical reasons. For most applications, what + matters is whether or not a bit array contains any data, + and this can be determined using isEmpty(). + + \sa isEmpty() +*/ + +/*! \fn bool QBitArray::fill(bool value, int size = -1) + + Sets every bit in the bit array to \a value, returning true if successful; + otherwise returns false. If \a size is different from -1 (the default), + the bit array is resized to \a size beforehand. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 6 + + \sa resize() +*/ + +/*! + \overload + + Sets bits at index positions \a begin up to and excluding \a end + to \a value. + + \a begin and \a end must be a valid index position in the bit + array (i.e., 0 <= \a begin <= size() and 0 <= \a end <= size()). +*/ + +void QBitArray::fill(bool value, int begin, int end) +{ + while (begin < end && begin & 0x7) + setBit(begin++, value); + int len = end - begin; + if (len <= 0) + return; + int s = len & ~0x7; + uchar *c = reinterpret_cast<uchar*>(d.data()); + memset(c + (begin >> 3) + 1, value ? 0xff : 0, s >> 3); + begin += s; + while (begin < end) + setBit(begin++, value); +} + +/*! \fn bool QBitArray::isDetached() const + + \internal +*/ + +/*! \fn void QBitArray::detach() + + \internal +*/ + +/*! \fn void QBitArray::clear() + + Clears the contents of the bit array and makes it empty. + + \sa resize(), isEmpty() +*/ + +/*! \fn void QBitArray::truncate(int pos) + + Truncates the bit array at index position \a pos. + + If \a pos is beyond the end of the array, nothing happens. + + \sa resize() +*/ + +/*! \fn bool QBitArray::toggleBit(int i) + + Inverts the value of the bit at index position \a i, returning the + previous value of that bit as either true (if it was set) or false (if + it was unset). + + If the previous value was 0, the new value will be 1. If the + previous value was 1, the new value will be 0. + + \a i must be a valid index position in the bit array (i.e., 0 <= + \a i < size()). + + \sa setBit(), clearBit() +*/ + +/*! \fn bool QBitArray::testBit(int i) const + + Returns true if the bit at index position \a i is 1; otherwise + returns false. + + \a i must be a valid index position in the bit array (i.e., 0 <= + \a i < size()). + + \sa setBit(), clearBit() +*/ + +/*! \fn bool QBitArray::setBit(int i) + + Sets the bit at index position \a i to 1. + + \a i must be a valid index position in the bit array (i.e., 0 <= + \a i < size()). + + \sa clearBit(), toggleBit() +*/ + +/*! \fn void QBitArray::setBit(int i, bool value) + + \overload + + Sets the bit at index position \a i to \a value. +*/ + +/*! \fn void QBitArray::clearBit(int i) + + Sets the bit at index position \a i to 0. + + \a i must be a valid index position in the bit array (i.e., 0 <= + \a i < size()). + + \sa setBit(), toggleBit() +*/ + +/*! \fn bool QBitArray::at(int i) const + + Returns the value of the bit at index position \a i. + + \a i must be a valid index position in the bit array (i.e., 0 <= + \a i < size()). + + \sa operator[]() +*/ + +/*! \fn QBitRef QBitArray::operator[](int i) + + Returns the bit at index position \a i as a modifiable reference. + + \a i must be a valid index position in the bit array (i.e., 0 <= + \a i < size()). + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 7 + + The return value is of type QBitRef, a helper class for QBitArray. + When you get an object of type QBitRef, you can assign to + it, and the assignment will apply to the bit in the QBitArray + from which you got the reference. + + The functions testBit(), setBit(), and clearBit() are slightly + faster. + + \sa at(), testBit(), setBit(), clearBit() +*/ + +/*! \fn bool QBitArray::operator[](int i) const + + \overload +*/ + +/*! \fn bool QBitArray::operator[](uint i) + + \overload +*/ + +/*! \fn bool QBitArray::operator[](uint i) const + + \overload +*/ + +/*! \fn QBitArray::QBitArray(const QBitArray &other) + + Constructs a copy of \a other. + + This operation takes \l{constant time}, because QBitArray is + \l{implicitly shared}. This makes returning a QBitArray from a + function very fast. If a shared instance is modified, it will be + copied (copy-on-write), and that takes \l{linear time}. + + \sa operator=() +*/ + +/*! \fn QBitArray &QBitArray::operator=(const QBitArray &other) + + Assigns \a other to this bit array and returns a reference to + this bit array. +*/ + +/*! \fn bool QBitArray::operator==(const QBitArray &other) const + + Returns true if \a other is equal to this bit array; otherwise + returns false. + + \sa operator!=() +*/ + +/*! \fn bool QBitArray::operator!=(const QBitArray &other) const + + Returns true if \a other is not equal to this bit array; + otherwise returns false. + + \sa operator==() +*/ + +/*! + Performs the AND operation between all bits in this bit array and + \a other. Assigns the result to this bit array, and returns a + reference to it. + + The result has the length of the longest of the two bit arrays, + with any missing bits (if one array is shorter than the other) + taken to be 0. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 8 + + \sa operator&(), operator|=(), operator^=(), operator~() +*/ + +QBitArray &QBitArray::operator&=(const QBitArray &other) +{ + resize(qMax(size(), other.size())); + uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1; + const uchar *a2 = reinterpret_cast<const uchar*>(other.d.constData()) + 1; + int n = other.d.size() -1 ; + int p = d.size() - 1 - n; + while (n-- > 0) + *a1++ &= *a2++; + while (p-- > 0) + *a1++ = 0; + return *this; +} + +/*! + Performs the OR operation between all bits in this bit array and + \a other. Assigns the result to this bit array, and returns a + reference to it. + + The result has the length of the longest of the two bit arrays, + with any missing bits (if one array is shorter than the other) + taken to be 0. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 9 + + \sa operator|(), operator&=(), operator^=(), operator~() +*/ + +QBitArray &QBitArray::operator|=(const QBitArray &other) +{ + resize(qMax(size(), other.size())); + uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1; + const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1; + int n = other.d.size() - 1; + while (n-- > 0) + *a1++ |= *a2++; + return *this; +} + +/*! + Performs the XOR operation between all bits in this bit array and + \a other. Assigns the result to this bit array, and returns a + reference to it. + + The result has the length of the longest of the two bit arrays, + with any missing bits (if one array is shorter than the other) + taken to be 0. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 10 + + \sa operator^(), operator&=(), operator|=(), operator~() +*/ + +QBitArray &QBitArray::operator^=(const QBitArray &other) +{ + resize(qMax(size(), other.size())); + uchar *a1 = reinterpret_cast<uchar*>(d.data()) + 1; + const uchar *a2 = reinterpret_cast<const uchar *>(other.d.constData()) + 1; + int n = other.d.size() - 1; + while (n-- > 0) + *a1++ ^= *a2++; + return *this; +} + +/*! + Returns a bit array that contains the inverted bits of this bit + array. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 11 + + \sa operator&(), operator|(), operator^() +*/ + +QBitArray QBitArray::operator~() const +{ + int sz = size(); + QBitArray a(sz); + const uchar *a1 = reinterpret_cast<const uchar *>(d.constData()) + 1; + uchar *a2 = reinterpret_cast<uchar*>(a.d.data()) + 1; + int n = d.size() - 1; + + while (n-- > 0) + *a2++ = ~*a1++; + + if (sz && sz%8) + *(a2-1) &= (1 << (sz%8)) - 1; + return a; +} + +/*! + \relates QBitArray + + Returns a bit array that is the AND of the bit arrays \a a1 and \a + a2. + + The result has the length of the longest of the two bit arrays, + with any missing bits (if one array is shorter than the other) + taken to be 0. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 12 + + \sa QBitArray::operator&=(), operator|(), operator^() +*/ + +QBitArray operator&(const QBitArray &a1, const QBitArray &a2) +{ + QBitArray tmp = a1; + tmp &= a2; + return tmp; +} + +/*! + \relates QBitArray + + Returns a bit array that is the OR of the bit arrays \a a1 and \a + a2. + + The result has the length of the longest of the two bit arrays, + with any missing bits (if one array is shorter than the other) + taken to be 0. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 13 + + \sa QBitArray::operator|=(), operator&(), operator^() +*/ + +QBitArray operator|(const QBitArray &a1, const QBitArray &a2) +{ + QBitArray tmp = a1; + tmp |= a2; + return tmp; +} + +/*! + \relates QBitArray + + Returns a bit array that is the XOR of the bit arrays \a a1 and \a + a2. + + The result has the length of the longest of the two bit arrays, + with any missing bits (if one array is shorter than the other) + taken to be 0. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbitarray.cpp 14 + + \sa QBitArray::operator^=(), operator&(), operator|() +*/ + +QBitArray operator^(const QBitArray &a1, const QBitArray &a2) +{ + QBitArray tmp = a1; + tmp ^= a2; + return tmp; +} + +/*! + \class QBitRef + \reentrant + \brief The QBitRef class is an internal class, used with QBitArray. + + \internal + + The QBitRef is required by the indexing [] operator on bit arrays. + It is not for use in any other context. +*/ + +/*! \fn QBitRef::QBitRef (QBitArray& a, int i) + + Constructs a reference to element \a i in the QBitArray \a a. + This is what QBitArray::operator[] constructs its return value + with. +*/ + +/*! \fn QBitRef::operator bool() const + + Returns the value referenced by the QBitRef. +*/ + +/*! \fn bool QBitRef::operator!() const + + \internal +*/ + +/*! \fn QBitRef& QBitRef::operator= (const QBitRef& v) + + Sets the value referenced by the QBitRef to that referenced by + QBitRef \a v. +*/ + +/*! \fn QBitRef& QBitRef::operator= (bool v) + \overload + + Sets the value referenced by the QBitRef to \a v. +*/ + + +/***************************************************************************** + QBitArray stream functions + *****************************************************************************/ + +/*! + \relates QBitArray + + Writes bit array \a ba to stream \a out. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ +#ifndef QT_NO_DATASTREAM +QDataStream &operator<<(QDataStream &out, const QBitArray &ba) +{ + quint32 len = ba.size(); + out << len; + if (len > 0) + out.writeRawData(ba.d.constData() + 1, ba.d.size() - 1); + return out; +} + +/*! + \relates QBitArray + + Reads a bit array into \a ba from stream \a in. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator>>(QDataStream &in, QBitArray &ba) +{ + ba.clear(); + quint32 len; + in >> len; + if (len == 0) { + ba.clear(); + return in; + } + + const quint32 Step = 8 * 1024 * 1024; + quint32 totalBytes = (len + 7) / 8; + quint32 allocated = 0; + + while (allocated < totalBytes) { + int blockSize = qMin(Step, totalBytes - allocated); + ba.d.resize(allocated + blockSize + 1); + if (in.readRawData(ba.d.data() + 1 + allocated, blockSize) != blockSize) { + ba.clear(); + in.setStatus(QDataStream::ReadPastEnd); + return in; + } + allocated += blockSize; + } + + int paddingMask = ~((0x1 << (len & 0x7)) - 1); + if (paddingMask != ~0x0 && (ba.d.constData()[ba.d.size() - 1] & paddingMask)) { + ba.clear(); + in.setStatus(QDataStream::ReadCorruptData); + return in; + } + + *ba.d.data() = ba.d.size() * 8 - len; + return in; +} +#endif + +/*! + \fn DataPtr &QBitArray::data_ptr() + \internal +*/ + +/*! + \typedef QBitArray::DataPtr + \internal +*/ + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h new file mode 100644 index 0000000..d754b07 --- /dev/null +++ b/src/corelib/tools/qbitarray.h @@ -0,0 +1,174 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBITARRAY_H +#define QBITARRAY_H + +#include <QtCore/qbytearray.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class QBitRef; +class Q_CORE_EXPORT QBitArray +{ + friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &); + friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &); + friend Q_CORE_EXPORT uint qHash(const QBitArray &key); + QByteArray d; + +public: + inline QBitArray() {} + explicit QBitArray(int size, bool val = false); + QBitArray(const QBitArray &other) : d(other.d) {} + inline QBitArray &operator=(const QBitArray &other) { d = other.d; return *this; } + + inline int size() const { return (d.size() << 3) - *d.constData(); } + inline int count() const { return (d.size() << 3) - *d.constData(); } + int count(bool on) const; + // ### Qt 5: Store the number of set bits separately + + inline bool isEmpty() const { return d.isEmpty(); } + inline bool isNull() const { return d.isNull(); } + + void resize(int size); + + inline void detach() { d.detach(); } + inline bool isDetached() const { return d.isDetached(); } + inline void clear() { d.clear(); } + + bool testBit(int i) const; + void setBit(int i); + void setBit(int i, bool val); + void clearBit(int i); + bool toggleBit(int i); + + bool at(int i) const; + QBitRef operator[](int i); + bool operator[](int i) const; + QBitRef operator[](uint i); + bool operator[](uint i) const; + + QBitArray& operator&=(const QBitArray &); + QBitArray& operator|=(const QBitArray &); + QBitArray& operator^=(const QBitArray &); + QBitArray operator~() const; + + inline bool operator==(const QBitArray& a) const { return d == a.d; } + inline bool operator!=(const QBitArray& a) const { return d != a.d; } + + inline bool fill(bool val, int size = -1); + void fill(bool val, int first, int last); + + inline void truncate(int pos) { if (pos < size()) resize(pos); } + +public: + typedef QByteArray::DataPtr DataPtr; + inline DataPtr &data_ptr() { return d.data_ptr(); } +}; + +inline bool QBitArray::fill(bool aval, int asize) +{ *this = QBitArray((asize < 0 ? this->size() : asize), aval); return true; } + +Q_CORE_EXPORT QBitArray operator&(const QBitArray &, const QBitArray &); +Q_CORE_EXPORT QBitArray operator|(const QBitArray &, const QBitArray &); +Q_CORE_EXPORT QBitArray operator^(const QBitArray &, const QBitArray &); + +inline bool QBitArray::testBit(int i) const +{ Q_ASSERT(i >= 0 && i < size()); + return (*(reinterpret_cast<const uchar*>(d.constData())+1+(i>>3)) & (1 << (i & 7))) != 0; } + +inline void QBitArray::setBit(int i) +{ Q_ASSERT(i >= 0 && i < size()); + *(reinterpret_cast<uchar*>(d.data())+1+(i>>3)) |= (1 << (i & 7)); } + +inline void QBitArray::clearBit(int i) +{ Q_ASSERT(i >= 0 && i < size()); + *(reinterpret_cast<uchar*>(d.data())+1+(i>>3)) &= ~(1 << (i & 7)); } + +inline void QBitArray::setBit(int i, bool val) +{ if (val) setBit(i); else clearBit(i); } + +inline bool QBitArray::toggleBit(int i) +{ Q_ASSERT(i >= 0 && i < size()); + uchar b = 1<< (i&7); uchar* p = reinterpret_cast<uchar*>(d.data())+1+(i>>3); + uchar c = *p&b; *p^=b; return c!=0; } + +inline bool QBitArray::operator[](int i) const { return testBit(i); } +inline bool QBitArray::operator[](uint i) const { return testBit(i); } +inline bool QBitArray::at(int i) const { return testBit(i); } + +class Q_CORE_EXPORT QBitRef +{ +private: + QBitArray& a; + int i; + inline QBitRef(QBitArray& array, int idx) : a(array), i(idx) {} + friend class QBitArray; +public: + inline operator bool() const { return a.testBit(i); } + inline bool operator!() const { return !a.testBit(i); } + QBitRef& operator=(const QBitRef& val) { a.setBit(i, val); return *this; } + QBitRef& operator=(bool val) { a.setBit(i, val); return *this; } +}; + +inline QBitRef QBitArray::operator[](int i) +{ Q_ASSERT(i >= 0); return QBitRef(*this, i); } +inline QBitRef QBitArray::operator[](uint i) +{ return QBitRef(*this, i); } + + +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QBitArray &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QBitArray &); +#endif + +Q_DECLARE_TYPEINFO(QBitArray, Q_MOVABLE_TYPE); +Q_DECLARE_SHARED(QBitArray) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QBITARRAY_H diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp new file mode 100644 index 0000000..6aa35f3 --- /dev/null +++ b/src/corelib/tools/qbytearray.cpp @@ -0,0 +1,4240 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbytearray.h" +#include "qbytearraymatcher.h" +#include "qtools_p.h" +#include "qstring.h" +#include "qlist.h" +#include "qlocale.h" +#include "qlocale_p.h" +#include "qunicodetables_p.h" +#ifndef QT_NO_DATASTREAM +#include <qdatastream.h> +#endif + +#ifndef QT_NO_COMPRESS +#include <zlib.h> +#endif +#include <ctype.h> +#include <limits.h> +#include <string.h> +#include <stdlib.h> + +#define IS_RAW_DATA(d) ((d)->data != (d)->array) + +QT_BEGIN_NAMESPACE + + +int qFindByteArray( + const char *haystack0, int haystackLen, int from, + const char *needle0, int needleLen); + + +int qAllocMore(int alloc, int extra) +{ + if (alloc == 0 && extra == 0) + return 0; + const int page = 1 << 12; + int nalloc; + alloc += extra; + if (alloc < 1<<6) { + nalloc = (1<<3) + ((alloc >>3) << 3); + } else { + // don't do anything if the loop will overflow signed int. + if (alloc >= INT_MAX/2) + return INT_MAX; + nalloc = (alloc < page) ? 1 << 3 : page; + while (nalloc < alloc) { + if (nalloc <= 0) + return INT_MAX; + nalloc *= 2; + } + } + return nalloc - extra; +} + +/***************************************************************************** + Safe and portable C string functions; extensions to standard string.h + *****************************************************************************/ + +/*! \relates QByteArray + + Returns a duplicate string. + + Allocates space for a copy of \a src, copies it, and returns a + pointer to the copy. If \a src is 0, it immediately returns 0. + + Ownership is passed to the caller, so the returned string must be + deleted using \c delete[]. +*/ + +char *qstrdup(const char *src) +{ + if (!src) + return 0; + char *dst = new char[strlen(src) + 1]; + return qstrcpy(dst, src); +} + +/*! \relates QByteArray + + Copies all the characters up to and including the '\\0' from \a + src into \a dst and returns a pointer to \a dst. If \a src is 0, + it immediately returns 0. + + This function assumes that \a dst is large enough to hold the + contents of \a src. + + \sa qstrncpy() +*/ + +char *qstrcpy(char *dst, const char *src) +{ + if (!src) + return 0; +#if defined(_MSC_VER) && _MSC_VER >= 1400 + int len = qstrlen(src); + // This is actually not secure!!! It will be fixed + // properly in a later release! + if (len >= 0 && strcpy_s(dst, len+1, src) == 0) + return dst; + return 0; +#else + return strcpy(dst, src); +#endif +} + +/*! \relates QByteArray + + A safe \c strncpy() function. + + Copies at most \a len bytes from \a src (stopping at \a len or the + terminating '\\0' whichever comes first) into \a dst and returns a + pointer to \a dst. Guarantees that \a dst is '\\0'-terminated. If + \a src or \a dst is 0, returns 0 immediately. + + This function assumes that \a dst is at least \a len characters + long. + + \sa qstrcpy() +*/ + +char *qstrncpy(char *dst, const char *src, uint len) +{ + if (!src || !dst) + return 0; +#if defined(_MSC_VER) && _MSC_VER >= 1400 + strncpy_s(dst, len, src, len-1); +#else + strncpy(dst, src, len); +#endif + if (len > 0) + dst[len-1] = '\0'; + return dst; +} + +/*! \fn uint qstrlen(const char *str) + \relates QByteArray + + A safe \c strlen() function. + + Returns the number of characters that precede the terminating '\\0', + or 0 if \a str is 0. + + \sa qstrnlen() +*/ + +/*! \fn uint qstrnlen(const char *str, uint maxlen) + \relates QByteArray + \since 4.2 + + A safe \c strnlen() function. + + Returns the number of characters that precede the terminating '\\0', but + at most \a maxlen. If \a str is 0, returns 0. + + \sa qstrlen() +*/ + +/*! + \relates QByteArray + + A safe \c strcmp() function. + + Compares \a str1 and \a str2. Returns a negative value if \a str1 + is less than \a str2, 0 if \a str1 is equal to \a str2 or a + positive value if \a str1 is greater than \a str2. + + Special case 1: Returns 0 if \a str1 and \a str2 are both 0. + + Special case 2: Returns an arbitrary non-zero value if \a str1 is 0 + or \a str2 is 0 (but not both). + + \sa qstrncmp(), qstricmp(), qstrnicmp(), {8-bit Character Comparisons} +*/ +int qstrcmp(const char *str1, const char *str2) +{ + return (str1 && str2) ? strcmp(str1, str2) + : (str1 ? 1 : (str2 ? -1 : 0)); +} + +/*! \fn int qstrncmp(const char *str1, const char *str2, uint len); + + \relates QByteArray + + A safe \c strncmp() function. + + Compares at most \a len bytes of \a str1 and \a str2. + + Returns a negative value if \a str1 is less than \a str2, 0 if \a + str1 is equal to \a str2 or a positive value if \a str1 is greater + than \a str2. + + Special case 1: Returns 0 if \a str1 and \a str2 are both 0. + + Special case 2: Returns a random non-zero value if \a str1 is 0 + or \a str2 is 0 (but not both). + + \sa qstrcmp(), qstricmp(), qstrnicmp(), {8-bit Character Comparisons} +*/ + +/*! \relates QByteArray + + A safe \c stricmp() function. + + Compares \a str1 and \a str2 ignoring the case of the + characters. The encoding of the strings is assumed to be Latin-1. + + Returns a negative value if \a str1 is less than \a str2, 0 if \a + str1 is equal to \a str2 or a positive value if \a str1 is greater + than \a str2. + + Special case 1: Returns 0 if \a str1 and \a str2 are both 0. + + Special case 2: Returns a random non-zero value if \a str1 is 0 + or \a str2 is 0 (but not both). + + \sa qstrcmp(), qstrncmp(), qstrnicmp(), {8-bit Character Comparisons} +*/ + +int qstricmp(const char *str1, const char *str2) +{ + register const uchar *s1 = reinterpret_cast<const uchar *>(str1); + register const uchar *s2 = reinterpret_cast<const uchar *>(str2); + int res; + uchar c; + if (!s1 || !s2) + return s1 ? 1 : (s2 ? -1 : 0); + for (; !(res = (c = QChar::toLower((ushort)*s1)) - QChar::toLower((ushort)*s2)); s1++, s2++) + if (!c) // strings are equal + break; + return res; +} + +/*! \relates QByteArray + + A safe \c strnicmp() function. + + Compares at most \a len bytes of \a str1 and \a str2 ignoring the + case of the characters. The encoding of the strings is assumed to + be Latin-1. + + Returns a negative value if \a str1 is less than \a str2, 0 if \a str1 + is equal to \a str2 or a positive value if \a str1 is greater than \a + str2. + + Special case 1: Returns 0 if \a str1 and \a str2 are both 0. + + Special case 2: Returns a random non-zero value if \a str1 is 0 + or \a str2 is 0 (but not both). + + \sa qstrcmp(), qstrncmp(), qstricmp(), {8-bit Character Comparisons} +*/ + +int qstrnicmp(const char *str1, const char *str2, uint len) +{ + register const uchar *s1 = reinterpret_cast<const uchar *>(str1); + register const uchar *s2 = reinterpret_cast<const uchar *>(str2); + int res; + uchar c; + if (!s1 || !s2) + return s1 ? 1 : (s2 ? -1 : 0); + for (; len--; s1++, s2++) { + if ((res = (c = QChar::toLower((ushort)*s1)) - QChar::toLower((ushort)*s2))) + return res; + if (!c) // strings are equal + break; + } + return 0; +} + +/*! + \internal + */ +int qstrcmp(const QByteArray &str1, const char *str2) +{ + if (!str2) + return str1.isEmpty() ? 0 : +1; + + const char *str1data = str1.constData(); + const char *str1end = str1data + str1.length(); + for ( ; str1data < str1end && *str2; ++str1data, ++str2) { + register int diff = int(uchar(*str1data)) - uchar(*str2); + if (diff) + // found a difference + return diff; + } + + // Why did we stop? + if (*str2 != '\0') + // not the null, so we stopped because str1 is shorter + return -1; + if (str1data < str1end) + // we haven't reached the end, so str1 must be longer + return +1; + return 0; +} + +/*! + \internal + */ +int qstrcmp(const QByteArray &str1, const QByteArray &str2) +{ + int l1 = str1.length(); + int l2 = str2.length(); + int ret = memcmp(str1, str2, qMin(l1, l2)); + if (ret != 0) + return ret; + + // they matched qMin(l1, l2) bytes + // so the longer one is lexically after the shorter one + return l1 - l2; +} + +// the CRC table below is created by the following piece of code +#if 0 +static void createCRC16Table() // build CRC16 lookup table +{ + register unsigned int i; + register unsigned int j; + unsigned short crc_tbl[16]; + unsigned int v0, v1, v2, v3; + for (i = 0; i < 16; i++) { + v0 = i & 1; + v1 = (i >> 1) & 1; + v2 = (i >> 2) & 1; + v3 = (i >> 3) & 1; + j = 0; +#undef SET_BIT +#define SET_BIT(x, b, v) (x) |= (v) << (b) + SET_BIT(j, 0, v0); + SET_BIT(j, 7, v0); + SET_BIT(j, 12, v0); + SET_BIT(j, 1, v1); + SET_BIT(j, 8, v1); + SET_BIT(j, 13, v1); + SET_BIT(j, 2, v2); + SET_BIT(j, 9, v2); + SET_BIT(j, 14, v2); + SET_BIT(j, 3, v3); + SET_BIT(j, 10, v3); + SET_BIT(j, 15, v3); + crc_tbl[i] = j; + } + printf("static const quint16 crc_tbl[16] = {\n"); + for (int i = 0; i < 16; i +=4) + printf(" 0x%04x, 0x%04x, 0x%04x, 0x%04x,\n", crc_tbl[i], crc_tbl[i+1], crc_tbl[i+2], crc_tbl[i+3]); + printf("};\n"); +} +#endif + +static const quint16 crc_tbl[16] = { + 0x0000, 0x1081, 0x2102, 0x3183, + 0x4204, 0x5285, 0x6306, 0x7387, + 0x8408, 0x9489, 0xa50a, 0xb58b, + 0xc60c, 0xd68d, 0xe70e, 0xf78f +}; + +/*! + \relates QByteArray + + Returns the CRC-16 checksum of the first \a len bytes of \a data. + + The checksum is independent of the byte order (endianness). + + \note This function is a 16-bit cache conserving (16 entry table) + implementation of the CRC-16-CCITT algorithm. +*/ + +quint16 qChecksum(const char *data, uint len) +{ + register quint16 crc = 0xffff; + uchar c; + const uchar *p = reinterpret_cast<const uchar *>(data); + while (len--) { + c = *p++; + crc = ((crc >> 4) & 0x0fff) ^ crc_tbl[((crc ^ c) & 15)]; + c >>= 4; + crc = ((crc >> 4) & 0x0fff) ^ crc_tbl[((crc ^ c) & 15)]; + } + return ~crc & 0xffff; +} + +/*! + \fn QByteArray qCompress(const QByteArray& data, int compressionLevel) + + \relates QByteArray + + Compresses the \a data byte array and returns the compressed data + in a new byte array. + + The \a compressionLevel parameter specifies how much compression + should be used. Valid values are between 0 and 9, with 9 + corresponding to the greatest compression (i.e. smaller compressed + data) at the cost of using a slower algorithm. Smaller values (8, + 7, ..., 1) provide successively less compression at slightly + faster speeds. The value 0 corresponds to no compression at all. + The default value is -1, which specifies zlib's default + compression. + + \sa qUncompress() +*/ + +/*! \relates QByteArray + + \overload + + Compresses the first \a nbytes of \a data and returns the + compressed data in a new byte array. +*/ + +#ifndef QT_NO_COMPRESS +QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel) +{ + if (nbytes == 0) { + return QByteArray(4, '\0'); + } + if (!data) { + qWarning("qCompress: Data is null"); + return QByteArray(); + } + if (compressionLevel < -1 || compressionLevel > 9) + compressionLevel = -1; + + ulong len = nbytes + nbytes / 100 + 13; + QByteArray bazip; + int res; + do { + bazip.resize(len + 4); + res = ::compress2((uchar*)bazip.data()+4, &len, (uchar*)data, nbytes, compressionLevel); + + switch (res) { + case Z_OK: + bazip.resize(len + 4); + bazip[0] = (nbytes & 0xff000000) >> 24; + bazip[1] = (nbytes & 0x00ff0000) >> 16; + bazip[2] = (nbytes & 0x0000ff00) >> 8; + bazip[3] = (nbytes & 0x000000ff); + break; + case Z_MEM_ERROR: + qWarning("qCompress: Z_MEM_ERROR: Not enough memory"); + bazip.resize(0); + break; + case Z_BUF_ERROR: + len *= 2; + break; + } + } while (res == Z_BUF_ERROR); + + return bazip; +} +#endif + +/*! + \fn QByteArray qUncompress(const QByteArray& data) + + \relates QByteArray + + Uncompresses the \a data byte array and returns a new byte array + with the uncompressed data. + + Returns an empty QByteArray if the input data was corrupt. + + This function will uncompress data compressed with qCompress() + from this and any earlier Qt version, back to Qt 3.1 when this + feature was added. + + \bold{Note:} If you want to use this function to uncompress external + data compressed using zlib, you first need to prepend four bytes to the + byte array that contain the expected length (as an unsigned integer) + of the uncompressed data encoded in big-endian order (most significant + byte first). + + \sa qCompress() +*/ + +/*! \relates QByteArray + + \overload + + Uncompresses the first \a nbytes of \a data and returns a new byte + array with the uncompressed data. +*/ + +#ifndef QT_NO_COMPRESS +QByteArray qUncompress(const uchar* data, int nbytes) +{ + if (!data) { + qWarning("qUncompress: Data is null"); + return QByteArray(); + } + if (nbytes <= 4) { + if (nbytes < 4 || (data[0]!=0 || data[1]!=0 || data[2]!=0 || data[3]!=0)) + qWarning("qUncompress: Input data is corrupted"); + return QByteArray(); + } + ulong expectedSize = (data[0] << 24) | (data[1] << 16) | + (data[2] << 8) | (data[3] ); + ulong len = qMax(expectedSize, 1ul); + QByteArray baunzip; + int res; + do { + baunzip.resize(len); + res = ::uncompress((uchar*)baunzip.data(), &len, + (uchar*)data+4, nbytes-4); + + switch (res) { + case Z_OK: + if ((int)len != baunzip.size()) + baunzip.resize(len); + break; + case Z_MEM_ERROR: + qWarning("qUncompress: Z_MEM_ERROR: Not enough memory"); + break; + case Z_BUF_ERROR: + len *= 2; + break; + case Z_DATA_ERROR: + qWarning("qUncompress: Z_DATA_ERROR: Input data is corrupted"); + break; + } + } while (res == Z_BUF_ERROR); + + if (res != Z_OK) + baunzip = QByteArray(); + + return baunzip; +} +#endif + +static inline bool qIsUpper(char c) +{ + return c >= 'A' && c <= 'Z'; +} + +static inline char qToLower(char c) +{ + if (c >= 'A' && c <= 'Z') + return c - 'A' + 'a'; + else + return c; +} + +Q_CORE_EXPORT QByteArray::Data QByteArray::shared_null = {Q_BASIC_ATOMIC_INITIALIZER(1), + 0, 0, shared_null.array, {0} }; +QByteArray::Data QByteArray::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), + 0, 0, shared_empty.array, {0} }; + +/*! + \class QByteArray + \brief The QByteArray class provides an array of bytes. + + \ingroup tools + \ingroup shared + \ingroup text + \mainclass + \reentrant + + QByteArray can be used to store both raw bytes (including '\\0's) + and traditional 8-bit '\\0'-terminated strings. Using QByteArray + is much more convenient than using \c{const char *}. Behind the + scenes, it always ensures that the data is followed by a '\\0' + terminator, and uses \l{implicit sharing} (copy-on-write) to + reduce memory usage and avoid needless copying of data. + + In addition to QByteArray, Qt also provides the QString class to + store string data. For most purposes, QString is the class you + want to use. It stores 16-bit Unicode characters, making it easy + to store non-ASCII/non-Latin-1 characters in your application. + Furthermore, QString is used throughout in the Qt API. The two + main cases where QByteArray is appropriate are when you need to + store raw binary data, and when memory conservation is critical + (e.g., with Qt for Embedded Linux). + + One way to initialize a QByteArray is simply to pass a \c{const + char *} to its constructor. For example, the following code + creates a byte array of size 5 containing the data "Hello": + + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 0 + + Although the size() is 5, the byte array also maintains an extra + '\\0' character at the end so that if a function is used that + asks for a pointer to the underlying data (e.g. a call to + data()), the data pointed to is guaranteed to be + '\\0'-terminated. + + QByteArray makes a deep copy of the \c{const char *} data, so you + can modify it later without experiencing side effects. (If for + performance reasons you don't want to take a deep copy of the + character data, use QByteArray::fromRawData() instead.) + + Another approach is to set the size of the array using resize() + and to initialize the data byte per byte. QByteArray uses 0-based + indexes, just like C++ arrays. To access the byte at a particular + index position, you can use operator[](). On non-const byte + arrays, operator[]() returns a reference to a byte that can be + used on the left side of an assignment. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 1 + + For read-only access, an alternative syntax is to use at(): + + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 2 + + at() can be faster than operator[](), because it never causes a + \l{deep copy} to occur. + + To extract many bytes at a time, use left(), right(), or mid(). + + A QByteArray can embed '\\0' bytes. The size() function always + returns the size of the whole array, including embedded '\\0' + bytes. If you want to obtain the length of the data up to and + excluding the first '\\0' character, call qstrlen() on the byte + array. + + After a call to resize(), newly allocated bytes have undefined + values. To set all the bytes to a particular value, call fill(). + + To obtain a pointer to the actual character data, call data() or + constData(). These functions return a pointer to the beginning of + the data. The pointer is guaranteed to remain valid until a + non-const function is called on the QByteArray. It is also + guaranteed that the data ends with a '\\0' byte. This '\\0' byte + is automatically provided by QByteArray and is not counted in + size(). + + QByteArray provides the following basic functions for modifying + the byte data: append(), prepend(), insert(), replace(), and + remove(). For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 3 + + The replace() and remove() functions' first two arguments are the + position from which to start erasing and the number of bytes that + should be erased. + + When you append() data to a non-empty array, the array will be + reallocated and the new data copied to it. You can avoid this + behavior by calling reserve(), which preallocates a certain amount + of memory. You can also call capacity() to find out how much + memory QByteArray actually allocated. Data appended to an empty + array is not copied. + + A frequent requirement is to remove whitespace characters from a + byte array ('\\n', '\\t', ' ', etc.). If you want to remove + whitespace from both ends of a QByteArray, use trimmed(). If you + want to remove whitespace from both ends and replace multiple + consecutive whitespaces with a single space character within the + byte array, use simplified(). + + If you want to find all occurrences of a particular character or + substring in a QByteArray, use indexOf() or lastIndexOf(). The + former searches forward starting from a given index position, the + latter searches backward. Both return the index position of the + character or substring if they find it; otherwise, they return -1. + For example, here's a typical loop that finds all occurrences of a + particular substring: + + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 4 + + If you simply want to check whether a QByteArray contains a + particular character or substring, use contains(). If you want to + find out how many times a particular character or substring + occurs in the byte array, use count(). If you want to replace all + occurrences of a particular value with another, use one of the + two-parameter replace() overloads. + + QByteArrays can be compared using overloaded operators such as + operator<(), operator<=(), operator==(), operator>=(), and so on. + The comparison is based exclusively on the numeric values + of the characters and is very fast, but is not what a human would + expect. QString::localeAwareCompare() is a better choice for + sorting user-interface strings. + + For historical reasons, QByteArray distinguishes between a null + byte array and an empty byte array. A \e null byte array is a + byte array that is initialized using QByteArray's default + constructor or by passing (const char *)0 to the constructor. An + \e empty byte array is any byte array with size 0. A null byte + array is always empty, but an empty byte array isn't necessarily + null: + + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 5 + + All functions except isNull() treat null byte arrays the same as + empty byte arrays. For example, data() returns a pointer to a + '\\0' character for a null byte array (\e not a null pointer), + and QByteArray() compares equal to QByteArray(""). We recommend + that you always use isEmpty() and avoid isNull(). + + \section1 Notes on Locale + + \section2 Number-String Conversions + + Functions that perform conversions between numeric data types and + strings are performed in the C locale, irrespective of the user's + locale settings. Use QString to perform locale-aware conversions + between numbers and strings. + + \section2 8-bit Character Comparisons + + In QByteArray, the notion of uppercase and lowercase and of which + character is greater than or less than another character is + locale dependent. This affects functions that support a case + insensitive option or that compare or lowercase or uppercase + their arguments. Case insensitive operations and comparisons will + be accurate if both strings contain only ASCII characters. (If \c + $LC_CTYPE is set, most Unix systems do "the right thing".) + Functions that this affects include contains(), indexOf(), + lastIndexOf(), operator<(), operator<=(), operator>(), + operator>=(), toLower() and toUpper(). + + This issue does not apply to QStrings since they represent + characters using Unicode. + + \sa QString, QBitArray +*/ + +/*! \fn QByteArray::iterator QByteArray::begin() + + \internal +*/ + +/*! \fn QByteArray::const_iterator QByteArray::begin() const + + \internal +*/ + +/*! \fn QByteArray::const_iterator QByteArray::constBegin() const + + \internal +*/ + +/*! \fn QByteArray::iterator QByteArray::end() + + \internal +*/ + +/*! \fn QByteArray::const_iterator QByteArray::end() const + + \internal +*/ + +/*! \fn QByteArray::const_iterator QByteArray::constEnd() const + + \internal +*/ + +/*! \fn void QByteArray::push_back(const QByteArray &other) + + This function is provided for STL compatibility. It is equivalent + to append(\a other). +*/ + +/*! \fn void QByteArray::push_back(const char *str) + + \overload + + Same as append(\a str). +*/ + +/*! \fn void QByteArray::push_back(char ch) + + \overload + + Same as append(\a ch). +*/ + +/*! \fn void QByteArray::push_front(const QByteArray &other) + + This function is provided for STL compatibility. It is equivalent + to prepend(\a other). +*/ + +/*! \fn void QByteArray::push_front(const char *str) + + \overload + + Same as prepend(\a str). +*/ + +/*! \fn void QByteArray::push_front(char ch) + + \overload + + Same as prepend(\a ch). +*/ + +/*! \fn QByteArray::QByteArray(const QByteArray &other) + + Constructs a copy of \a other. + + This operation takes \l{constant time}, because QByteArray is + \l{implicitly shared}. This makes returning a QByteArray from a + function very fast. If a shared instance is modified, it will be + copied (copy-on-write), and that takes \l{linear time}. + + \sa operator=() +*/ + +/*! \fn QByteArray::~QByteArray() + Destroys the byte array. +*/ + +/*! + Assigns \a other to this byte array and returns a reference to + this byte array. +*/ +QByteArray &QByteArray::operator=(const QByteArray & other) +{ + other.d->ref.ref(); + if (!d->ref.deref()) + qFree(d); + d = other.d; + return *this; +} + + +/*! + \overload + + Assigns \a str to this byte array. +*/ + +QByteArray &QByteArray::operator=(const char *str) +{ + Data *x; + if (!str) { + x = &shared_null; + } else if (!*str) { + x = &shared_empty; + } else { + int len = qstrlen(str); + if (d->ref != 1 || len > d->alloc || (len < d->size && len < d->alloc >> 1)) + realloc(len); + x = d; + memcpy(x->data, str, len + 1); // include null terminator + x->size = len; + } + x->ref.ref(); + if (!d->ref.deref()) + qFree(d); + d = x; + return *this; +} + +/*! \fn int QByteArray::size() const + + Returns the number of bytes in this byte array. + + The last byte in the byte array is at position size() - 1. In + addition, QByteArray ensures that the byte at position size() is + always '\\0', so that you can use the return value of data() and + constData() as arguments to functions that expect + '\\0'-terminated strings. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 6 + + \sa isEmpty(), resize() +*/ + +/*! \fn bool QByteArray::isEmpty() const + + Returns true if the byte array has size 0; otherwise returns false. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 7 + + \sa size() +*/ + +/*! \fn int QByteArray::capacity() const + + Returns the maximum number of bytes that can be stored in the + byte array without forcing a reallocation. + + The sole purpose of this function is to provide a means of fine + tuning QByteArray's memory usage. In general, you will rarely + ever need to call this function. If you want to know how many + bytes are in the byte array, call size(). + + \sa reserve(), squeeze() +*/ + +/*! \fn void QByteArray::reserve(int size) + + Attempts to allocate memory for at least \a size bytes. If you + know in advance how large the byte array will be, you can call + this function, and if you call resize() often you are likely to + get better performance. If \a size is an underestimate, the worst + that will happen is that the QByteArray will be a bit slower. + + The sole purpose of this function is to provide a means of fine + tuning QByteArray's memory usage. In general, you will rarely + ever need to call this function. If you want to change the size + of the byte array, call resize(). + + \sa squeeze(), capacity() +*/ + +/*! \fn void QByteArray::squeeze() + + Releases any memory not required to store the array's data. + + The sole purpose of this function is to provide a means of fine + tuning QByteArray's memory usage. In general, you will rarely + ever need to call this function. + + \sa reserve(), capacity() +*/ + +/*! \fn QByteArray::operator const char *() const + \fn QByteArray::operator const void *() const + + Returns a pointer to the data stored in the byte array. The + pointer can be used to access the bytes that compose the array. + The data is '\\0'-terminated. The pointer remains valid as long + as the array isn't reallocated or destroyed. + + This operator is mostly useful to pass a byte array to a function + that accepts a \c{const char *}. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_BYTEARRAY when you compile your applications. + + Note: A QByteArray can store any byte values including '\\0's, + but most functions that take \c{char *} arguments assume that the + data ends at the first '\\0' they encounter. + + \sa constData() +*/ + +/*! + \macro QT_NO_CAST_FROM_BYTEARRAY + \relates QByteArray + + Disables automatic conversions from QByteArray to + const char * or const void *. + + \sa QT_NO_CAST_TO_ASCII, QT_NO_CAST_FROM_ASCII +*/ + +/*! \fn char *QByteArray::data() + + Returns a pointer to the data stored in the byte array. The + pointer can be used to access and modify the bytes that compose + the array. The data is '\\0'-terminated. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 8 + + The pointer remains valid as long as the byte array isn't + reallocated or destroyed. For read-only access, constData() is + faster because it never causes a \l{deep copy} to occur. + + This function is mostly useful to pass a byte array to a function + that accepts a \c{const char *}. + + Note: A QByteArray can store any byte values including '\\0's, + but most functions that take \c{char *} arguments assume that the + data ends at the first '\\0' they encounter. + + \sa constData(), operator[]() +*/ + +/*! \fn const char *QByteArray::data() const + + \overload +*/ + +/*! \fn const char *QByteArray::constData() const + + Returns a pointer to the data stored in the byte array. The + pointer can be used to access the bytes that compose the array. + The data is '\\0'-terminated. The pointer remains valid as long + as the byte array isn't reallocated or destroyed. + + This function is mostly useful to pass a byte array to a function + that accepts a \c{const char *}. + + Note: A QByteArray can store any byte values including '\\0's, + but most functions that take \c{char *} arguments assume that the + data ends at the first '\\0' they encounter. + + \sa data(), operator[]() +*/ + +/*! \fn void QByteArray::detach() + + \internal +*/ + +/*! \fn bool QByteArray::isDetached() const + + \internal +*/ + +/*! \fn char QByteArray::at(int i) const + + Returns the character at index position \a i in the byte array. + + \a i must be a valid index position in the byte array (i.e., 0 <= + \a i < size()). + + \sa operator[]() +*/ + +/*! \fn QByteRef QByteArray::operator[](int i) + + Returns the byte at index position \a i as a modifiable reference. + + If an assignment is made beyond the end of the byte array, the + array is extended with resize() before the assignment takes + place. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 9 + + The return value is of type QByteRef, a helper class for + QByteArray. When you get an object of type QByteRef, you can use + it as if it were a char &. If you assign to it, the assignment + will apply to the character in the QByteArray from which you got + the reference. + + \sa at() +*/ + +/*! \fn char QByteArray::operator[](int i) const + + \overload + + Same as at(\a i). +*/ + +/*! \fn QByteRef QByteArray::operator[](uint i) + + \overload +*/ + +/*! \fn char QByteArray::operator[](uint i) const + + \overload +*/ + +/*! \fn QBool QByteArray::contains(const QByteArray &ba) const + + Returns true if the byte array contains an occurrence of the byte + array \a ba; otherwise returns false. + + \sa indexOf(), count() +*/ + +/*! \fn QBool QByteArray::contains(const char *str) const + + \overload + + Returns true if the byte array contains the string \a str; + otherwise returns false. +*/ + +/*! \fn QBool QByteArray::contains(char ch) const + + \overload + + Returns true if the byte array contains the character \a ch; + otherwise returns false. +*/ + +/*! + + Truncates the byte array at index position \a pos. + + If \a pos is beyond the end of the array, nothing happens. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 10 + + \sa chop(), resize(), left() +*/ +void QByteArray::truncate(int pos) +{ + if (pos < d->size) + resize(pos); +} + +/*! + + Removes \a n bytes from the end of the byte array. + + If \a n is greater than size(), the result is an empty byte + array. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 11 + + \sa truncate(), resize(), left() +*/ + +void QByteArray::chop(int n) +{ + if (n > 0) + resize(d->size - n); +} + + +/*! \fn QByteArray &QByteArray::operator+=(const QByteArray &ba) + + Appends the byte array \a ba onto the end of this byte array and + returns a reference to this byte array. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 12 + + This operation is typically very fast (\l{constant time}), + because QByteArray preallocates extra space at the end of the + character data so it can grow without reallocating the entire + data each time. + + \sa append(), prepend() +*/ + +/*! \fn QByteArray &QByteArray::operator+=(const QString &str) + + \overload + + Appends the string \a str onto the end of this byte array and + returns a reference to this byte array. The Unicode data is + converted into 8-bit characters using QString::toAscii(). + + If the QString contains non-ASCII Unicode characters, using this + operator can lead to loss of information. You can disable this + operator by defining \c QT_NO_CAST_TO_ASCII when you compile your + applications. You then need to call QString::toAscii() (or + QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit()) + explicitly if you want to convert the data to \c{const char *}. +*/ + +/*! \fn QByteArray &QByteArray::operator+=(const char *str) + + \overload + + Appends the string \a str onto the end of this byte array and + returns a reference to this byte array. +*/ + +/*! \fn QByteArray &QByteArray::operator+=(char ch) + + \overload + + Appends the character \a ch onto the end of this byte array and + returns a reference to this byte array. +*/ + +/*! \fn int QByteArray::length() const + + Same as size(). +*/ + +/*! \fn bool QByteArray::isNull() const + + Returns true if this byte array is null; otherwise returns false. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 13 + + Qt makes a distinction between null byte arrays and empty byte + arrays for historical reasons. For most applications, what + matters is whether or not a byte array contains any data, + and this can be determined using isEmpty(). + + \sa isEmpty() +*/ + +/*! \fn QByteArray::QByteArray() + + Constructs an empty byte array. + + \sa isEmpty() +*/ + +/*! \fn QByteArray::QByteArray(const char *str) + + Constructs a byte array initialized with the string \a str. + + QByteArray makes a deep copy of the string data. +*/ + +QByteArray::QByteArray(const char *str) +{ + if (!str) { + d = &shared_null; + } else if (!*str) { + d = &shared_empty; + } else { + int len = qstrlen(str); + d = static_cast<Data *>(qMalloc(sizeof(Data)+len)); + if (!d) { + d = &shared_null; + } else { + d->ref = 0;; + d->alloc = d->size = len; + d->data = d->array; + memcpy(d->array, str, len+1); // include null terminator + } + } + d->ref.ref(); +} + +/*! + Constructs a byte array containing the first \a size bytes of + array \a data. + + If \a data is 0, a null byte array is constructed. + + QByteArray makes a deep copy of the string data. + + \sa fromRawData() +*/ + +QByteArray::QByteArray(const char *data, int size) +{ + if (!data) { + d = &shared_null; + } else if (size <= 0) { + d = &shared_empty; + } else { + d = static_cast<Data *>(qMalloc(sizeof(Data) + size)); + if (!d) { + d = &shared_null; + } else { + d->ref = 0; + d->alloc = d->size = size; + d->data = d->array; + memcpy(d->array, data, size); + d->array[size] = '\0'; + } + } + d->ref.ref(); +} + +/*! + Constructs a byte array of size \a size with every byte set to + character \a ch. + + \sa fill() +*/ + +QByteArray::QByteArray(int size, char ch) +{ + if (size <= 0) { + d = &shared_null; + } else { + d = static_cast<Data *>(qMalloc(sizeof(Data)+size)); + if (!d) { + d = &shared_null; + } else { + d->ref = 0; + d->alloc = d->size = size; + d->data = d->array; + d->array[size] = '\0'; + memset(d->array, ch, size); + } + } + d->ref.ref(); +} + +/*! + Sets the size of the byte array to \a size bytes. + + If \a size is greater than the current size, the byte array is + extended to make it \a size bytes with the extra bytes added to + the end. The new bytes are uninitialized. + + If \a size is less than the current size, bytes are removed from + the end. + + \sa size() +*/ + +void QByteArray::resize(int size) +{ + if (size <= 0) { + Data *x = &shared_empty; + x->ref.ref(); + if (!d->ref.deref()) + qFree(d); + d = x; + } else if (d == &shared_null) { + // + // Optimize the idiom: + // QByteArray a; + // a.resize(sz); + // ... + // which is used in place of the Qt 3 idiom: + // QByteArray a(sz); + // + Data *x = static_cast<Data *>(qMalloc(sizeof(Data)+size)); + if (!x) + return; + x->ref = 1; + x->alloc = x->size = size; + x->data = x->array; + x->array[size] = '\0'; + (void) d->ref.deref(); // cannot be 0, x points to shared_null + d = x; + } else { + if (d->ref != 1 || size > d->alloc || (size < d->size && size < d->alloc >> 1)) + realloc(qAllocMore(size, sizeof(Data))); + if (d->alloc >= size) { + d->size = size; + if (d->data == d->array) { + d->array[size] = '\0'; + } + } + } +} + +/*! + Sets every byte in the byte array to character \a ch. If \a size + is different from -1 (the default), the byte array is resized to + size \a size beforehand. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 14 + + \sa resize() +*/ + +QByteArray &QByteArray::fill(char ch, int size) +{ + resize(size < 0 ? d->size : size); + if (d->size) + memset(d->data, ch, d->size); + return *this; +} + +void QByteArray::realloc(int alloc) +{ + if (d->ref != 1 || d->data != d->array) { + Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc)); + if (!x) + return; + x->size = qMin(alloc, d->size); + ::memcpy(x->array, d->data, x->size); + x->array[x->size] = '\0'; + x->ref = 1; + x->alloc = alloc; + x->data = x->array; + if (!d->ref.deref()) + qFree(d); + d = x; + } else { + Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc)); + if (!x) + return; + x->alloc = alloc; + x->data = x->array; + d = x; + } +} + +void QByteArray::expand(int i) +{ + resize(qMax(i + 1, d->size)); +} + +/*! + \internal + Return a QByteArray that is sure to be NUL-terminated. + + By default, all QByteArray have an extra NUL at the end, + guaranteeing that assumption. However, if QByteArray::fromRawData + is used, then the NUL is there only if the user put it there. We + can't be sure. +*/ +QByteArray QByteArray::nulTerminated() const +{ + // is this fromRawData? + if (d->data == d->array) + return *this; // no, then we're sure we're zero terminated + + QByteArray copy(*this); + copy.detach(); + return copy; +} + +/*! + Prepends the byte array \a ba to this byte array and returns a + reference to this byte array. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 15 + + This is the same as insert(0, \a ba). + + Note: QByteArray is an \l{implicitly shared} class. Consequently, + if \e this is an empty QByteArray, then \e this will just share + the data held in \a ba. In this case, no copying of data is done. + + \sa append(), insert() +*/ + +QByteArray &QByteArray::prepend(const QByteArray &ba) +{ + if ((d == &shared_null || d == &shared_empty) && !IS_RAW_DATA(ba.d)) { + *this = ba; + } else if (ba.d != &shared_null) { + QByteArray tmp = *this; + *this = ba; + append(tmp); + } + return *this; +} + +/*! + \overload + + Prepends the string \a str to this byte array. +*/ + +QByteArray &QByteArray::prepend(const char *str) +{ + if (str) { + int len = qstrlen(str); + if (d->ref != 1 || d->size + len > d->alloc) + realloc(qAllocMore(d->size + len, sizeof(Data))); + memmove(d->data+len, d->data, d->size); + memcpy(d->data, str, len); + d->size += len; + d->data[d->size] = '\0'; + } + return *this; +} + +/*! + \overload + + Prepends the character \a ch to this byte array. +*/ + +QByteArray &QByteArray::prepend(char ch) +{ + if (d->ref != 1 || d->size + 1 > d->alloc) + realloc(qAllocMore(d->size + 1, sizeof(Data))); + memmove(d->data+1, d->data, d->size); + d->data[0] = ch; + ++d->size; + d->data[d->size] = '\0'; + return *this; +} + +/*! + Appends the byte array \a ba onto the end of this byte array. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 16 + + This is the same as insert(size(), \a ba). + + This operation is typically very fast (\l{constant time}), + because QByteArray preallocates extra space at the end of the + character data so it can grow without reallocating the entire + data each time. + + Note: QByteArray is an \l{implicitly shared} class. Consequently, + if \e this is an empty QByteArray, then \e this will just share + the data held in \a ba. In this case, no copying of data is done. + + \sa operator+=(), prepend(), insert() +*/ + +QByteArray &QByteArray::append(const QByteArray &ba) +{ + if ((d == &shared_null || d == &shared_empty) && !IS_RAW_DATA(ba.d)) { + *this = ba; + } else if (ba.d != &shared_null) { + if (d->ref != 1 || d->size + ba.d->size > d->alloc) + realloc(qAllocMore(d->size + ba.d->size, sizeof(Data))); + memcpy(d->data + d->size, ba.d->data, ba.d->size); + d->size += ba.d->size; + d->data[d->size] = '\0'; + } + return *this; +} + +/*! \fn QByteArray &QByteArray::append(const QString &str) + + \overload + + Appends the string \a str to this byte array. The Unicode data is + converted into 8-bit characters using QString::toAscii(). + + If the QString contains non-ASCII Unicode characters, using this + function can lead to loss of information. You can disable this + function by defining \c QT_NO_CAST_TO_ASCII when you compile your + applications. You then need to call QString::toAscii() (or + QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit()) + explicitly if you want to convert the data to \c{const char *}. +*/ + +/*! + \overload + + Appends the string \a str to this byte array. +*/ + +QByteArray& QByteArray::append(const char *str) +{ + if (str) { + int len = qstrlen(str); + if (d->ref != 1 || d->size + len > d->alloc) + realloc(qAllocMore(d->size + len, sizeof(Data))); + memcpy(d->data + d->size, str, len + 1); // include null terminator + d->size += len; + } + return *this; +} + +/*! + \overload append() + + Appends the first \a len characters of the string \a str to this byte + array and returns a reference to this byte array. + + If \a len is negative, the length of the string will be determined + automatically using qstrlen(). If \a len is zero or the length of the + string is zero, nothing will be appended to the byte array. +*/ + +QByteArray &QByteArray::append(const char *str, int len) +{ + if (len < 0) + len = qstrlen(str); + if (str && len) { + if (d->ref != 1 || d->size + len > d->alloc) + realloc(qAllocMore(d->size + len, sizeof(Data))); + memcpy(d->data + d->size, str, len); // include null terminator + d->size += len; + d->data[d->size] = '\0'; + } + return *this; +} + +/*! + \overload + + Appends the character \a ch to this byte array. +*/ + +QByteArray& QByteArray::append(char ch) +{ + if (d->ref != 1 || d->size + 1 > d->alloc) + realloc(qAllocMore(d->size + 1, sizeof(Data))); + d->data[d->size++] = ch; + d->data[d->size] = '\0'; + return *this; +} + +/*! + \internal + Inserts \a len bytes from the array \a arr at position \a pos and returns a + reference the modified byte array. +*/ +static inline QByteArray &qbytearray_insert(QByteArray *ba, + int pos, const char *arr, int len) +{ + Q_ASSERT(pos >= 0); + + if (pos < 0 || len <= 0 || arr == 0) + return *ba; + + int oldsize = ba->size(); + ba->resize(qMax(pos, oldsize) + len); + char *dst = ba->data(); + if (pos > oldsize) + ::memset(dst + oldsize, 0x20, pos - oldsize); + else + ::memmove(dst + pos + len, dst + pos, oldsize - pos); + memcpy(dst + pos, arr, len); + return *ba; +} + +/*! + Inserts the byte array \a ba at index position \a i and returns a + reference to this byte array. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 17 + + \sa append(), prepend(), replace(), remove() +*/ + +QByteArray &QByteArray::insert(int i, const QByteArray &ba) +{ + QByteArray copy(ba); + return qbytearray_insert(this, i, copy.d->data, copy.d->size); +} + +/*! + \fn QByteArray &QByteArray::insert(int i, const QString &str) + + \overload + + Inserts the string \a str at index position \a i in the byte + array. The Unicode data is converted into 8-bit characters using + QString::toAscii(). + + If \a i is greater than size(), the array is first extended using + resize(). + + If the QString contains non-ASCII Unicode characters, using this + function can lead to loss of information. You can disable this + function by defining \c QT_NO_CAST_TO_ASCII when you compile your + applications. You then need to call QString::toAscii() (or + QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit()) + explicitly if you want to convert the data to \c{const char *}. +*/ + +/*! + \overload + + Inserts the string \a str at position \a i in the byte array. + + If \a i is greater than size(), the array is first extended using + resize(). +*/ + +QByteArray &QByteArray::insert(int i, const char *str) +{ + return qbytearray_insert(this, i, str, qstrlen(str)); +} + +/*! + \overload + + Inserts character \a ch at index position \a i in the byte array. + If \a i is greater than size(), the array is first extended using + resize(). +*/ + +QByteArray &QByteArray::insert(int i, char ch) +{ + return qbytearray_insert(this, i, &ch, 1); +} + +/*! + Removes \a len bytes from the array, starting at index position \a + pos, and returns a reference to the array. + + If \a pos is out of range, nothing happens. If \a pos is valid, + but \a pos + \a len is larger than the size of the array, the + array is truncated at position \a pos. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 18 + + \sa insert(), replace() +*/ + +QByteArray &QByteArray::remove(int pos, int len) +{ + if (len <= 0 || pos >= d->size || pos < 0) + return *this; + detach(); + if (pos + len >= d->size) { + resize(pos); + } else { + memmove(d->data + pos, d->data + pos + len, d->size - pos - len); + resize(d->size - len); + } + return *this; +} + +/*! + Replaces \a len bytes from index position \a pos with the byte + array \a after, and returns a reference to this byte array. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 19 + + \sa insert(), remove() +*/ + +QByteArray &QByteArray::replace(int pos, int len, const QByteArray &after) +{ + if (len == after.d->size && (pos + len <= d->size)) { + detach(); + memmove(d->data + pos, after.d->data, len*sizeof(char)); + return *this; + } else { + QByteArray copy(after); + // ### optimise me + remove(pos, len); + return insert(pos, copy); + } +} + +/*! \fn QByteArray &QByteArray::replace(int pos, int len, const char *after) + + \overload +*/ +QByteArray &QByteArray::replace(int pos, int len, const char *after) +{ + int alen = qstrlen(after); + if (len == alen && (pos + len <= d->size)) { + detach(); + memcpy(d->data + pos, after, len*sizeof(char)); + return *this; + } else { + remove(pos, len); + return qbytearray_insert(this, pos, after, alen); + } +} + +// ### optimise all other replace method, by offering +// QByteArray::replace(const char *before, int blen, const char *after, int alen) + +/*! + \overload + + Replaces every occurrence of the byte array \a before with the + byte array \a after. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 20 +*/ + +QByteArray &QByteArray::replace(const QByteArray &before, const QByteArray &after) +{ + if (isNull() || before.d == after.d) + return *this; + + QByteArray aft = after; + if (after.d == d) + aft.detach(); + + return replace(before.constData(), before.size(), aft.constData(), aft.size()); +} + +/*! + \fn QByteArray &QByteArray::replace(const char *before, const QByteArray &after) + \overload + + Replaces every occurrence of the string \a before with the + byte array \a after. +*/ + +QByteArray &QByteArray::replace(const char *c, const QByteArray &after) +{ + QByteArray aft = after; + if (after.d == d) + aft.detach(); + + return replace(c, qstrlen(c), aft.constData(), aft.size()); +} + +/*! + \fn QByteArray &QByteArray::replace(const char *before, int bsize, const char *after, int asize) + \overload + + Replaces every occurrence of the string \a before with the string \a after. + Since the sizes of the strings are given by \a bsize and \a asize, they + may contain zero characters and do not need to be zero-terminated. +*/ + +QByteArray &QByteArray::replace(const char *before, int bsize, const char *after, int asize) +{ + if (isNull() || (before == after && bsize == asize)) + return *this; + + // protect against before or after being part of this + const char *a = after; + const char *b = before; + if (after >= d->data && after < d->data + d->size) { + char *copy = (char *)malloc(asize); + memcpy(copy, after, asize); + a = copy; + } + if (before >= d->data && before < d->data + d->size) { + char *copy = (char *)malloc(bsize); + memcpy(copy, before, bsize); + b = copy; + } + + QByteArrayMatcher matcher(before, bsize); + int index = 0; + int len = d->size; + char *d = data(); + + if (bsize == asize) { + if (bsize) { + while ((index = matcher.indexIn(*this, index)) != -1) { + memcpy(d + index, after, asize); + index += bsize; + } + } + } else if (asize < bsize) { + uint to = 0; + uint movestart = 0; + uint num = 0; + while ((index = matcher.indexIn(*this, index)) != -1) { + if (num) { + int msize = index - movestart; + if (msize > 0) { + memmove(d + to, d + movestart, msize); + to += msize; + } + } else { + to = index; + } + if (asize) { + memcpy(d + to, after, asize); + to += asize; + } + index += bsize; + movestart = index; + num++; + } + if (num) { + int msize = len - movestart; + if (msize > 0) + memmove(d + to, d + movestart, msize); + resize(len - num*(bsize-asize)); + } + } else { + // the most complex case. We don't want to lose performance by doing repeated + // copies and reallocs of the string. + while (index != -1) { + uint indices[4096]; + uint pos = 0; + while(pos < 4095) { + index = matcher.indexIn(*this, index); + if (index == -1) + break; + indices[pos++] = index; + index += bsize; + // avoid infinite loop + if (!bsize) + index++; + } + if (!pos) + break; + + // we have a table of replacement positions, use them for fast replacing + int adjust = pos*(asize-bsize); + // index has to be adjusted in case we get back into the loop above. + if (index != -1) + index += adjust; + int newlen = len + adjust; + int moveend = len; + if (newlen > len) { + resize(newlen); + len = newlen; + } + d = this->d->data; + + while(pos) { + pos--; + int movestart = indices[pos] + bsize; + int insertstart = indices[pos] + pos*(asize-bsize); + int moveto = insertstart + asize; + memmove(d + moveto, d + movestart, (moveend - movestart)); + if (asize) + memcpy(d + insertstart, after, asize); + moveend = movestart - bsize; + } + } + } + + if (a != after) + ::free((char *)a); + if (b != before) + ::free((char *)b); + + + return *this; +} + + +/*! + \fn QByteArray &QByteArray::replace(const QByteArray &before, const char *after) + \overload + + Replaces every occurrence of the byte array \a before with the + string \a after. +*/ + +/*! \fn QByteArray &QByteArray::replace(const QString &before, const QByteArray &after) + + \overload + + Replaces every occurrence of the string \a before with the byte + array \a after. The Unicode data is converted into 8-bit + characters using QString::toAscii(). + + If the QString contains non-ASCII Unicode characters, using this + function can lead to loss of information. You can disable this + function by defining \c QT_NO_CAST_TO_ASCII when you compile your + applications. You then need to call QString::toAscii() (or + QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit()) + explicitly if you want to convert the data to \c{const char *}. +*/ + +/*! \fn QByteArray &QByteArray::replace(const QString &before, const char *after) + \overload + + Replaces every occurrence of the string \a before with the string + \a after. +*/ + +/*! \fn QByteArray &QByteArray::replace(const char *before, const char *after) + + \overload + + Replaces every occurrence of the string \a before with the string + \a after. +*/ + +/*! + \overload + + Replaces every occurrence of the character \a before with the + byte array \a after. +*/ + +QByteArray &QByteArray::replace(char before, const QByteArray &after) +{ + char b[2] = { before, '\0' }; + QByteArray cb = fromRawData(b, 1); + return replace(cb, after); +} + +/*! \fn QByteArray &QByteArray::replace(char before, const QString &after) + + \overload + + Replaces every occurrence of the character \a before with the + string \a after. The Unicode data is converted into 8-bit + characters using QString::toAscii(). + + If the QString contains non-ASCII Unicode characters, using this + function can lead to loss of information. You can disable this + function by defining \c QT_NO_CAST_TO_ASCII when you compile your + applications. You then need to call QString::toAscii() (or + QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit()) + explicitly if you want to convert the data to \c{const char *}. +*/ + +/*! \fn QByteArray &QByteArray::replace(char before, const char *after) + + \overload + + Replaces every occurrence of the character \a before with the + string \a after. +*/ + +/*! + \overload + + Replaces every occurrence of the character \a before with the + character \a after. +*/ + +QByteArray &QByteArray::replace(char before, char after) +{ + if (d->size) { + char *i = data(); + char *e = i + d->size; + for (; i != e; ++i) + if (*i == before) + * i = after; + } + return *this; +} + +/*! + Splits the byte array into subarrays wherever \a sep occurs, and + returns the list of those arrays. If \a sep does not match + anywhere in the byte array, split() returns a single-element list + containing this byte array. +*/ + +QList<QByteArray> QByteArray::split(char sep) const +{ + QList<QByteArray> list; + int start = 0; + int end; + while ((end = indexOf(sep, start)) != -1) { + list.append(mid(start, end - start)); + start = end + 1; + } + list.append(mid(start)); + return list; +} + +/*! + \since 4.5 + + Returns a copy of this byte array repeated the specified number of \a times. + + If \a times is less than 1, an empty byte array is returned. + + Example: + + \code + QByteArray ba("ab"); + ba.repeated(4); // returns "abababab" + \endcode +*/ +QByteArray QByteArray::repeated(int times) const +{ + if (d->size == 0) + return *this; + + if (times <= 1) { + if (times == 1) + return *this; + return QByteArray(); + } + + const int resultSize = times * d->size; + + QByteArray result; + result.reserve(resultSize); + if (result.d->alloc != resultSize) + return QByteArray(); // not enough memory + + qMemCopy(result.d->data, d->data, d->size); + + int sizeSoFar = d->size; + char *end = result.d->data + sizeSoFar; + + const int halfResultSize = resultSize >> 1; + while (sizeSoFar <= halfResultSize) { + qMemCopy(end, result.d->data, sizeSoFar); + end += sizeSoFar; + sizeSoFar <<= 1; + } + qMemCopy(end, result.d->data, resultSize - sizeSoFar); + result.d->data[resultSize] = '\0'; + result.d->size = resultSize; + return result; +} + +#define REHASH(a) \ + if (ol_minus_1 < sizeof(uint) * CHAR_BIT) \ + hashHaystack -= (a) << ol_minus_1; \ + hashHaystack <<= 1 + +/*! + Returns the index position of the first occurrence of the byte + array \a ba in this byte array, searching forward from index + position \a from. Returns -1 if \a ba could not be found. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 21 + + \sa lastIndexOf(), contains(), count() +*/ + +int QByteArray::indexOf(const QByteArray &ba, int from) const +{ + const int ol = ba.d->size; + if (ol == 0) + return from; + if (ol == 1) + return indexOf(*ba.d->data, from); + + const int l = d->size; + if (from > d->size || ol + from > l) + return -1; + + return qFindByteArray(d->data, d->size, from, ba.d->data, ol); +} + +/*! \fn int QByteArray::indexOf(const QString &str, int from) const + + \overload + + Returns the index position of the first occurrence of the string + \a str in the byte array, searching forward from index position + \a from. Returns -1 if \a str could not be found. + + The Unicode data is converted into 8-bit characters using + QString::toAscii(). + + If the QString contains non-ASCII Unicode characters, using this + function can lead to loss of information. You can disable this + function by defining \c QT_NO_CAST_TO_ASCII when you compile your + applications. You then need to call QString::toAscii() (or + QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit()) + explicitly if you want to convert the data to \c{const char *}. +*/ + +/*! \fn int QByteArray::indexOf(const char *str, int from) const + + \overload + + Returns the index position of the first occurrence of the string + \a str in the byte array, searching forward from index position \a + from. Returns -1 if \a str could not be found. +*/ +int QByteArray::indexOf(const char *c, int from) const +{ + const int ol = qstrlen(c); + if (ol == 1) + return indexOf(*c, from); + + const int l = d->size; + if (from > d->size || ol + from > l) + return -1; + if (ol == 0) + return from; + + return qFindByteArray(d->data, d->size, from, c, ol); +} + +/*! + \overload + + Returns the index position of the first occurrence of the + character \a ch in the byte array, searching forward from index + position \a from. Returns -1 if \a ch could not be found. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 22 + + \sa lastIndexOf(), contains() +*/ + +int QByteArray::indexOf(char ch, int from) const +{ + if (from < 0) + from = qMax(from + d->size, 0); + if (from < d->size) { + const char *n = d->data + from - 1; + const char *e = d->data + d->size; + while (++n != e) + if (*n == ch) + return n - d->data; + } + return -1; +} + + +static int lastIndexOfHelper(const char *haystack, int l, const char *needle, int ol, int from) +{ + int delta = l - ol; + if (from < 0) + from = delta; + if (from < 0 || from > l) + return -1; + if (from > delta) + from = delta; + + const char *end = haystack; + haystack += from; + const uint ol_minus_1 = ol - 1; + const char *n = needle + ol_minus_1; + const char *h = haystack + ol_minus_1; + uint hashNeedle = 0, hashHaystack = 0; + int idx; + for (idx = 0; idx < ol; ++idx) { + hashNeedle = ((hashNeedle<<1) + *(n-idx)); + hashHaystack = ((hashHaystack<<1) + *(h-idx)); + } + hashHaystack -= *haystack; + while (haystack >= end) { + hashHaystack += *haystack; + if (hashHaystack == hashNeedle && memcmp(needle, haystack, ol) == 0) + return haystack - end; + --haystack; + REHASH(*(haystack + ol)); + } + return -1; + +} + +/*! + \fn int QByteArray::lastIndexOf(const QByteArray &ba, int from) const + + Returns the index position of the last occurrence of the byte + array \a ba in this byte array, searching backward from index + position \a from. If \a from is -1 (the default), the search + starts at the last byte. Returns -1 if \a ba could not be found. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 23 + + \sa indexOf(), contains(), count() +*/ + +int QByteArray::lastIndexOf(const QByteArray &ba, int from) const +{ + const int ol = ba.d->size; + if (ol == 1) + return lastIndexOf(*ba.d->data, from); + + return lastIndexOfHelper(d->data, d->size, ba.d->data, ol, from); +} + +/*! \fn int QByteArray::lastIndexOf(const QString &str, int from) const + + \overload + + Returns the index position of the last occurrence of the string \a + str in the byte array, searching backward from index position \a + from. If \a from is -1 (the default), the search starts at the + last (size() - 1) byte. Returns -1 if \a str could not be found. + + The Unicode data is converted into 8-bit characters using + QString::toAscii(). + + If the QString contains non-ASCII Unicode characters, using this + function can lead to loss of information. You can disable this + function by defining \c QT_NO_CAST_TO_ASCII when you compile your + applications. You then need to call QString::toAscii() (or + QString::toLatin1() or QString::toUtf8() or QString::toLocal8Bit()) + explicitly if you want to convert the data to \c{const char *}. +*/ + +/*! \fn int QByteArray::lastIndexOf(const char *str, int from) const + \overload + + Returns the index position of the last occurrence of the string \a + str in the byte array, searching backward from index position \a + from. If \a from is -1 (the default), the search starts at the + last (size() - 1) byte. Returns -1 if \a str could not be found. +*/ +int QByteArray::lastIndexOf(const char *str, int from) const +{ + const int ol = qstrlen(str); + if (ol == 1) + return lastIndexOf(*str, from); + + return lastIndexOfHelper(d->data, d->size, str, ol, from); +} + +/*! + \overload + + Returns the index position of the last occurrence of character \a + ch in the byte array, searching backward from index position \a + from. If \a from is -1 (the default), the search starts at the + last (size() - 1) byte. Returns -1 if \a ch could not be found. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 24 + + \sa indexOf(), contains() +*/ + +int QByteArray::lastIndexOf(char ch, int from) const +{ + if (from < 0) + from += d->size; + else if (from > d->size) + from = d->size-1; + if (from >= 0) { + const char *b = d->data; + const char *n = d->data + from + 1; + while (n-- != b) + if (*n == ch) + return n - b; + } + return -1; +} + +/*! + Returns the number of (potentially overlapping) occurrences of + byte array \a ba in this byte array. + + \sa contains(), indexOf() +*/ + +int QByteArray::count(const QByteArray &ba) const +{ + int num = 0; + int i = -1; + if (d->size > 500 && ba.d->size > 5) { + QByteArrayMatcher matcher(ba); + while ((i = matcher.indexIn(*this, i + 1)) != -1) + ++num; + } else { + while ((i = indexOf(ba, i + 1)) != -1) + ++num; + } + return num; +} + +/*! + \overload + + Returns the number of (potentially overlapping) occurrences of + string \a str in the byte array. +*/ + +int QByteArray::count(const char *str) const +{ + return count(fromRawData(str, qstrlen(str))); +} + +/*! + \overload + + Returns the number of occurrences of character \a ch in the byte + array. + + \sa contains(), indexOf() +*/ + +int QByteArray::count(char ch) const +{ + int num = 0; + const char *i = d->data + d->size; + const char *b = d->data; + while (i != b) + if (*--i == ch) + ++num; + return num; +} + +/*! \fn int QByteArray::count() const + + \overload + + Same as size(). +*/ + +/*! + Returns true if this byte array starts with byte array \a ba; + otherwise returns false. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 25 + + \sa endsWith(), left() +*/ +bool QByteArray::startsWith(const QByteArray &ba) const +{ + if (d == ba.d || ba.d->size == 0) + return true; + if (d->size < ba.d->size) + return false; + return memcmp(d->data, ba.d->data, ba.d->size) == 0; +} + +/*! \overload + + Returns true if this byte array starts with string \a str; + otherwise returns false. +*/ +bool QByteArray::startsWith(const char *str) const +{ + if (!str || !*str) + return true; + int len = qstrlen(str); + if (d->size < len) + return false; + return qstrncmp(d->data, str, len) == 0; +} + +/*! \overload + + Returns true if this byte array starts with character \a ch; + otherwise returns false. +*/ +bool QByteArray::startsWith(char ch) const +{ + if (d->size == 0) + return false; + return d->data[0] == ch; +} + +/*! + Returns true if this byte array ends with byte array \a ba; + otherwise returns false. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 26 + + \sa startsWith(), right() +*/ +bool QByteArray::endsWith(const QByteArray &ba) const +{ + if (d == ba.d || ba.d->size == 0) + return true; + if (d->size < ba.d->size) + return false; + return memcmp(d->data + d->size - ba.d->size, ba.d->data, ba.d->size) == 0; +} + +/*! \overload + + Returns true if this byte array ends with string \a str; otherwise + returns false. +*/ +bool QByteArray::endsWith(const char *str) const +{ + if (!str || !*str) + return true; + int len = qstrlen(str); + if (d->size < len) + return false; + return qstrncmp(d->data + d->size - len, str, len) == 0; +} + +/*! \overload + + Returns true if this byte array ends with character \a ch; + otherwise returns false. +*/ +bool QByteArray::endsWith(char ch) const +{ + if (d->size == 0) + return false; + return d->data[d->size - 1] == ch; +} + +/*! + Returns a byte array that contains the leftmost \a len bytes of + this byte array. + + The entire byte array is returned if \a len is greater than + size(). + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 27 + + \sa right(), mid(), startsWith(), truncate() +*/ + +QByteArray QByteArray::left(int len) const +{ + if (len >= d->size) + return *this; + if (len < 0) + len = 0; + return QByteArray(d->data, len); +} + +/*! + Returns a byte array that contains the rightmost \a len bytes of + this byte array. + + The entire byte array is returned if \a len is greater than + size(). + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 28 + + \sa endsWith(), left(), mid() +*/ + +QByteArray QByteArray::right(int len) const +{ + if (len >= d->size) + return *this; + if (len < 0) + len = 0; + return QByteArray(d->data + d->size - len, len); +} + +/*! + Returns a byte array containing \a len bytes from this byte array, + starting at position \a pos. + + If \a len is -1 (the default), or \a pos + \a len >= size(), + returns a byte array containing all bytes starting at position \a + pos until the end of the byte array. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 29 + + \sa left(), right() +*/ + +QByteArray QByteArray::mid(int pos, int len) const +{ + if (d == &shared_null || d == &shared_empty || pos >= d->size) + return QByteArray(); + if (len < 0) + len = d->size - pos; + if (pos < 0) { + len += pos; + pos = 0; + } + if (len + pos > d->size) + len = d->size - pos; + if (pos == 0 && len == d->size) + return *this; + return QByteArray(d->data + pos, len); +} + +/*! + Returns a lowercase copy of the byte array. The bytearray is + interpreted as a Latin-1 encoded string. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 30 + + \sa toUpper(), {8-bit Character Comparisons} +*/ +QByteArray QByteArray::toLower() const +{ + QByteArray s(*this); + register uchar *p = reinterpret_cast<uchar *>(s.data()); + if (p) { + while (*p) { + *p = QChar::toLower((ushort)*p); + p++; + } + } + return s; +} + +/*! + Returns an uppercase copy of the byte array. The bytearray is + interpreted as a Latin-1 encoded string. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 31 + + \sa toLower(), {8-bit Character Comparisons} +*/ + +QByteArray QByteArray::toUpper() const +{ + QByteArray s(*this); + register uchar *p = reinterpret_cast<uchar *>(s.data()); + if (p) { + while (*p) { + *p = QChar::toUpper((ushort)*p); + p++; + } + } + return s; +} + +/*! \fn void QByteArray::clear() + + Clears the contents of the byte array and makes it empty. + + \sa resize(), isEmpty() +*/ + +void QByteArray::clear() +{ + if (!d->ref.deref()) + qFree(d); + d = &shared_null; + d->ref.ref(); +} + +/*! \relates QByteArray + + Writes byte array \a ba to the stream \a out and returns a reference + to the stream. + + \sa {Format of the QDataStream operators} +*/ +#ifndef QT_NO_DATASTREAM + +QDataStream &operator<<(QDataStream &out, const QByteArray &ba) +{ + if (ba.isNull() && out.version() >= 6) { + out << (quint32)0xffffffff; + return out; + } + return out.writeBytes(ba, ba.size()); +} + +/*! \relates QByteArray + + Reads a byte array into \a ba from the stream \a in and returns a + reference to the stream. + + \sa {Format of the QDataStream operators} +*/ + +QDataStream &operator>>(QDataStream &in, QByteArray &ba) +{ + ba.clear(); + quint32 len; + in >> len; + if (len == 0xffffffff) + return in; + + const quint32 Step = 1024 * 1024; + quint32 allocated = 0; + + do { + int blockSize = qMin(Step, len - allocated); + ba.resize(allocated + blockSize); + if (in.readRawData(ba.data() + allocated, blockSize) != blockSize) { + ba.clear(); + in.setStatus(QDataStream::ReadPastEnd); + return in; + } + allocated += blockSize; + } while (allocated < len); + + return in; +} +#endif //QT_NO_DATASTREAM + +/*! \fn bool QByteArray::operator==(const QString &str) const + + Returns true if this byte array is equal to string \a str; + otherwise returns false. + + The Unicode data is converted into 8-bit characters using + QString::toAscii(). + + The comparison is case sensitive. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. You + then need to call QString::fromAscii(), QString::fromLatin1(), + QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if + you want to convert the byte array to a QString before doing the + comparison. +*/ + +/*! \fn bool QByteArray::operator!=(const QString &str) const + + Returns true if this byte array is not equal to string \a str; + otherwise returns false. + + The Unicode data is converted into 8-bit characters using + QString::toAscii(). + + The comparison is case sensitive. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. You + then need to call QString::fromAscii(), QString::fromLatin1(), + QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if + you want to convert the byte array to a QString before doing the + comparison. +*/ + +/*! \fn bool QByteArray::operator<(const QString &str) const + + Returns true if this byte array is lexically less than string \a + str; otherwise returns false. + + The Unicode data is converted into 8-bit characters using + QString::toAscii(). + + The comparison is case sensitive. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. You + then need to call QString::fromAscii(), QString::fromLatin1(), + QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if + you want to convert the byte array to a QString before doing the + comparison. +*/ + +/*! \fn bool QByteArray::operator>(const QString &str) const + + Returns true if this byte array is lexically greater than string + \a str; otherwise returns false. + + The Unicode data is converted into 8-bit characters using + QString::toAscii(). + + The comparison is case sensitive. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. You + then need to call QString::fromAscii(), QString::fromLatin1(), + QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if + you want to convert the byte array to a QString before doing the + comparison. +*/ + +/*! \fn bool QByteArray::operator<=(const QString &str) const + + Returns true if this byte array is lexically less than or equal + to string \a str; otherwise returns false. + + The Unicode data is converted into 8-bit characters using + QString::toAscii(). + + The comparison is case sensitive. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. You + then need to call QString::fromAscii(), QString::fromLatin1(), + QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if + you want to convert the byte array to a QString before doing the + comparison. +*/ + +/*! \fn bool QByteArray::operator>=(const QString &str) const + + Returns true if this byte array is greater than or equal to string + \a str; otherwise returns false. + + The Unicode data is converted into 8-bit characters using + QString::toAscii(). + + The comparison is case sensitive. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. You + then need to call QString::fromAscii(), QString::fromLatin1(), + QString::fromUtf8(), or QString::fromLocal8Bit() explicitly if + you want to convert the byte array to a QString before doing the + comparison. +*/ + +/*! \fn bool operator==(const QByteArray &a1, const QByteArray &a2) + \relates QByteArray + + \overload + + Returns true if byte array \a a1 is equal to byte array \a a2; + otherwise returns false. +*/ + +/*! \fn bool operator==(const QByteArray &a1, const char *a2) + \relates QByteArray + + \overload + + Returns true if byte array \a a1 is equal to string \a a2; + otherwise returns false. +*/ + +/*! \fn bool operator==(const char *a1, const QByteArray &a2) + \relates QByteArray + + \overload + + Returns true if string \a a1 is equal to byte array \a a2; + otherwise returns false. +*/ + +/*! \fn bool operator!=(const QByteArray &a1, const QByteArray &a2) + \relates QByteArray + + \overload + + Returns true if byte array \a a1 is not equal to byte array \a a2; + otherwise returns false. +*/ + +/*! \fn bool operator!=(const QByteArray &a1, const char *a2) + \relates QByteArray + + \overload + + Returns true if byte array \a a1 is not equal to string \a a2; + otherwise returns false. +*/ + +/*! \fn bool operator!=(const char *a1, const QByteArray &a2) + \relates QByteArray + + \overload + + Returns true if string \a a1 is not equal to byte array \a a2; + otherwise returns false. +*/ + +/*! \fn bool operator<(const QByteArray &a1, const QByteArray &a2) + \relates QByteArray + + \overload + + Returns true if byte array \a a1 is lexically less than byte array + \a a2; otherwise returns false. +*/ + +/*! \fn inline bool operator<(const QByteArray &a1, const char *a2) + \relates QByteArray + + \overload + + Returns true if byte array \a a1 is lexically less than string + \a a2; otherwise returns false. +*/ + +/*! \fn bool operator<(const char *a1, const QByteArray &a2) + \relates QByteArray + + \overload + + Returns true if string \a a1 is lexically less than byte array + \a a2; otherwise returns false. +*/ + +/*! \fn bool operator<=(const QByteArray &a1, const QByteArray &a2) + \relates QByteArray + + \overload + + Returns true if byte array \a a1 is lexically less than or equal + to byte array \a a2; otherwise returns false. +*/ + +/*! \fn bool operator<=(const QByteArray &a1, const char *a2) + \relates QByteArray + + \overload + + Returns true if byte array \a a1 is lexically less than or equal + to string \a a2; otherwise returns false. +*/ + +/*! \fn bool operator<=(const char *a1, const QByteArray &a2) + \relates QByteArray + + \overload + + Returns true if string \a a1 is lexically less than or equal + to byte array \a a2; otherwise returns false. +*/ + +/*! \fn bool operator>(const QByteArray &a1, const QByteArray &a2) + \relates QByteArray + + \overload + + Returns true if byte array \a a1 is lexically greater than byte + array \a a2; otherwise returns false. +*/ + +/*! \fn bool operator>(const QByteArray &a1, const char *a2) + \relates QByteArray + + \overload + + Returns true if byte array \a a1 is lexically greater than string + \a a2; otherwise returns false. +*/ + +/*! \fn bool operator>(const char *a1, const QByteArray &a2) + \relates QByteArray + + \overload + + Returns true if string \a a1 is lexically greater than byte array + \a a2; otherwise returns false. +*/ + +/*! \fn bool operator>=(const QByteArray &a1, const QByteArray &a2) + \relates QByteArray + + \overload + + Returns true if byte array \a a1 is lexically greater than or + equal to byte array \a a2; otherwise returns false. +*/ + +/*! \fn bool operator>=(const QByteArray &a1, const char *a2) + \relates QByteArray + + \overload + + Returns true if byte array \a a1 is lexically greater than or + equal to string \a a2; otherwise returns false. +*/ + +/*! \fn bool operator>=(const char *a1, const QByteArray &a2) + \relates QByteArray + + \overload + + Returns true if string \a a1 is lexically greater than or + equal to byte array \a a2; otherwise returns false. +*/ + +/*! \fn const QByteArray operator+(const QByteArray &a1, const QByteArray &a2) + \relates QByteArray + + Returns a byte array that is the result of concatenating byte + array \a a1 and byte array \a a2. + + \sa QByteArray::operator+=() +*/ + +/*! \fn const QByteArray operator+(const QByteArray &a1, const char *a2) + \relates QByteArray + + \overload + + Returns a byte array that is the result of concatenating byte + array \a a1 and string \a a2. +*/ + +/*! \fn const QByteArray operator+(const QByteArray &a1, char a2) + \relates QByteArray + + \overload + + Returns a byte array that is the result of concatenating byte + array \a a1 and character \a a2. +*/ + +/*! \fn const QByteArray operator+(const char *a1, const QByteArray &a2) + \relates QByteArray + + \overload + + Returns a byte array that is the result of concatenating string + \a a1 and byte array \a a2. +*/ + +/*! \fn const QByteArray operator+(char a1, const QByteArray &a2) + \relates QByteArray + + \overload + + Returns a byte array that is the result of concatenating character + \a a1 and byte array \a a2. +*/ + +/*! + Returns a byte array that has whitespace removed from the start + and the end, and which has each sequence of internal whitespace + replaced with a single space. + + Whitespace means any character for which the standard C++ + isspace() function returns true. This includes the ASCII + characters '\\t', '\\n', '\\v', '\\f', '\\r', and ' '. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 32 + + \sa trimmed() +*/ +QByteArray QByteArray::simplified() const +{ + if (d->size == 0) + return *this; + QByteArray result; + result.resize(d->size); + const char *from = d->data; + const char *fromend = from + d->size; + int outc=0; + char *to = result.d->data; + for (;;) { + while (from!=fromend && isspace(uchar(*from))) + from++; + while (from!=fromend && !isspace(uchar(*from))) + to[outc++] = *from++; + if (from!=fromend) + to[outc++] = ' '; + else + break; + } + if (outc > 0 && to[outc-1] == ' ') + outc--; + result.resize(outc); + return result; +} + +/*! + Returns a byte array that has whitespace removed from the start + and the end. + + Whitespace means any character for which the standard C++ + isspace() function returns true. This includes the ASCII + characters '\\t', '\\n', '\\v', '\\f', '\\r', and ' '. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 33 + + Unlike simplified(), trimmed() leaves internal whitespace alone. + + \sa simplified() +*/ +QByteArray QByteArray::trimmed() const +{ + if (d->size == 0) + return *this; + const char *s = d->data; + if (!isspace(uchar(*s)) && !isspace(uchar(s[d->size-1]))) + return *this; + int start = 0; + int end = d->size - 1; + while (start<=end && isspace(uchar(s[start]))) // skip white space from start + start++; + if (start <= end) { // only white space + while (end && isspace(uchar(s[end]))) // skip white space from end + end--; + } + int l = end - start + 1; + if (l <= 0) { + shared_empty.ref.ref(); + return QByteArray(&shared_empty, 0, 0); + } + return QByteArray(s+start, l); +} + +/*! + Returns a byte array of size \a width that contains this byte + array padded by the \a fill character. + + If \a truncate is false and the size() of the byte array is more + than \a width, then the returned byte array is a copy of this byte + array. + + If \a truncate is true and the size() of the byte array is more + than \a width, then any bytes in a copy of the byte array + after position \a width are removed, and the copy is returned. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 34 + + \sa rightJustified() +*/ + +QByteArray QByteArray::leftJustified(int width, char fill, bool truncate) const +{ + QByteArray result; + int len = d->size; + int padlen = width - len; + if (padlen > 0) { + result.resize(len+padlen); + if (len) + memcpy(result.d->data, d->data, len); + memset(result.d->data+len, fill, padlen); + } else { + if (truncate) + result = left(width); + else + result = *this; + } + return result; +} + +/*! + Returns a byte array of size \a width that contains the \a fill + character followed by this byte array. + + If \a truncate is false and the size of the byte array is more + than \a width, then the returned byte array is a copy of this byte + array. + + If \a truncate is true and the size of the byte array is more + than \a width, then the resulting byte array is truncated at + position \a width. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 35 + + \sa leftJustified() +*/ + +QByteArray QByteArray::rightJustified(int width, char fill, bool truncate) const +{ + QByteArray result; + int len = d->size; + int padlen = width - len; + if (padlen > 0) { + result.resize(len+padlen); + if (len) + memcpy(result.d->data+padlen, data(), len); + memset(result.d->data, fill, padlen); + } else { + if (truncate) + result = left(width); + else + result = *this; + } + return result; +} + +bool QByteArray::isNull() const { return d == &shared_null; } + + +/*! + Returns the byte array converted to a \c {long long} using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + + If \a base is 0, the base is determined automatically using the + following rules: If the byte array begins with "0x", it is assumed to + be hexadecimal; if it begins with "0", it is assumed to be octal; + otherwise it is assumed to be decimal. + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to + false; otherwise *\a{ok} is set to true. + + \note The conversion of the number is performed in the default C locale, + irrespective of the user's locale. + + \sa number() +*/ + +qlonglong QByteArray::toLongLong(bool *ok, int base) const +{ +#if defined(QT_CHECK_RANGE) + if (base != 0 && (base < 2 || base > 36)) { + qWarning("QByteArray::toLongLong: Invalid base %d", base); + base = 10; + } +#endif + + return QLocalePrivate::bytearrayToLongLong(nulTerminated().constData(), base, ok); +} + +/*! + Returns the byte array converted to an \c {unsigned long long} + using base \a base, which is 10 by default and must be between 2 + and 36, or 0. + + If \a base is 0, the base is determined automatically using the + following rules: If the byte array begins with "0x", it is assumed to + be hexadecimal; if it begins with "0", it is assumed to be octal; + otherwise it is assumed to be decimal. + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to + false; otherwise *\a{ok} is set to true. + + \note The conversion of the number is performed in the default C locale, + irrespective of the user's locale. + + \sa number() +*/ + +qulonglong QByteArray::toULongLong(bool *ok, int base) const +{ +#if defined(QT_CHECK_RANGE) + if (base != 0 && (base < 2 || base > 36)) { + qWarning("QByteArray::toULongLong: Invalid base %d", base); + base = 10; + } +#endif + + return QLocalePrivate::bytearrayToUnsLongLong(nulTerminated().constData(), base, ok); +} + + +/*! + Returns the byte array converted to an \c int using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + + If \a base is 0, the base is determined automatically using the + following rules: If the byte array begins with "0x", it is assumed to + be hexadecimal; if it begins with "0", it is assumed to be octal; + otherwise it is assumed to be decimal. + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to + false; otherwise *\a{ok} is set to true. + + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 36 + + \note The conversion of the number is performed in the default C locale, + irrespective of the user's locale. + + \sa number() +*/ + +int QByteArray::toInt(bool *ok, int base) const +{ + qlonglong v = toLongLong(ok, base); + if (v < INT_MIN || v > INT_MAX) { + if (ok) + *ok = false; + v = 0; + } + return int(v); +} + +/*! + Returns the byte array converted to an \c {unsigned int} using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + + If \a base is 0, the base is determined automatically using the + following rules: If the byte array begins with "0x", it is assumed to + be hexadecimal; if it begins with "0", it is assumed to be octal; + otherwise it is assumed to be decimal. + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to + false; otherwise *\a{ok} is set to true. + + \note The conversion of the number is performed in the default C locale, + irrespective of the user's locale. + + \sa number() +*/ + +uint QByteArray::toUInt(bool *ok, int base) const +{ + qulonglong v = toULongLong(ok, base); + if (v > UINT_MAX) { + if (ok) + *ok = false; + v = 0; + } + return uint(v); +} + +/*! + \since 4.1 + + Returns the byte array converted to a \c long int using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + + If \a base is 0, the base is determined automatically using the + following rules: If the byte array begins with "0x", it is assumed to + be hexadecimal; if it begins with "0", it is assumed to be octal; + otherwise it is assumed to be decimal. + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to + false; otherwise *\a{ok} is set to true. + + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 37 + + \note The conversion of the number is performed in the default C locale, + irrespective of the user's locale. + + \sa number() +*/ +long QByteArray::toLong(bool *ok, int base) const +{ + qlonglong v = toLongLong(ok, base); + if (v < LONG_MIN || v > LONG_MAX) { + if (ok) + *ok = false; + v = 0; + } + return long(v); +} + +/*! + \since 4.1 + + Returns the byte array converted to an \c {unsigned long int} using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + + If \a base is 0, the base is determined automatically using the + following rules: If the byte array begins with "0x", it is assumed to + be hexadecimal; if it begins with "0", it is assumed to be octal; + otherwise it is assumed to be decimal. + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to + false; otherwise *\a{ok} is set to true. + + \note The conversion of the number is performed in the default C locale, + irrespective of the user's locale. + + \sa number() +*/ +ulong QByteArray::toULong(bool *ok, int base) const +{ + qulonglong v = toULongLong(ok, base); + if (v > ULONG_MAX) { + if (ok) + *ok = false; + v = 0; + } + return ulong(v); +} + +/*! + Returns the byte array converted to a \c short using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + + If \a base is 0, the base is determined automatically using the + following rules: If the byte array begins with "0x", it is assumed to + be hexadecimal; if it begins with "0", it is assumed to be octal; + otherwise it is assumed to be decimal. + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to + false; otherwise *\a{ok} is set to true. + + \note The conversion of the number is performed in the default C locale, + irrespective of the user's locale. + + \sa number() +*/ + +short QByteArray::toShort(bool *ok, int base) const +{ + qlonglong v = toLongLong(ok, base); + if (v < SHRT_MIN || v > SHRT_MAX) { + if (ok) + *ok = false; + v = 0; + } + return short(v); +} + +/*! + Returns the byte array converted to an \c {unsigned short} using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + + If \a base is 0, the base is determined automatically using the + following rules: If the byte array begins with "0x", it is assumed to + be hexadecimal; if it begins with "0", it is assumed to be octal; + otherwise it is assumed to be decimal. + + Returns 0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to + false; otherwise *\a{ok} is set to true. + + \note The conversion of the number is performed in the default C locale, + irrespective of the user's locale. + + \sa number() +*/ + +ushort QByteArray::toUShort(bool *ok, int base) const +{ + qulonglong v = toULongLong(ok, base); + if (v > USHRT_MAX) { + if (ok) + *ok = false; + v = 0; + } + return ushort(v); +} + + +/*! + Returns the byte array converted to a \c double value. + + Returns 0.0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to + false; otherwise *\a{ok} is set to true. + + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 38 + + \note The conversion of the number is performed in the default C locale, + irrespective of the user's locale. + + \sa number() +*/ + +double QByteArray::toDouble(bool *ok) const +{ + return QLocalePrivate::bytearrayToDouble(nulTerminated().constData(), ok); +} + +/*! + Returns the byte array converted to a \c float value. + + Returns 0.0 if the conversion fails. + + If \a ok is not 0: if a conversion error occurs, *\a{ok} is set to + false; otherwise *\a{ok} is set to true. + + \note The conversion of the number is performed in the default C locale, + irrespective of the user's locale. + + \sa number() +*/ + +float QByteArray::toFloat(bool *ok) const +{ + return float(toDouble(ok)); +} + +/*! + Returns a copy of the byte array, encoded as Base64. + + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 39 + + The algorithm used to encode Base64-encoded data is defined in \l{RFC 2045}. + + \sa fromBase64() +*/ +QByteArray QByteArray::toBase64() const +{ + const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" + "ghijklmn" "opqrstuv" "wxyz0123" "456789+/"; + const char padchar = '='; + int padlen = 0; + + QByteArray tmp; + tmp.resize(((d->size * 4) / 3) + 3); + + int i = 0; + char *out = tmp.data(); + while (i < d->size) { + int chunk = 0; + chunk |= int(uchar(d->data[i++])) << 16; + if (i == d->size) { + padlen = 2; + } else { + chunk |= int(uchar(d->data[i++])) << 8; + if (i == d->size) padlen = 1; + else chunk |= int(uchar(d->data[i++])); + } + + int j = (chunk & 0x00fc0000) >> 18; + int k = (chunk & 0x0003f000) >> 12; + int l = (chunk & 0x00000fc0) >> 6; + int m = (chunk & 0x0000003f); + *out++ = alphabet[j]; + *out++ = alphabet[k]; + if (padlen > 1) *out++ = padchar; + else *out++ = alphabet[l]; + if (padlen > 0) *out++ = padchar; + else *out++ = alphabet[m]; + } + + tmp.truncate(out - tmp.data()); + return tmp; +} + +/*! + \fn QByteArray &QByteArray::setNum(int n, int base) + + Sets the byte array to the printed value of \a n in base \a base (10 + by default) and returns a reference to the byte array. The \a base can + be any value between 2 and 36. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 40 + + \note The format of the number is not localized; the default C locale + is used irrespective of the user's locale. + + \sa number(), toInt() +*/ + +/*! + \fn QByteArray &QByteArray::setNum(uint n, int base) + \overload + + \sa toUInt() +*/ + +/*! + \fn QByteArray &QByteArray::setNum(short n, int base) + \overload + + \sa toShort() +*/ + +/*! + \fn QByteArray &QByteArray::setNum(ushort n, int base) + \overload + + \sa toUShort() +*/ + +/*! + \overload + + \sa toLongLong() +*/ + +QByteArray &QByteArray::setNum(qlonglong n, int base) +{ +#if defined(QT_CHECK_RANGE) + if (base < 2 || base > 36) { + qWarning("QByteArray::setNum: Invalid base %d", base); + base = 10; + } +#endif + QLocale locale(QLocale::C); + *this = locale.d()->longLongToString(n, -1, base).toLatin1(); + return *this; +} + +/*! + \overload + + \sa toULongLong() +*/ + +QByteArray &QByteArray::setNum(qulonglong n, int base) +{ +#if defined(QT_CHECK_RANGE) + if (base < 2 || base > 36) { + qWarning("QByteArray::setNum: Invalid base %d", base); + base = 10; + } +#endif + QLocale locale(QLocale::C); + *this = locale.d()->unsLongLongToString(n, -1, base).toLatin1(); + return *this; +} + +/*! + \overload + + Sets the byte array to the printed value of \a n, formatted in format + \a f with precision \a prec, and returns a reference to the + byte array. + + The format \a f can be any of the following: + + \table + \header \i Format \i Meaning + \row \i \c e \i format as [-]9.9e[+|-]999 + \row \i \c E \i format as [-]9.9E[+|-]999 + \row \i \c f \i format as [-]9.9 + \row \i \c g \i use \c e or \c f format, whichever is the most concise + \row \i \c G \i use \c E or \c f format, whichever is the most concise + \endtable + + With 'e', 'E', and 'f', \a prec is the number of digits after the + decimal point. With 'g' and 'G', \a prec is the maximum number of + significant digits (trailing zeroes are omitted). + + \note The format of the number is not localized; the default C locale + is used irrespective of the user's locale. + + \sa toDouble() +*/ + +QByteArray &QByteArray::setNum(double n, char f, int prec) +{ + QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal; + uint flags = 0; + + if (qIsUpper(f)) + flags = QLocalePrivate::CapitalEorX; + f = qToLower(f); + + switch (f) { + case 'f': + form = QLocalePrivate::DFDecimal; + break; + case 'e': + form = QLocalePrivate::DFExponent; + break; + case 'g': + form = QLocalePrivate::DFSignificantDigits; + break; + default: +#if defined(QT_CHECK_RANGE) + qWarning("QByteArray::setNum: Invalid format char '%c'", f); +#endif + break; + } + + QLocale locale(QLocale::C); + *this = locale.d()->doubleToString(n, prec, form, -1, flags).toLatin1(); + return *this; +} + +/*! + \fn QByteArray &QByteArray::setNum(float n, char f, int prec) + \overload + + Sets the byte array to the printed value of \a n, formatted in format + \a f with precision \a prec, and returns a reference to the + byte array. + + \note The format of the number is not localized; the default C locale + is used irrespective of the user's locale. + + \sa toFloat() +*/ + +/*! + Returns a byte array containing the string equivalent of the + number \a n to base \a base (10 by default). The \a base can be + any value between 2 and 36. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 41 + + \note The format of the number is not localized; the default C locale + is used irrespective of the user's locale. + + \sa setNum(), toInt() +*/ +QByteArray QByteArray::number(int n, int base) +{ + QByteArray s; + s.setNum(n, base); + return s; +} + +/*! + \overload + + \sa toUInt() +*/ +QByteArray QByteArray::number(uint n, int base) +{ + QByteArray s; + s.setNum(n, base); + return s; +} + +/*! + \overload + + \sa toLongLong() +*/ +QByteArray QByteArray::number(qlonglong n, int base) +{ + QByteArray s; + s.setNum(n, base); + return s; +} + +/*! + \overload + + \sa toULongLong() +*/ +QByteArray QByteArray::number(qulonglong n, int base) +{ + QByteArray s; + s.setNum(n, base); + return s; +} + +/*! + \overload + + Returns a byte array that contains the printed value of \a n, + formatted in format \a f with precision \a prec. + + Argument \a n is formatted according to the \a f format specified, + which is \c g by default, and can be any of the following: + + \table + \header \i Format \i Meaning + \row \i \c e \i format as [-]9.9e[+|-]999 + \row \i \c E \i format as [-]9.9E[+|-]999 + \row \i \c f \i format as [-]9.9 + \row \i \c g \i use \c e or \c f format, whichever is the most concise + \row \i \c G \i use \c E or \c f format, whichever is the most concise + \endtable + + With 'e', 'E', and 'f', \a prec is the number of digits after the + decimal point. With 'g' and 'G', \a prec is the maximum number of + significant digits (trailing zeroes are omitted). + + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 42 + + \note The format of the number is not localized; the default C locale + is used irrespective of the user's locale. + + \sa toDouble() +*/ +QByteArray QByteArray::number(double n, char f, int prec) +{ + QByteArray s; + s.setNum(n, f, prec); + return s; +} + +/*! + Constructs a QByteArray that uses the first \a size bytes of the + \a data array. The bytes are \e not copied. The QByteArray will + contain the \a data pointer. The caller guarantees that \a data + will not be deleted or modified as long as this QByteArray and any + copies of it exist that have not been modified. In other words, + because QByteArray is an \l{implicitly shared} class and the + instance returned by this function contains the \a data pointer, + the caller must not delete \a data or modify it directly as long + as the returned QByteArray and any copies exist. However, + QByteArray does not take ownership of \a data, so the QByteArray + destructor will never delete the raw \a data, even when the + last QByteArray referring to \a data is destroyed. + + A subsequent attempt to modify the contents of the returned + QByteArray or any copy made from it will cause it to create a deep + copy of the \a data array before doing the modification. This + ensures that the raw \a data array itself will never be modified + by QByteArray. + + Here is an example of how to read data using a QDataStream on raw + data in memory without copying the raw data into a QByteArray: + + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 43 + + \warning A byte array created with fromRawData() is \e not + null-terminated, unless the raw data contains a 0 character at + position \a size. While that does not matter for QDataStream or + functions like indexOf(), passing the byte array to a function + accepting a \c{const char *} expected to be '\\0'-terminated will + fail. + + \sa data(), constData() +*/ + +QByteArray QByteArray::fromRawData(const char *data, int size) +{ + Data *x = static_cast<Data *>(qMalloc(sizeof(Data))); + if (data) { + x->data = const_cast<char *>(data); + } else { + x->data = x->array; + size = 0; + } + x->ref = 1; + x->alloc = x->size = size; + *x->array = '\0'; + return QByteArray(x, 0, 0); +} + +/*! + Returns a decoded copy of the Base64 array \a base64. Input is not checked + for validity; invalid characters in the input are skipped, enabling the + decoding process to continue with subsequent characters. + + For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 44 + + The algorithm used to decode Base64-encoded data is defined in \l{RFC 2045}. + + \sa toBase64() +*/ +QByteArray QByteArray::fromBase64(const QByteArray &base64) +{ + unsigned int buf = 0; + int nbits = 0; + QByteArray tmp; + tmp.resize((base64.size() * 3) / 4); + + int offset = 0; + for (int i = 0; i < base64.size(); ++i) { + int ch = base64.at(i); + int d; + + if (ch >= 'A' && ch <= 'Z') + d = ch - 'A'; + else if (ch >= 'a' && ch <= 'z') + d = ch - 'a' + 26; + else if (ch >= '0' && ch <= '9') + d = ch - '0' + 52; + else if (ch == '+') + d = 62; + else if (ch == '/') + d = 63; + else + d = -1; + + if (d != -1) { + buf = (buf << 6) | d; + nbits += 6; + if (nbits >= 8) { + nbits -= 8; + tmp[offset++] = buf >> nbits; + buf &= (1 << nbits) - 1; + } + } + } + + tmp.truncate(offset); + return tmp; +} + +/*! + Returns a decoded copy of the hex encoded array \a hexEncoded. Input is not checked + for validity; invalid characters in the input are skipped, enabling the + decoding process to continue with subsequent characters. + + For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qbytearray.cpp 45 + + \sa toHex() +*/ +QByteArray QByteArray::fromHex(const QByteArray &hexEncoded) +{ + QByteArray res; + res.resize((hexEncoded.size() + 1)/ 2); + uchar *result = (uchar *)res.data() + res.size(); + + bool odd_digit = true; + for (int i = hexEncoded.size() - 1; i >= 0; --i) { + int ch = hexEncoded.at(i); + int tmp; + if (ch >= '0' && ch <= '9') + tmp = ch - '0'; + else if (ch >= 'a' && ch <= 'f') + tmp = ch - 'a' + 10; + else if (ch >= 'A' && ch <= 'F') + tmp = ch - 'A' + 10; + else + continue; + if (odd_digit) { + --result; + *result = tmp; + odd_digit = false; + } else { + *result |= tmp << 4; + odd_digit = true; + } + } + + res.remove(0, result - (const uchar *)res.constData()); + return res; +} + +/*! + Returns a hex encoded copy of the byte array. The hex encoding uses the numbers 0-9 and + the letters a-f. + + \sa fromHex() +*/ +QByteArray QByteArray::toHex() const +{ + QByteArray hex; + hex.resize(d->size*2); + char *hexData = hex.data(); + const uchar *data = (const uchar *)d->data; + for (int i = 0; i < d->size; ++i) { + int j = (data[i] >> 4) & 0xf; + if (j <= 9) + hexData[i*2] = (j + '0'); + else + hexData[i*2] = (j + 'a' - 10); + j = data[i] & 0xf; + if (j <= 9) + hexData[i*2+1] = (j + '0'); + else + hexData[i*2+1] = (j + 'a' - 10); + } + return hex; +} + +static void q_fromPercentEncoding(QByteArray *ba, char percent) +{ + if (ba->isEmpty()) + return; + + char *data = ba->data(); + const char *inputPtr = data; + + int i = 0; + int len = ba->count(); + int outlen = 0; + int a, b; + char c; + while (i < len) { + c = inputPtr[i]; + if (c == percent && i + 2 < len) { + a = inputPtr[++i]; + b = inputPtr[++i]; + + if (a >= '0' && a <= '9') a -= '0'; + else if (a >= 'a' && a <= 'f') a = a - 'a' + 10; + else if (a >= 'A' && a <= 'F') a = a - 'A' + 10; + + if (b >= '0' && b <= '9') b -= '0'; + else if (b >= 'a' && b <= 'f') b = b - 'a' + 10; + else if (b >= 'A' && b <= 'F') b = b - 'A' + 10; + + *data++ = (char)((a << 4) | b); + } else { + *data++ = c; + } + + ++i; + ++outlen; + } + + if (outlen != len) + ba->truncate(outlen); +} + +void q_fromPercentEncoding(QByteArray *ba) +{ + q_fromPercentEncoding(ba, '%'); +} + +/*! + \since 4.4 + + Returns a decoded copy of the URI/URL-style percent-encoded \a input. + The \a percent parameter allows you to replace the '%' character for + another (for instance, '_' or '='). + + For example: + \code + QByteArray text = QByteArray::fromPercentEncoding("Qt%20is%20great%33"); + text.data(); // returns "Qt is great!" + \endcode + + \sa toPercentEncoding(), QUrl::fromPercentEncoding() +*/ +QByteArray QByteArray::fromPercentEncoding(const QByteArray &input, char percent) +{ + if (input.isNull()) + return QByteArray(); // preserve null + if (input.isEmpty()) + return QByteArray(input.data(), 0); + + QByteArray tmp = input; + q_fromPercentEncoding(&tmp, percent); + return tmp; +} + +static inline bool q_strchr(const char str[], char chr) +{ + if (!str) return false; + + const char *ptr = str; + char c; + while ((c = *ptr++)) + if (c == chr) + return true; + return false; +} + +static inline char toHexHelper(char c) +{ + static const char hexnumbers[] = "0123456789ABCDEF"; + return hexnumbers[c & 0xf]; +} + +static void q_toPercentEncoding(QByteArray *ba, const char *dontEncode, const char *alsoEncode, char percent) +{ + if (ba->isEmpty()) + return; + + QByteArray input = *ba; + int len = input.count(); + const char *inputData = input.constData(); + char *output = 0; + int length = 0; + + for (int i = 0; i < len; ++i) { + unsigned char c = *inputData++; + if (((c >= 0x61 && c <= 0x7A) // ALPHA + || (c >= 0x41 && c <= 0x5A) // ALPHA + || (c >= 0x30 && c <= 0x39) // DIGIT + || c == 0x2D // - + || c == 0x2E // . + || c == 0x5F // _ + || c == 0x7E // ~ + || q_strchr(dontEncode, c)) + && !q_strchr(alsoEncode, c)) { + if (output) + output[length] = c; + ++length; + } else { + if (!output) { + // detach now + ba->resize(len*3); // worst case + output = ba->data(); + } + output[length++] = percent; + output[length++] = toHexHelper((c & 0xf0) >> 4); + output[length++] = toHexHelper(c & 0xf); + } + } + if (output) + ba->truncate(length); +} + +void q_toPercentEncoding(QByteArray *ba, const char *exclude, const char *include) +{ + q_toPercentEncoding(ba, exclude, include, '%'); +} + +void q_normalizePercentEncoding(QByteArray *ba, const char *exclude) +{ + q_fromPercentEncoding(ba, '%'); + q_toPercentEncoding(ba, exclude, 0, '%'); +} + +/*! + \since 4.4 + + Returns a URI/URL-style percent-encoded copy of this byte array. The + \a percent parameter allows you to override the default '%' + character for another. + + By default, this function will encode all characters that are not + one of the following: + + ALPHA ("a" to "z" and "A" to "Z") / DIGIT (0 to 9) / "-" / "." / "_" / "~" + + To prevent characters from being encoded pass them to \a + exclude. To force characters to be encoded pass them to \a + include. The \a percent character is always encoded. + + Example: + + \code + QByteArray text = "{a fishy string?}"; + QByteArray ba = text.toPercentEncoding("{}", "s"); + qDebug(ba.constData()); + // prints "{a fi%73hy %73tring%3F}" + \endcode + + The hex encoding uses the numbers 0-9 and the uppercase letters A-F. + + \sa fromPercentEncoding(), QUrl::toPercentEncoding() +*/ +QByteArray QByteArray::toPercentEncoding(const QByteArray &exclude, const QByteArray &include, + char percent) const +{ + if (isNull()) + return QByteArray(); // preserve null + if (isEmpty()) + return QByteArray(data(), 0); + + QByteArray include2 = include; + if (percent != '%') // the default + if ((percent >= 0x61 && percent <= 0x7A) // ALPHA + || (percent >= 0x41 && percent <= 0x5A) // ALPHA + || (percent >= 0x30 && percent <= 0x39) // DIGIT + || percent == 0x2D // - + || percent == 0x2E // . + || percent == 0x5F // _ + || percent == 0x7E) // ~ + include2 += percent; + + QByteArray result = *this; + q_toPercentEncoding(&result, exclude.nulTerminated().constData(), include2.nulTerminated().constData(), percent); + + return result; +} + +/*! \typedef QByteArray::ConstIterator + \internal +*/ + +/*! \typedef QByteArray::Iterator + \internal +*/ + +/*! \typedef QByteArray::const_iterator + \internal +*/ + +/*! \typedef QByteArray::iterator + \internal +*/ + +/*! \typedef QByteArray::const_reference + \internal +*/ + +/*! \typedef QByteArray::reference + \internal +*/ + +/*! + \fn QByteArray::QByteArray(int size) + + Use QByteArray(int, char) instead. +*/ + + +/*! + \fn QByteArray QByteArray::leftJustify(uint width, char fill, bool truncate) const + + Use leftJustified() instead. +*/ + +/*! + \fn QByteArray QByteArray::rightJustify(uint width, char fill, bool truncate) const + + Use rightJustified() instead. +*/ + +/*! + \fn QByteArray& QByteArray::duplicate(const QByteArray& a) + + \oldcode + QByteArray bdata; + bdata.duplicate(original); + \newcode + QByteArray bdata; + bdata = original; + \endcode + + \note QByteArray uses implicit sharing so if you modify a copy, only the + copy is changed. +*/ + +/*! + \fn QByteArray& QByteArray::duplicate(const char *a, uint n) + + \overload + + \oldcode + QByteArray bdata; + bdata.duplicate(ptr, size); + \newcode + QByteArray bdata; + bdata = QByteArray(ptr, size); + \endcode + + \note QByteArray uses implicit sharing so if you modify a copy, only the + copy is changed. +*/ + +/*! + \fn QByteArray& QByteArray::setRawData(const char *a, uint n) + + Use fromRawData() instead. +*/ + +/*! + \fn void QByteArray::resetRawData(const char *data, uint n) + + Use clear() instead. +*/ + +/*! + \fn QByteArray QByteArray::lower() const + + Use toLower() instead. +*/ + +/*! + \fn QByteArray QByteArray::upper() const + + Use toUpper() instead. +*/ + +/*! + \fn QByteArray QByteArray::stripWhiteSpace() const + + Use trimmed() instead. +*/ + +/*! + \fn QByteArray QByteArray::simplifyWhiteSpace() const + + Use simplified() instead. +*/ + +/*! + \fn int QByteArray::find(char c, int from = 0) const + + Use indexOf() instead. +*/ + +/*! + \fn int QByteArray::find(const char *c, int from = 0) const + + Use indexOf() instead. +*/ + +/*! + \fn int QByteArray::find(const QByteArray &ba, int from = 0) const + + Use indexOf() instead. +*/ + +/*! + \fn int QByteArray::findRev(char c, int from = -1) const + + Use lastIndexOf() instead. +*/ + +/*! + \fn int QByteArray::findRev(const char *c, int from = -1) const + + Use lastIndexOf() instead. +*/ + +/*! + \fn int QByteArray::findRev(const QByteArray &ba, int from = -1) const + + Use lastIndexOf() instead. +*/ + +/*! + \fn int QByteArray::find(const QString &s, int from = 0) const + + Use indexOf() instead. +*/ + +/*! + \fn int QByteArray::findRev(const QString &s, int from = -1) const + + Use lastIndexOf() instead. +*/ + +/*! + \fn DataPtr &QByteArray::data_ptr() + \internal +*/ + +/*! + \typedef QByteArray::DataPtr + \internal +*/ + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h new file mode 100644 index 0000000..f6422fb --- /dev/null +++ b/src/corelib/tools/qbytearray.h @@ -0,0 +1,589 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBYTEARRAY_H +#define QBYTEARRAY_H + +#include <QtCore/qglobal.h> +#include <QtCore/qatomic.h> + +#include <string.h> +#include <stdarg.h> + +#ifdef truncate +#error qbytearray.h must be included before any header file that defines truncate +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +/***************************************************************************** + Safe and portable C string functions; extensions to standard string.h + *****************************************************************************/ + +Q_CORE_EXPORT char *qstrdup(const char *); + +inline uint qstrlen(const char *str) +{ return str ? uint(strlen(str)) : 0; } + +inline uint qstrnlen(const char *str, uint maxlen) +{ + uint length = 0; + if (str) { + while (length < maxlen && *str++) + length++; + } + return length; +} + +Q_CORE_EXPORT char *qstrcpy(char *dst, const char *src); +Q_CORE_EXPORT char *qstrncpy(char *dst, const char *src, uint len); + +Q_CORE_EXPORT int qstrcmp(const char *str1, const char *str2); +Q_CORE_EXPORT int qstrcmp(const QByteArray &str1, const QByteArray &str2); +Q_CORE_EXPORT int qstrcmp(const QByteArray &str1, const char *str2); +static inline int qstrcmp(const char *str1, const QByteArray &str2) +{ return -qstrcmp(str2, str1); } + +inline int qstrncmp(const char *str1, const char *str2, uint len) +{ + return (str1 && str2) ? strncmp(str1, str2, len) + : (str1 ? 1 : (str2 ? -1 : 0)); +} +Q_CORE_EXPORT int qstricmp(const char *, const char *); +Q_CORE_EXPORT int qstrnicmp(const char *, const char *, uint len); + +// implemented in qvsnprintf.cpp +Q_CORE_EXPORT int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap); +Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt, ...); + +#ifdef QT3_SUPPORT +inline QT3_SUPPORT void *qmemmove(void *dst, const void *src, uint len) +{ return memmove(dst, src, len); } +inline QT3_SUPPORT uint cstrlen(const char *str) +{ return uint(strlen(str)); } +inline QT3_SUPPORT char *cstrcpy(char *dst, const char *src) +{ return qstrcpy(dst,src); } +inline QT3_SUPPORT int cstrcmp(const char *str1, const char *str2) +{ return strcmp(str1,str2); } +inline QT3_SUPPORT int cstrncmp(const char *str1, const char *str2, uint len) +{ return strncmp(str1,str2,len); } +#endif + +// qChecksum: Internet checksum + +Q_CORE_EXPORT quint16 qChecksum(const char *s, uint len); + +class QByteRef; +class QString; +class QDataStream; +template <typename T> class QList; + +class Q_CORE_EXPORT QByteArray +{ +public: + inline QByteArray(); + QByteArray(const char *); + QByteArray(const char *, int size); + QByteArray(int size, char c); + inline QByteArray(const QByteArray &); + inline ~QByteArray(); + + QByteArray &operator=(const QByteArray &); + QByteArray &operator=(const char *str); + + inline int size() const; + bool isEmpty() const; + void resize(int size); + + QByteArray &fill(char c, int size = -1); + + int capacity() const; + void reserve(int size); + void squeeze(); + +#ifndef QT_NO_CAST_FROM_BYTEARRAY + operator const char *() const; + operator const void *() const; +#endif + char *data(); + const char *data() const; + inline const char *constData() const; + inline void detach(); + bool isDetached() const; + void clear(); + +#ifdef Q_COMPILER_MANGLES_RETURN_TYPE + const char at(int i) const; + const char operator[](int i) const; + const char operator[](uint i) const; +#else + char at(int i) const; + char operator[](int i) const; + char operator[](uint i) const; +#endif + QByteRef operator[](int i); + QByteRef operator[](uint i); + + int indexOf(char c, int from = 0) const; + int indexOf(const char *c, int from = 0) const; + int indexOf(const QByteArray &a, int from = 0) const; + int lastIndexOf(char c, int from = -1) const; + int lastIndexOf(const char *c, int from = -1) const; + int lastIndexOf(const QByteArray &a, int from = -1) const; + + QBool contains(char c) const; + QBool contains(const char *a) const; + QBool contains(const QByteArray &a) const; + int count(char c) const; + int count(const char *a) const; + int count(const QByteArray &a) const; + + QByteArray left(int len) const; + QByteArray right(int len) const; + QByteArray mid(int index, int len = -1) const; + + bool startsWith(const QByteArray &a) const; + bool startsWith(char c) const; + bool startsWith(const char *c) const; + + bool endsWith(const QByteArray &a) const; + bool endsWith(char c) const; + bool endsWith(const char *c) const; + + void truncate(int pos); + void chop(int n); + + QByteArray toLower() const; + QByteArray toUpper() const; + + QByteArray trimmed() const; + QByteArray simplified() const; + QByteArray leftJustified(int width, char fill = ' ', bool truncate = false) const; + QByteArray rightJustified(int width, char fill = ' ', bool truncate = false) const; + +#ifdef QT3_SUPPORT + inline QT3_SUPPORT QByteArray leftJustify(uint width, char aFill = ' ', bool aTruncate = false) const + { return leftJustified(int(width), aFill, aTruncate); } + inline QT3_SUPPORT QByteArray rightJustify(uint width, char aFill = ' ', bool aTruncate = false) const + { return rightJustified(int(width), aFill, aTruncate); } +#endif + + QByteArray &prepend(char c); + QByteArray &prepend(const char *s); + QByteArray &prepend(const QByteArray &a); + QByteArray &append(char c); + QByteArray &append(const char *s); + QByteArray &append(const char *s, int len); + QByteArray &append(const QByteArray &a); + QByteArray &insert(int i, char c); + QByteArray &insert(int i, const char *s); + QByteArray &insert(int i, const QByteArray &a); + QByteArray &remove(int index, int len); + QByteArray &replace(int index, int len, const char *s); + QByteArray &replace(int index, int len, const QByteArray &s); + QByteArray &replace(char before, const char *after); + QByteArray &replace(char before, const QByteArray &after); + QByteArray &replace(const char *before, const char *after); + QByteArray &replace(const char *before, int bsize, const char *after, int asize); + QByteArray &replace(const QByteArray &before, const QByteArray &after); + QByteArray &replace(const QByteArray &before, const char *after); + QByteArray &replace(const char *before, const QByteArray &after); + QByteArray &replace(char before, char after); + QByteArray &operator+=(char c); + QByteArray &operator+=(const char *s); + QByteArray &operator+=(const QByteArray &a); + + QList<QByteArray> split(char sep) const; + + QByteArray repeated(int times) const; + +#ifndef QT_NO_CAST_TO_ASCII + QT_ASCII_CAST_WARN QByteArray &append(const QString &s); + QT_ASCII_CAST_WARN QByteArray &insert(int i, const QString &s); + QT_ASCII_CAST_WARN QByteArray &replace(const QString &before, const char *after); + QT_ASCII_CAST_WARN QByteArray &replace(char c, const QString &after); + QT_ASCII_CAST_WARN QByteArray &replace(const QString &before, const QByteArray &after); + + QT_ASCII_CAST_WARN QByteArray &operator+=(const QString &s); + QT_ASCII_CAST_WARN int indexOf(const QString &s, int from = 0) const; + QT_ASCII_CAST_WARN int lastIndexOf(const QString &s, int from = -1) const; +#endif +#ifndef QT_NO_CAST_FROM_ASCII + inline QT_ASCII_CAST_WARN bool operator==(const QString &s2) const; + inline QT_ASCII_CAST_WARN bool operator!=(const QString &s2) const; + inline QT_ASCII_CAST_WARN bool operator<(const QString &s2) const; + inline QT_ASCII_CAST_WARN bool operator>(const QString &s2) const; + inline QT_ASCII_CAST_WARN bool operator<=(const QString &s2) const; + inline QT_ASCII_CAST_WARN bool operator>=(const QString &s2) const; +#endif + + short toShort(bool *ok = 0, int base = 10) const; + ushort toUShort(bool *ok = 0, int base = 10) const; + int toInt(bool *ok = 0, int base = 10) const; + uint toUInt(bool *ok = 0, int base = 10) const; + long toLong(bool *ok = 0, int base = 10) const; + ulong toULong(bool *ok = 0, int base = 10) const; + qlonglong toLongLong(bool *ok = 0, int base = 10) const; + qulonglong toULongLong(bool *ok = 0, int base = 10) const; + float toFloat(bool *ok = 0) const; + double toDouble(bool *ok = 0) const; + QByteArray toBase64() const; + QByteArray toHex() const; + QByteArray toPercentEncoding(const QByteArray &exclude = QByteArray(), + const QByteArray &include = QByteArray(), + char percent = '%') const; + + QByteArray &setNum(short, int base = 10); + QByteArray &setNum(ushort, int base = 10); + QByteArray &setNum(int, int base = 10); + QByteArray &setNum(uint, int base = 10); + QByteArray &setNum(qlonglong, int base = 10); + QByteArray &setNum(qulonglong, int base = 10); + QByteArray &setNum(float, char f = 'g', int prec = 6); + QByteArray &setNum(double, char f = 'g', int prec = 6); + + static QByteArray number(int, int base = 10); + static QByteArray number(uint, int base = 10); + static QByteArray number(qlonglong, int base = 10); + static QByteArray number(qulonglong, int base = 10); + static QByteArray number(double, char f = 'g', int prec = 6); + static QByteArray fromRawData(const char *, int size); + static QByteArray fromBase64(const QByteArray &base64); + static QByteArray fromHex(const QByteArray &hexEncoded); + static QByteArray fromPercentEncoding(const QByteArray &pctEncoded, char percent = '%'); + + + typedef char *iterator; + typedef const char *const_iterator; + typedef iterator Iterator; + typedef const_iterator ConstIterator; + iterator begin(); + const_iterator begin() const; + const_iterator constBegin() const; + iterator end(); + const_iterator end() const; + const_iterator constEnd() const; + + // stl compatibility + typedef const char & const_reference; + typedef char & reference; + void push_back(char c); + void push_back(const char *c); + void push_back(const QByteArray &a); + void push_front(char c); + void push_front(const char *c); + void push_front(const QByteArray &a); + + inline int count() const { return d->size; } + int length() const { return d->size; } + bool isNull() const; + + // compatibility +#ifdef QT3_SUPPORT + QT3_SUPPORT_CONSTRUCTOR QByteArray(int size); + inline QT3_SUPPORT QByteArray& duplicate(const QByteArray& a) { *this = a; return *this; } + inline QT3_SUPPORT QByteArray& duplicate(const char *a, uint n) + { *this = QByteArray(a, n); return *this; } + inline QT3_SUPPORT QByteArray& setRawData(const char *a, uint n) + { *this = fromRawData(a, n); return *this; } + inline QT3_SUPPORT void resetRawData(const char *, uint) { clear(); } + inline QT3_SUPPORT QByteArray lower() const { return toLower(); } + inline QT3_SUPPORT QByteArray upper() const { return toUpper(); } + inline QT3_SUPPORT QByteArray stripWhiteSpace() const { return trimmed(); } + inline QT3_SUPPORT QByteArray simplifyWhiteSpace() const { return simplified(); } + inline QT3_SUPPORT int find(char c, int from = 0) const { return indexOf(c, from); } + inline QT3_SUPPORT int find(const char *c, int from = 0) const { return indexOf(c, from); } + inline QT3_SUPPORT int find(const QByteArray &ba, int from = 0) const { return indexOf(ba, from); } + inline QT3_SUPPORT int findRev(char c, int from = -1) const { return lastIndexOf(c, from); } + inline QT3_SUPPORT int findRev(const char *c, int from = -1) const { return lastIndexOf(c, from); } + inline QT3_SUPPORT int findRev(const QByteArray &ba, int from = -1) const { return lastIndexOf(ba, from); } +#ifndef QT_NO_CAST_TO_ASCII + QT3_SUPPORT int find(const QString &s, int from = 0) const; + QT3_SUPPORT int findRev(const QString &s, int from = -1) const; +#endif +#endif + +private: + operator QNoImplicitBoolCast() const; + struct Data { + QBasicAtomicInt ref; + int alloc, size; + // ### Qt 5.0: We need to add the missing capacity bit + // (like other tool classes have), to maintain the + // reserved memory on resize. + char *data; + char array[1]; + }; + static Data shared_null; + static Data shared_empty; + Data *d; + QByteArray(Data *dd, int /*dummy*/, int /*dummy*/) : d(dd) {} + void realloc(int alloc); + void expand(int i); + QByteArray nulTerminated() const; + + friend class QByteRef; + friend class QString; +public: + typedef Data * DataPtr; + inline DataPtr &data_ptr() { return d; } +}; + +inline QByteArray::QByteArray(): d(&shared_null) { d->ref.ref(); } +inline QByteArray::~QByteArray() { if (!d->ref.deref()) qFree(d); } +inline int QByteArray::size() const +{ return d->size; } + +#ifdef Q_COMPILER_MANGLES_RETURN_TYPE +inline const char QByteArray::at(int i) const +{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; } +inline const char QByteArray::operator[](int i) const +{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; } +inline const char QByteArray::operator[](uint i) const +{ Q_ASSERT(i < uint(size())); return d->data[i]; } +#else +inline char QByteArray::at(int i) const +{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; } +inline char QByteArray::operator[](int i) const +{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; } +inline char QByteArray::operator[](uint i) const +{ Q_ASSERT(i < uint(size())); return d->data[i]; } +#endif + +inline bool QByteArray::isEmpty() const +{ return d->size == 0; } +#ifndef QT_NO_CAST_FROM_BYTEARRAY +inline QByteArray::operator const char *() const +{ return d->data; } +inline QByteArray::operator const void *() const +{ return d->data; } +#endif +inline char *QByteArray::data() +{ detach(); return d->data; } +inline const char *QByteArray::data() const +{ return d->data; } +inline const char *QByteArray::constData() const +{ return d->data; } +inline void QByteArray::detach() +{ if (d->ref != 1 || d->data != d->array) realloc(d->size); } +inline bool QByteArray::isDetached() const +{ return d->ref == 1; } +inline QByteArray::QByteArray(const QByteArray &a) : d(a.d) +{ d->ref.ref(); } +#ifdef QT3_SUPPORT +inline QByteArray::QByteArray(int aSize) : d(&shared_null) +{ d->ref.ref(); if (aSize > 0) fill('\0', aSize); } +#endif + +inline int QByteArray::capacity() const +{ return d->alloc; } + +inline void QByteArray::reserve(int asize) +{ if (d->ref != 1 || asize > d->alloc) realloc(asize); } + +inline void QByteArray::squeeze() +{ if (d->size < d->alloc) realloc(d->size); } + +class Q_CORE_EXPORT QByteRef { + QByteArray &a; + int i; + inline QByteRef(QByteArray &array, int idx) + : a(array),i(idx) {} + friend class QByteArray; +public: +#ifdef Q_COMPILER_MANGLES_RETURN_TYPE + inline operator const char() const + { return i < a.d->size ? a.d->data[i] : 0; } +#else + inline operator char() const + { return i < a.d->size ? a.d->data[i] : 0; } +#endif + inline QByteRef &operator=(char c) + { if (i >= a.d->size) a.expand(i); else a.detach(); + a.d->data[i] = c; return *this; } + inline QByteRef &operator=(const QByteRef &c) + { if (i >= a.d->size) a.expand(i); else a.detach(); + a.d->data[i] = c.a.d->data[c.i]; return *this; } + inline bool operator==(char c) const + { return a.d->data[i] == c; } + inline bool operator!=(char c) const + { return a.d->data[i] != c; } + inline bool operator>(char c) const + { return a.d->data[i] > c; } + inline bool operator>=(char c) const + { return a.d->data[i] >= c; } + inline bool operator<(char c) const + { return a.d->data[i] < c; } + inline bool operator<=(char c) const + { return a.d->data[i] <= c; } +}; + +inline QByteRef QByteArray::operator[](int i) +{ Q_ASSERT(i >= 0); return QByteRef(*this, i); } +inline QByteRef QByteArray::operator[](uint i) +{ return QByteRef(*this, i); } +inline QByteArray::iterator QByteArray::begin() +{ detach(); return d->data; } +inline QByteArray::const_iterator QByteArray::begin() const +{ return d->data; } +inline QByteArray::const_iterator QByteArray::constBegin() const +{ return d->data; } +inline QByteArray::iterator QByteArray::end() +{ detach(); return d->data + d->size; } +inline QByteArray::const_iterator QByteArray::end() const +{ return d->data + d->size; } +inline QByteArray::const_iterator QByteArray::constEnd() const +{ return d->data + d->size; } +inline QByteArray &QByteArray::operator+=(char c) +{ return append(c); } +inline QByteArray &QByteArray::operator+=(const char *s) +{ return append(s); } +inline QByteArray &QByteArray::operator+=(const QByteArray &a) +{ return append(a); } +inline void QByteArray::push_back(char c) +{ append(c); } +inline void QByteArray::push_back(const char *c) +{ append(c); } +inline void QByteArray::push_back(const QByteArray &a) +{ append(a); } +inline void QByteArray::push_front(char c) +{ prepend(c); } +inline void QByteArray::push_front(const char *c) +{ prepend(c); } +inline void QByteArray::push_front(const QByteArray &a) +{ prepend(a); } +inline QBool QByteArray::contains(const QByteArray &a) const +{ return QBool(indexOf(a) != -1); } +inline QBool QByteArray::contains(char c) const +{ return QBool(indexOf(c) != -1); } +inline bool operator==(const QByteArray &a1, const QByteArray &a2) +{ return (a1.size() == a2.size()) && (memcmp(a1.constData(), a2.constData(), a1.size())==0); } +inline bool operator==(const QByteArray &a1, const char *a2) +{ return a2 ? qstrcmp(a1,a2) == 0 : a1.isEmpty(); } +inline bool operator==(const char *a1, const QByteArray &a2) +{ return a1 ? qstrcmp(a1,a2) == 0 : a2.isEmpty(); } +inline bool operator!=(const QByteArray &a1, const QByteArray &a2) +{ return !(a1==a2); } +inline bool operator!=(const QByteArray &a1, const char *a2) +{ return a2 ? qstrcmp(a1,a2) != 0 : !a1.isEmpty(); } +inline bool operator!=(const char *a1, const QByteArray &a2) +{ return a1 ? qstrcmp(a1,a2) != 0 : !a2.isEmpty(); } +inline bool operator<(const QByteArray &a1, const QByteArray &a2) +{ return qstrcmp(a1, a2) < 0; } + inline bool operator<(const QByteArray &a1, const char *a2) +{ return qstrcmp(a1, a2) < 0; } +inline bool operator<(const char *a1, const QByteArray &a2) +{ return qstrcmp(a1, a2) < 0; } +inline bool operator<=(const QByteArray &a1, const QByteArray &a2) +{ return qstrcmp(a1, a2) <= 0; } +inline bool operator<=(const QByteArray &a1, const char *a2) +{ return qstrcmp(a1, a2) <= 0; } +inline bool operator<=(const char *a1, const QByteArray &a2) +{ return qstrcmp(a1, a2) <= 0; } +inline bool operator>(const QByteArray &a1, const QByteArray &a2) +{ return qstrcmp(a1, a2) > 0; } +inline bool operator>(const QByteArray &a1, const char *a2) +{ return qstrcmp(a1, a2) > 0; } +inline bool operator>(const char *a1, const QByteArray &a2) +{ return qstrcmp(a1, a2) > 0; } +inline bool operator>=(const QByteArray &a1, const QByteArray &a2) +{ return qstrcmp(a1, a2) >= 0; } +inline bool operator>=(const QByteArray &a1, const char *a2) +{ return qstrcmp(a1, a2) >= 0; } +inline bool operator>=(const char *a1, const QByteArray &a2) +{ return qstrcmp(a1, a2) >= 0; } +inline const QByteArray operator+(const QByteArray &a1, const QByteArray &a2) +{ return QByteArray(a1) += a2; } +inline const QByteArray operator+(const QByteArray &a1, const char *a2) +{ return QByteArray(a1) += a2; } +inline const QByteArray operator+(const QByteArray &a1, char a2) +{ return QByteArray(a1) += a2; } +inline const QByteArray operator+(const char *a1, const QByteArray &a2) +{ return QByteArray(a1) += a2; } +inline const QByteArray operator+(char a1, const QByteArray &a2) +{ return QByteArray(&a1, 1) += a2; } +inline QBool QByteArray::contains(const char *c) const +{ return QBool(indexOf(c) != -1); } +inline QByteArray &QByteArray::replace(char before, const char *c) +{ return replace(&before, 1, c, qstrlen(c)); } +inline QByteArray &QByteArray::replace(const QByteArray &before, const char *c) +{ return replace(before.constData(), before.size(), c, qstrlen(c)); } +inline QByteArray &QByteArray::replace(const char *before, const char *after) +{ return replace(before, qstrlen(before), after, qstrlen(after)); } + +inline QByteArray &QByteArray::setNum(short n, int base) +{ return setNum(qlonglong(n), base); } +inline QByteArray &QByteArray::setNum(ushort n, int base) +{ return setNum(qulonglong(n), base); } +inline QByteArray &QByteArray::setNum(int n, int base) +{ return setNum(qlonglong(n), base); } +inline QByteArray &QByteArray::setNum(uint n, int base) +{ return setNum(qulonglong(n), base); } +inline QByteArray &QByteArray::setNum(float n, char f, int prec) +{ return setNum(double(n),f,prec); } + + +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QByteArray &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QByteArray &); +#endif + +#ifndef QT_NO_COMPRESS +Q_CORE_EXPORT QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel = -1); +Q_CORE_EXPORT QByteArray qUncompress(const uchar* data, int nbytes); +inline QByteArray qCompress(const QByteArray& data, int compressionLevel = -1) +{ return qCompress(reinterpret_cast<const uchar *>(data.constData()), data.size(), compressionLevel); } +inline QByteArray qUncompress(const QByteArray& data) +{ return qUncompress(reinterpret_cast<const uchar*>(data.constData()), data.size()); } +#endif + +Q_DECLARE_TYPEINFO(QByteArray, Q_MOVABLE_TYPE); +Q_DECLARE_SHARED(QByteArray) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QBYTEARRAY_H diff --git a/src/corelib/tools/qbytearraymatcher.cpp b/src/corelib/tools/qbytearraymatcher.cpp new file mode 100644 index 0000000..cd4cf90 --- /dev/null +++ b/src/corelib/tools/qbytearraymatcher.cpp @@ -0,0 +1,323 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbytearraymatcher.h" + +#include <limits.h> + +QT_BEGIN_NAMESPACE + +static inline void bm_init_skiptable(const uchar *cc, int len, uchar *skiptable) +{ + int l = qMin(len, 255); + memset(skiptable, l, 256*sizeof(uchar)); + cc += len - l; + while (l--) + skiptable[*cc++] = l; +} + +static inline int bm_find(const uchar *cc, int l, int index, const uchar *puc, uint pl, + const uchar *skiptable) +{ + if (pl == 0) + return index > l ? -1 : index; + const uint pl_minus_one = pl - 1; + + register const uchar *current = cc + index + pl_minus_one; + const uchar *end = cc + l; + while (current < end) { + uint skip = skiptable[*current]; + if (!skip) { + // possible match + while (skip < pl) { + if (*(current - skip) != puc[pl_minus_one - skip]) + break; + skip++; + } + if (skip > pl_minus_one) // we have a match + return (current - cc) - skip + 1; + + // in case we don't have a match we are a bit inefficient as we only skip by one + // when we have the non matching char in the string. + if (skiptable[*(current - skip)] == pl) + skip = pl - skip; + else + skip = 1; + } + if (current > end - skip) + break; + current += skip; + } + return -1; // not found +} + +/*! \class QByteArrayMatcher + \brief The QByteArrayMatcher class holds a sequence of bytes that + can be quickly matched in a byte array. + + \ingroup tools + \ingroup text + + This class is useful when you have a sequence of bytes that you + want to repeatedly match against some byte arrays (perhaps in a + loop), or when you want to search for the same sequence of bytes + multiple times in the same byte array. Using a matcher object and + indexIn() is faster than matching a plain QByteArray with + QByteArray::indexOf() if repeated matching takes place. This + class offers no benefit if you are doing one-off byte array + matches. + + Create the QByteArrayMatcher with the QByteArray you want to + search for. Then call indexIn() on the QByteArray that you want to + search. + + \sa QByteArray, QStringMatcher +*/ + +/*! + Constructs an empty byte array matcher that won't match anything. + Call setPattern() to give it a pattern to match. +*/ +QByteArrayMatcher::QByteArrayMatcher() + : d(0) +{ + p.p = 0; + qMemSet(p.q_skiptable, 0, sizeof(p.q_skiptable)); +} + +/*! + Constructs a byte array matcher from \a pattern. \a pattern + has the given \a length. \a pattern must remain in scope, but + the destructor does not delete \a pattern. + */ +QByteArrayMatcher::QByteArrayMatcher(const char *pattern, int length) + : d(0) +{ + p.p = reinterpret_cast<const uchar *>(pattern); + p.l = length; + bm_init_skiptable(p.p, p.l, p.q_skiptable); +} + +/*! + Constructs a byte array matcher that will search for \a pattern. + Call indexIn() to perform a search. +*/ +QByteArrayMatcher::QByteArrayMatcher(const QByteArray &pattern) + : d(0), q_pattern(pattern) +{ + p.p = reinterpret_cast<const uchar *>(pattern.constData()); + p.l = pattern.size(); + bm_init_skiptable(p.p, p.l, p.q_skiptable); +} + +/*! + Copies the \a other byte array matcher to this byte array matcher. +*/ +QByteArrayMatcher::QByteArrayMatcher(const QByteArrayMatcher &other) + : d(0) +{ + operator=(other); +} + +/*! + Destroys the byte array matcher. +*/ +QByteArrayMatcher::~QByteArrayMatcher() +{ +} + +/*! + Assigns the \a other byte array matcher to this byte array matcher. +*/ +QByteArrayMatcher &QByteArrayMatcher::operator=(const QByteArrayMatcher &other) +{ + q_pattern = other.q_pattern; + qMemCopy(p.q_skiptable, other.p.q_skiptable, sizeof(p.q_skiptable)); + return *this; +} + +/*! + Sets the byte array that this byte array matcher will search for + to \a pattern. + + \sa pattern(), indexIn() +*/ +void QByteArrayMatcher::setPattern(const QByteArray &pattern) +{ + q_pattern = pattern; + p.p = reinterpret_cast<const uchar *>(pattern.constData()); + p.l = pattern.size(); + bm_init_skiptable(p.p, p.l, p.q_skiptable); +} + +/*! + Searches the byte array \a ba, from byte position \a from (default + 0, i.e. from the first byte), for the byte array pattern() that + was set in the constructor or in the most recent call to + setPattern(). Returns the position where the pattern() matched in + \a ba, or -1 if no match was found. +*/ +int QByteArrayMatcher::indexIn(const QByteArray &ba, int from) const +{ + if (from < 0) + from = 0; + return bm_find(reinterpret_cast<const uchar *>(ba.constData()), ba.size(), from, + p.p, p.l, p.q_skiptable); +} + +/*! + Searches the char string \a str, which has length \a len, from + byte position \a from (default 0, i.e. from the first byte), for + the byte array pattern() that was set in the constructor or in the + most recent call to setPattern(). Returns the position where the + pattern() matched in \a str, or -1 if no match was found. +*/ +int QByteArrayMatcher::indexIn(const char *str, int len, int from) const +{ + if (from < 0) + from = 0; + return bm_find(reinterpret_cast<const uchar *>(str), len, from, + p.p, p.l, p.q_skiptable); +} + +/*! + \fn QByteArray QByteArrayMatcher::pattern() const + + Returns the byte array pattern that this byte array matcher will + search for. + + \sa setPattern() +*/ + + +static int findChar(const char *str, int len, char ch, int from) +{ + const uchar *s = (const uchar *)str; + uchar c = (uchar)ch; + if (from < 0) + from = qMax(from + len, 0); + if (from < len) { + const uchar *n = s + from - 1; + const uchar *e = s + len; + while (++n != e) + if (*n == c) + return n - s; + } + return -1; +} + +/*! \internal + */ +static int qFindByteArrayBoyerMoore( + const char *haystack, int haystackLen, int haystackOffset, + const char *needle, int needleLen) +{ + uchar skiptable[256]; + bm_init_skiptable((const uchar *)needle, needleLen, skiptable); + if (haystackOffset < 0) + haystackOffset = 0; + return bm_find((const uchar *)haystack, haystackLen, haystackOffset, + (const uchar *)needle, needleLen, skiptable); +} + +#define REHASH(a) \ + if (sl_minus_1 < sizeof(uint) * CHAR_BIT) \ + hashHaystack -= (a) << sl_minus_1; \ + hashHaystack <<= 1 + +/*! \internal + */ +int qFindByteArray( + const char *haystack0, int haystackLen, int from, + const char *needle, int needleLen) +{ + const int l = haystackLen; + const int sl = needleLen; + if (from < 0) + from += l; + if (uint(sl + from) > (uint)l) + return -1; + if (!sl) + return from; + if (!l) + return -1; + + if (sl == 1) + return findChar(haystack0, haystackLen, needle[0], from); + + /* + We use the Boyer-Moore algorithm in cases where the overhead + for the skip table should pay off, otherwise we use a simple + hash function. + */ + if (l > 500 && sl > 5) + return qFindByteArrayBoyerMoore(haystack0, haystackLen, from, + needle, needleLen); + + /* + We use some hashing for efficiency's sake. Instead of + comparing strings, we compare the hash value of str with that + of a part of this QString. Only if that matches, we call memcmp(). + */ + const char *haystack = haystack0 + from; + const char *end = haystack0 + (l - sl); + const uint sl_minus_1 = sl - 1; + uint hashNeedle = 0, hashHaystack = 0; + int idx; + for (idx = 0; idx < sl; ++idx) { + hashNeedle = ((hashNeedle<<1) + needle[idx]); + hashHaystack = ((hashHaystack<<1) + haystack[idx]); + } + hashHaystack -= *(haystack + sl_minus_1); + + while (haystack <= end) { + hashHaystack += *(haystack + sl_minus_1); + if (hashHaystack == hashNeedle && *needle == *haystack + && memcmp(needle, haystack, sl) == 0) + return haystack - haystack0; + + REHASH(*haystack); + ++haystack; + } + return -1; +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qbytearraymatcher.h b/src/corelib/tools/qbytearraymatcher.h new file mode 100644 index 0000000..d7f2366 --- /dev/null +++ b/src/corelib/tools/qbytearraymatcher.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBYTEARRAYMATCHER_H +#define QBYTEARRAYMATCHER_H + +#include <QtCore/qbytearray.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class QByteArrayMatcherPrivate; + +class Q_CORE_EXPORT QByteArrayMatcher +{ +public: + QByteArrayMatcher(); + explicit QByteArrayMatcher(const QByteArray &pattern); + explicit QByteArrayMatcher(const char *pattern, int length); + QByteArrayMatcher(const QByteArrayMatcher &other); + ~QByteArrayMatcher(); + + QByteArrayMatcher &operator=(const QByteArrayMatcher &other); + + void setPattern(const QByteArray &pattern); + + int indexIn(const QByteArray &ba, int from = 0) const; + int indexIn(const char *str, int len, int from = 0) const; + inline QByteArray pattern() const { return q_pattern; } + +private: + QByteArrayMatcherPrivate *d; + QByteArray q_pattern; +#ifdef Q_CC_RVCT +// explicitely allow anonymous unions for RVCT to prevent compiler warnings +#pragma anon_unions +#endif + union { + uint dummy[256]; + struct { + uchar q_skiptable[256]; + const uchar *p; + int l; + } p; + }; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QBYTEARRAYMATCHER_H diff --git a/src/corelib/tools/qcache.h b/src/corelib/tools/qcache.h new file mode 100644 index 0000000..38adac6 --- /dev/null +++ b/src/corelib/tools/qcache.h @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCACHE_H +#define QCACHE_H + +#include <QtCore/qhash.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +template <class Key, class T> +class QCache +{ + struct Node { + inline Node() : keyPtr(0) {} + inline Node(T *data, int cost) + : keyPtr(0), t(data), c(cost), p(0), n(0) {} + const Key *keyPtr; T *t; int c; Node *p,*n; + }; + Node *f, *l; + QHash<Key, Node> hash; + void *unused; + int mx, total; + + inline void unlink(Node &n) { + if (n.p) n.p->n = n.n; + if (n.n) n.n->p = n.p; + if (l == &n) l = n.p; + if (f == &n) f = n.n; + total -= n.c; + delete n.t; + hash.remove(*n.keyPtr); + } + inline T *relink(const Key &key) { + typename QHash<Key, Node>::iterator i = hash.find(key); + if (typename QHash<Key, Node>::const_iterator(i) == hash.constEnd()) + return 0; + + Node &n = *i; + if (f != &n) { + if (n.p) n.p->n = n.n; + if (n.n) n.n->p = n.p; + if (l == &n) l = n.p; + n.p = 0; + n.n = f; + f->p = &n; + f = &n; + } + return n.t; + } + + Q_DISABLE_COPY(QCache) + +public: + inline explicit QCache(int maxCost = 100); +#ifdef QT3_SUPPORT + inline QT3_SUPPORT_CONSTRUCTOR QCache(int maxCost, int /* dummy */) + : f(0), l(0), mx(maxCost), total(0) {} +#endif + inline ~QCache() { clear(); } + + inline int maxCost() const { return mx; } + void setMaxCost(int m); + inline int totalCost() const { return total; } + + inline int size() const { return hash.size(); } + inline int count() const { return hash.size(); } + inline bool isEmpty() const { return hash.isEmpty(); } + inline QList<Key> keys() const { return hash.keys(); } + + void clear(); + + bool insert(const Key &key, T *object, int cost = 1); + T *object(const Key &key) const; + inline bool contains(const Key &key) const { return hash.contains(key); } + T *operator[](const Key &key) const; + + bool remove(const Key &key); + T *take(const Key &key); + +private: + void trim(int m); + +#ifdef QT3_SUPPORT + inline QT3_SUPPORT T *find(const Key &key) const { return object(key); } +#endif + +}; + +template <class Key, class T> +inline QCache<Key, T>::QCache(int amaxCost) + : f(0), l(0), mx(amaxCost), total(0) {} + +template <class Key, class T> +inline void QCache<Key,T>::clear() +{ while (f) { delete f->t; f = f->n; } + hash.clear(); l = 0; total = 0; } + +template <class Key, class T> +inline void QCache<Key,T>::setMaxCost(int m) +{ mx = m; trim(mx); } + +template <class Key, class T> +inline T *QCache<Key,T>::object(const Key &key) const +{ return const_cast<QCache<Key,T>*>(this)->relink(key); } + +template <class Key, class T> +inline T *QCache<Key,T>::operator[](const Key &key) const +{ return object(key); } + +template <class Key, class T> +inline bool QCache<Key,T>::remove(const Key &key) +{ + typename QHash<Key, Node>::iterator i = hash.find(key); + if (typename QHash<Key, Node>::const_iterator(i) == hash.constEnd()) { + return false; + } else { + unlink(*i); + return true; + } +} + +template <class Key, class T> +inline T *QCache<Key,T>::take(const Key &key) +{ + typename QHash<Key, Node>::iterator i = hash.find(key); + if (i == hash.end()) + return 0; + + Node &n = *i; + T *t = n.t; + n.t = 0; + unlink(n); + return t; +} + +template <class Key, class T> +bool QCache<Key,T>::insert(const Key &akey, T *aobject, int acost) +{ + remove(akey); + if (acost > mx) { + delete aobject; + return false; + } + trim(mx - acost); + Node sn(aobject, acost); + typename QHash<Key, Node>::iterator i = hash.insert(akey, sn); + total += acost; + Node *n = &i.value(); + n->keyPtr = &i.key(); + if (f) f->p = n; + n->n = f; + f = n; + if (!l) l = f; + return true; +} + +template <class Key, class T> +void QCache<Key,T>::trim(int m) +{ + Node *n = l; + while (n && total > m) { + Node *u = n; + n = n->p; + if (qIsDetached(*u->t)) + unlink(*u); + } +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QCACHE_H diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp new file mode 100644 index 0000000..a940cda --- /dev/null +++ b/src/corelib/tools/qchar.cpp @@ -0,0 +1,1618 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// Don't define it while compiling this module, or USERS of Qt will +// not be able to link. +#ifdef QT_NO_CAST_FROM_ASCII +#undef QT_NO_CAST_FROM_ASCII +#endif +#ifdef QT_NO_CAST_TO_ASCII +#undef QT_NO_CAST_TO_ASCII +#endif +#include "qchar.h" +#include "qdatastream.h" +#include "qtextcodec.h" + +#include "qunicodetables_p.h" + +#include "qunicodetables.cpp" + +QT_BEGIN_NAMESPACE + +#define LAST_UNICODE_CHAR 0x10ffff + +#ifndef QT_NO_CODEC_FOR_C_STRINGS +#ifdef QT_NO_TEXTCODEC +#define QT_NO_CODEC_FOR_C_STRINGS +#endif +#endif + +#define FLAG(x) (1 << (x)) + +/*! \class QLatin1Char + \brief The QLatin1Char class provides an 8-bit ASCII/Latin-1 character. + + \ingroup text + + This class is only useful to avoid the codec for C strings business + in the QChar(ch) constructor. You can avoid it by writing + QChar(ch, 0). + + \sa QChar, QLatin1String, QString +*/ + +/*! + \fn const char QLatin1Char::toLatin1() const + + Converts a Latin-1 character to an 8-bit ASCII representation of + the character. +*/ + +/*! + \fn const ushort QLatin1Char::unicode() const + + Converts a Latin-1 character to an 16-bit-encoded Unicode representation + of the character. +*/ + +/*! + \fn QLatin1Char::QLatin1Char(char c) + + Constructs a Latin-1 character for \a c. This constructor should be + used when the encoding of the input character is known to be Latin-1. +*/ + +/*! + \class QChar + \brief The QChar class provides a 16-bit Unicode character. + + \ingroup text + \reentrant + + In Qt, Unicode characters are 16-bit entities without any markup + or structure. This class represents such an entity. It is + lightweight, so it can be used everywhere. Most compilers treat + it like a \c{unsigned short}. + + QChar provides a full complement of testing/classification + functions, converting to and from other formats, converting from + composed to decomposed Unicode, and trying to compare and + case-convert if you ask it to. + + The classification functions include functions like those in the + standard C++ header \<cctype\> (formerly \<ctype.h\>), but + operating on the full range of Unicode characters. They all + return true if the character is a certain type of character; + otherwise they return false. These classification functions are + isNull() (returns true if the character is '\\0'), isPrint() + (true if the character is any sort of printable character, + including whitespace), isPunct() (any sort of punctation), + isMark() (Unicode Mark), isLetter() (a letter), isNumber() (any + sort of numeric character, not just 0-9), isLetterOrNumber(), and + isDigit() (decimal digits). All of these are wrappers around + category() which return the Unicode-defined category of each + character. + + QChar also provides direction(), which indicates the "natural" + writing direction of this character. The joining() function + indicates how the character joins with its neighbors (needed + mostly for Arabic) and finally hasMirrored(), which indicates + whether the character needs to be mirrored when it is printed in + its "unnatural" writing direction. + + Composed Unicode characters (like \aring) can be converted to + decomposed Unicode ("a" followed by "ring above") by using + decomposition(). + + In Unicode, comparison is not necessarily possible and case + conversion is very difficult at best. Unicode, covering the + "entire" world, also includes most of the world's case and + sorting problems. operator==() and friends will do comparison + based purely on the numeric Unicode value (code point) of the + characters, and toUpper() and toLower() will do case changes when + the character has a well-defined uppercase/lowercase equivalent. + For locale-dependent comparisons, use + QString::localeAwareCompare(). + + The conversion functions include unicode() (to a scalar), + toLatin1() (to scalar, but converts all non-Latin-1 characters to + 0), row() (gives the Unicode row), cell() (gives the Unicode + cell), digitValue() (gives the integer value of any of the + numerous digit characters), and a host of constructors. + + QChar provides constructors and cast operators that make it easy + to convert to and from traditional 8-bit \c{char}s. If you + defined \c QT_NO_CAST_FROM_ASCII and \c QT_NO_CAST_TO_ASCII, as + explained in the QString documentation, you will need to + explicitly call fromAscii() or fromLatin1(), or use QLatin1Char, + to construct a QChar from an 8-bit \c char, and you will need to + call toAscii() or toLatin1() to get the 8-bit value back. + + \sa QString, Unicode, QLatin1Char +*/ + +/*! + \enum QChar::UnicodeVersion + + Specifies which version of the \l{http://www.unicode.org/}{Unicode standard} + introduced a certain character. + + \value Unicode_1_1 Version 1.1 + \value Unicode_2_0 Version 2.0 + \value Unicode_2_1_2 Version 2.1.2 + \value Unicode_3_0 Version 3.0 + \value Unicode_3_1 Version 3.1 + \value Unicode_3_2 Version 3.2 + \value Unicode_4_0 Version 4.0 + \value Unicode_4_1 Version 4.1 + \value Unicode_5_0 Version 5.0 + \value Unicode_Unassigned The value is not assigned to any character + in version 5.0 of Unicode. + + \sa unicodeVersion() +*/ + +/*! + \enum QChar::Category + + This enum maps the Unicode character categories. + + The following characters are normative in Unicode: + + \value Mark_NonSpacing Unicode class name Mn + + \value Mark_SpacingCombining Unicode class name Mc + + \value Mark_Enclosing Unicode class name Me + + \value Number_DecimalDigit Unicode class name Nd + + \value Number_Letter Unicode class name Nl + + \value Number_Other Unicode class name No + + \value Separator_Space Unicode class name Zs + + \value Separator_Line Unicode class name Zl + + \value Separator_Paragraph Unicode class name Zp + + \value Other_Control Unicode class name Cc + + \value Other_Format Unicode class name Cf + + \value Other_Surrogate Unicode class name Cs + + \value Other_PrivateUse Unicode class name Co + + \value Other_NotAssigned Unicode class name Cn + + + The following categories are informative in Unicode: + + \value Letter_Uppercase Unicode class name Lu + + \value Letter_Lowercase Unicode class name Ll + + \value Letter_Titlecase Unicode class name Lt + + \value Letter_Modifier Unicode class name Lm + + \value Letter_Other Unicode class name Lo + + \value Punctuation_Connector Unicode class name Pc + + \value Punctuation_Dash Unicode class name Pd + + \value Punctuation_Open Unicode class name Ps + + \value Punctuation_Close Unicode class name Pe + + \value Punctuation_InitialQuote Unicode class name Pi + + \value Punctuation_FinalQuote Unicode class name Pf + + \value Punctuation_Other Unicode class name Po + + \value Symbol_Math Unicode class name Sm + + \value Symbol_Currency Unicode class name Sc + + \value Symbol_Modifier Unicode class name Sk + + \value Symbol_Other Unicode class name So + + \value NoCategory Qt cannot find an appropriate category for the character. + + \omitvalue Punctuation_Dask + + \sa category() +*/ + +/*! + \enum QChar::Direction + + This enum type defines the Unicode direction attributes. See the + \l{http://www.unicode.org/}{Unicode Standard} for a description + of the values. + + In order to conform to C/C++ naming conventions "Dir" is prepended + to the codes used in the Unicode Standard. + + \value DirAL + \value DirAN + \value DirB + \value DirBN + \value DirCS + \value DirEN + \value DirES + \value DirET + \value DirL + \value DirLRE + \value DirLRO + \value DirNSM + \value DirON + \value DirPDF + \value DirR + \value DirRLE + \value DirRLO + \value DirS + \value DirWS + + \sa direction() +*/ + +/*! + \enum QChar::Decomposition + + This enum type defines the Unicode decomposition attributes. See + the \l{http://www.unicode.org/}{Unicode Standard} for a + description of the values. + + \value NoDecomposition + \value Canonical + \value Circle + \value Compat + \value Final + \value Font + \value Fraction + \value Initial + \value Isolated + \value Medial + \value Narrow + \value NoBreak + \value Small + \value Square + \value Sub + \value Super + \value Vertical + \value Wide + + \omitvalue Single + + \sa decomposition() +*/ + +/*! + \enum QChar::Joining + + This enum type defines the Unicode joining attributes. See the + \l{http://www.unicode.org/}{Unicode Standard} for a description + of the values. + + \value Center + \value Dual + \value OtherJoining + \value Right + + \sa joining() +*/ + +/*! + \enum QChar::CombiningClass + + \internal + + This enum type defines names for some of the Unicode combining + classes. See the \l{http://www.unicode.org/}{Unicode Standard} + for a description of the values. + + \value Combining_Above + \value Combining_AboveAttached + \value Combining_AboveLeft + \value Combining_AboveLeftAttached + \value Combining_AboveRight + \value Combining_AboveRightAttached + \value Combining_Below + \value Combining_BelowAttached + \value Combining_BelowLeft + \value Combining_BelowLeftAttached + \value Combining_BelowRight + \value Combining_BelowRightAttached + \value Combining_DoubleAbove + \value Combining_DoubleBelow + \value Combining_IotaSubscript + \value Combining_Left + \value Combining_LeftAttached + \value Combining_Right + \value Combining_RightAttached +*/ + +/*! + \enum QChar::SpecialCharacter + + \value Null A QChar with this value isNull(). + \value Nbsp Non-breaking space. + \value ReplacementCharacter + \value ObjectReplacementCharacter The character shown when a font has no glyph for a certain codepoint. The square character is normally used. + \value ByteOrderMark + \value ByteOrderSwapped + \value ParagraphSeparator + \value LineSeparator + + \omitvalue null + \omitvalue replacement + \omitvalue byteOrderMark + \omitvalue byteOrderSwapped + \omitvalue nbsp +*/ + +/*! + \fn void QChar::setCell(uchar cell) + \internal +*/ + +/*! + \fn void QChar::setRow(uchar row) + \internal +*/ + +/*! + \fn QChar::QChar() + + Constructs a null QChar ('\\0'). + + \sa isNull() +*/ + +/*! + \fn QChar::QChar(QLatin1Char ch) + + Constructs a QChar corresponding to ASCII/Latin-1 character \a ch. +*/ + +/*! + \fn QChar::QChar(SpecialCharacter ch) + + Constructs a QChar for the predefined character value \a ch. +*/ + +/*! + Constructs a QChar corresponding to ASCII/Latin-1 character \a + ch. +*/ +QChar::QChar(char ch) +{ +#ifndef QT_NO_CODEC_FOR_C_STRINGS + if (QTextCodec::codecForCStrings()) + // ##### + ucs = QTextCodec::codecForCStrings()->toUnicode(&ch, 1).at(0).unicode(); + else +#endif + ucs = uchar(ch); +} + +/*! + Constructs a QChar corresponding to ASCII/Latin-1 character \a ch. +*/ +QChar::QChar(uchar ch) +{ +#ifndef QT_NO_CODEC_FOR_C_STRINGS + if (QTextCodec::codecForCStrings()) { + // ##### + char c = char(ch); + ucs = QTextCodec::codecForCStrings()->toUnicode(&c, 1).at(0).unicode(); + } else +#endif + ucs = ch; +} + +/*! + \fn QChar::QChar(uchar cell, uchar row) + + Constructs a QChar for Unicode cell \a cell in row \a row. + + \sa cell(), row() +*/ + +/*! + \fn QChar::QChar(ushort code) + + Constructs a QChar for the character with Unicode code point \a + code. +*/ + + +/*! + \fn QChar::QChar(short code) + + Constructs a QChar for the character with Unicode code point \a + code. +*/ + + +/*! + \fn QChar::QChar(uint code) + + Constructs a QChar for the character with Unicode code point \a + code. +*/ + + +/*! + \fn QChar::QChar(int code) + + Constructs a QChar for the character with Unicode code point \a + code. +*/ + + +/*! + \fn bool QChar::isNull() const + + Returns true if the character is the Unicode character 0x0000 + ('\\0'); otherwise returns false. +*/ + +/*! + \fn uchar QChar::cell() const + + Returns the cell (least significant byte) of the Unicode + character. + + \sa row() +*/ + +/*! + \fn uchar QChar::row() const + + Returns the row (most significant byte) of the Unicode character. + + \sa cell() +*/ + +/*! + Returns true if the character is a printable character; otherwise + returns false. This is any character not of category Cc or Cn. + + Note that this gives no indication of whether the character is + available in a particular font. +*/ +bool QChar::isPrint() const +{ + const int test = FLAG(Other_Control) | + FLAG(Other_NotAssigned); + return !(FLAG(qGetProp(ucs)->category) & test); +} + +/*! + Returns true if the character is a separator character + (Separator_* categories); otherwise returns false. +*/ +bool QChar::isSpace() const +{ + if(ucs >= 9 && ucs <=13) + return true; + const int test = FLAG(Separator_Space) | + FLAG(Separator_Line) | + FLAG(Separator_Paragraph); + return FLAG(qGetProp(ucs)->category) & test; +} + +/*! + Returns true if the character is a mark (Mark_* categories); + otherwise returns false. + + See QChar::Category for more information regarding marks. +*/ +bool QChar::isMark() const +{ + const int test = FLAG(Mark_NonSpacing) | + FLAG(Mark_SpacingCombining) | + FLAG(Mark_Enclosing); + return FLAG(qGetProp(ucs)->category) & test; +} + +/*! + Returns true if the character is a punctuation mark (Punctuation_* + categories); otherwise returns false. +*/ +bool QChar::isPunct() const +{ + const int test = FLAG(Punctuation_Connector) | + FLAG(Punctuation_Dash) | + FLAG(Punctuation_Open) | + FLAG(Punctuation_Close) | + FLAG(Punctuation_InitialQuote) | + FLAG(Punctuation_FinalQuote) | + FLAG(Punctuation_Other); + return FLAG(qGetProp(ucs)->category) & test; +} + +/*! + Returns true if the character is a letter (Letter_* categories); + otherwise returns false. +*/ +bool QChar::isLetter() const +{ + const int test = FLAG(Letter_Uppercase) | + FLAG(Letter_Lowercase) | + FLAG(Letter_Titlecase) | + FLAG(Letter_Modifier) | + FLAG(Letter_Other); + return FLAG(qGetProp(ucs)->category) & test; +} + +/*! + Returns true if the character is a number (Number_* categories, + not just 0-9); otherwise returns false. + + \sa isDigit() +*/ +bool QChar::isNumber() const +{ + const int test = FLAG(Number_DecimalDigit) | + FLAG(Number_Letter) | + FLAG(Number_Other); + return FLAG(qGetProp(ucs)->category) & test; +} + +/*! + Returns true if the character is a letter or number (Letter_* or + Number_* categories); otherwise returns false. +*/ +bool QChar::isLetterOrNumber() const +{ + const int test = FLAG(Letter_Uppercase) | + FLAG(Letter_Lowercase) | + FLAG(Letter_Titlecase) | + FLAG(Letter_Modifier) | + FLAG(Letter_Other) | + FLAG(Number_DecimalDigit) | + FLAG(Number_Letter) | + FLAG(Number_Other); + return FLAG(qGetProp(ucs)->category) & test; +} + + +/*! + Returns true if the character is a decimal digit + (Number_DecimalDigit); otherwise returns false. +*/ +bool QChar::isDigit() const +{ + return (qGetProp(ucs)->category == Number_DecimalDigit); +} + + +/*! + Returns true if the character is a symbol (Symbol_* categories); + otherwise returns false. +*/ +bool QChar::isSymbol() const +{ + const int test = FLAG(Symbol_Math) | + FLAG(Symbol_Currency) | + FLAG(Symbol_Modifier) | + FLAG(Symbol_Other); + return FLAG(qGetProp(ucs)->category) & test; +} + +/*! + \fn bool QChar::isHighSurrogate() const + + Returns true if the QChar is the high part of a utf16 surrogate + (ie. if its code point is between 0xd800 and 0xdbff). +*/ + +/*! + \fn bool QChar::isLowSurrogate() const + + Returns true if the QChar is the low part of a utf16 surrogate + (ie. if its code point is between 0xdc00 and 0xdfff). +*/ + +/*! + \fn static uint QChar::surrogateToUcs4(ushort high, ushort low) + + Converts a UTF16 surrogate pair with the given \a high and \a low values + to its UCS-4 code point. +*/ + +/*! + \fn static uint QChar::surrogateToUcs4(QChar high, QChar low) + + Converts a utf16 surrogate pair (\a high, \a low) to its ucs4 code + point. +*/ + +/*! + \fn static ushort QChar::highSurrogate(uint ucs4) + + Returns the high surrogate value of a ucs4 code point. + The returned result is undefined if \a ucs4 is smaller than 0x10000. +*/ + +/*! + \fn static ushort QChar::lowSurrogate(uint ucs4) + + Returns the low surrogate value of a ucs4 code point. + The returned result is undefined if \a ucs4 is smaller than 0x10000. +*/ + +/*! + Returns the numeric value of the digit, or -1 if the character is + not a digit. +*/ +int QChar::digitValue() const +{ + return qGetProp(ucs)->digitValue; +} + +/*! + \overload + Returns the numeric value of the digit, specified by the UCS-2-encoded + character, \a ucs2, or -1 if the character is not a digit. +*/ +int QChar::digitValue(ushort ucs2) +{ + return qGetProp(ucs2)->digitValue; +} + +/*! + \overload + Returns the numeric value of the digit specified by the UCS-4-encoded + character, \a ucs4, or -1 if the character is not a digit. +*/ +int QChar::digitValue(uint ucs4) +{ + if (ucs4 > LAST_UNICODE_CHAR) + return 0; + return qGetProp(ucs4)->digitValue; +} + +/*! + Returns the character's category. +*/ +QChar::Category QChar::category() const +{ + return (QChar::Category) qGetProp(ucs)->category; +} + +/*! + \overload + \since 4.3 + Returns the category of the UCS-4-encoded character specified by \a ucs4. + */ +QChar::Category QChar::category(uint ucs4) +{ + if (ucs4 > LAST_UNICODE_CHAR) + return QChar::NoCategory; + return (QChar::Category) qGetProp(ucs4)->category; +} + +/*! + \overload + Returns the category of the UCS-2-encoded character specified by \a ucs2. + */ +QChar::Category QChar::category(ushort ucs2) +{ + return (QChar::Category) qGetProp(ucs2)->category; +} + + +/*! + Returns the character's direction. +*/ +QChar::Direction QChar::direction() const +{ + return (QChar::Direction) qGetProp(ucs)->direction; +} + +/*! +\overload +Returns the direction of the UCS-4-encoded character specified by \a ucs4. + */ +QChar::Direction QChar::direction(uint ucs4) +{ + if (ucs4 > LAST_UNICODE_CHAR) + return QChar::DirL; + return (QChar::Direction) qGetProp(ucs4)->direction; +} + +/*! +\overload +Returns the direction of the UCS-2-encoded character specified by \a ucs2. + */ +QChar::Direction QChar::direction(ushort ucs2) +{ + return (QChar::Direction) qGetProp(ucs2)->direction; +} + +/*! + Returns information about the joining properties of the character + (needed for certain languages such as Arabic). +*/ +QChar::Joining QChar::joining() const +{ + return (QChar::Joining) qGetProp(ucs)->joining; +} + +/*! +\overload +Returns information about the joining properties of the UCS-4-encoded +character specified by \a ucs4 (needed for certain languages such as +Arabic). + */ +QChar::Joining QChar::joining(uint ucs4) +{ + if (ucs4 > LAST_UNICODE_CHAR) + return QChar::OtherJoining; + return (QChar::Joining) qGetProp(ucs4)->joining; +} + +/*! +\overload +Returns information about the joining properties of the UCS-2-encoded +character specified by \a ucs2 (needed for certain languages such as +Arabic). + */ +QChar::Joining QChar::joining(ushort ucs2) +{ + return (QChar::Joining) qGetProp(ucs2)->joining; +} + + +/*! + Returns true if the character should be reversed if the text + direction is reversed; otherwise returns false. + + Same as (ch.mirroredChar() != ch). + + \sa mirroredChar() +*/ +bool QChar::hasMirrored() const +{ + return qGetProp(ucs)->mirrorDiff != 0; +} + +/*! + \fn bool QChar::isLower() const + + Returns true if the character is a lowercase letter, i.e. + category() is Letter_Lowercase. + + \sa isUpper(), toLower(), toUpper() +*/ + +/*! + \fn bool QChar::isUpper() const + + Returns true if the character is an uppercase letter, i.e. + category() is Letter_Uppercase. + + \sa isLower(), toUpper(), toLower() +*/ + +/*! + \fn bool QChar::isTitleCase() const + \since 4.3 + + Returns true if the character is a titlecase letter, i.e. + category() is Letter_Titlecase. + + \sa isLower(), toUpper(), toLower(), toTitleCase() +*/ + +/*! + Returns the mirrored character if this character is a mirrored + character; otherwise returns the character itself. + + \sa hasMirrored() +*/ +QChar QChar::mirroredChar() const +{ + return ucs + qGetProp(ucs)->mirrorDiff; +} + +/*! \overload +Returns the mirrored character if the UCS-4-encoded character specified +by \a ucs4 is a mirrored character; otherwise returns the character itself. + +\sa hasMirrored() + */ +uint QChar::mirroredChar(uint ucs4) +{ + if (ucs4 > LAST_UNICODE_CHAR) + return ucs4; + return ucs4 + qGetProp(ucs4)->mirrorDiff; +} + +/*! +\overload +Returns the mirrored character if the UCS-2-encoded character specified +by \a ucs2 is a mirrored character; otherwise returns the character itself. + +\sa hasMirrored() + */ +ushort QChar::mirroredChar(ushort ucs2) +{ + return ucs2 + qGetProp(ucs2)->mirrorDiff; +} + + +enum { + Hangul_SBase = 0xac00, + Hangul_LBase = 0x1100, + Hangul_VBase = 0x1161, + Hangul_TBase = 0x11a7, + Hangul_SCount = 11172, + Hangul_LCount = 19, + Hangul_VCount = 21, + Hangul_TCount = 28, + Hangul_NCount = 21*28 +}; + +// buffer has to have a length of 3. It's needed for Hangul decomposition +static const unsigned short * QT_FASTCALL decompositionHelper + (uint ucs4, int *length, int *tag, unsigned short *buffer) +{ + *length = 0; + if (ucs4 > LAST_UNICODE_CHAR) + return 0; + if (ucs4 >= Hangul_SBase && ucs4 < Hangul_SBase + Hangul_SCount) { + int SIndex = ucs4 - Hangul_SBase; + buffer[0] = Hangul_LBase + SIndex / Hangul_NCount; // L + buffer[1] = Hangul_VBase + (SIndex % Hangul_NCount) / Hangul_TCount; // V + buffer[2] = Hangul_TBase + SIndex % Hangul_TCount; // T + *length = buffer[2] == Hangul_TBase ? 2 : 3; + *tag = QChar::Canonical; + return buffer; + } + + const unsigned short index = GET_DECOMPOSITION_INDEX(ucs4); + if (index == 0xffff) + return 0; + const unsigned short *decomposition = uc_decomposition_map+index; + *tag = (*decomposition) & 0xff; + *length = (*decomposition) >> 8; + return decomposition+1; +} + +/*! + Decomposes a character into its parts. Returns an empty string if + no decomposition exists. +*/ +QString QChar::decomposition() const +{ + return decomposition(ucs); +} + +/*! +\overload +Decomposes the UCS-4-encoded character specified by \a ucs4 into its +constituent parts. Returns an empty string if no decomposition exists. + */ +QString QChar::decomposition(uint ucs4) +{ + unsigned short buffer[3]; + int length; + int tag; + const unsigned short *d = decompositionHelper(ucs4, &length, &tag, buffer); + return QString::fromUtf16(d, length); +} + +/*! + Returns the tag defining the composition of the character. Returns + QChar::Single if no decomposition exists. +*/ +QChar::Decomposition QChar::decompositionTag() const +{ + return decompositionTag(ucs); +} + +/*! +\overload +Returns the tag defining the composition of the UCS-4-encoded character +specified by \a ucs4. Returns QChar::Single if no decomposition exists. + */ +QChar::Decomposition QChar::decompositionTag(uint ucs4) +{ + if (ucs4 > LAST_UNICODE_CHAR) + return QChar::NoDecomposition; + const unsigned short index = GET_DECOMPOSITION_INDEX(ucs4); + if (index == 0xffff) + return QChar::NoDecomposition; + return (QChar::Decomposition)(uc_decomposition_map[index] & 0xff); +} + +/*! + Returns the combining class for the character as defined in the + Unicode standard. This is mainly useful as a positioning hint for + marks attached to a base character. + + The Qt text rendering engine uses this information to correctly + position non-spacing marks around a base character. +*/ +unsigned char QChar::combiningClass() const +{ + return (unsigned char) qGetProp(ucs)->combiningClass; +} + +/*! \overload +Returns the combining class for the UCS-4-encoded character specified by +\a ucs4, as defined in the Unicode standard. + */ +unsigned char QChar::combiningClass(uint ucs4) +{ + if (ucs4 > LAST_UNICODE_CHAR) + return 0; + return (unsigned char) qGetProp(ucs4)->combiningClass; +} + +/*! \overload +Returns the combining class for the UCS-2-encoded character specified by +\a ucs2, as defined in the Unicode standard. + */ +unsigned char QChar::combiningClass(ushort ucs2) +{ + return (unsigned char) qGetProp(ucs2)->combiningClass; +} + + +/*! + Returns the Unicode version that introduced this character. +*/ +QChar::UnicodeVersion QChar::unicodeVersion() const +{ + return (QChar::UnicodeVersion) qGetProp(ucs)->unicodeVersion; +} + +/*! \overload +Returns the Unicode version that introduced the character specified in +its UCS-4-encoded form as \a ucs4. + */ +QChar::UnicodeVersion QChar::unicodeVersion(uint ucs4) +{ + if (ucs4 > LAST_UNICODE_CHAR) + return QChar::Unicode_Unassigned; + return (QChar::UnicodeVersion) qGetProp(ucs4)->unicodeVersion; +} + +/*! \overload +Returns the Unicode version that introduced the character specified in +its UCS-2-encoded form as \a ucs2. + */ +QChar::UnicodeVersion QChar::unicodeVersion(ushort ucs2) +{ + return (QChar::UnicodeVersion) qGetProp(ucs2)->unicodeVersion; +} + + +/*! + Returns the lowercase equivalent if the character is uppercase or titlecase; + otherwise returns the character itself. +*/ +QChar QChar::toLower() const +{ + const QUnicodeTables::Properties *p = qGetProp(ucs); + if (!p->lowerCaseSpecial) + return ucs + p->lowerCaseDiff; + return ucs; +} + +/*! \overload +Returns the lowercase equivalent of the UCS-4-encoded character specified +by \a ucs4 if the character is uppercase or titlecase; otherwise returns +the character itself. + */ +uint QChar::toLower(uint ucs4) +{ + if (ucs4 > LAST_UNICODE_CHAR) + return ucs4; + const QUnicodeTables::Properties *p = qGetProp(ucs4); + if (!p->lowerCaseSpecial) + return ucs4 + p->lowerCaseDiff; + return ucs4; +} + +/*! \overload +Returns the lowercase equivalent of the UCS-2-encoded character specified +by \a ucs2 if the character is uppercase or titlecase; otherwise returns +the character itself. + */ +ushort QChar::toLower(ushort ucs2) +{ + const QUnicodeTables::Properties *p = qGetProp(ucs2); + if (!p->lowerCaseSpecial) + return ucs2 + p->lowerCaseDiff; + return ucs2; +} + +/*! + Returns the uppercase equivalent if the character is lowercase or titlecase; + otherwise returns the character itself. +*/ +QChar QChar::toUpper() const +{ + const QUnicodeTables::Properties *p = qGetProp(ucs); + if (!p->upperCaseSpecial) + return ucs + p->upperCaseDiff; + return ucs; +} + +/*! \overload +Returns the uppercase equivalent of the UCS-4-encoded character specified +by \a ucs4 if the character is lowercase or titlecase; otherwise returns +the character itself. + */ +uint QChar::toUpper(uint ucs4) +{ + if (ucs4 > LAST_UNICODE_CHAR) + return ucs4; + const QUnicodeTables::Properties *p = qGetProp(ucs4); + if (!p->upperCaseSpecial) + return ucs4 + p->upperCaseDiff; + return ucs4; +} + +/*! \overload +Returns the uppercase equivalent of the UCS-2-encoded character specified +by \a ucs2 if the character is lowercase or titlecase; otherwise returns +the character itself. + */ +ushort QChar::toUpper(ushort ucs2) +{ + const QUnicodeTables::Properties *p = qGetProp(ucs2); + if (!p->upperCaseSpecial) + return ucs2 + p->upperCaseDiff; + return ucs2; +} + +/*! + Returns the title case equivalent if the character is lowercase or uppercase; + otherwise returns the character itself. +*/ +QChar QChar::toTitleCase() const +{ + const QUnicodeTables::Properties *p = qGetProp(ucs); + if (!p->titleCaseSpecial) + return ucs + p->titleCaseDiff; + return ucs; +} + +/*! + \overload + Returns the title case equivalent of the UCS-4-encoded character specified + by \a ucs4 if the character is lowercase or uppercase; otherwise returns + the character itself. +*/ +uint QChar::toTitleCase(uint ucs4) +{ + if (ucs4 > LAST_UNICODE_CHAR) + return ucs4; + const QUnicodeTables::Properties *p = qGetProp(ucs4); + if (!p->titleCaseSpecial) + return ucs4 + p->titleCaseDiff; + return ucs4; +} + +/*! + \overload + Returns the title case equivalent of the UCS-2-encoded character specified + by \a ucs2 if the character is lowercase or uppercase; otherwise returns + the character itself. +*/ +ushort QChar::toTitleCase(ushort ucs2) +{ + const QUnicodeTables::Properties *p = qGetProp(ucs2); + if (!p->titleCaseSpecial) + return ucs2 + p->titleCaseDiff; + return ucs2; +} + + +static inline uint foldCase(const ushort *ch, const ushort *start) +{ + uint c = *ch; + if (QChar(c).isLowSurrogate() && ch > start && QChar(*(ch - 1)).isHighSurrogate()) + c = QChar::surrogateToUcs4(*(ch - 1), c); + return *ch + qGetProp(c)->caseFoldDiff; +} + +static inline uint foldCase(uint ch, uint &last) +{ + uint c = ch; + if (QChar(c).isLowSurrogate() && QChar(last).isHighSurrogate()) + c = QChar::surrogateToUcs4(last, c); + last = ch; + return ch + qGetProp(c)->caseFoldDiff; +} + +static inline ushort foldCase(ushort ch) +{ + return ch + qGetProp(ch)->caseFoldDiff; +} + +/*! + Returns the case folded equivalent of the character. For most Unicode characters this + is the same as toLowerCase(). +*/ +QChar QChar::toCaseFolded() const +{ + return ucs + qGetProp(ucs)->caseFoldDiff; +} + +/*! + \overload + Returns the case folded equivalent of the UCS-4-encoded character specified + by \a ucs4. For most Unicode characters this is the same as toLowerCase(). +*/ +uint QChar::toCaseFolded(uint ucs4) +{ + if (ucs4 > LAST_UNICODE_CHAR) + return ucs4; + return ucs4 + qGetProp(ucs4)->caseFoldDiff; +} + +/*! + \overload + Returns the case folded equivalent of the UCS-2-encoded character specified + by \a ucs2. For most Unicode characters this is the same as toLowerCase(). +*/ +ushort QChar::toCaseFolded(ushort ucs2) +{ + return ucs2 + qGetProp(ucs2)->caseFoldDiff; +} + + +/*! + \fn char QChar::latin1() const + + Use toLatin1() instead. +*/ + +/*! + \fn char QChar::ascii() const + + Use toAscii() instead. +*/ + +/*! + \fn char QChar::toLatin1() const + + Returns the Latin-1 character equivalent to the QChar, or 0. This + is mainly useful for non-internationalized software. + + \sa toAscii(), unicode(), QTextCodec::codecForCStrings() +*/ + +/*! + \fn char QChar::toAscii() const + Returns the character value of the QChar obtained using the current + codec used to read C strings, or 0 if the character is not representable + using this codec. The default codec handles Latin-1 encoded text, + but this can be changed to assist developers writing source code using + other encodings. + + The main purpose of this function is to preserve ASCII characters used + in C strings. This is mainly useful for developers of non-internationalized + software. + + \sa toLatin1(), unicode(), QTextCodec::codecForCStrings() +*/ +#ifdef Q_COMPILER_MANGLES_RETURN_TYPE +const char QChar::toAscii() const +#else +char QChar::toAscii() const +#endif +{ +#ifndef QT_NO_CODEC_FOR_C_STRINGS + if (QTextCodec::codecForCStrings()) + // ##### + return QTextCodec::codecForCStrings()->fromUnicode(QString(*this)).at(0); +#endif + return ucs > 0xff ? 0 : char(ucs); +} + +/*! + \fn QChar QChar::fromLatin1(char c) + + Converts the Latin-1 character \a c to its equivalent QChar. This + is mainly useful for non-internationalized software. + + \sa fromAscii(), unicode(), QTextCodec::codecForCStrings() +*/ + +/*! + Converts the ASCII character \a c to its equivalent QChar. This + is mainly useful for non-internationalized software. + + An alternative is to use QLatin1Char. + + \sa fromLatin1(), unicode(), QTextCodec::codecForCStrings() +*/ +QChar QChar::fromAscii(char c) +{ +#ifndef QT_NO_CODEC_FOR_C_STRINGS + if (QTextCodec::codecForCStrings()) + // ##### + return QTextCodec::codecForCStrings()->toUnicode(&c, 1).at(0).unicode(); +#endif + return QChar(ushort((uchar)c)); +} + +#ifndef QT_NO_DATASTREAM +/*! + \relates QChar + + Writes the char \a chr to the stream \a out. + + \sa {Format of the QDataStream operators} + */ + +QDataStream &operator<<(QDataStream &out, const QChar &chr) +{ + out << quint16(chr.unicode()); + return out; +} + + +/*! + \relates QChar + + Reads a char from the stream \a in into char \a chr. + + \sa {Format of the QDataStream operators} + */ + +QDataStream &operator>>(QDataStream &in, QChar &chr) +{ + quint16 u; + in >> u; + chr.unicode() = ushort(u); + return in; +} +#endif + +/*! + \fn ushort & QChar::unicode() + + Returns a reference to the numeric Unicode value of the QChar. +*/ + +/*! + \fn ushort QChar::unicode() const + + \overload +*/ + +/***************************************************************************** + Documentation of QChar related functions + *****************************************************************************/ + +/*! + \fn bool operator==(QChar c1, QChar c2) + + \relates QChar + + Returns true if \a c1 and \a c2 are the same Unicode character; + otherwise returns false. +*/ + +/*! + \fn int operator!=(QChar c1, QChar c2) + + \relates QChar + + Returns true if \a c1 and \a c2 are not the same Unicode + character; otherwise returns false. +*/ + +/*! + \fn int operator<=(QChar c1, QChar c2) + + \relates QChar + + Returns true if the numeric Unicode value of \a c1 is less than + or equal to that of \a c2; otherwise returns false. +*/ + +/*! + \fn int operator>=(QChar c1, QChar c2) + + \relates QChar + + Returns true if the numeric Unicode value of \a c1 is greater than + or equal to that of \a c2; otherwise returns false. +*/ + +/*! + \fn int operator<(QChar c1, QChar c2) + + \relates QChar + + Returns true if the numeric Unicode value of \a c1 is less than + that of \a c2; otherwise returns false. +*/ + +/*! + \fn int operator>(QChar c1, QChar c2) + + \relates QChar + + Returns true if the numeric Unicode value of \a c1 is greater than + that of \a c2; otherwise returns false. +*/ + +/*! + \fn bool QChar::mirrored() const + + Use hasMirrored() instead. +*/ + +/*! + \fn QChar QChar::lower() const + + Use toLower() instead. +*/ + +/*! + \fn QChar QChar::upper() const + + Use toUpper() instead. +*/ + +/*! + \fn bool QChar::networkOrdered() + + See if QSysInfo::ByteOrder == QSysInfo::BigEndian instead. +*/ + + +// --------------------------------------------------------------------------- + + +static QString decomposeHelper + (const QString &str, bool canonical, QChar::UnicodeVersion version) +{ + unsigned short buffer[3]; + + QString s = str; + + const unsigned short *utf16 = s.utf16(); + const unsigned short *uc = utf16 + s.length(); + while (uc != utf16) { + uint ucs4 = *(--uc); + if (QChar(ucs4).isLowSurrogate() && uc != utf16) { + ushort high = *(uc - 1); + if (QChar(high).isHighSurrogate()) { + --uc; + ucs4 = QChar::surrogateToUcs4(high, ucs4); + } + } + if (QChar::unicodeVersion(ucs4) > version) + continue; + int length; + int tag; + const unsigned short *d = decompositionHelper(ucs4, &length, &tag, buffer); + if (!d || (canonical && tag != QChar::Canonical)) + continue; + + s.replace(uc - utf16, ucs4 > 0x10000 ? 2 : 1, (const QChar *)d, length); + // since the insert invalidates the pointers and we do decomposition recursive + int pos = uc - utf16; + utf16 = s.utf16(); + uc = utf16 + pos + length; + } + + return s; +} + + +static ushort ligatureHelper(ushort u1, ushort u2) +{ + // hangul L-V pair + int LIndex = u1 - Hangul_LBase; + if (0 <= LIndex && LIndex < Hangul_LCount) { + int VIndex = u2 - Hangul_VBase; + if (0 <= VIndex && VIndex < Hangul_VCount) + return Hangul_SBase + (LIndex * Hangul_VCount + VIndex) * Hangul_TCount; + } + + // hangul LV-T pair + int SIndex = u1 - Hangul_SBase; + if (0 <= SIndex && SIndex < Hangul_SCount && (SIndex % Hangul_TCount) == 0) { + int TIndex = u2 - Hangul_TBase; + if (0 <= TIndex && TIndex <= Hangul_TCount) + return u1 + TIndex; + } + + const unsigned short index = GET_LIGATURE_INDEX(u2); + if (index == 0xffff) + return 0; + const unsigned short *ligatures = uc_ligature_map+index; + ushort length = *ligatures; + ++ligatures; + // ### use bsearch + for (uint i = 0; i < length; ++i) + if (ligatures[2*i] == u1) + return ligatures[2*i+1]; + return 0; +} + +static QString composeHelper(const QString &str) +{ + QString s = str; + + if (s.length() < 2) + return s; + + // the loop can partly ignore high Unicode as all ligatures are in the BMP + int starter = 0; + int lastCombining = 0; + int pos = 0; + while (pos < s.length()) { + uint uc = s.utf16()[pos]; + if (QChar(uc).isHighSurrogate() && pos < s.length()-1) { + ushort low = s.utf16()[pos+1]; + if (QChar(low).isLowSurrogate()) { + uc = QChar::surrogateToUcs4(uc, low); + ++pos; + } + } + int combining = QChar::combiningClass(uc); + if (starter == pos - 1 || combining > lastCombining) { + // allowed to form ligature with S + QChar ligature = ligatureHelper(s.utf16()[starter], uc); + if (ligature.unicode()) { + s[starter] = ligature; + s.remove(pos, 1); + continue; + } + } + if (!combining) + starter = pos; + lastCombining = combining; + ++pos; + } + return s; +} + + +static QString canonicalOrderHelper + (const QString &str, QChar::UnicodeVersion version) +{ + QString s = str; + const int l = s.length()-1; + int pos = 0; + while (pos < l) { + int p2 = pos+1; + uint u1 = s.at(pos).unicode(); + if (QChar(u1).isHighSurrogate()) { + ushort low = s.at(pos+1).unicode(); + if (QChar(low).isLowSurrogate()) { + p2++; + u1 = QChar::surrogateToUcs4(u1, low); + if (p2 >= l) + break; + } + } + uint u2 = s.at(p2).unicode(); + if (QChar(u2).isHighSurrogate() && p2 < l-1) { + ushort low = s.at(p2+1).unicode(); + if (QChar(low).isLowSurrogate()) { + p2++; + u2 = QChar::surrogateToUcs4(u2, low); + } + } + + int c2 = QChar::combiningClass(u2); + if (QChar::unicodeVersion(u2) > version) + c2 = 0; + + if (c2 == 0) { + pos = p2+1; + continue; + } + int c1 = QChar::combiningClass(u1); + if (QChar::unicodeVersion(u1) > version) + c1 = 0; + + if (c1 > c2) { + QChar *uc = s.data(); + int p = pos; + // exchange characters + if (u2 < 0x10000) { + uc[p++] = u2; + } else { + uc[p++] = QChar::highSurrogate(u2); + uc[p++] = QChar::lowSurrogate(u2); + } + if (u1 < 0x10000) { + uc[p++] = u1; + } else { + uc[p++] = QChar::highSurrogate(u1); + uc[p++] = QChar::lowSurrogate(u1); + } + if (pos > 0) + --pos; + if (pos > 0 && s.at(pos).isLowSurrogate()) + --pos; + } else { + ++pos; + if (u1 > 0x10000) + ++pos; + } + } + return s; +} + +int QT_FASTCALL QUnicodeTables::script(unsigned int uc) +{ + if (uc > 0xffff) + return Common; + int script = uc_scripts[uc >> 7]; + if (script < ScriptSentinel) + return script; + script = (((script - ScriptSentinel) * UnicodeBlockSize) + UnicodeBlockCount); + script = uc_scripts[script + (uc & 0x7f)]; + return script; +} + + +Q_CORE_EXPORT QUnicodeTables::LineBreakClass QT_FASTCALL QUnicodeTables::lineBreakClass(uint ucs4) +{ + return (QUnicodeTables::LineBreakClass) qGetProp(ucs4)->line_break_class; +} + + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h new file mode 100644 index 0000000..ccf7e87 --- /dev/null +++ b/src/corelib/tools/qchar.h @@ -0,0 +1,397 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCHAR_H +#define QCHAR_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class QString; + +struct QLatin1Char +{ +public: + inline explicit QLatin1Char(char c) : ch(c) {} +#ifdef Q_COMPILER_MANGLES_RETURN_TYPE + inline const char toLatin1() const { return ch; } + inline const ushort unicode() const { return ushort(uchar(ch)); } +#else + inline char toLatin1() const { return ch; } + inline ushort unicode() const { return ushort(uchar(ch)); } +#endif + +private: + char ch; +}; + + +class Q_CORE_EXPORT QChar { +public: + QChar(); +#ifndef QT_NO_CAST_FROM_ASCII + QT_ASCII_CAST_WARN_CONSTRUCTOR QChar(char c); + QT_ASCII_CAST_WARN_CONSTRUCTOR QChar(uchar c); +#endif + QChar(QLatin1Char ch); + QChar(uchar c, uchar r); + inline QChar(ushort rc) : ucs(rc){} + QChar(short rc); + QChar(uint rc); + QChar(int rc); + enum SpecialCharacter { + Null = 0x0000, + Nbsp = 0x00a0, + ReplacementCharacter = 0xfffd, + ObjectReplacementCharacter = 0xfffc, + ByteOrderMark = 0xfeff, + ByteOrderSwapped = 0xfffe, +#ifdef QT3_SUPPORT + null = Null, + replacement = ReplacementCharacter, + byteOrderMark = ByteOrderMark, + byteOrderSwapped = ByteOrderSwapped, + nbsp = Nbsp, +#endif + ParagraphSeparator = 0x2029, + LineSeparator = 0x2028 + }; + QChar(SpecialCharacter sc); + + // Unicode information + + enum Category + { + NoCategory, + + Mark_NonSpacing, // Mn + Mark_SpacingCombining, // Mc + Mark_Enclosing, // Me + + Number_DecimalDigit, // Nd + Number_Letter, // Nl + Number_Other, // No + + Separator_Space, // Zs + Separator_Line, // Zl + Separator_Paragraph, // Zp + + Other_Control, // Cc + Other_Format, // Cf + Other_Surrogate, // Cs + Other_PrivateUse, // Co + Other_NotAssigned, // Cn + + Letter_Uppercase, // Lu + Letter_Lowercase, // Ll + Letter_Titlecase, // Lt + Letter_Modifier, // Lm + Letter_Other, // Lo + + Punctuation_Connector, // Pc + Punctuation_Dash, // Pd + Punctuation_Open, // Ps + Punctuation_Close, // Pe + Punctuation_InitialQuote, // Pi + Punctuation_FinalQuote, // Pf + Punctuation_Other, // Po + + Symbol_Math, // Sm + Symbol_Currency, // Sc + Symbol_Modifier, // Sk + Symbol_Other, // So + + Punctuation_Dask = Punctuation_Dash // oops + }; + + enum Direction + { + DirL, DirR, DirEN, DirES, DirET, DirAN, DirCS, DirB, DirS, DirWS, DirON, + DirLRE, DirLRO, DirAL, DirRLE, DirRLO, DirPDF, DirNSM, DirBN + }; + + enum Decomposition + { + NoDecomposition, + Canonical, + Font, + NoBreak, + Initial, + Medial, + Final, + Isolated, + Circle, + Super, + Sub, + Vertical, + Wide, + Narrow, + Small, + Square, + Compat, + Fraction + +#ifdef QT3_SUPPORT + , Single = NoDecomposition +#endif + }; + + enum Joining + { + OtherJoining, Dual, Right, Center + }; + + enum CombiningClass + { + Combining_BelowLeftAttached = 200, + Combining_BelowAttached = 202, + Combining_BelowRightAttached = 204, + Combining_LeftAttached = 208, + Combining_RightAttached = 210, + Combining_AboveLeftAttached = 212, + Combining_AboveAttached = 214, + Combining_AboveRightAttached = 216, + + Combining_BelowLeft = 218, + Combining_Below = 220, + Combining_BelowRight = 222, + Combining_Left = 224, + Combining_Right = 226, + Combining_AboveLeft = 228, + Combining_Above = 230, + Combining_AboveRight = 232, + + Combining_DoubleBelow = 233, + Combining_DoubleAbove = 234, + Combining_IotaSubscript = 240 + }; + + enum UnicodeVersion { + Unicode_Unassigned, + Unicode_1_1, + Unicode_2_0, + Unicode_2_1_2, + Unicode_3_0, + Unicode_3_1, + Unicode_3_2, + Unicode_4_0, + Unicode_4_1, + Unicode_5_0 + }; + // ****** WHEN ADDING FUNCTIONS, CONSIDER ADDING TO QCharRef TOO + + Category category() const; + Direction direction() const; + Joining joining() const; + bool hasMirrored() const; + unsigned char combiningClass() const; + + QChar mirroredChar() const; + QString decomposition() const; + Decomposition decompositionTag() const; + + int digitValue() const; + QChar toLower() const; + QChar toUpper() const; + QChar toTitleCase() const; + QChar toCaseFolded() const; + + UnicodeVersion unicodeVersion() const; + +#ifdef Q_COMPILER_MANGLES_RETURN_TYPE + const char toAscii() const; + inline const char toLatin1() const; + inline const ushort unicode() const { return ucs; } +#else + char toAscii() const; + inline char toLatin1() const; + inline ushort unicode() const { return ucs; } +#endif +#ifdef Q_NO_PACKED_REFERENCE + inline ushort &unicode() { return const_cast<ushort&>(ucs); } +#else + inline ushort &unicode() { return ucs; } +#endif + + static QChar fromAscii(char c); + static QChar fromLatin1(char c); + + inline bool isNull() const { return ucs == 0; } + bool isPrint() const; + bool isPunct() const; + bool isSpace() const; + bool isMark() const; + bool isLetter() const; + bool isNumber() const; + bool isLetterOrNumber() const; + bool isDigit() const; + bool isSymbol() const; + inline bool isLower() const { return category() == Letter_Lowercase; } + inline bool isUpper() const { return category() == Letter_Uppercase; } + inline bool isTitleCase() const { return category() == Letter_Titlecase; } + + inline bool isHighSurrogate() const { + return ((ucs & 0xfc00) == 0xd800); + } + inline bool isLowSurrogate() const { + return ((ucs & 0xfc00) == 0xdc00); + } + + inline uchar cell() const { return uchar(ucs & 0xff); } + inline uchar row() const { return uchar((ucs>>8)&0xff); } + inline void setCell(uchar cell); + inline void setRow(uchar row); + + static inline uint surrogateToUcs4(ushort high, ushort low) { + return (uint(high)<<10) + low - 0x35fdc00; + } + static inline uint surrogateToUcs4(QChar high, QChar low) { + return (uint(high.ucs)<<10) + low.ucs - 0x35fdc00; + } + static inline ushort highSurrogate(uint ucs4) { + return (ucs4>>10) + 0xd7c0; + } + static inline ushort lowSurrogate(uint ucs4) { + return ucs4%0x400 + 0xdc00; + } + + static Category QT_FASTCALL category(uint ucs4); + static Category QT_FASTCALL category(ushort ucs2); + static Direction QT_FASTCALL direction(uint ucs4); + static Direction QT_FASTCALL direction(ushort ucs2); + static Joining QT_FASTCALL joining(uint ucs4); + static Joining QT_FASTCALL joining(ushort ucs2); + static unsigned char QT_FASTCALL combiningClass(uint ucs4); + static unsigned char QT_FASTCALL combiningClass(ushort ucs2); + + static uint QT_FASTCALL mirroredChar(uint ucs4); + static ushort QT_FASTCALL mirroredChar(ushort ucs2); + static Decomposition QT_FASTCALL decompositionTag(uint ucs4); + + static int QT_FASTCALL digitValue(uint ucs4); + static int QT_FASTCALL digitValue(ushort ucs2); + static uint QT_FASTCALL toLower(uint ucs4); + static ushort QT_FASTCALL toLower(ushort ucs2); + static uint QT_FASTCALL toUpper(uint ucs4); + static ushort QT_FASTCALL toUpper(ushort ucs2); + static uint QT_FASTCALL toTitleCase(uint ucs4); + static ushort QT_FASTCALL toTitleCase(ushort ucs2); + static uint QT_FASTCALL toCaseFolded(uint ucs4); + static ushort QT_FASTCALL toCaseFolded(ushort ucs2); + + static UnicodeVersion QT_FASTCALL unicodeVersion(uint ucs4); + static UnicodeVersion QT_FASTCALL unicodeVersion(ushort ucs2); + + static QString QT_FASTCALL decomposition(uint ucs4); + +#ifdef QT3_SUPPORT + inline QT3_SUPPORT bool mirrored() const { return hasMirrored(); } + inline QT3_SUPPORT QChar lower() const { return toLower(); } + inline QT3_SUPPORT QChar upper() const { return toUpper(); } + static inline QT3_SUPPORT bool networkOrdered() { + return QSysInfo::ByteOrder == QSysInfo::BigEndian; + } +#ifdef Q_COMPILER_MANGLES_RETURN_TYPE + inline QT3_SUPPORT const char latin1() const { return toLatin1(); } + inline QT3_SUPPORT const char ascii() const { return toAscii(); } +#else + inline QT3_SUPPORT char latin1() const { return toLatin1(); } + inline QT3_SUPPORT char ascii() const { return toAscii(); } +#endif +#endif + +private: +#ifdef QT_NO_CAST_FROM_ASCII + QChar(char c); + QChar(uchar c); +#endif + ushort ucs; +} +#if (defined(__arm__) || defined(__ARMEL__)) + Q_PACKED +#endif + ; + +Q_DECLARE_TYPEINFO(QChar, Q_MOVABLE_TYPE); + +inline QChar::QChar() : ucs(0) {} + +#ifdef Q_COMPILER_MANGLES_RETURN_TYPE +inline const char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); } +#else +inline char QChar::toLatin1() const { return ucs > 0xff ? '\0' : char(ucs); } +#endif +inline QChar QChar::fromLatin1(char c) { return QChar(ushort(uchar(c))); } + +inline QChar::QChar(uchar c, uchar r) : ucs((r << 8) | c){} +inline QChar::QChar(short rc) : ucs(ushort(rc)){} +inline QChar::QChar(uint rc) : ucs(ushort(rc & 0xffff)){} +inline QChar::QChar(int rc) : ucs(ushort(rc & 0xffff)){} +inline QChar::QChar(SpecialCharacter s) : ucs(ushort(s)) {} +inline QChar::QChar(QLatin1Char ch) : ucs(ch.unicode()) {} + +inline void QChar::setCell(uchar acell) +{ ucs = (ucs & 0xff00) + acell; } +inline void QChar::setRow(uchar arow) +{ ucs = (ushort(arow)<<8) + (ucs&0xff); } + +inline bool operator==(QChar c1, QChar c2) { return c1.unicode() == c2.unicode(); } +inline bool operator!=(QChar c1, QChar c2) { return c1.unicode() != c2.unicode(); } +inline bool operator<=(QChar c1, QChar c2) { return c1.unicode() <= c2.unicode(); } +inline bool operator>=(QChar c1, QChar c2) { return c1.unicode() >= c2.unicode(); } +inline bool operator<(QChar c1, QChar c2) { return c1.unicode() < c2.unicode(); } +inline bool operator>(QChar c1, QChar c2) { return c1.unicode() > c2.unicode(); } + +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QChar &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QChar &); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QCHAR_H diff --git a/src/corelib/tools/qcontainerfwd.h b/src/corelib/tools/qcontainerfwd.h new file mode 100644 index 0000000..8af9557 --- /dev/null +++ b/src/corelib/tools/qcontainerfwd.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCONTAINERFWD_H +#define QCONTAINERFWD_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +template <class Key, class T> class QCache; +template <class Key, class T> class QHash; +template <class T> class QLinkedList; +template <class T> class QList; +template <class Key, class T> class QMap; +template <class Key, class T> class QMultiHash; +template <class Key, class T> class QMultiMap; +template <class T1, class T2> struct QPair; +template <class T> class QQueue; +template <class T> class QSet; +template <class T> class QStack; +template<class T, int Prealloc = 256> class QVarLengthArray; +template <class T> class QVector; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QCONTAINERFWD_H diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp new file mode 100644 index 0000000..7232626 --- /dev/null +++ b/src/corelib/tools/qcryptographichash.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qcryptographichash.h> + +#include "../../3rdparty/md5/md5.h" +#include "../../3rdparty/md5/md5.cpp" +#include "../../3rdparty/md4/md4.h" +#include "../../3rdparty/md4/md4.cpp" +#include "../../3rdparty/sha1/sha1.cpp" + + +QT_BEGIN_NAMESPACE + +class QCryptographicHashPrivate +{ +public: + QCryptographicHash::Algorithm method; + union { + MD5Context md5Context; + md4_context md4Context; + Sha1State sha1Context; + }; + QByteArray result; +}; + +/*! + \class QCryptographicHash + + \brief The QCryptographicHash class provides a way to generate cryptographic hashes. + + \since 4.3 + + \ingroup tools + \reentrant + + QCryptographicHash can be used to generate cryptographic hashes of binary or text data. + + Currently MD4, MD5, and SHA1 are supported. +*/ + +/*! + \enum QCryptographicHash::Algorithm + + \value Md4 Generate an MD4 hash sum + \value Md5 Generate an MD5 hash sum + \value Sha1 Generate an SHA1 hash sum +*/ + +/*! + Constructs an object that can be used to create a cryptographic hash from data using \a method. +*/ +QCryptographicHash::QCryptographicHash(Algorithm method) + : d(new QCryptographicHashPrivate) +{ + d->method = method; + reset(); +} + +/*! + Destroys the object. +*/ +QCryptographicHash::~QCryptographicHash() +{ + delete d; +} + +/*! + Resets the object. +*/ +void QCryptographicHash::reset() +{ + switch (d->method) { + case Md4: + md4_init(&d->md4Context); + break; + case Md5: + MD5Init(&d->md5Context); + break; + case Sha1: + sha1InitState(&d->sha1Context); + break; + } + d->result.clear(); +} + +/*! + Adds the first \a length chars of \a data to the cryptographic + hash. +*/ +void QCryptographicHash::addData(const char *data, int length) +{ + switch (d->method) { + case Md4: + md4_update(&d->md4Context, (const unsigned char *)data, length); + break; + case Md5: + MD5Update(&d->md5Context, (const unsigned char *)data, length); + break; + case Sha1: + sha1Update(&d->sha1Context, (const unsigned char *)data, length); + break; + } + d->result.clear(); +} + +/*! + /overload +*/ +void QCryptographicHash::addData(const QByteArray &data) +{ + addData(data.constData(), data.length()); +} + +/*! + Returns the final hash value. + + \sa QByteArray::toHex() +*/ +QByteArray QCryptographicHash::result() const +{ + if (!d->result.isEmpty()) + return d->result; + + switch (d->method) { + case Md4: { + md4_context copy = d->md4Context; + d->result.resize(MD4_RESULTLEN); + md4_final(©, (unsigned char *)d->result.data()); + break; + } + case Md5: { + MD5Context copy = d->md5Context; + d->result.resize(16); + MD5Final(©, (unsigned char *)d->result.data()); + break; + } + case Sha1: { + Sha1State copy = d->sha1Context; + d->result.resize(20); + sha1FinalizeState(©); + sha1ToHash(©, (unsigned char *)d->result.data()); + } + } + return d->result; +} + +/*! + Returns the hash of \a data using \a method. +*/ +QByteArray QCryptographicHash::hash(const QByteArray &data, Algorithm method) +{ + QCryptographicHash hash(method); + hash.addData(data); + return hash.result(); +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qcryptographichash.h b/src/corelib/tools/qcryptographichash.h new file mode 100644 index 0000000..ab549e6 --- /dev/null +++ b/src/corelib/tools/qcryptographichash.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCRYPTOGRAPHICSHASH_H +#define QCRYPTOGRAPHICSHASH_H + +#include <QtCore/qbytearray.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class QCryptographicHashPrivate; + +class Q_CORE_EXPORT QCryptographicHash +{ +public: + enum Algorithm { + Md4, + Md5, + Sha1 + }; + + QCryptographicHash(Algorithm method); + ~QCryptographicHash(); + + void reset(); + + void addData(const char *data, int length); + void addData(const QByteArray &data); + + QByteArray result() const; + + static QByteArray hash(const QByteArray &data, Algorithm method); +private: + Q_DISABLE_COPY(QCryptographicHash) + QCryptographicHashPrivate *d; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp new file mode 100644 index 0000000..781514c --- /dev/null +++ b/src/corelib/tools/qdatetime.cpp @@ -0,0 +1,5506 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformdefs.h" +#include "private/qdatetime_p.h" + +#include "qdatastream.h" +#include "qset.h" +#include "qlocale.h" +#include "qdatetime.h" +#include "qregexp.h" +#include "qdebug.h" +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) +#include <windows.h> +#endif +#ifndef Q_WS_WIN +#include <locale.h> +#endif + +#include <time.h> +#if defined(Q_OS_WINCE) +#include "qfunctions_wince.h" +#endif + +//#define QDATETIMEPARSER_DEBUG +#if defined (QDATETIMEPARSER_DEBUG) && !defined(QT_NO_DEBUG_STREAM) +# define QDTPDEBUG qDebug() << QString("%1:%2").arg(__FILE__).arg(__LINE__) +# define QDTPDEBUGN qDebug +#else +# define QDTPDEBUG if (false) qDebug() +# define QDTPDEBUGN if (false) qDebug +#endif + +#if defined(Q_WS_MAC) +#include <private/qcore_mac_p.h> +#endif + +QT_BEGIN_NAMESPACE + +enum { + FIRST_YEAR = -4713, + FIRST_MONTH = 1, + FIRST_DAY = 2, // ### Qt 5: make FIRST_DAY = 1, by support jd == 0 as valid + SECS_PER_DAY = 86400, + MSECS_PER_DAY = 86400000, + SECS_PER_HOUR = 3600, + MSECS_PER_HOUR = 3600000, + SECS_PER_MIN = 60, + MSECS_PER_MIN = 60000 +}; + +static inline QDate fixedDate(int y, int m, int d) +{ + QDate result(y, m, 1); + result.setDate(y, m, qMin(d, result.daysInMonth())); + return result; +} + +static uint julianDayFromDate(int year, int month, int day) +{ + if (year < 0) + ++year; + + if (year > 1582 || (year == 1582 && (month > 10 || (month == 10 && day >= 15)))) { + // Gregorian calendar starting from October 15, 1582 + // Algorithm from Henry F. Fliegel and Thomas C. Van Flandern + 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; + } else if (year < 1582 || (year == 1582 && (month < 10 || (month == 10 && day <= 4)))) { + // Julian calendar until October 4, 1582 + // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering + int a = (14 - month) / 12; + return (153 * (month + (12 * a) - 3) + 2) / 5 + + (1461 * (year + 4800 - a)) / 4 + + day - 32083; + } else { + // the day following October 4, 1582 is October 15, 1582 + return 0; + } +} + +static void getDateFromJulianDay(uint julianDay, int *year, int *month, int *day) +{ + int y, m, d; + + if (julianDay >= 2299161) { + // Gregorian calendar starting from October 15, 1582 + // This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern + qulonglong ell, n, i, j; + ell = qulonglong(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; + } else { + // Julian calendar until October 4, 1582 + // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering + julianDay += 32082; + int dd = (4 * julianDay + 3) / 1461; + int ee = julianDay - (1461 * dd) / 4; + int mm = ((5 * ee) + 2) / 153; + d = ee - (153 * mm + 2) / 5 + 1; + m = mm + 3 - 12 * (mm / 10); + y = dd - 4800 + (mm / 10); + if (y <= 0) + --y; + } + if (year) + *year = y; + if (month) + *month = m; + if (day) + *day = d; +} + + +static const char monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +#ifndef QT_NO_TEXTDATE +static const char * const qt_shortMonthNames[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +#endif +#ifndef QT_NO_DATESTRING +static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* dd = 0); +#endif + +/***************************************************************************** + QDate member functions + *****************************************************************************/ + +/*! + \since 4.5 + + \enum QDate::MonthNameType + + This enum describes the types of the string representation used + for the month name. + + \value DateFormat This type of name can be used for date-to-string formatting. + \value StandaloneFormat This type is used when you need to enumerate months or weekdays. + Usually standalone names are represented in singular forms with + capitalized first letter. +*/ + +/*! + \class QDate + \reentrant + \brief The QDate class provides date functions. + + \ingroup time + \mainclass + + A QDate object contains a calendar date, i.e. year, month, and day + numbers, in the Gregorian calendar. (see \l{QDate G and J} {Use of + Gregorian and Julian Calendars} for dates prior to 15 October + 1582). It can read the current date from the system clock. It + provides functions for comparing dates, and for manipulating + dates. For example, it is possible to add and subtract days, + months, and years to dates. + + A QDate object is typically created either by giving the year, + month, and day numbers explicitly. Note that QDate interprets two + digit years as is, i.e., years 0 - 99. A QDate can also be + constructed with the static function currentDate(), which creates + a QDate object containing the system clock's date. An explicit + date can also be set using setDate(). The fromString() function + returns a QDate given a string and a date format which is used to + interpret the date within the string. + + The year(), month(), and day() functions provide access to the + year, month, and day numbers. Also, dayOfWeek() and dayOfYear() + functions are provided. The same information is provided in + textual format by the toString(), shortDayName(), longDayName(), + shortMonthName(), and longMonthName() functions. + + QDate provides a full set of operators to compare two QDate + objects where smaller means earlier, and larger means later. + + You can increment (or decrement) a date by a given number of days + using addDays(). Similarly you can use addMonths() and addYears(). + The daysTo() function returns the number of days between two + dates. + + The daysInMonth() and daysInYear() functions return how many days + there are in this date's month and year, respectively. The + isLeapYear() function indicates whether a date is in a leap year. + + \section1 + + \target QDate G and J + \section2 Use of Gregorian and Julian Calendars + + QDate uses the Gregorian calendar in all locales, beginning + on the date 15 October 1582. For dates up to and including 4 + October 1582, the Julian calendar is used. This means there is a + 10-day gap in the internal calendar between the 4th and the 15th + of October 1582. When you use QDateTime for dates in that epoch, + the day after 4 October 1582 is 15 October 1582, and the dates in + the gap are invalid. + + The Julian to Gregorian changeover date used here is the date when + the Gregorian calendar was first introduced, by Pope Gregory + XIII. That change was not universally accepted and some localities + only executed it at a later date (if at all). QDateTime + doesn't take any of these historical facts into account. If an + application must support a locale-specific dating system, it must + do so on its own, remembering to convert the dates using the + Julian day. + + \section2 No Year 0 + + There is no year 0. Dates in that year are considered invalid. The + year -1 is the year "1 before Christ" or "1 before current era." + The day before 0001-01-01 is December 31st, 1 BCE. + + \section2 Range of Valid Dates + + The range of valid dates is from January 2nd, 4713 BCE, to + sometime in the year 11 million CE. The Julian Day returned by + QDate::toJulianDay() is a number in the contiguous range from 1 to + \e{overflow}, even across QDateTime's "date holes". It is suitable + for use in applications that must convert a QDateTime to a date in + another calendar system, e.g., Hebrew, Islamic or Chinese. + + \sa QTime, QDateTime, QDateEdit, QDateTimeEdit, QCalendarWidget +*/ + +/*! + \fn QDate::QDate() + + Constructs a null date. Null dates are invalid. + + \sa isNull(), isValid() +*/ + +/*! + Constructs a date with year \a y, month \a m and day \a d. + + If the specified date is invalid, the date is not set and + isValid() returns false. A date before 2 January 4713 B.C. is + considered invalid. + + \warning Years 0 to 99 are interpreted as is, i.e., years + 0-99. + + \sa isValid() +*/ + +QDate::QDate(int y, int m, int d) +{ + setDate(y, m, d); +} + + +/*! + \fn bool QDate::isNull() const + + Returns true if the date is null; otherwise returns false. A null + date is invalid. + + \note The behavior of this function is equivalent to isValid(). + + \sa isValid() +*/ + + +/*! + Returns true if this date is valid; otherwise returns false. + + \sa isNull() +*/ + +bool QDate::isValid() const +{ + return !isNull(); +} + + +/*! + Returns the year of this date. Negative numbers indicate years + before 1 A.D. = 1 C.E., such that year -44 is 44 B.C. + + \sa month(), day() +*/ + +int QDate::year() const +{ + int y; + getDateFromJulianDay(jd, &y, 0, 0); + return y; +} + +/*! + Returns the number corresponding to the month of this date, using + the following convention: + + \list + \i 1 = "January" + \i 2 = "February" + \i 3 = "March" + \i 4 = "April" + \i 5 = "May" + \i 6 = "June" + \i 7 = "July" + \i 8 = "August" + \i 9 = "September" + \i 10 = "October" + \i 11 = "November" + \i 12 = "December" + \endlist + + \sa year(), day() +*/ + +int QDate::month() const +{ + int m; + getDateFromJulianDay(jd, 0, &m, 0); + return m; +} + +/*! + Returns the day of the month (1 to 31) of this date. + + \sa year(), month(), dayOfWeek() +*/ + +int QDate::day() const +{ + int d; + getDateFromJulianDay(jd, 0, 0, &d); + return d; +} + +/*! + Returns the weekday (1 to 7) for this date. + + \sa day(), dayOfYear(), Qt::DayOfWeek +*/ + +int QDate::dayOfWeek() const +{ + return (jd % 7) + 1; +} + +/*! + Returns the day of the year (1 to 365 or 366 on leap years) for + this date. + + \sa day(), dayOfWeek() +*/ + +int QDate::dayOfYear() const +{ + return jd - julianDayFromDate(year(), 1, 1) + 1; +} + +/*! + Returns the number of days in the month (28 to 31) for this date. + + \sa day(), daysInYear() +*/ + +int QDate::daysInMonth() const +{ + int y, m, d; + getDateFromJulianDay(jd, &y, &m, &d); + if (m == 2 && isLeapYear(y)) + return 29; + else + return monthDays[m]; +} + +/*! + Returns the number of days in the year (365 or 366) for this date. + + \sa day(), daysInMonth() +*/ + +int QDate::daysInYear() const +{ + int y, m, d; + getDateFromJulianDay(jd, &y, &m, &d); + return isLeapYear(y) ? 366 : 365; +} + +/*! + Returns the week number (1 to 53), and stores the year in + *\a{yearNumber} unless \a yearNumber is null (the default). + + Returns 0 if the date is invalid. + + In accordance with ISO 8601, weeks start on Monday and the first + Thursday of a year is always in week 1 of that year. Most years + have 52 weeks, but some have 53. + + *\a{yearNumber} is not always the same as year(). For example, 1 + January 2000 has week number 52 in the year 1999, and 31 December + 2002 has week number 1 in the year 2003. + + \legalese + Copyright (c) 1989 The Regents of the University of California. + All rights reserved. + + Redistribution and use in source and binary forms are permitted + provided that the above copyright notice and this paragraph are + duplicated in all such forms and that any documentation, + advertising materials, and other materials related to such + distribution and use acknowledge that the software was developed + by the University of California, Berkeley. The name of the + University may not be used to endorse or promote products derived + from this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + \sa isValid() +*/ + +int QDate::weekNumber(int *yearNumber) const +{ + if (!isValid()) + return 0; + + int year = QDate::year(); + int yday = dayOfYear() - 1; + int wday = dayOfWeek(); + if (wday == 7) + wday = 0; + int w; + + for (;;) { + int len; + int bot; + int top; + + len = isLeapYear(year) ? 366 : 365; + /* + ** What yday (-3 ... 3) does + ** the ISO year begin on? + */ + bot = ((yday + 11 - wday) % 7) - 3; + /* + ** What yday does the NEXT + ** ISO year begin on? + */ + top = bot - (len % 7); + if (top < -3) + top += 7; + top += len; + if (yday >= top) { + ++year; + w = 1; + break; + } + if (yday >= bot) { + w = 1 + ((yday - bot) / 7); + break; + } + --year; + yday += isLeapYear(year) ? 366 : 365; + } + if (yearNumber != 0) + *yearNumber = year; + return w; +} + +#ifndef QT_NO_TEXTDATE +/*! + \since 4.5 + + Returns the short name of the \a month for the representation specified + by \a type. + + The months are enumerated using the following convention: + + \list + \i 1 = "Jan" + \i 2 = "Feb" + \i 3 = "Mar" + \i 4 = "Apr" + \i 5 = "May" + \i 6 = "Jun" + \i 7 = "Jul" + \i 8 = "Aug" + \i 9 = "Sep" + \i 10 = "Oct" + \i 11 = "Nov" + \i 12 = "Dec" + \endlist + + The month names will be localized according to the system's locale + settings. + + \sa toString(), longMonthName(), shortDayName(), longDayName() +*/ + +QString QDate::shortMonthName(int month, QDate::MonthNameType type) +{ + if (month < 1 || month > 12) { + month = 1; + } + switch (type) { + case QDate::DateFormat: + return QLocale::system().monthName(month, QLocale::ShortFormat); + case QDate::StandaloneFormat: + return QLocale::system().standaloneMonthName(month, QLocale::ShortFormat); + default: + break; + } + return QString(); +} + +/*! + Returns the short version of the name of the \a month. The + returned name is in normal type which can be used for date formatting. + + \sa toString(), longMonthName(), shortDayName(), longDayName() + */ + +QString QDate::shortMonthName(int month) +{ + return shortMonthName(month, QDate::DateFormat); +} + +/*! + \since 4.5 + + Returns the long name of the \a month for the representation specified + by \a type. + + The months are enumerated using the following convention: + + \list + \i 1 = "January" + \i 2 = "February" + \i 3 = "March" + \i 4 = "April" + \i 5 = "May" + \i 6 = "June" + \i 7 = "July" + \i 8 = "August" + \i 9 = "September" + \i 10 = "October" + \i 11 = "November" + \i 12 = "December" + \endlist + + The month names will be localized according to the system's locale + settings. + + \sa toString(), shortMonthName(), shortDayName(), longDayName() +*/ + +QString QDate::longMonthName(int month, MonthNameType type) +{ + if (month < 1 || month > 12) { + month = 1; + } + switch (type) { + case QDate::DateFormat: + return QLocale::system().monthName(month, QLocale::LongFormat); + case QDate::StandaloneFormat: + return QLocale::system().standaloneMonthName(month, QLocale::LongFormat); + default: + break; + } + return QString(); +} + +/*! + Returns the long version of the name of the \a month. The + returned name is in normal type which can be used for date formatting. + + \sa toString(), shortMonthName(), shortDayName(), longDayName() + */ + +QString QDate::longMonthName(int month) +{ + if (month < 1 || month > 12) { + month = 1; + } + return QLocale::system().monthName(month, QLocale::LongFormat); +} + +/*! + \since 4.5 + + Returns the short name of the \a weekday for the representation specified + by \a type. + + The days are enumerated using the following convention: + + \list + \i 1 = "Mon" + \i 2 = "Tue" + \i 3 = "Wed" + \i 4 = "Thu" + \i 5 = "Fri" + \i 6 = "Sat" + \i 7 = "Sun" + \endlist + + The day names will be localized according to the system's locale + settings. + + \sa toString(), shortMonthName(), longMonthName(), longDayName() +*/ + +QString QDate::shortDayName(int weekday, MonthNameType type) +{ + if (weekday < 1 || weekday > 7) { + weekday = 1; + } + switch (type) { + case QDate::DateFormat: + return QLocale::system().dayName(weekday, QLocale::ShortFormat); + case QDate::StandaloneFormat: + return QLocale::system().standaloneDayName(weekday, QLocale::ShortFormat); + default: + break; + } + return QString(); +} + +/*! + Returns the short version of the name of the \a weekday. The + returned name is in normal type which can be used for date formatting. + + \sa toString(), longDayName(), shortMonthName(), longMonthName() + */ + +QString QDate::shortDayName(int weekday) +{ + if (weekday < 1 || weekday > 7) { + weekday = 1; + } + return QLocale::system().dayName(weekday, QLocale::ShortFormat); +} + +/*! + \since 4.5 + + Returns the long name of the \a weekday for the representation specified + by \a type. + + The days are enumerated using the following convention: + + \list + \i 1 = "Monday" + \i 2 = "Tuesday" + \i 3 = "Wednesday" + \i 4 = "Thursday" + \i 5 = "Friday" + \i 6 = "Saturday" + \i 7 = "Sunday" + \endlist + + The day names will be localized according to the system's locale + settings. + + \sa toString(), shortDayName(), shortMonthName(), longMonthName() +*/ + +QString QDate::longDayName(int weekday, MonthNameType type) +{ + if (weekday < 1 || weekday > 7) { + weekday = 1; + } + switch (type) { + case QDate::DateFormat: + return QLocale::system().dayName(weekday, QLocale::LongFormat); + case QDate::StandaloneFormat: + return QLocale::system().standaloneDayName(weekday, QLocale::LongFormat); + default: + break; + } + return QLocale::system().dayName(weekday, QLocale::LongFormat); +} + +/*! + Returns the long version of the name of the \a weekday. The + returned name is in normal type which can be used for date formatting. + + \sa toString(), shortDayName(), shortMonthName(), longMonthName() + */ + +QString QDate::longDayName(int weekday) +{ + if (weekday < 1 || weekday > 7) { + weekday = 1; + } + return QLocale::system().dayName(weekday, QLocale::LongFormat); +} +#endif //QT_NO_TEXTDATE + +#ifndef QT_NO_DATESTRING + +/*! + \fn QString QDate::toString(Qt::DateFormat format) const + + \overload + + Returns the date as a string. The \a format parameter determines + the format of the string. + + If the \a format is Qt::TextDate, the string is formatted in + the default way. QDate::shortDayName() and QDate::shortMonthName() + are used to generate the string, so the day and month names will + be localized names. An example of this formatting is + "Sat May 20 1995". + + If the \a format is Qt::ISODate, the string format corresponds + to the ISO 8601 extended specification for representations of + dates and times, taking the form YYYY-MM-DD, where YYYY is the + year, MM is the month of the year (between 01 and 12), and DD is + the day of the month between 01 and 31. + + If the \a format is Qt::SystemLocaleShortDate or + Qt::SystemLocaleLongDate, the string format depends on the locale + settings of the system. Identical to calling + QLocale::system().toString(date, QLocale::ShortFormat) or + QLocale::system().toString(date, QLocale::LongFormat). + + If the \a format is Qt::DefaultLocaleShortDate or + Qt::DefaultLocaleLongDate, the string format depends on the + default application locale. This is the locale set with + QLocale::setDefault(), or the system locale if no default locale + has been set. Identical to calling QLocale().toString(date, + QLocale::ShortFormat) or QLocale().toString(date, + QLocale::LongFormat). + + If the date is invalid, an empty string will be returned. + + \warning The Qt::ISODate format is only valid for years in the + range 0 to 9999. This restriction may apply to locale-aware + formats as well, depending on the locale settings. + + \sa shortDayName(), shortMonthName() +*/ +QString QDate::toString(Qt::DateFormat f) const +{ + if (!isValid()) + return QString(); + int y, m, d; + getDateFromJulianDay(jd, &y, &m, &d); + switch (f) { + case Qt::SystemLocaleDate: + case Qt::SystemLocaleShortDate: + case Qt::SystemLocaleLongDate: + return QLocale::system().toString(*this, f == Qt::SystemLocaleLongDate ? QLocale::LongFormat + : QLocale::ShortFormat); + case Qt::LocaleDate: + case Qt::DefaultLocaleShortDate: + case Qt::DefaultLocaleLongDate: + return QLocale().toString(*this, f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat + : QLocale::ShortFormat); + default: +#ifndef QT_NO_TEXTDATE + case Qt::TextDate: + { + return QString::fromLatin1("%0 %1 %2 %3") + .arg(shortDayName(dayOfWeek())) + .arg(shortMonthName(m)) + .arg(d) + .arg(y); + } +#endif + case Qt::ISODate: + { + if (year() < 0 || year() > 9999) + return QString(); + QString month(QString::number(m).rightJustified(2, QLatin1Char('0'))); + QString day(QString::number(d).rightJustified(2, QLatin1Char('0'))); + return QString::number(y) + QLatin1Char('-') + month + QLatin1Char('-') + day; + } + } +} + +/*! + Returns the date as a string. The \a format parameter determines + the format of the result string. + + These expressions may be used: + + \table + \header \i Expression \i Output + \row \i d \i the day as number without a leading zero (1 to 31) + \row \i dd \i the day as number with a leading zero (01 to 31) + \row \i ddd + \i the abbreviated localized day name (e.g. 'Mon' to 'Sun'). + Uses QDate::shortDayName(). + \row \i dddd + \i the long localized day name (e.g. 'Monday' to 'Sunday'). + Uses QDate::longDayName(). + \row \i M \i the month as number without a leading zero (1 to 12) + \row \i MM \i the month as number with a leading zero (01 to 12) + \row \i MMM + \i the abbreviated localized month name (e.g. 'Jan' to 'Dec'). + Uses QDate::shortMonthName(). + \row \i MMMM + \i the long localized month name (e.g. 'January' to 'December'). + Uses QDate::longMonthName(). + \row \i yy \i the year as two digit number (00 to 99) + \row \i yyyy \i the year as four digit number. If the year is negative, + a minus sign is prepended in addition. + \endtable + + All other input characters will be ignored. Any sequence of characters that + are enclosed in singlequotes will be treated as text and not be used as an + expression. Two consecutive singlequotes ("''") are replaced by a singlequote + in the output. + + Example format strings (assuming that the QDate is the 20 July + 1969): + + \table + \header \o Format \o Result + \row \o dd.MM.yyyy \o 20.07.1969 + \row \o ddd MMMM d yy \o Sun July 20 69 + \row \o 'The day is' dddd \o The day is Sunday + \endtable + + If the datetime is invalid, an empty string will be returned. + + \warning The Qt::ISODate format is only valid for years in the + range 0 to 9999. This restriction may apply to locale-aware + formats as well, depending on the locale settings. + + \sa QDateTime::toString() QTime::toString() + +*/ +QString QDate::toString(const QString& format) const +{ + if (year() > 9999) + return QString(); + return fmtDateTime(format, 0, this); +} +#endif //QT_NO_DATESTRING + +/*! + \obsolete + + Sets the date's year \a y, month \a m, and day \a d. + + If \a y is in the range 0 to 99, it is interpreted as 1900 to + 1999. + + Use setDate() instead. +*/ + +bool QDate::setYMD(int y, int m, int d) +{ + if (uint(y) <= 99) + y += 1900; + return setDate(y, m, d); +} + +/*! + \since 4.2 + + Sets the date's \a year, \a month, and \a day. Returns true if + the date is valid; otherwise returns false. + + If the specified date is invalid, the QDate object is set to be + invalid. Any date before 2 January 4713 B.C. is considered + invalid. + + \sa isValid() +*/ +bool QDate::setDate(int year, int month, int day) +{ + if (!isValid(year, month, day)) { + jd = 0; + } else { + jd = julianDayFromDate(year, month, day); + } + return jd != 0; +} + +/*! + \since 4.5 + + Extracts the date's year, month, and day, and assigns them to + *\a year, *\a month, and *\a day. The pointers may be null. + + \sa year(), month(), day(), isValid() +*/ +void QDate::getDate(int *year, int *month, int *day) +{ + getDateFromJulianDay(jd, year, month, day); +} + +/*! + Returns a QDate object containing a date \a ndays later than the + date of this object (or earlier if \a ndays is negative). + + \sa addMonths() addYears() daysTo() +*/ + +QDate QDate::addDays(int ndays) const +{ + QDate d; + // this is basically "d.jd = jd + ndays" with checks for integer overflow + if (ndays >= 0) + d.jd = (jd + ndays >= jd) ? jd + ndays : 0; + else + d.jd = (jd + ndays < jd) ? jd + ndays : 0; + return d; +} + +/*! + Returns a QDate object containing a date \a nmonths later than the + date of this object (or earlier if \a nmonths is negative). + + \note If the ending day/month combination does not exist in the + resulting month/year, this function will return a date that is the + latest valid date. + + \warning QDate has a date hole around the days introducing the + Gregorian calendar (the days 5 to 14 October 1582, inclusive, do + not exist). If the calculation ends in one of those days, QDate + will return either October 4 or October 15. + + \sa addDays() addYears() +*/ + +QDate QDate::addMonths(int nmonths) const +{ + if (!isValid()) + return QDate(); + if (!nmonths) + return *this; + + int old_y, y, m, d; + getDateFromJulianDay(jd, &y, &m, &d); + old_y = y; + + bool increasing = nmonths > 0; + + while (nmonths != 0) { + if (nmonths < 0 && nmonths + 12 <= 0) { + y--; + nmonths+=12; + } else if (nmonths < 0) { + m+= nmonths; + nmonths = 0; + if (m <= 0) { + --y; + m += 12; + } + } else if (nmonths - 12 >= 0) { + y++; + nmonths -= 12; + } else if (m == 12) { + y++; + m = 0; + } else { + m += nmonths; + nmonths = 0; + if (m > 12) { + ++y; + m -= 12; + } + } + } + + // was there a sign change? + if ((old_y > 0 && y <= 0) || + (old_y < 0 && y >= 0)) + // yes, adjust the date by +1 or -1 years + y += increasing ? +1 : -1; + + // did we end up in the Gregorian/Julian conversion hole? + if (y == 1582 && m == 10 && d > 4 && d < 15) + d = increasing ? 15 : 4; + + return fixedDate(y, m, d); +} + +/*! + Returns a QDate object containing a date \a nyears later than the + date of this object (or earlier if \a nyears is negative). + + \note If the ending day/month combination does not exist in the + resulting year (i.e., if the date was Feb 29 and the final year is + not a leap year), this function will return a date that is the + latest valid date (that is, Feb 28). + + \sa addDays(), addMonths() +*/ + +QDate QDate::addYears(int nyears) const +{ + if (!isValid()) + return QDate(); + + int y, m, d; + getDateFromJulianDay(jd, &y, &m, &d); + + int old_y = y; + y += nyears; + + // was there a sign change? + if ((old_y > 0 && y <= 0) || + (old_y < 0 && y >= 0)) + // yes, adjust the date by +1 or -1 years + y += nyears > 0 ? +1 : -1; + + return fixedDate(y, m, d); +} + +/*! + Returns the number of days from this date to \a d (which is + negative if \a d is earlier than this date). + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 0 + + \sa addDays() +*/ + +int QDate::daysTo(const QDate &d) const +{ + return d.jd - jd; +} + + +/*! + \fn bool QDate::operator==(const QDate &d) const + + Returns true if this date is equal to \a d; otherwise returns + false. + +*/ + +/*! + \fn bool QDate::operator!=(const QDate &d) const + + Returns true if this date is different from \a d; otherwise + returns false. +*/ + +/*! + \fn bool QDate::operator<(const QDate &d) const + + Returns true if this date is earlier than \a d; otherwise returns + false. +*/ + +/*! + \fn bool QDate::operator<=(const QDate &d) const + + Returns true if this date is earlier than or equal to \a d; + otherwise returns false. +*/ + +/*! + \fn bool QDate::operator>(const QDate &d) const + + Returns true if this date is later than \a d; otherwise returns + false. +*/ + +/*! + \fn bool QDate::operator>=(const QDate &d) const + + Returns true if this date is later than or equal to \a d; + otherwise returns false. +*/ + +/*! + \overload + Returns the current date, as reported by the system clock. + + \sa QTime::currentTime(), QDateTime::currentDateTime() +*/ + +QDate QDate::currentDate() +{ + QDate d; +#if defined(Q_OS_WIN) + SYSTEMTIME st; + memset(&st, 0, sizeof(SYSTEMTIME)); + GetLocalTime(&st); + d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay); +#else + // posix compliant system + time_t ltime; + time(<ime); + tm *t = 0; + +#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) + // use the reentrant version of localtime() where available + tzset(); + tm res; + t = localtime_r(<ime, &res); +#else + t = localtime(<ime); +#endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS + + d.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday); +#endif + return d; +} + +#ifndef QT_NO_DATESTRING +/*! + \fn QDate QDate::fromString(const QString &string, Qt::DateFormat format) + + Returns the QDate represented by the \a string, using the + \a format given, or an invalid date if the string cannot be + parsed. + + Note for Qt::TextDate: It is recommended that you use the + English short month names (e.g. "Jan"). Although localized month + names can also be used, they depend on the user's locale settings. +*/ +QDate QDate::fromString(const QString& s, Qt::DateFormat f) +{ + if (s.isEmpty()) + return QDate(); + + switch (f) { + case Qt::ISODate: + { + int year(s.mid(0, 4).toInt()); + int month(s.mid(5, 2).toInt()); + int day(s.mid(8, 2).toInt()); + if (year && month && day) + return QDate(year, month, day); + } + break; + case Qt::SystemLocaleDate: + case Qt::SystemLocaleShortDate: + case Qt::SystemLocaleLongDate: + return fromString(s, QLocale::system().dateFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat + : QLocale::ShortFormat)); + case Qt::LocaleDate: + case Qt::DefaultLocaleShortDate: + case Qt::DefaultLocaleLongDate: + return fromString(s, QLocale().dateFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat + : QLocale::ShortFormat)); + default: +#ifndef QT_NO_TEXTDATE + case Qt::TextDate: { + QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts); + + if (parts.count() != 4) { + return QDate(); + } + + QString monthName = parts.at(1); + int month = -1; + // Assume that English monthnames are the default + for (int i = 0; i < 12; ++i) { + if (monthName == QLatin1String(qt_shortMonthNames[i])) { + month = i + 1; + break; + } + } + // If English names can't be found, search the localized ones + if (month == -1) { + for (int i = 1; i <= 12; ++i) { + if (monthName == QDate::shortMonthName(i)) { + month = i; + break; + } + } + } + if (month < 1 || month > 12) { + return QDate(); + } + + bool ok; + int day = parts.at(2).toInt(&ok); + if (!ok) { + return QDate(); + } + + int year = parts.at(3).toInt(&ok); + if (!ok) { + return QDate(); + } + + return QDate(year, month, day); + } +#else + break; +#endif + } + return QDate(); +} + +/*! + \fn QDate::fromString(const QString &string, const QString &format) + + Returns the QDate represented by the \a string, using the \a + format given, or an invalid date if the string cannot be parsed. + + These expressions may be used for the format: + + \table + \header \i Expression \i Output + \row \i d \i The day as a number without a leading zero (1 to 31) + \row \i dd \i The day as a number with a leading zero (01 to 31) + \row \i ddd + \i The abbreviated localized day name (e.g. 'Mon' to 'Sun'). + Uses QDate::shortDayName(). + \row \i dddd + \i The long localized day name (e.g. 'Monday' to 'Sunday'). + Uses QDate::longDayName(). + \row \i M \i The month as a number without a leading zero (1 to 12) + \row \i MM \i The month as a number with a leading zero (01 to 12) + \row \i MMM + \i The abbreviated localized month name (e.g. 'Jan' to 'Dec'). + Uses QDate::shortMonthName(). + \row \i MMMM + \i The long localized month name (e.g. 'January' to 'December'). + Uses QDate::longMonthName(). + \row \i yy \i The year as two digit number (00 to 99) + \row \i yyyy \i The year as four digit number. If the year is negative, + a minus sign is prepended in addition. + \endtable + + All other input characters will be treated as text. Any sequence + of characters that are enclosed in single quotes will also be + treated as text and will not be used as an expression. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 1 + + If the format is not satisfied, an invalid QDate is returned. The + expressions that don't expect leading zeroes (d, M) will be + greedy. This means that they will use two digits even if this + will put them outside the accepted range of values and leaves too + few digits for other sections. For example, the following format + string could have meant January 30 but the M will grab two + digits, resulting in an invalid date: + + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 2 + + For any field that is not represented in the format the following + defaults are used: + + \table + \header \i Field \i Default value + \row \i Year \i 1900 + \row \i Month \i 1 + \row \i Day \i 1 + \endtable + + The following examples demonstrate the default values: + + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 3 + + \sa QDateTime::fromString(), QTime::fromString(), QDate::toString(), + QDateTime::toString(), QTime::toString() +*/ + +QDate QDate::fromString(const QString &string, const QString &format) +{ + QDate date; +#ifndef QT_BOOTSTRAPPED + QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString); + if (dt.parseFormat(format)) + dt.fromString(string, &date, 0); +#else + Q_UNUSED(string); + Q_UNUSED(format); +#endif + return date; +} +#endif // QT_NO_DATESTRING + +/*! + \overload + + Returns true if the specified date (\a year, \a month, and \a + day) is valid; otherwise returns false. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 4 + + \sa isNull(), setDate() +*/ + +bool QDate::isValid(int year, int month, int day) +{ + if (year < FIRST_YEAR + || (year == FIRST_YEAR && + (month < FIRST_MONTH + || (month == FIRST_MONTH && day < FIRST_DAY))) + || year == 0) // there is no year 0 in the Julian calendar + return false; + + // passage from Julian to Gregorian calendar + if (year == 1582 && month == 10 && day > 4 && day < 15) + return 0; + + return (day > 0 && month > 0 && month <= 12) && + (day <= monthDays[month] || (day == 29 && month == 2 && isLeapYear(year))); +} + +/*! + \fn bool QDate::isLeapYear(int year) + + Returns true if the specified \a year is a leap year; otherwise + returns false. +*/ + +bool QDate::isLeapYear(int y) +{ + if (y < 1582) { + return qAbs(y) % 4 == 0; + } else { + return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0; + } +} + +/*! + \internal + + This function has a confusing name and shouldn't be part of the + API anyway, since we have toJulian() and fromJulian(). + ### Qt 5: remove it +*/ +uint QDate::gregorianToJulian(int y, int m, int d) +{ + return julianDayFromDate(y, m, d); +} + +/*! + \internal + + This function has a confusing name and shouldn't be part of the + API anyway, since we have toJulian() and fromJulian(). + ### Qt 5: remove it +*/ +void QDate::julianToGregorian(uint jd, int &y, int &m, int &d) +{ + getDateFromJulianDay(jd, &y, &m, &d); +} + +/*! \fn static QDate QDate::fromJulianDay(int jd) + + Converts the Julian day \a jd to a QDate. + + \sa toJulianDay() +*/ + +/*! \fn int QDate::toJulianDay() const + + Converts the date to a Julian day. + + \sa fromJulianDay() +*/ + +/***************************************************************************** + QTime member functions + *****************************************************************************/ + +/*! + \class QTime + \reentrant + + \brief The QTime class provides clock time functions. + + \ingroup time + \mainclass + + A QTime object contains a clock time, i.e. the number of hours, + minutes, seconds, and milliseconds since midnight. It can read the + current time from the system clock and measure a span of elapsed + time. It provides functions for comparing times and for + manipulating a time by adding a number of milliseconds. + + QTime uses the 24-hour clock format; it has no concept of AM/PM. + Unlike QDateTime, QTime knows nothing about time zones or + daylight savings time (DST). + + A QTime object is typically created either by giving the number + of hours, minutes, seconds, and milliseconds explicitly, or by + using the static function currentTime(), which creates a QTime + object that contains the system's local time. Note that the + accuracy depends on the accuracy of the underlying operating + system; not all systems provide 1-millisecond accuracy. + + The hour(), minute(), second(), and msec() functions provide + access to the number of hours, minutes, seconds, and milliseconds + of the time. The same information is provided in textual format by + the toString() function. + + QTime provides a full set of operators to compare two QTime + objects. One time is considered smaller than another if it is + earlier than the other. + + The time a given number of seconds or milliseconds later than a + given time can be found using the addSecs() or addMSecs() + functions. Correspondingly, the number of seconds or milliseconds + between two times can be found using secsTo() or msecsTo(). + + QTime can be used to measure a span of elapsed time using the + start(), restart(), and elapsed() functions. + + \sa QDate, QDateTime +*/ + +/*! + \fn QTime::QTime() + + Constructs a null time object. A null time can be a QTime(0, 0, 0, 0) + (i.e., midnight) object, except that isNull() returns true and isValid() + returns false. + + \sa isNull(), isValid() +*/ + +/*! + Constructs a time with hour \a h, minute \a m, seconds \a s and + milliseconds \a ms. + + \a h must be in the range 0 to 23, \a m and \a s must be in the + range 0 to 59, and \a ms must be in the range 0 to 999. + + \sa isValid() +*/ + +QTime::QTime(int h, int m, int s, int ms) +{ + setHMS(h, m, s, ms); +} + + +/*! + \fn bool QTime::isNull() const + + Returns true if the time is null (i.e., the QTime object was + constructed using the default constructor); otherwise returns + false. A null time is also an invalid time. + + \sa isValid() +*/ + +/*! + Returns true if the time is valid; otherwise returns false. For example, + the time 23:30:55.746 is valid, but 24:12:30 is invalid. + + \sa isNull() +*/ + +bool QTime::isValid() const +{ + return mds > NullTime && mds < MSECS_PER_DAY; +} + + +/*! + Returns the hour part (0 to 23) of the time. + + \sa minute(), second(), msec() +*/ + +int QTime::hour() const +{ + return ds() / MSECS_PER_HOUR; +} + +/*! + Returns the minute part (0 to 59) of the time. + + \sa hour(), second(), msec() +*/ + +int QTime::minute() const +{ + return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN; +} + +/*! + Returns the second part (0 to 59) of the time. + + \sa hour(), minute(), msec() +*/ + +int QTime::second() const +{ + return (ds() / 1000)%SECS_PER_MIN; +} + +/*! + Returns the millisecond part (0 to 999) of the time. + + \sa hour(), minute(), second() +*/ + +int QTime::msec() const +{ + return ds() % 1000; +} + +#ifndef QT_NO_DATESTRING +/*! + \overload + + Returns the time as a string. Milliseconds are not included. The + \a format parameter determines the format of the string. + + If \a format is Qt::TextDate, the string format is HH:MM:SS; e.g. 1 + second before midnight would be "23:59:59". + + If \a format is Qt::ISODate, the string format corresponds to the + ISO 8601 extended specification for representations of dates, + which is also HH:MM:SS. (However, contrary to ISO 8601, dates + before 15 October 1582 are handled as Julian dates, not Gregorian + dates. See \l{QDate G and J} {Use of Gregorian and Julian + Calendars}. This might change in a future version of Qt.) + + If the \a format is Qt::SystemLocaleShortDate or + Qt::SystemLocaleLongDate, the string format depends on the locale + settings of the system. Identical to calling + QLocale::system().toString(time, QLocale::ShortFormat) or + QLocale::system().toString(time, QLocale::LongFormat). + + If the \a format is Qt::DefaultLocaleShortDate or + Qt::DefaultLocaleLongDate, the string format depends on the + default application locale. This is the locale set with + QLocale::setDefault(), or the system locale if no default locale + has been set. Identical to calling QLocale().toString(time, + QLocale::ShortFormat) or QLocale().toString(time, + QLocale::LongFormat). + + If the time is invalid, an empty string will be returned. +*/ + +QString QTime::toString(Qt::DateFormat format) const +{ + if (!isValid()) + return QString(); + + switch (format) { + case Qt::SystemLocaleDate: + case Qt::SystemLocaleShortDate: + case Qt::SystemLocaleLongDate: + return QLocale::system().toString(*this, format == Qt::SystemLocaleLongDate ? QLocale::LongFormat + : QLocale::ShortFormat); + case Qt::LocaleDate: + case Qt::DefaultLocaleShortDate: + case Qt::DefaultLocaleLongDate: + return QLocale().toString(*this, format == Qt::DefaultLocaleLongDate ? QLocale::LongFormat + : QLocale::ShortFormat); + + default: + case Qt::ISODate: + case Qt::TextDate: + return QString::fromLatin1("%1:%2:%3") + .arg(hour(), 2, 10, QLatin1Char('0')) + .arg(minute(), 2, 10, QLatin1Char('0')) + .arg(second(), 2, 10, QLatin1Char('0')); + } +} + +/*! + Returns the time as a string. The \a format parameter determines + the format of the result string. + + These expressions may be used: + + \table + \header \i Expression \i Output + \row \i h + \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) + \row \i hh + \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) + \row \i H + \i the hour without a leading zero (0 to 23, even with AM/PM display) + \row \i HH + \i the hour with a leading zero (00 to 23, even with AM/PM display) + \row \i m \i the minute without a leading zero (0 to 59) + \row \i mm \i the minute with a leading zero (00 to 59) + \row \i s \i the second without a leading zero (0 to 59) + \row \i ss \i the second with a leading zero (00 to 59) + \row \i z \i the milliseconds without leading zeroes (0 to 999) + \row \i zzz \i the milliseconds with leading zeroes (000 to 999) + \row \i AP or A + \i use AM/PM display. \e AP will be replaced by either "AM" or "PM". + \row \i ap or a + \i use am/pm display. \e ap will be replaced by either "am" or "pm". + \endtable + + All other input characters will be ignored. Any sequence of characters that + are enclosed in singlequotes will be treated as text and not be used as an + expression. Two consecutive singlequotes ("''") are replaced by a singlequote + in the output. + + Example format strings (assuming that the QTime is 14:13:09.042) + + \table + \header \i Format \i Result + \row \i hh:mm:ss.zzz \i 14:13:09.042 + \row \i h:m:s ap \i 2:13:9 pm + \row \i H:m:s a \i 14:13:9 pm + \endtable + + If the datetime is invalid, an empty string will be returned. + + \sa QDate::toString() QDateTime::toString() +*/ +QString QTime::toString(const QString& format) const +{ + return fmtDateTime(format, this, 0); +} +#endif //QT_NO_DATESTRING +/*! + Sets the time to hour \a h, minute \a m, seconds \a s and + milliseconds \a ms. + + \a h must be in the range 0 to 23, \a m and \a s must be in the + range 0 to 59, and \a ms must be in the range 0 to 999. + Returns true if the set time is valid; otherwise returns false. + + \sa isValid() +*/ + +bool QTime::setHMS(int h, int m, int s, int ms) +{ +#if defined(Q_OS_WINCE) + startTick = NullTime; +#endif + if (!isValid(h,m,s,ms)) { + mds = NullTime; // make this invalid + return false; + } + mds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms; + return true; +} + +/*! + Returns a QTime object containing a time \a s seconds later + than the time of this object (or earlier if \a s is negative). + + Note that the time will wrap if it passes midnight. + + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 5 + + \sa addMSecs(), secsTo(), QDateTime::addSecs() +*/ + +QTime QTime::addSecs(int s) const +{ + return addMSecs(s * 1000); +} + +/*! + Returns the number of seconds from this time to \a t. + If \a t is earlier than this time, the number of seconds returned + is negative. + + Because QTime measures time within a day and there are 86400 + seconds in a day, the result is always between -86400 and 86400. + + secsTo() does not take into account any milliseconds. + + \sa addSecs(), QDateTime::secsTo() +*/ + +int QTime::secsTo(const QTime &t) const +{ + return (t.ds() - ds()) / 1000; +} + +/*! + Returns a QTime object containing a time \a ms milliseconds later + than the time of this object (or earlier if \a ms is negative). + + Note that the time will wrap if it passes midnight. See addSecs() + for an example. + + \sa addSecs(), msecsTo() +*/ + +QTime QTime::addMSecs(int ms) const +{ + QTime t; + if (ms < 0) { + // % not well-defined for -ve, but / is. + int negdays = (MSECS_PER_DAY - ms) / MSECS_PER_DAY; + t.mds = (ds() + ms + negdays * MSECS_PER_DAY) % MSECS_PER_DAY; + } else { + t.mds = (ds() + ms) % MSECS_PER_DAY; + } +#if defined(Q_OS_WINCE) + if (startTick > NullTime) + t.startTick = (startTick + ms) % MSECS_PER_DAY; +#endif + return t; +} + +/*! + Returns the number of milliseconds from this time to \a t. + If \a t is earlier than this time, the number of milliseconds returned + is negative. + + Because QTime measures time within a day and there are 86400 + seconds in a day, the result is always between -86400000 and + 86400000 ms. + + \sa secsTo(), addMSecs() +*/ + +int QTime::msecsTo(const QTime &t) const +{ +#if defined(Q_OS_WINCE) + // GetLocalTime() for Windows CE has no milliseconds resolution + if (t.startTick > NullTime && startTick > NullTime) + return t.startTick - startTick; + else +#endif + return t.ds() - ds(); +} + + +/*! + \fn bool QTime::operator==(const QTime &t) const + + Returns true if this time is equal to \a t; otherwise returns false. +*/ + +/*! + \fn bool QTime::operator!=(const QTime &t) const + + Returns true if this time is different from \a t; otherwise returns false. +*/ + +/*! + \fn bool QTime::operator<(const QTime &t) const + + Returns true if this time is earlier than \a t; otherwise returns false. +*/ + +/*! + \fn bool QTime::operator<=(const QTime &t) const + + Returns true if this time is earlier than or equal to \a t; + otherwise returns false. +*/ + +/*! + \fn bool QTime::operator>(const QTime &t) const + + Returns true if this time is later than \a t; otherwise returns false. +*/ + +/*! + \fn bool QTime::operator>=(const QTime &t) const + + Returns true if this time is later than or equal to \a t; + otherwise returns false. +*/ + +/*! + \overload + + Returns the current time as reported by the system clock. + + Note that the accuracy depends on the accuracy of the underlying + operating system; not all systems provide 1-millisecond accuracy. +*/ + +QTime QTime::currentTime() +{ + QTime ct; + +#if defined(Q_OS_WIN) + SYSTEMTIME st; + memset(&st, 0, sizeof(SYSTEMTIME)); + GetLocalTime(&st); + ct.mds = MSECS_PER_HOUR * st.wHour + MSECS_PER_MIN * st.wMinute + 1000 * st.wSecond + + st.wMilliseconds; +#if defined(Q_OS_WINCE) + ct.startTick = GetTickCount() % MSECS_PER_DAY; +#endif +#elif defined(Q_OS_UNIX) + // posix compliant system + struct timeval tv; + gettimeofday(&tv, 0); + time_t ltime = tv.tv_sec; + tm *t = 0; + +#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) + // use the reentrant version of localtime() where available + tzset(); + tm res; + t = localtime_r(<ime, &res); +#else + t = localtime(<ime); +#endif + + ct.mds = MSECS_PER_HOUR * t->tm_hour + MSECS_PER_MIN * t->tm_min + 1000 * t->tm_sec + + tv.tv_usec / 1000; +#else + time_t ltime; // no millisecond resolution + ::time(<ime); + tm *t = 0; + localtime(<ime); + ct.mds = MSECS_PER_HOUR * t->tm_hour + MSECS_PER_MIN * t->tm_min + 1000 * t->tm_sec; +#endif + return ct; +} + +#ifndef QT_NO_DATESTRING +/*! + \fn QTime QTime::fromString(const QString &string, Qt::DateFormat format) + + Returns the time represented in the \a string as a QTime using the + \a format given, or an invalid time if this is not possible. + + Note that fromString() uses a "C" locale encoded string to convert + milliseconds to a float value. If the default locale is not "C", + this may result in two conversion attempts (if the conversion + fails for the default locale). This should be considered an + implementation detail. +*/ +QTime QTime::fromString(const QString& s, Qt::DateFormat f) +{ + if (s.isEmpty()) { + QTime t; + t.mds = NullTime; + return t; + } + + switch (f) { + case Qt::SystemLocaleDate: + case Qt::SystemLocaleShortDate: + case Qt::SystemLocaleLongDate: + return fromString(s, QLocale::system().timeFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat + : QLocale::ShortFormat)); + case Qt::LocaleDate: + case Qt::DefaultLocaleShortDate: + case Qt::DefaultLocaleLongDate: + return fromString(s, QLocale().timeFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat + : QLocale::ShortFormat)); + default: + { + bool ok = true; + const int hour(s.mid(0, 2).toInt(&ok)); + if (!ok) + return QTime(); + const int minute(s.mid(3, 2).toInt(&ok)); + if (!ok) + return QTime(); + const int second(s.mid(6, 2).toInt(&ok)); + if (!ok) + return QTime(); + const QString msec_s(QLatin1String("0.") + s.mid(9, 4)); + const float msec(msec_s.toFloat(&ok)); + if (!ok) + return QTime(); + return QTime(hour, minute, second, qMin(qRound(msec * 1000.0), 999)); + } + } +} + +/*! + \fn QTime::fromString(const QString &string, const QString &format) + + Returns the QTime represented by the \a string, using the \a + format given, or an invalid time if the string cannot be parsed. + + These expressions may be used for the format: + + \table + \header \i Expression \i Output + \row \i h + \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) + \row \i hh + \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) + \row \i m \i the minute without a leading zero (0 to 59) + \row \i mm \i the minute with a leading zero (00 to 59) + \row \i s \i the second without a leading zero (0 to 59) + \row \i ss \i the second with a leading zero (00 to 59) + \row \i z \i the milliseconds without leading zeroes (0 to 999) + \row \i zzz \i the milliseconds with leading zeroes (000 to 999) + \row \i AP + \i interpret as an AM/PM time. \e AP must be either "AM" or "PM". + \row \i ap + \i Interpret as an AM/PM time. \e ap must be either "am" or "pm". + \endtable + + All other input characters will be treated as text. Any sequence + of characters that are enclosed in single quotes will also be + treated as text and not be used as an expression. + + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 6 + + If the format is not satisfied an invalid QTime is returned. + Expressions that do not expect leading zeroes to be given (h, m, s + and z) are greedy. This means that they will use two digits even if + this puts them outside the range of accepted values and leaves too + few digits for other sections. For example, the following string + could have meant 00:07:10, but the m will grab two digits, resulting + in an invalid time: + + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 7 + + Any field that is not represented in the format will be set to zero. + For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 8 + + \sa QDateTime::fromString() QDate::fromString() QDate::toString() + QDateTime::toString() QTime::toString() +*/ + +QTime QTime::fromString(const QString &string, const QString &format) +{ + QTime time; +#ifndef QT_BOOTSTRAPPED + QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString); + if (dt.parseFormat(format)) + dt.fromString(string, 0, &time); +#else + Q_UNUSED(string); + Q_UNUSED(format); +#endif + return time; +} + +#endif // QT_NO_DATESTRING + + +/*! + \overload + + Returns true if the specified time is valid; otherwise returns + false. + + The time is valid if \a h is in the range 0 to 23, \a m and + \a s are in the range 0 to 59, and \a ms is in the range 0 to 999. + + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 9 +*/ + +bool QTime::isValid(int h, int m, int s, int ms) +{ + return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000; +} + + +/*! + Sets this time to the current time. This is practical for timing: + + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 10 + + \sa restart(), elapsed(), currentTime() +*/ + +void QTime::start() +{ + *this = currentTime(); +} + +/*! + Sets this time to the current time and returns the number of + milliseconds that have elapsed since the last time start() or + restart() was called. + + This function is guaranteed to be atomic and is thus very handy + for repeated measurements. Call start() to start the first + measurement, and restart() for each later measurement. + + Note that the counter wraps to zero 24 hours after the last call + to start() or restart(). + + \warning If the system's clock setting has been changed since the + last time start() or restart() was called, the result is + undefined. This can happen when daylight savings time is turned on + or off. + + \sa start(), elapsed(), currentTime() +*/ + +int QTime::restart() +{ + QTime t = currentTime(); + int n = msecsTo(t); + if (n < 0) // passed midnight + n += 86400*1000; + *this = t; + return n; +} + +/*! + Returns the number of milliseconds that have elapsed since the + last time start() or restart() was called. + + Note that the counter wraps to zero 24 hours after the last call + to start() or restart. + + Note that the accuracy depends on the accuracy of the underlying + operating system; not all systems provide 1-millisecond accuracy. + + \warning If the system's clock setting has been changed since the + last time start() or restart() was called, the result is + undefined. This can happen when daylight savings time is turned on + or off. + + \sa start(), restart() +*/ + +int QTime::elapsed() const +{ + int n = msecsTo(currentTime()); + if (n < 0) // passed midnight + n += 86400 * 1000; + return n; +} + + +/***************************************************************************** + QDateTime member functions + *****************************************************************************/ + +/*! + \class QDateTime + \reentrant + \brief The QDateTime class provides date and time functions. + + \ingroup time + \mainclass + + A QDateTime object contains a calendar date and a clock time (a + "datetime"). It is a combination of the QDate and QTime classes. + It can read the current datetime from the system clock. It + provides functions for comparing datetimes and for manipulating a + datetime by adding a number of seconds, days, months, or years. + + A QDateTime object is typically created either by giving a date + and time explicitly in the constructor, or by using the static + function currentDateTime() that returns a QDateTime object set + to the system clock's time. The date and time can be changed with + setDate() and setTime(). A datetime can also be set using the + setTime_t() function that takes a POSIX-standard "number of + seconds since 00:00:00 on January 1, 1970" value. The fromString() + function returns a QDateTime, given a string and a date format + used to interpret the date within the string. + + The date() and time() functions provide access to the date and + time parts of the datetime. The same information is provided in + textual format by the toString() function. + + QDateTime provides a full set of operators to compare two + QDateTime objects where smaller means earlier and larger means + later. + + You can increment (or decrement) a datetime by a given number of + seconds using addSecs(), or days using addDays(). Similarly you can + use addMonths() and addYears(). The daysTo() function returns the + number of days between two datetimes, and secsTo() returns the + number of seconds between two datetimes. + + QDateTime can store datetimes as \l{Qt::LocalTime}{local time} or + as \l{Qt::UTC}{UTC}. QDateTime::currentDateTime() returns a + QDateTime expressed as local time; use toUTC() to convert it to + UTC. You can also use timeSpec() to find out if a QDateTime + object stores a UTC time or a local time. Operations such as + addSecs() and secsTo() are aware of daylight saving time (DST). + + \note QDateTime does not account for leap seconds. + + \section1 + + \target QDateTime G and J + \section2 Use of Gregorian and Julian Calendars + + QDate uses the Gregorian calendar in all locales, beginning + on the date 15 October 1582. For dates up to and including 4 + October 1582, the Julian calendar is used. This means there is a + 10-day gap in the internal calendar between the 4th and the 15th + of October 1582. When you use QDateTime for dates in that epoch, + the day after 4 October 1582 is 15 October 1582, and the dates in + the gap are invalid. + + The Julian to Gregorian changeover date used here is the date when + the Gregorian calendar was first introduced, by Pope Gregory + XIII. That change was not universally accepted and some localities + only executed it at a later date (if at all). QDateTime + doesn't take any of these historical facts into account. If an + application must support a locale-specific dating system, it must + do so on its own, remembering to convert the dates using the + Julian day. + + \section2 No Year 0 + + There is no year 0. Dates in that year are considered invalid. The + year -1 is the year "1 before Christ" or "1 before current era." + The day before 0001-01-01 is December 31st, 1 BCE. + + \section2 Range of Valid Dates + + The range of valid dates is from January 2nd, 4713 BCE, to + sometime in the year 11 million CE. The Julian Day returned by + QDate::toJulianDay() is a number in the contiguous range from 1 to + \e{overflow}, even across QDateTime's "date holes". It is suitable + for use in applications that must convert a QDateTime to a date in + another calendar system, e.g., Hebrew, Islamic or Chinese. + + The Gregorian calendar was introduced in different places around + the world on different dates. QDateTime uses QDate to store the + date, so it uses the Gregorian calendar for all locales, beginning + on the date 15 October 1582. For dates up to and including 4 + October 1582, QDateTime uses the Julian calendar. This means + there is a 10-day gap in the QDateTime calendar between the 4th + and the 15th of October 1582. When you use QDateTime for dates in + that epoch, the day after 4 October 1582 is 15 October 1582, and + the dates in the gap are invalid. + + \section2 + Use of System Timezone + + QDateTime uses the system's time zone information to determine the + offset of local time from UTC. If the system is not configured + correctly or not up-to-date, QDateTime will give wrong results as + well. + + \section2 Daylight Savings Time (DST) + + QDateTime takes into account the system's time zone information + when dealing with DST. On modern Unix systems, this means it + applies the correct historical DST data whenever possible. On + Windows and Windows CE, where the system doesn't support + historical DST data, historical accuracy is not maintained with + respect to DST. + + The range of valid dates taking DST into account is 1970-01-01 to + the present, and rules are in place for handling DST correctly + until 2037-12-31, but these could change. For dates falling + outside that range, QDateTime makes a \e{best guess} using the + rules for year 1970 or 2037, but we can't guarantee accuracy. This + means QDateTime doesn't take into account changes in a locale's + time zone before 1970, even if the system's time zone database + supports that information. + + \sa QDate QTime QDateTimeEdit +*/ + +/*! + Constructs a null datetime (i.e. null date and null time). A null + datetime is invalid, since the date is invalid. + + \sa isValid() +*/ +QDateTime::QDateTime() +{ + d = new QDateTimePrivate; +} + + +/*! + Constructs a datetime with the given \a date, a valid + time(00:00:00.000), and sets the timeSpec() to Qt::LocalTime. +*/ + +QDateTime::QDateTime(const QDate &date) +{ + d = new QDateTimePrivate; + d->date = date; + d->time = QTime(0, 0, 0); +} + +/*! + Constructs a datetime with the given \a date and \a time, using + the time specification defined by \a spec. + + If \a date is valid and \a time is not, the time will be set to midnight. +*/ + +QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec) +{ + d = new QDateTimePrivate; + d->date = date; + d->time = date.isValid() && !time.isValid() ? QTime(0, 0, 0) : time; + d->spec = (spec == Qt::UTC) ? QDateTimePrivate::UTC : QDateTimePrivate::LocalUnknown; +} + +/*! + Constructs a copy of the \a other datetime. +*/ + +QDateTime::QDateTime(const QDateTime &other) +{ + d = other.d; + d->ref.ref(); +} + +/*! + Destroys the datetime. +*/ +QDateTime::~QDateTime() +{ + if (!d->ref.deref()) + delete d; +} + +/*! + Makes a copy of the \a other datetime and returns a reference to the + copy. +*/ + +QDateTime &QDateTime::operator=(const QDateTime &other) +{ + qAtomicAssign(d, other.d); + return *this; +} + +/*! + Returns true if both the date and the time are null; otherwise + returns false. A null datetime is invalid. + + \sa QDate::isNull(), QTime::isNull(), isValid() +*/ + +bool QDateTime::isNull() const +{ + return d->date.isNull() && d->time.isNull(); +} + +/*! + Returns true if both the date and the time are valid; otherwise + returns false. + + \sa QDate::isValid(), QTime::isValid() +*/ + +bool QDateTime::isValid() const +{ + return d->date.isValid() && d->time.isValid(); +} + +/*! + Returns the date part of the datetime. + + \sa setDate(), time(), timeSpec() +*/ + +QDate QDateTime::date() const +{ + return d->date; +} + +/*! + Returns the time part of the datetime. + + \sa setTime(), date(), timeSpec() +*/ + +QTime QDateTime::time() const +{ + return d->time; +} + +/*! + Returns the time specification of the datetime. + + \sa setTimeSpec(), date(), time(), Qt::TimeSpec +*/ + +Qt::TimeSpec QDateTime::timeSpec() const +{ + switch(d->spec) + { + case QDateTimePrivate::UTC: + return Qt::UTC; + case QDateTimePrivate::OffsetFromUTC: + return Qt::OffsetFromUTC; + default: + return Qt::LocalTime; + } +} + +/*! + Sets the date part of this datetime to \a date. + If no time is set, it is set to midnight. + + \sa date(), setTime(), setTimeSpec() +*/ + +void QDateTime::setDate(const QDate &date) +{ + detach(); + d->date = date; + if (d->spec == QDateTimePrivate::LocalStandard + || d->spec == QDateTimePrivate::LocalDST) + d->spec = QDateTimePrivate::LocalUnknown; + if (date.isValid() && !d->time.isValid()) + d->time = QTime(0, 0, 0); +} + +/*! + Sets the time part of this datetime to \a time. + + \sa time(), setDate(), setTimeSpec() +*/ + +void QDateTime::setTime(const QTime &time) +{ + detach(); + if (d->spec == QDateTimePrivate::LocalStandard + || d->spec == QDateTimePrivate::LocalDST) + d->spec = QDateTimePrivate::LocalUnknown; + d->time = time; +} + +/*! + Sets the time specification used in this datetime to \a spec. + + \sa timeSpec(), setDate(), setTime(), Qt::TimeSpec +*/ + +void QDateTime::setTimeSpec(Qt::TimeSpec spec) +{ + detach(); + + switch(spec) + { + case Qt::UTC: + d->spec = QDateTimePrivate::UTC; + break; + case Qt::OffsetFromUTC: + d->spec = QDateTimePrivate::OffsetFromUTC; + break; + default: + d->spec = QDateTimePrivate::LocalUnknown; + break; + } +} + +static uint toTime_tHelper(const QDate &utcDate, const QTime &utcTime) +{ + int days = QDate(1970, 1, 1).daysTo(utcDate); + int secs = QTime().secsTo(utcTime); + if (days < 0 || (days == 0 && secs < 0)) + return uint(-1); + + qlonglong retval = (qlonglong(days) * SECS_PER_DAY) + secs; + if (retval >= Q_INT64_C(0xFFFFFFFF)) + return uint(-1); + return uint(retval); +} + +/*! + Returns the datetime as the number of seconds that have passed + since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC). + + On systems that do not support time zones, this function will + behave as if local time were Qt::UTC. + + \sa setTime_t() +*/ + +uint QDateTime::toTime_t() const +{ + QDate utcDate; + QTime utcTime; + d->getUTC(utcDate, utcTime); + + return toTime_tHelper(utcDate, utcTime); +} + +/*! + \fn void QDateTime::setTime_t(uint seconds) + + Sets the date and time given the number of \a seconds that have + passed since 1970-01-01T00:00:00, Coordinated Universal Time + (Qt::UTC). On systems that do not support time zones this function + will behave as if local time were Qt::UTC. + + \sa toTime_t() +*/ + +void QDateTime::setTime_t(uint secsSince1Jan1970UTC) +{ + detach(); + + QDateTimePrivate::Spec oldSpec = d->spec; + + d->date = QDate(1970, 1, 1).addDays(secsSince1Jan1970UTC / SECS_PER_DAY); + d->time = QTime().addSecs(secsSince1Jan1970UTC % SECS_PER_DAY); + d->spec = QDateTimePrivate::UTC; + + if (oldSpec != QDateTimePrivate::UTC) + d->spec = d->getLocal(d->date, d->time); +} + +#ifndef QT_NO_DATESTRING +/*! + \fn QString QDateTime::toString(Qt::DateFormat format) const + + \overload + + Returns the datetime as a string in the \a format given. + + If the \a format is Qt::TextDate, the string is formatted in + the default way. QDate::shortDayName(), QDate::shortMonthName(), + and QTime::toString() are used to generate the string, so the + day and month names will be localized names. An example of this + formatting is "Wed May 20 03:40:13 1998". + + If the \a format is Qt::ISODate, the string format corresponds + to the ISO 8601 extended specification for representations of + dates and times, taking the form YYYY-MM-DDTHH:MM:SS. + + If the \a format is Qt::SystemLocaleShortDate or + Qt::SystemLocaleLongDate, the string format depends on the locale + settings of the system. Identical to calling + QLocale::system().toString(datetime, QLocale::ShortFormat) or + QLocale::system().toString(datetime, QLocale::LongFormat). + + If the \a format is Qt::DefaultLocaleShortDate or + Qt::DefaultLocaleLongDate, the string format depends on the + default application locale. This is the locale set with + QLocale::setDefault(), or the system locale if no default locale + has been set. Identical to calling QLocale().toString(datetime, + QLocale::ShortFormat) or QLocale().toString(datetime, + QLocale::LongFormat). + + If the datetime is invalid, an empty string will be returned. + + \warning The Qt::ISODate format is only valid for years in the + range 0 to 9999. This restriction may apply to locale-aware + formats as well, depending on the locale settings. + + \sa QDate::toString() QTime::toString() Qt::DateFormat +*/ + +QString QDateTime::toString(Qt::DateFormat f) const +{ + QString buf; + if (!isValid()) + return buf; + + if (f == Qt::ISODate) { + buf = d->date.toString(Qt::ISODate); + if (buf.isEmpty()) + return QString(); // failed to convert + buf += QLatin1Char('T'); + buf += d->time.toString(Qt::ISODate); + } +#ifndef QT_NO_TEXTDATE + else if (f == Qt::TextDate) { +#ifndef Q_WS_WIN + buf = d->date.shortDayName(d->date.dayOfWeek()); + buf += QLatin1Char(' '); + buf += d->date.shortMonthName(d->date.month()); + buf += QLatin1Char(' '); + buf += QString::number(d->date.day()); +#else + QString winstr; + QT_WA({ + TCHAR out[255]; + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255); + winstr = QString::fromUtf16((ushort*)out); + } , { + char out[255]; + GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ILDATE, (char*)&out, 255); + winstr = QString::fromLocal8Bit(out); + }); + switch (winstr.toInt()) { + case 1: + buf = d->date.shortDayName(d->date.dayOfWeek()); + buf += QLatin1Char(' '); + buf += QString::number(d->date.day()); + buf += QLatin1String(". "); + buf += d->date.shortMonthName(d->date.month()); + break; + default: + buf = d->date.shortDayName(d->date.dayOfWeek()); + buf += QLatin1Char(' '); + buf += d->date.shortMonthName(d->date.month()); + buf += QLatin1Char(' '); + buf += QString::number(d->date.day()); + } +#endif + buf += QLatin1Char(' '); + buf += d->time.toString(); + buf += QLatin1Char(' '); + buf += QString::number(d->date.year()); + } +#endif + else { + buf = d->date.toString(f); + if (buf.isEmpty()) + return QString(); // failed to convert + buf += QLatin1Char(' '); + buf += d->time.toString(f); + } + + return buf; +} + +/*! + Returns the datetime as a string. The \a format parameter + determines the format of the result string. + + These expressions may be used for the date: + + \table + \header \i Expression \i Output + \row \i d \i the day as number without a leading zero (1 to 31) + \row \i dd \i the day as number with a leading zero (01 to 31) + \row \i ddd + \i the abbreviated localized day name (e.g. 'Mon' to 'Sun'). + Uses QDate::shortDayName(). + \row \i dddd + \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday'). + Uses QDate::longDayName(). + \row \i M \i the month as number without a leading zero (1-12) + \row \i MM \i the month as number with a leading zero (01-12) + \row \i MMM + \i the abbreviated localized month name (e.g. 'Jan' to 'Dec'). + Uses QDate::shortMonthName(). + \row \i MMMM + \i the long localized month name (e.g. 'January' to 'December'). + Uses QDate::longMonthName(). + \row \i yy \i the year as two digit number (00-99) + \row \i yyyy \i the year as four digit number + \endtable + + These expressions may be used for the time: + + \table + \header \i Expression \i Output + \row \i h + \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) + \row \i hh + \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) + \row \i m \i the minute without a leading zero (0 to 59) + \row \i mm \i the minute with a leading zero (00 to 59) + \row \i s \i the second without a leading zero (0 to 59) + \row \i ss \i the second with a leading zero (00 to 59) + \row \i z \i the milliseconds without leading zeroes (0 to 999) + \row \i zzz \i the milliseconds with leading zeroes (000 to 999) + \row \i AP + \i use AM/PM display. \e AP will be replaced by either "AM" or "PM". + \row \i ap + \i use am/pm display. \e ap will be replaced by either "am" or "pm". + \endtable + + All other input characters will be ignored. Any sequence of characters that + are enclosed in singlequotes will be treated as text and not be used as an + expression. Two consecutive singlequotes ("''") are replaced by a singlequote + in the output. + + Example format strings (assumed that the QDateTime is 21 May 2001 + 14:13:09): + + \table + \header \i Format \i Result + \row \i dd.MM.yyyy \i 21.05.2001 + \row \i ddd MMMM d yy \i Tue May 21 01 + \row \i hh:mm:ss.zzz \i 14:13:09.042 + \row \i h:m:s ap \i 2:13:9 pm + \endtable + + If the datetime is invalid, an empty string will be returned. + + \sa QDate::toString() QTime::toString() +*/ +QString QDateTime::toString(const QString& format) const +{ + return fmtDateTime(format, &d->time, &d->date); +} +#endif //QT_NO_DATESTRING + +/*! + Returns a QDateTime object containing a datetime \a ndays days + later than the datetime of this object (or earlier if \a ndays is + negative). + + \sa daysTo(), addMonths(), addYears(), addSecs() +*/ + +QDateTime QDateTime::addDays(int ndays) const +{ + return QDateTime(d->date.addDays(ndays), d->time, timeSpec()); +} + +/*! + Returns a QDateTime object containing a datetime \a nmonths months + later than the datetime of this object (or earlier if \a nmonths + is negative). + + \sa daysTo(), addDays(), addYears(), addSecs() +*/ + +QDateTime QDateTime::addMonths(int nmonths) const +{ + return QDateTime(d->date.addMonths(nmonths), d->time, timeSpec()); +} + +/*! + Returns a QDateTime object containing a datetime \a nyears years + later than the datetime of this object (or earlier if \a nyears is + negative). + + \sa daysTo(), addDays(), addMonths(), addSecs() +*/ + +QDateTime QDateTime::addYears(int nyears) const +{ + return QDateTime(d->date.addYears(nyears), d->time, timeSpec()); +} + +QDateTime QDateTimePrivate::addMSecs(const QDateTime &dt, qint64 msecs) +{ + QDate utcDate; + QTime utcTime; + dt.d->getUTC(utcDate, utcTime); + + addMSecs(utcDate, utcTime, msecs); + + return QDateTime(utcDate, utcTime, Qt::UTC).toTimeSpec(dt.timeSpec()); +} + +/*! + Adds \a msecs to utcDate and \a utcTime as appropriate. It is assumed that + utcDate and utcTime are adjusted to UTC. + + \since 4.5 + \internal + */ +void QDateTimePrivate::addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs) +{ + uint dd = utcDate.jd; + int tt = utcTime.ds(); + int sign = 1; + if (msecs < 0) { + msecs = -msecs; + sign = -1; + } + if (msecs >= int(MSECS_PER_DAY)) { + dd += sign * (msecs / MSECS_PER_DAY); + msecs %= MSECS_PER_DAY; + } + + tt += sign * msecs; + if (tt < 0) { + tt = MSECS_PER_DAY - tt - 1; + dd -= tt / MSECS_PER_DAY; + tt = tt % MSECS_PER_DAY; + tt = MSECS_PER_DAY - tt - 1; + } else if (tt >= int(MSECS_PER_DAY)) { + dd += tt / MSECS_PER_DAY; + tt = tt % MSECS_PER_DAY; + } + + utcDate.jd = dd; + utcTime.mds = tt; +} + +/*! + Returns a QDateTime object containing a datetime \a s seconds + later than the datetime of this object (or earlier if \a s is + negative). + + \sa addMSecs(), secsTo(), addDays(), addMonths(), addYears() +*/ + +QDateTime QDateTime::addSecs(int s) const +{ + return d->addMSecs(*this, qint64(s) * 1000); +} + +/*! + Returns a QDateTime object containing a datetime \a msecs miliseconds + later than the datetime of this object (or earlier if \a msecs is + negative). + + \sa addSecs(), secsTo(), addDays(), addMonths(), addYears() +*/ +QDateTime QDateTime::addMSecs(qint64 msecs) const +{ + return d->addMSecs(*this, msecs); +} + +/*! + Returns the number of days from this datetime to the \a other + datetime. If the \a other datetime is earlier than this datetime, + the value returned is negative. + + \sa addDays(), secsTo() +*/ + +int QDateTime::daysTo(const QDateTime &other) const +{ + return d->date.daysTo(other.d->date); +} + +/*! + Returns the number of seconds from this datetime to the \a other + datetime. If the \a other datetime is earlier than this datetime, + the value returned is negative. + + Before performing the comparison, the two datetimes are converted + to Qt::UTC to ensure that the result is correct if one of the two + datetimes has daylight saving time (DST) and the other doesn't. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 11 + + \sa addSecs(), daysTo(), QTime::secsTo() +*/ + +int QDateTime::secsTo(const QDateTime &other) const +{ + QDate date1, date2; + QTime time1, time2; + + d->getUTC(date1, time1); + other.d->getUTC(date2, time2); + + return (date1.daysTo(date2) * SECS_PER_DAY) + time1.secsTo(time2); +} + +/*! + \fn QDateTime QDateTime::toTimeSpec(Qt::TimeSpec specification) const + + Returns a copy of this datetime configured to use the given time + \a specification. + + \sa timeSpec(), toUTC(), toLocalTime() +*/ + +QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const +{ + if ((d->spec == QDateTimePrivate::UTC) == (spec == Qt::UTC)) + return *this; + + QDateTime ret; + if (spec == Qt::UTC) { + d->getUTC(ret.d->date, ret.d->time); + ret.d->spec = QDateTimePrivate::UTC; + } else { + ret.d->spec = d->getLocal(ret.d->date, ret.d->time); + } + return ret; +} + +/*! + Returns true if this datetime is equal to the \a other datetime; + otherwise returns false. + + \sa operator!=() +*/ + +bool QDateTime::operator==(const QDateTime &other) const +{ + if (d->spec == other.d->spec && d->utcOffset == other.d->utcOffset) + return d->time == other.d->time && d->date == other.d->date; + else { + QDate date1, date2; + QTime time1, time2; + + d->getUTC(date1, time1); + other.d->getUTC(date2, time2); + return time1 == time2 && date1 == date2; + } +} + +/*! + \fn bool QDateTime::operator!=(const QDateTime &other) const + + Returns true if this datetime is different from the \a other + datetime; otherwise returns false. + + Two datetimes are different if either the date, the time, or the + time zone components are different. + + \sa operator==() +*/ + +/*! + Returns true if this datetime is earlier than the \a other + datetime; otherwise returns false. +*/ + +bool QDateTime::operator<(const QDateTime &other) const +{ + if (d->spec == other.d->spec && d->spec != QDateTimePrivate::OffsetFromUTC) { + if (d->date != other.d->date) + return d->date < other.d->date; + return d->time < other.d->time; + } else { + QDate date1, date2; + QTime time1, time2; + d->getUTC(date1, time1); + other.d->getUTC(date2, time2); + if (date1 != date2) + return date1 < date2; + return time1 < time2; + } +} + +/*! + \fn bool QDateTime::operator<=(const QDateTime &other) const + + Returns true if this datetime is earlier than or equal to the + \a other datetime; otherwise returns false. +*/ + +/*! + \fn bool QDateTime::operator>(const QDateTime &other) const + + Returns true if this datetime is later than the \a other datetime; + otherwise returns false. +*/ + +/*! + \fn bool QDateTime::operator>=(const QDateTime &other) const + + Returns true if this datetime is later than or equal to the + \a other datetime; otherwise returns false. +*/ + +/*! + Returns the current datetime, as reported by the system clock, in + the local time zone. + + \sa QDate::currentDate(), QTime::currentTime(), toTimeSpec() +*/ + +QDateTime QDateTime::currentDateTime() +{ +#if defined(Q_OS_WIN) + QDate d; + QTime t; + SYSTEMTIME st; + memset(&st, 0, sizeof(SYSTEMTIME)); + GetLocalTime(&st); + d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay); + t.mds = MSECS_PER_HOUR * st.wHour + MSECS_PER_MIN * st.wMinute + 1000 * st.wSecond + + st.wMilliseconds; + return QDateTime(d, t); +#else +#if defined(Q_OS_UNIX) + // posix compliant system + // we have milliseconds + struct timeval tv; + gettimeofday(&tv, 0); + time_t ltime = tv.tv_sec; + tm *t = 0; + +#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) + // use the reentrant version of localtime() where available + tzset(); + tm res; + t = localtime_r(<ime, &res); +#else + t = localtime(<ime); +#endif + + QDateTime dt; + dt.d->time.mds = MSECS_PER_HOUR * t->tm_hour + MSECS_PER_MIN * t->tm_min + 1000 * t->tm_sec + + tv.tv_usec / 1000; +#else + time_t ltime; // no millisecond resolution + ::time(<ime); + tm *t = 0; + localtime(<ime); + dt.d->time.mds = MSECS_PER_HOUR * t->tm_hour + MSECS_PER_MIN * t->tm_min + 1000 * t->tm_sec; +#endif // Q_OS_UNIX + + dt.d->date.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday); + dt.d->spec = t->tm_isdst > 0 ? QDateTimePrivate::LocalDST : + t->tm_isdst == 0 ? QDateTimePrivate::LocalStandard : + QDateTimePrivate::LocalUnknown; + return dt; +#endif +} + +/*! + \since 4.2 + + Returns a datetime whose date and time are the number of \a seconds + that have passed since 1970-01-01T00:00:00, Coordinated Universal + Time (Qt::UTC). On systems that do not support time zones, the time + will be set as if local time were Qt::UTC. + + \sa toTime_t(), setTime_t() +*/ +QDateTime QDateTime::fromTime_t(uint seconds) +{ + QDateTime d; + d.setTime_t(seconds); + return d; +} + +/*! + \since 4.4 + \internal + + Sets the offset from UTC to \a seconds, and also sets timeSpec() to + Qt::OffsetFromUTC. + + The maximum and minimum offset is 14 positive or negative hours. If + \a seconds is larger or smaller than that, the result is undefined. + + 0 as offset is identical to UTC. Therefore, if \a seconds is 0, the + timeSpec() will be set to Qt::UTC. Hence the UTC offset always + relates to UTC, and can never relate to local time. + + \sa isValid(), utcOffset() + */ +void QDateTime::setUtcOffset(int seconds) +{ + detach(); + + /* The motivation to also setting d->spec is to ensure that the QDateTime + * instance stay in well-defined states all the time, instead of that + * we instruct the user to ensure it. */ + if(seconds == 0) + d->spec = QDateTimePrivate::UTC; + else + d->spec = QDateTimePrivate::OffsetFromUTC; + + /* Even if seconds is 0 we assign it to utcOffset. */ + d->utcOffset = seconds; +} + +/*! + \since 4.4 + \internal + + Returns the UTC offset in seconds. If the timeSpec() isn't + Qt::OffsetFromUTC, 0 is returned. However, since 0 is a valid UTC + offset the return value of this function cannot be used to determine + whether a utcOffset() is used or is valid, timeSpec() must be + checked. + + Likewise, if this QDateTime() is invalid or if timeSpec() isn't + Qt::OffsetFromUTC, 0 is returned. + + The UTC offset only applies if the timeSpec() is Qt::OffsetFromUTC. + + \sa isValid(), setUtcOffset() + */ +int QDateTime::utcOffset() const +{ + if(isValid() && d->spec == QDateTimePrivate::OffsetFromUTC) + return d->utcOffset; + else + return 0; +} + +#ifndef QT_NO_DATESTRING + +static int fromShortMonthName(const QString &monthName) +{ + // Assume that English monthnames are the default + for (int i = 0; i < 12; ++i) { + if (monthName == QLatin1String(qt_shortMonthNames[i])) + return i + 1; + } + // If English names can't be found, search the localized ones + for (int i = 1; i <= 12; ++i) { + if (monthName == QDate::shortMonthName(i)) + return i; + } + return -1; +} + +/*! + \fn QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format) + + Returns the QDateTime represented by the \a string, using the + \a format given, or an invalid datetime if this is not possible. + + Note for Qt::TextDate: It is recommended that you use the + English short month names (e.g. "Jan"). Although localized month + names can also be used, they depend on the user's locale settings. +*/ +QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f) +{ + if (s.isEmpty()) { + return QDateTime(); + } + + switch (f) { + case Qt::ISODate: { + QString tmp = s; + Qt::TimeSpec ts = Qt::LocalTime; + const QDate date = QDate::fromString(tmp.left(10), Qt::ISODate); + if (tmp.size() == 10) + return QDateTime(date); + + // Recognize UTC specifications + if (tmp.endsWith(QLatin1Char('Z'))) { + ts = Qt::UTC; + tmp.chop(1); + } + return QDateTime(date, QTime::fromString(tmp.mid(11), Qt::ISODate), ts); + } + case Qt::SystemLocaleDate: + case Qt::SystemLocaleShortDate: + case Qt::SystemLocaleLongDate: + return fromString(s, QLocale::system().dateTimeFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat + : QLocale::ShortFormat)); + case Qt::LocaleDate: + case Qt::DefaultLocaleShortDate: + case Qt::DefaultLocaleLongDate: + return fromString(s, QLocale().dateTimeFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat + : QLocale::ShortFormat)); +#if !defined(QT_NO_TEXTDATE) + case Qt::TextDate: { + QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts); + + if ((parts.count() < 5) || (parts.count() > 6)) { + return QDateTime(); + } + + // Accept "Sun Dec 1 13:02:00 1974" and "Sun 1. Dec 13:02:00 1974" + int month = -1, day = -1; + bool ok; + + month = fromShortMonthName(parts.at(1)); + if (month != -1) { + day = parts.at(2).toInt(&ok); + if (!ok) + day = -1; + } + + if (month == -1 || day == -1) { + // first variant failed, lets try the other + month = fromShortMonthName(parts.at(2)); + if (month != -1) { + QString dayStr = parts.at(1); + if (dayStr.endsWith(QLatin1Char('.'))) { + dayStr.chop(1); + day = dayStr.toInt(&ok); + if (!ok) + day = -1; + } else { + day = -1; + } + } + } + + if (month == -1 || day == -1) { + // both variants failed, give up + return QDateTime(); + } + + int year; + QStringList timeParts = parts.at(3).split(QLatin1Char(':')); + if ((timeParts.count() == 3) || (timeParts.count() == 2)) { + year = parts.at(4).toInt(&ok); + if (!ok) + return QDateTime(); + } else { + timeParts = parts.at(4).split(QLatin1Char(':')); + if ((timeParts.count() != 3) && (timeParts.count() != 2)) + return QDateTime(); + year = parts.at(3).toInt(&ok); + if (!ok) + return QDateTime(); + } + + int hour = timeParts.at(0).toInt(&ok); + if (!ok) { + return QDateTime(); + } + + int minute = timeParts.at(1).toInt(&ok); + if (!ok) { + return QDateTime(); + } + + int second = (timeParts.count() > 2) ? timeParts.at(2).toInt(&ok) : 0; + if (!ok) { + return QDateTime(); + } + + QDate date(year, month, day); + QTime time(hour, minute, second); + + if (parts.count() == 5) + return QDateTime(date, time, Qt::LocalTime); + + QString tz = parts.at(5); + if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive)) + return QDateTime(); + int tzoffset = 0; + if (tz.length() > 3) { + QChar sign = tz.at(3); + if ((sign != QLatin1Char('+')) + && (sign != QLatin1Char('-'))) { + return QDateTime(); + } + int tzhour = tz.mid(4, 2).toInt(&ok); + if (!ok) + return QDateTime(); + int tzminute = tz.mid(6).toInt(&ok); + if (!ok) + return QDateTime(); + tzoffset = (tzhour*60 + tzminute) * 60; + if (sign == QLatin1Char('-')) + tzoffset = -tzoffset; + } + return QDateTime(date, time, Qt::UTC).addSecs(-tzoffset).toLocalTime(); + } +#endif //QT_NO_TEXTDATE + } + + return QDateTime(); +} + +/*! + \fn QDateTime::fromString(const QString &string, const QString &format) + + Returns the QDateTime represented by the \a string, using the \a + format given, or an invalid datetime if the string cannot be parsed. + + These expressions may be used for the date part of the format string: + + \table + \header \i Expression \i Output + \row \i d \i the day as number without a leading zero (1 to 31) + \row \i dd \i the day as number with a leading zero (01 to 31) + \row \i ddd + \i the abbreviated localized day name (e.g. 'Mon' to 'Sun'). + Uses QDate::shortDayName(). + \row \i dddd + \i the long localized day name (e.g. 'Monday' to 'Sunday'). + Uses QDate::longDayName(). + \row \i M \i the month as number without a leading zero (1-12) + \row \i MM \i the month as number with a leading zero (01-12) + \row \i MMM + \i the abbreviated localized month name (e.g. 'Jan' to 'Dec'). + Uses QDate::shortMonthName(). + \row \i MMMM + \i the long localized month name (e.g. 'January' to 'December'). + Uses QDate::longMonthName(). + \row \i yy \i the year as two digit number (00-99) + \row \i yyyy \i the year as four digit number + \endtable + + \note Unlike the other version of this function, day and month names must + be given in the user's local language. It is only possible to use the English + names if the user's language is English. + + These expressions may be used for the time part of the format string: + + \table + \header \i Expression \i Output + \row \i h + \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) + \row \i hh + \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) + \row \i H + \i the hour without a leading zero (0 to 23, even with AM/PM display) + \row \i HH + \i the hour with a leading zero (00 to 23, even with AM/PM display) + \row \i m \i the minute without a leading zero (0 to 59) + \row \i mm \i the minute with a leading zero (00 to 59) + \row \i s \i the second without a leading zero (0 to 59) + \row \i ss \i the second with a leading zero (00 to 59) + \row \i z \i the milliseconds without leading zeroes (0 to 999) + \row \i zzz \i the milliseconds with leading zeroes (000 to 999) + \row \i AP or A + \i interpret as an AM/PM time. \e AP must be either "AM" or "PM". + \row \i ap or a + \i Interpret as an AM/PM time. \e ap must be either "am" or "pm". + \endtable + + All other input characters will be treated as text. Any sequence + of characters that are enclosed in singlequotes will also be + treated as text and not be used as an expression. + + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 12 + + If the format is not satisfied an invalid QDateTime is returned. + The expressions that don't have leading zeroes (d, M, h, m, s, z) will be + greedy. This means that they will use two digits even if this will + put them outside the range and/or leave too few digits for other + sections. + + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 13 + + This could have meant 1 January 00:30.00 but the M will grab + two digits. + + For any field that is not represented in the format the following + defaults are used: + + \table + \header \i Field \i Default value + \row \i Year \i 1900 + \row \i Month \i 1 (January) + \row \i Day \i 1 + \row \i Hour \i 0 + \row \i Minute \i 0 + \row \i Second \i 0 + \endtable + + For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 14 + + \sa QDate::fromString() QTime::fromString() QDate::toString() + QDateTime::toString() QTime::toString() +*/ + +QDateTime QDateTime::fromString(const QString &string, const QString &format) +{ +#ifndef QT_BOOTSTRAPPED + QTime time; + QDate date; + + QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString); + if (dt.parseFormat(format) && dt.fromString(string, &date, &time)) + return QDateTime(date, time); +#else + Q_UNUSED(string); + Q_UNUSED(format); +#endif + return QDateTime(QDate(), QTime(-1, -1, -1)); +} + +#endif // QT_NO_DATESTRING +/*! + \fn QDateTime QDateTime::toLocalTime() const + + Returns a datetime containing the date and time information in + this datetime, but specified using the Qt::LocalTime definition. + + \sa toTimeSpec() +*/ + +/*! + \fn QDateTime QDateTime::toUTC() const + + Returns a datetime containing the date and time information in + this datetime, but specified using the Qt::UTC definition. + + \sa toTimeSpec() +*/ + +/*! \internal + */ +void QDateTime::detach() +{ + qAtomicDetach(d); +} + +/***************************************************************************** + Date/time stream functions + *****************************************************************************/ + +#ifndef QT_NO_DATASTREAM +/*! + \relates QDate + + Writes the \a date to stream \a out. + + \sa {Format of the QDataStream operators} +*/ + +QDataStream &operator<<(QDataStream &out, const QDate &date) +{ + return out << (quint32)(date.jd); +} + +/*! + \relates QDate + + Reads a date from stream \a in into the \a date. + + \sa {Format of the QDataStream operators} +*/ + +QDataStream &operator>>(QDataStream &in, QDate &date) +{ + quint32 jd; + in >> jd; + date.jd = jd; + return in; +} + +/*! + \relates QTime + + Writes \a time to stream \a out. + + \sa {Format of the QDataStream operators} +*/ + +QDataStream &operator<<(QDataStream &out, const QTime &time) +{ + return out << quint32(time.mds); +} + +/*! + \relates QTime + + Reads a time from stream \a in into the given \a time. + + \sa {Format of the QDataStream operators} +*/ + +QDataStream &operator>>(QDataStream &in, QTime &time) +{ + quint32 ds; + in >> ds; + time.mds = int(ds); + return in; +} + +/*! + \relates QDateTime + + Writes \a dateTime to the \a out stream. + + \sa {Format of the QDataStream operators} +*/ +QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime) +{ + out << dateTime.d->date << dateTime.d->time; + if (out.version() >= 7) + out << (qint8)dateTime.d->spec; + return out; +} + +/*! + \relates QDateTime + + Reads a datetime from the stream \a in into \a dateTime. + + \sa {Format of the QDataStream operators} +*/ + +QDataStream &operator>>(QDataStream &in, QDateTime &dateTime) +{ + dateTime.detach(); + + qint8 ts = (qint8)QDateTimePrivate::LocalUnknown; + in >> dateTime.d->date >> dateTime.d->time; + if (in.version() >= 7) + in >> ts; + dateTime.d->spec = (QDateTimePrivate::Spec)ts; + return in; +} +#endif // QT_NO_DATASTREAM + + +/*! + \fn QString QDate::monthName(int month) + + Use shortMonthName() instead. +*/ + +/*! + \fn QString QDate::dayName(int weekday) + + Use shortDayName() instead. +*/ + +/*! + \fn bool QDate::leapYear(int year) + + Use isLeapYear() instead. +*/ + +/*! + \fn QDate QDate::currentDate(Qt::TimeSpec spec) + + If \a spec is Qt::LocalTime, use the currentDate() overload that + takes no parameters instead; otherwise, use + QDateTime::currentDateTime(). + + \oldcode + QDate localDate = QDate::currentDate(Qt::LocalTime); + QDate utcDate = QDate::currentDate(Qt::UTC); + \newcode + QDate localDate = QDate::currentDate(); + QDate utcDate = QDateTime::currentDateTime().toUTC().date(); + \endcode + + \sa QDateTime::toUTC() +*/ + +/*! + \fn QTime QTime::currentTime(Qt::TimeSpec specification) + + Returns the current time for the given \a specification. + + To replace uses of this function where the \a specification is Qt::LocalTime, + use the currentDate() overload that takes no parameters instead; otherwise, + use QDateTime::currentDateTime() and convert the result to a UTC measurement. + + \oldcode + QTime localTime = QTime::currentTime(Qt::LocalTime); + QTime utcTime = QTime::currentTime(Qt::UTC); + \newcode + QTime localTime = QTime::currentTime(); + QTime utcTime = QTimeTime::currentDateTime().toUTC().time(); + \endcode + + \sa QDateTime::toUTC() +*/ + +/*! + \fn void QDateTime::setTime_t(uint secsSince1Jan1970UTC, Qt::TimeSpec spec) + + Use the single-argument overload of setTime_t() instead. +*/ + +/*! + \fn QDateTime QDateTime::currentDateTime(Qt::TimeSpec spec) + + Use the currentDateTime() overload that takes no parameters + instead. +*/ + +// checks if there is an unqoted 'AP' or 'ap' in the string +static bool hasUnquotedAP(const QString &f) +{ + const QLatin1Char quote('\''); + bool inquote = false; + const int max = f.size(); + for (int i=0; i<max; ++i) { + if (f.at(i) == quote) { + inquote = !inquote; + } else if (!inquote && f.at(i).toUpper() == QLatin1Char('A')) { + return true; + } + } + return false; +} + +#ifndef QT_NO_DATESTRING +/***************************************************************************** + Some static function used by QDate, QTime and QDateTime +*****************************************************************************/ + +// Replaces tokens by their value. See QDateTime::toString() for a list of valid tokens +static QString getFmtString(const QString& f, const QTime* dt = 0, const QDate* dd = 0, bool am_pm = false) +{ + if (f.isEmpty()) + return QString(); + + QString buf = f; + int removed = 0; + + if (dt) { + if (f.startsWith(QLatin1String("hh")) || f.startsWith(QLatin1String("HH"))) { + const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm; + if (hour12 && dt->hour() > 12) + buf = QString::number(dt->hour() - 12).rightJustified(2, QLatin1Char('0'), true); + else if (hour12 && dt->hour() == 0) + buf = QLatin1String("12"); + else + buf = QString::number(dt->hour()).rightJustified(2, QLatin1Char('0'), true); + removed = 2; + } else if (f.at(0) == QLatin1Char('h') || f.at(0) == QLatin1Char('H')) { + const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm; + if (hour12 && dt->hour() > 12) + buf = QString::number(dt->hour() - 12); + else if (hour12 && dt->hour() == 0) + buf = QLatin1String("12"); + else + buf = QString::number(dt->hour()); + removed = 1; + } else if (f.startsWith(QLatin1String("mm"))) { + buf = QString::number(dt->minute()).rightJustified(2, QLatin1Char('0'), true); + removed = 2; + } else if (f.at(0) == (QLatin1Char('m'))) { + buf = QString::number(dt->minute()); + removed = 1; + } else if (f.startsWith(QLatin1String("ss"))) { + buf = QString::number(dt->second()).rightJustified(2, QLatin1Char('0'), true); + removed = 2; + } else if (f.at(0) == QLatin1Char('s')) { + buf = QString::number(dt->second()); + } else if (f.startsWith(QLatin1String("zzz"))) { + buf = QString::number(dt->msec()).rightJustified(3, QLatin1Char('0'), true); + removed = 3; + } else if (f.at(0) == QLatin1Char('z')) { + buf = QString::number(dt->msec()); + removed = 1; + } else if (f.at(0).toUpper() == QLatin1Char('A')) { + const bool upper = f.at(0) == QLatin1Char('A'); + buf = dt->hour() < 12 ? QLatin1String("am") : QLatin1String("pm"); + if (upper) + buf = buf.toUpper(); + if (f.size() > 1 && f.at(1).toUpper() == QLatin1Char('P') && + f.at(0).isUpper() == f.at(1).isUpper()) { + removed = 2; + } else { + removed = 1; + } + } + } + + if (dd) { + if (f.startsWith(QLatin1String("dddd"))) { + buf = dd->longDayName(dd->dayOfWeek()); + removed = 4; + } else if (f.startsWith(QLatin1String("ddd"))) { + buf = dd->shortDayName(dd->dayOfWeek()); + removed = 3; + } else if (f.startsWith(QLatin1String("dd"))) { + buf = QString::number(dd->day()).rightJustified(2, QLatin1Char('0'), true); + removed = 2; + } else if (f.at(0) == QLatin1Char('d')) { + buf = QString::number(dd->day()); + removed = 1; + } else if (f.startsWith(QLatin1String("MMMM"))) { + buf = dd->longMonthName(dd->month()); + removed = 4; + } else if (f.startsWith(QLatin1String("MMM"))) { + buf = dd->shortMonthName(dd->month()); + removed = 3; + } else if (f.startsWith(QLatin1String("MM"))) { + buf = QString::number(dd->month()).rightJustified(2, QLatin1Char('0'), true); + removed = 2; + } else if (f.at(0) == QLatin1Char('M')) { + buf = QString::number(dd->month()); + removed = 1; + } else if (f.startsWith(QLatin1String("yyyy"))) { + const int year = dd->year(); + buf = QString::number(qAbs(year)).rightJustified(4, QLatin1Char('0')); + if(year > 0) + removed = 4; + else + { + buf.prepend(QLatin1Char('-')); + removed = 5; + } + + } else if (f.startsWith(QLatin1String("yy"))) { + buf = QString::number(dd->year()).right(2).rightJustified(2, QLatin1Char('0')); + removed = 2; + } + } + if (removed == 0 || removed >= f.size()) { + return buf; + } + + return buf + getFmtString(f.mid(removed), dt, dd, am_pm); +} + +// Parses the format string and uses getFmtString to get the values for the tokens. Ret +static QString fmtDateTime(const QString& f, const QTime* dt, const QDate* dd) +{ + const QLatin1Char quote('\''); + if (f.isEmpty()) + return QString(); + if (dt && !dt->isValid()) + return QString(); + if (dd && !dd->isValid()) + return QString(); + + const bool ap = hasUnquotedAP(f); + + QString buf; + QString frm; + QChar status(QLatin1Char('0')); + + for (int i = 0; i < (int)f.length(); ++i) { + if (f.at(i) == quote) { + if (status == quote) { + if (i > 0 && f.at(i - 1) == quote) + buf += QLatin1Char('\''); + status = QLatin1Char('0'); + } else { + if (!frm.isEmpty()) { + buf += getFmtString(frm, dt, dd, ap); + frm.clear(); + } + status = quote; + } + } else if (status == quote) { + buf += f.at(i); + } else if (f.at(i) == status) { + if ((ap) && ((f.at(i) == QLatin1Char('P')) || (f.at(i) == QLatin1Char('p')))) + status = QLatin1Char('0'); + frm += f.at(i); + } else { + buf += getFmtString(frm, dt, dd, ap); + frm.clear(); + if ((f.at(i) == QLatin1Char('h')) || (f.at(i) == QLatin1Char('m')) + || (f.at(i) == QLatin1Char('H')) + || (f.at(i) == QLatin1Char('s')) || (f.at(i) == QLatin1Char('z'))) { + status = f.at(i); + frm += f.at(i); + } else if ((f.at(i) == QLatin1Char('d')) || (f.at(i) == QLatin1Char('M')) || (f.at(i) == QLatin1Char('y'))) { + status = f.at(i); + frm += f.at(i); + } else if ((ap) && (f.at(i) == QLatin1Char('A'))) { + status = QLatin1Char('P'); + frm += f.at(i); + } else if((ap) && (f.at(i) == QLatin1Char('a'))) { + status = QLatin1Char('p'); + frm += f.at(i); + } else { + buf += f.at(i); + status = QLatin1Char('0'); + } + } + } + + buf += getFmtString(frm, dt, dd, ap); + + return buf; +} +#endif // QT_NO_DATESTRING + +#ifdef Q_OS_WIN +static const int LowerYear = 1980; +#else +static const int LowerYear = 1970; +#endif +static const int UpperYear = 2037; + +static QDate adjustDate(QDate date) +{ + QDate lowerLimit(LowerYear, 1, 2); + QDate upperLimit(UpperYear, 12, 30); + + if (date > lowerLimit && date < upperLimit) + return date; + + int month = date.month(); + int day = date.day(); + + // neither 1970 nor 2037 are leap years, so make sure date isn't Feb 29 + if (month == 2 && day == 29) + --day; + + if (date < lowerLimit) + date.setDate(LowerYear, month, day); + else + date.setDate(UpperYear, month, day); + + return date; +} + +static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time) +{ + QDate fakeDate = adjustDate(date); + + time_t secsSince1Jan1970UTC = toTime_tHelper(fakeDate, time); + tm *brokenDown = 0; + +#if defined(Q_OS_WINCE) + tm res; + FILETIME utcTime = time_tToFt(secsSince1Jan1970UTC); + FILETIME resultTime; + FileTimeToLocalFileTime(&utcTime , &resultTime); + SYSTEMTIME sysTime; + FileTimeToSystemTime(&resultTime , &sysTime); + + res.tm_sec = sysTime.wSecond; + res.tm_min = sysTime.wMinute; + res.tm_hour = sysTime.wHour; + res.tm_mday = sysTime.wDay; + res.tm_mon = sysTime.wMonth - 1; + res.tm_year = sysTime.wYear - 1900; + brokenDown = &res; +#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) + // use the reentrant version of localtime() where available + tzset(); + tm res; + brokenDown = localtime_r(&secsSince1Jan1970UTC, &res); +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + tm res; + if (!_localtime64_s(&res, &secsSince1Jan1970UTC)) + brokenDown = &res; +#else + brokenDown = localtime(&secsSince1Jan1970UTC); +#endif + if (!brokenDown) { + date = QDate(1970, 1, 1); + time = QTime(); + return QDateTimePrivate::LocalUnknown; + } else { + int deltaDays = fakeDate.daysTo(date); + date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday); + time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec()); + date = date.addDays(deltaDays); + if (brokenDown->tm_isdst > 0) + return QDateTimePrivate::LocalDST; + else if (brokenDown->tm_isdst < 0) + return QDateTimePrivate::LocalUnknown; + else + return QDateTimePrivate::LocalStandard; + } +} + +static void localToUtc(QDate &date, QTime &time, int isdst) +{ + if (!date.isValid()) + return; + + QDate fakeDate = adjustDate(date); + + tm localTM; + localTM.tm_sec = time.second(); + localTM.tm_min = time.minute(); + localTM.tm_hour = time.hour(); + localTM.tm_mday = fakeDate.day(); + localTM.tm_mon = fakeDate.month() - 1; + localTM.tm_year = fakeDate.year() - 1900; + localTM.tm_isdst = (int)isdst; +#if defined(Q_OS_WINCE) + time_t secsSince1Jan1970UTC = toTime_tHelper(fakeDate, time); +#else +#if defined(Q_OS_WIN) + _tzset(); +#endif + time_t secsSince1Jan1970UTC = mktime(&localTM); +#endif + tm *brokenDown = 0; +#if defined(Q_OS_WINCE) + tm res; + FILETIME localTime = time_tToFt(secsSince1Jan1970UTC); + SYSTEMTIME sysTime; + FileTimeToSystemTime(&localTime, &sysTime); + FILETIME resultTime; + LocalFileTimeToFileTime(&localTime , &resultTime); + FileTimeToSystemTime(&resultTime , &sysTime); + res.tm_sec = sysTime.wSecond; + res.tm_min = sysTime.wMinute; + res.tm_hour = sysTime.wHour; + res.tm_mday = sysTime.wDay; + res.tm_mon = sysTime.wMonth - 1; + res.tm_year = sysTime.wYear - 1900; + res.tm_isdst = (int)isdst; + brokenDown = &res; +#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) + // use the reentrant version of gmtime() where available + tm res; + brokenDown = gmtime_r(&secsSince1Jan1970UTC, &res); +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + tm res; + if (!_gmtime64_s(&res, &secsSince1Jan1970UTC)) + brokenDown = &res; +#else + brokenDown = gmtime(&secsSince1Jan1970UTC); +#endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS + if (!brokenDown) { + date = QDate(1970, 1, 1); + time = QTime(); + } else { + int deltaDays = fakeDate.daysTo(date); + date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday); + time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec()); + date = date.addDays(deltaDays); + } +} + +QDateTimePrivate::Spec QDateTimePrivate::getLocal(QDate &outDate, QTime &outTime) const +{ + outDate = date; + outTime = time; + if (spec == QDateTimePrivate::UTC) + return utcToLocal(outDate, outTime); + return spec; +} + +void QDateTimePrivate::getUTC(QDate &outDate, QTime &outTime) const +{ + outDate = date; + outTime = time; + const bool isOffset = spec == QDateTimePrivate::OffsetFromUTC; + + if (spec != QDateTimePrivate::UTC && !isOffset) + localToUtc(outDate, outTime, (int)spec); + + if (isOffset) + addMSecs(outDate, outTime, -(qint64(utcOffset) * 1000)); +} + +#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING) +QDebug operator<<(QDebug dbg, const QDate &date) +{ + dbg.nospace() << "QDate(" << date.toString() << ")"; + return dbg.space(); +} + +QDebug operator<<(QDebug dbg, const QTime &time) +{ + dbg.nospace() << "QTime(" << time.toString() << ")"; + return dbg.space(); +} + +QDebug operator<<(QDebug dbg, const QDateTime &date) +{ + dbg.nospace() << "QDateTime(" << date.toString() << ")"; + return dbg.space(); +} +#endif + +#ifndef QT_BOOTSTRAPPED + +/*! + \internal + Gets the digit from a datetime. E.g. + + QDateTime var(QDate(2004, 02, 02)); + int digit = getDigit(var, Year); + // digit = 2004 +*/ + +int QDateTimeParser::getDigit(const QDateTime &t, int index) const +{ + if (index < 0 || index >= sectionNodes.size()) { +#ifndef QT_NO_DATESTRING + qWarning("QDateTimeParser::getDigit() Internal error (%s %d)", + qPrintable(t.toString()), index); +#else + qWarning("QDateTimeParser::getDigit() Internal error (%d)", index); +#endif + return -1; + } + const SectionNode &node = sectionNodes.at(index); + switch (node.type) { + case Hour24Section: case Hour12Section: return t.time().hour(); + case MinuteSection: return t.time().minute(); + case SecondSection: return t.time().second(); + case MSecSection: return t.time().msec(); + case YearSection2Digits: + case YearSection: return t.date().year(); + case MonthSection: return t.date().month(); + case DaySection: return t.date().day(); + case DayOfWeekSection: return t.date().day(); + case AmPmSection: return t.time().hour() > 11 ? 1 : 0; + + default: break; + } + +#ifndef QT_NO_DATESTRING + qWarning("QDateTimeParser::getDigit() Internal error 2 (%s %d)", + qPrintable(t.toString()), index); +#else + qWarning("QDateTimeParser::getDigit() Internal error 2 (%d)", index); +#endif + return -1; +} + +/*! + \internal + Sets a digit in a datetime. E.g. + + QDateTime var(QDate(2004, 02, 02)); + int digit = getDigit(var, Year); + // digit = 2004 + setDigit(&var, Year, 2005); + digit = getDigit(var, Year); + // digit = 2005 +*/ + +bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const +{ + if (index < 0 || index >= sectionNodes.size()) { +#ifndef QT_NO_DATESTRING + qWarning("QDateTimeParser::setDigit() Internal error (%s %d %d)", + qPrintable(v.toString()), index, newVal); +#else + qWarning("QDateTimeParser::setDigit() Internal error (%d %d)", index, newVal); +#endif + return false; + } + const SectionNode &node = sectionNodes.at(index); + + int year, month, day, hour, minute, second, msec; + year = v.date().year(); + month = v.date().month(); + day = v.date().day(); + hour = v.time().hour(); + minute = v.time().minute(); + second = v.time().second(); + msec = v.time().msec(); + + switch (node.type) { + case Hour24Section: case Hour12Section: hour = newVal; break; + case MinuteSection: minute = newVal; break; + case SecondSection: second = newVal; break; + case MSecSection: msec = newVal; break; + case YearSection2Digits: + case YearSection: year = newVal; break; + case MonthSection: month = newVal; break; + case DaySection: + case DayOfWeekSection: + if (newVal > 31) { + // have to keep legacy behavior. setting the + // date to 32 should return false. Setting it + // to 31 for february should return true + return false; + } + day = newVal; + break; + case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break; + default: + qWarning("QDateTimeParser::setDigit() Internal error (%s)", + qPrintable(sectionName(node.type))); + break; + } + + if (!(node.type & (DaySection|DayOfWeekSection))) { + if (day < cachedDay) + day = cachedDay; + const int max = QDate(year, month, 1).daysInMonth(); + if (day > max) { + day = max; + } + } + if (QDate::isValid(year, month, day) && QTime::isValid(hour, minute, second, msec)) { + v = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec); + return true; + } + return false; +} + + + +/*! + \ + + Returns the absolute maximum for a section +*/ + +int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const +{ + const SectionNode &sn = sectionNode(s); + switch (sn.type) { + case Hour24Section: + case Hour12Section: return 23; // this is special-cased in + // parseSection. We want it to be + // 23 for the stepBy case. + case MinuteSection: + case SecondSection: return 59; + case MSecSection: return 999; + case YearSection2Digits: + case YearSection: return 9999; // sectionMaxSize will prevent + // people from typing in a larger + // number in count == 2 sections. + // stepBy() will work on real years anyway + case MonthSection: return 12; + case DaySection: + case DayOfWeekSection: return cur.isValid() ? cur.date().daysInMonth() : 31; + case AmPmSection: return 1; + default: break; + } + qWarning("QDateTimeParser::absoluteMax() Internal error (%s)", + qPrintable(sectionName(sn.type))); + return -1; +} + +/*! + \internal + + Returns the absolute minimum for a section +*/ + +int QDateTimeParser::absoluteMin(int s) const +{ + const SectionNode &sn = sectionNode(s); + switch (sn.type) { + case Hour24Section: + case Hour12Section: + case MinuteSection: + case SecondSection: + case MSecSection: + case YearSection2Digits: + case YearSection: return 0; + case MonthSection: + case DaySection: + case DayOfWeekSection: return 1; + case AmPmSection: return 0; + default: break; + } + qWarning("QDateTimeParser::absoluteMin() Internal error (%s, %0x)", + qPrintable(sectionName(sn.type)), sn.type); + return -1; +} + +/*! + \internal + + Returns the sectionNode for the Section \a s. +*/ + +const QDateTimeParser::SectionNode &QDateTimeParser::sectionNode(int sectionIndex) const +{ + if (sectionIndex < 0) { + switch (sectionIndex) { + case FirstSectionIndex: + return first; + case LastSectionIndex: + return last; + case NoSectionIndex: + return none; + } + } else if (sectionIndex < sectionNodes.size()) { + return sectionNodes.at(sectionIndex); + } + + qWarning("QDateTimeParser::sectionNode() Internal error (%d)", + sectionIndex); + return none; +} + +QDateTimeParser::Section QDateTimeParser::sectionType(int sectionIndex) const +{ + return sectionNode(sectionIndex).type; +} + + +/*! + \internal + + Returns the starting position for section \a s. +*/ + +int QDateTimeParser::sectionPos(int sectionIndex) const +{ + return sectionPos(sectionNode(sectionIndex)); +} + +int QDateTimeParser::sectionPos(const SectionNode &sn) const +{ + switch (sn.type) { + case FirstSection: return 0; + case LastSection: return displayText().size() - 1; + default: break; + } + if (sn.pos == -1) { + qWarning("QDateTimeParser::sectionPos Internal error (%s)", qPrintable(sectionName(sn.type))); + return -1; + } + return sn.pos; +} + + +/*! + \internal helper function for parseFormat. removes quotes that are + not escaped and removes the escaping on those that are escaped + +*/ + +static QString unquote(const QString &str) +{ + const QChar quote(QLatin1Char('\'')); + const QChar slash(QLatin1Char('\\')); + const QChar zero(QLatin1Char('0')); + QString ret; + QChar status(zero); + const int max = str.size(); + for (int i=0; i<max; ++i) { + if (str.at(i) == quote) { + if (status != quote) { + status = quote; + } else if (!ret.isEmpty() && str.at(i - 1) == slash) { + ret[ret.size() - 1] = quote; + } else { + status = zero; + } + } else { + ret += str.at(i); + } + } + return ret; +} +/*! + \internal + + Parses the format \a newFormat. If successful, returns true and + sets up the format. Else keeps the old format and returns false. + +*/ + +static inline int countRepeat(const QString &str, int index, int maxCount) +{ + int count = 1; + const QChar ch(str.at(index)); + const int max = qMin(index + maxCount, str.size()); + while (index + count < max && str.at(index + count) == ch) { + ++count; + } + return count; +} + +static inline void appendSeparator(QStringList *list, const QString &string, int from, int size, int lastQuote) +{ + QString str(string.mid(from, size)); + if (lastQuote >= from) + str = unquote(str); + list->append(str); +} + + +bool QDateTimeParser::parseFormat(const QString &newFormat) +{ + const QLatin1Char quote('\''); + const QLatin1Char slash('\\'); + const QLatin1Char zero('0'); + if (newFormat == displayFormat && !newFormat.isEmpty()) { + return true; + } + + QDTPDEBUGN("parseFormat: %s", newFormat.toLatin1().constData()); + + QVector<SectionNode> newSectionNodes; + Sections newDisplay = 0; + QStringList newSeparators; + int i, index = 0; + int add = 0; + QChar status(zero); + const int max = newFormat.size(); + int lastQuote = -1; + for (i = 0; i<max; ++i) { + if (newFormat.at(i) == quote) { + lastQuote = i; + ++add; + if (status != quote) { + status = quote; + } else if (newFormat.at(i - 1) != slash) { + status = zero; + } + } else if (status != quote) { + const char sect = newFormat.at(i).toLatin1(); + switch (sect) { + case 'H': + case 'h': + if (parserType != QVariant::Date) { + const Section hour = (sect == 'h') ? Hour12Section : Hour24Section; + const SectionNode sn = { hour, i - add, countRepeat(newFormat, i, 2) }; + newSectionNodes.append(sn); + appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); + i += sn.count - 1; + index = i + 1; + newDisplay |= hour; + } + break; + case 'm': + if (parserType != QVariant::Date) { + const SectionNode sn = { MinuteSection, i - add, countRepeat(newFormat, i, 2) }; + newSectionNodes.append(sn); + appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); + i += sn.count - 1; + index = i + 1; + newDisplay |= MinuteSection; + } + break; + case 's': + if (parserType != QVariant::Date) { + const SectionNode sn = { SecondSection, i - add, countRepeat(newFormat, i, 2) }; + newSectionNodes.append(sn); + appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); + i += sn.count - 1; + index = i + 1; + newDisplay |= SecondSection; + } + break; + + case 'z': + if (parserType != QVariant::Date) { + const SectionNode sn = { MSecSection, i - add, countRepeat(newFormat, i, 3) < 3 ? 1 : 3 }; + newSectionNodes.append(sn); + appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); + i += sn.count - 1; + index = i + 1; + newDisplay |= MSecSection; + } + break; + case 'A': + case 'a': + if (parserType != QVariant::Date) { + const bool cap = (sect == 'A'); + const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0) }; + newSectionNodes.append(sn); + appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); + newDisplay |= AmPmSection; + if (i + 1 < newFormat.size() + && newFormat.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) { + ++i; + } + index = i + 1; + } + break; + case 'y': + if (parserType != QVariant::Time) { + const int repeat = countRepeat(newFormat, i, 4); + if (repeat >= 2) { + const SectionNode sn = { repeat == 4 ? YearSection : YearSection2Digits, + i - add, repeat == 4 ? 4 : 2 }; + newSectionNodes.append(sn); + appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); + i += sn.count - 1; + index = i + 1; + newDisplay |= sn.type; + } + } + break; + case 'M': + if (parserType != QVariant::Time) { + const SectionNode sn = { MonthSection, i - add, countRepeat(newFormat, i, 4) }; + newSectionNodes.append(sn); + newSeparators.append(unquote(newFormat.mid(index, i - index))); + i += sn.count - 1; + index = i + 1; + newDisplay |= MonthSection; + } + break; + case 'd': + if (parserType != QVariant::Time) { + const int repeat = countRepeat(newFormat, i, 4); + const SectionNode sn = { repeat >= 3 ? DayOfWeekSection : DaySection, i - add, repeat }; + newSectionNodes.append(sn); + appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote); + i += sn.count - 1; + index = i + 1; + newDisplay |= sn.type; + } + break; + + default: + break; + } + } + } + if (newSectionNodes.isEmpty() && context == DateTimeEdit) { + return false; + } + + if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) { + const int max = newSectionNodes.size(); + for (int i=0; i<max; ++i) { + SectionNode &node = newSectionNodes[i]; + if (node.type == Hour12Section) + node.type = Hour24Section; + } + } + + if (index < newFormat.size()) { + appendSeparator(&newSeparators, newFormat, index, index - max, lastQuote); + } else { + newSeparators.append(QString()); + } + + displayFormat = newFormat; + separators = newSeparators; + sectionNodes = newSectionNodes; + display = newDisplay; + last.pos = -1; + +// for (int i=0; i<sectionNodes.size(); ++i) { +// QDTPDEBUG << sectionName(sectionNodes.at(i).type) << sectionNodes.at(i).count; +// } + + QDTPDEBUG << newFormat << displayFormat; + QDTPDEBUGN("separators:\n'%s'", separators.join(QLatin1String("\n")).toLatin1().constData()); + + return true; +} + +/*! + \internal + + Returns the size of section \a s. +*/ + +int QDateTimeParser::sectionSize(int sectionIndex) const +{ + if (sectionIndex < 0) + return 0; + + if (sectionIndex >= sectionNodes.size()) { + qWarning("QDateTimeParser::sectionSize Internal error (%d)", sectionIndex); + return -1; + } + if (sectionIndex == sectionNodes.size() - 1) { + return displayText().size() - sectionPos(sectionIndex) - separators.last().size(); + } else { + return sectionPos(sectionIndex + 1) - sectionPos(sectionIndex) + - separators.at(sectionIndex + 1).size(); + } +} + + +int QDateTimeParser::sectionMaxSize(Section s, int count) const +{ +#ifndef QT_NO_TEXTDATE + int mcount = 12; +#endif + + switch (s) { + case FirstSection: + case NoSection: + case LastSection: return 0; + + case AmPmSection: { + const int lowerMax = qMin(getAmPmText(AmText, LowerCase).size(), + getAmPmText(PmText, LowerCase).size()); + const int upperMax = qMin(getAmPmText(AmText, UpperCase).size(), + getAmPmText(PmText, UpperCase).size()); + return qMin(4, qMin(lowerMax, upperMax)); + } + + case Hour24Section: + case Hour12Section: + case MinuteSection: + case SecondSection: + case DaySection: return 2; + case DayOfWeekSection: +#ifdef QT_NO_TEXTDATE + return 2; +#else + mcount = 7; + // fall through +#endif + case MonthSection: + if (count <= 2) + return 2; + +#ifdef QT_NO_TEXTDATE + return 2; +#else + { + int ret = 0; + const QLocale l = locale(); + for (int i=1; i<=mcount; ++i) { + const QString str = (s == MonthSection + ? l.monthName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat) + : l.dayName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat)); + ret = qMax(str.size(), ret); + } + return ret; + } +#endif + case MSecSection: return 3; + case YearSection: return 4; + case YearSection2Digits: return 2; + + case CalendarPopupSection: + case Internal: + case TimeSectionMask: + case DateSectionMask: + qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s", + sectionName(s).toLatin1().constData()); + } + return -1; +} + + +int QDateTimeParser::sectionMaxSize(int index) const +{ + const SectionNode &sn = sectionNode(index); + return sectionMaxSize(sn.type, sn.count); +} + +/*! + \internal + + Returns the text of section \a s. This function operates on the + arg text rather than edit->text(). +*/ + + +QString QDateTimeParser::sectionText(const QString &text, int sectionIndex, int index) const +{ + const SectionNode &sn = sectionNode(sectionIndex); + switch (sn.type) { + case NoSectionIndex: + case FirstSectionIndex: + case LastSectionIndex: + return QString(); + default: break; + } + + return text.mid(index, sectionSize(sectionIndex)); +} + +QString QDateTimeParser::sectionText(int sectionIndex) const +{ + const SectionNode &sn = sectionNode(sectionIndex); + switch (sn.type) { + case NoSectionIndex: + case FirstSectionIndex: + case LastSectionIndex: + return QString(); + default: break; + } + + return displayText().mid(sn.pos, sectionSize(sectionIndex)); +} + + +#ifndef QT_NO_TEXTDATE +/*! + \internal:skipToNextSection + + Parses the part of \a text that corresponds to \a s and returns + the value of that field. Sets *stateptr to the right state if + stateptr != 0. +*/ + +int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionIndex, + QString &text, int &cursorPosition, int index, + State &state, int *usedptr) const +{ + state = Invalid; + int num = 0; + const SectionNode &sn = sectionNode(sectionIndex); + if ((sn.type & Internal) == Internal) { + qWarning("QDateTimeParser::parseSection Internal error (%s %d)", + qPrintable(sectionName(sn.type)), sectionIndex); + return -1; + } + + const int sectionmaxsize = sectionMaxSize(sectionIndex); + QString sectiontext = text.mid(index, sectionmaxsize); + int sectiontextSize = sectiontext.size(); + + QDTPDEBUG << "sectionValue for" << sectionName(sn.type) + << "with text" << text << "and st" << sectiontext + << text.mid(index, sectionmaxsize) + << index; + + int used = 0; + switch (sn.type) { + case AmPmSection: { + const int ampm = findAmPm(sectiontext, sectionIndex, &used); + switch (ampm) { + case AM: // sectiontext == AM + case PM: // sectiontext == PM + num = ampm; + state = Acceptable; + break; + case PossibleAM: // sectiontext => AM + case PossiblePM: // sectiontext => PM + num = ampm - 2; + state = Intermediate; + break; + case PossibleBoth: // sectiontext => AM|PM + num = 0; + state = Intermediate; + break; + case Neither: + state = Invalid; + QDTPDEBUG << "invalid because findAmPm(" << sectiontext << ") returned -1"; + break; + default: + QDTPDEBUGN("This should never happen (findAmPm returned %d)", ampm); + break; + } + if (state != Invalid) { + QString str = text; + text.replace(index, used, sectiontext.left(used)); + } + break; } + case MonthSection: + case DayOfWeekSection: + if (sn.count >= 3) { + if (sn.type == MonthSection) { + int min = 1; + const QDate minDate = getMinimum().date(); + if (currentValue.date().year() == minDate.year()) { + min = minDate.month(); + } + num = findMonth(sectiontext.toLower(), min, sectionIndex, §iontext, &used); + } else { + num = findDay(sectiontext.toLower(), 1, sectionIndex, §iontext, &used); + } + + if (num != -1) { + state = (used == sectiontext.size() ? Acceptable : Intermediate); + QString str = text; + text.replace(index, used, sectiontext.left(used)); + } else { + state = Intermediate; + } + break; } + // fall through + case DaySection: + case YearSection: + case YearSection2Digits: + case Hour12Section: + case Hour24Section: + case MinuteSection: + case SecondSection: + case MSecSection: { + if (sectiontextSize == 0) { + num = 0; + used = 0; + state = Intermediate; + } else { + const int absMax = absoluteMax(sectionIndex); + QLocale loc; + bool ok = true; + int last = -1; + used = -1; + + QString digitsStr(sectiontext); + for (int i = 0; i < sectiontextSize; ++i) { + if (digitsStr.at(i).isSpace()) { + sectiontextSize = i; + break; + } + } + + const int max = qMin(sectionmaxsize, sectiontextSize); + for (int digits = max; digits >= 1; --digits) { + digitsStr.truncate(digits); + int tmp = (int)loc.toUInt(digitsStr, &ok, 10); + if (ok && sn.type == Hour12Section) { + if (tmp > 12) { + tmp = -1; + ok = false; + } else if (tmp == 12) { + tmp = 0; + } + } + if (ok && tmp <= absMax) { + QDTPDEBUG << sectiontext.left(digits) << tmp << digits; + last = tmp; + used = digits; + break; + } + } + + if (last == -1) { + QChar first(sectiontext.at(0)); + if (separators.at(sectionIndex + 1).startsWith(first)) { + used = 0; + state = Intermediate; + } else { + state = Invalid; + QDTPDEBUG << "invalid because" << sectiontext << "can't become a uint" << last << ok; + } + } else { + num += last; + const FieldInfo fi = fieldInfo(sectionIndex); + const bool done = (used == sectionmaxsize); + if (!done && fi & Fraction) { // typing 2 in a zzz field should be .200, not .002 + for (int i=used; i<sectionmaxsize; ++i) { + num *= 10; + } + } + const int absMin = absoluteMin(sectionIndex); + if (num < absMin) { + state = done ? Invalid : Intermediate; + if (done) + QDTPDEBUG << "invalid because" << num << "is less than absoluteMin" << absMin; + } else if (num > absMax) { + state = Intermediate; + } else if (!done && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) { + if (skipToNextSection(sectionIndex, currentValue, digitsStr)) { + state = Acceptable; + const int missingZeroes = sectionmaxsize - digitsStr.size(); + text.insert(index, QString().fill(QLatin1Char('0'), missingZeroes)); + used = sectionmaxsize; + cursorPosition += missingZeroes; + } else { + state = Intermediate;; + } + } else { + state = Acceptable; + } + } + } + break; } + default: + qWarning("QDateTimeParser::parseSection Internal error (%s %d)", + qPrintable(sectionName(sn.type)), sectionIndex); + return -1; + } + + if (usedptr) + *usedptr = used; + + return (state != Invalid ? num : -1); +} +#endif // QT_NO_TEXTDATE + +#ifndef QT_NO_DATESTRING +/*! + \internal +*/ + +QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPosition, + const QDateTime ¤tValue, bool fixup) const +{ + const QDateTime minimum = getMinimum(); + const QDateTime maximum = getMaximum(); + + State state = Acceptable; + + QDateTime newCurrentValue; + int pos = 0; + bool conflicts = false; + const int sectionNodesCount = sectionNodes.size(); + + QDTPDEBUG << "parse" << input; + { + int year, month, day, hour12, hour, minute, second, msec, ampm, dayofweek, year2digits; + getDateFromJulianDay(currentValue.date().toJulianDay(), &year, &month, &day); + year2digits = year % 100; + hour = currentValue.time().hour(); + hour12 = -1; + minute = currentValue.time().minute(); + second = currentValue.time().second(); + msec = currentValue.time().msec(); + dayofweek = currentValue.date().dayOfWeek(); + + ampm = -1; + Sections isSet = NoSection; + int num; + State tmpstate; + + for (int index=0; state != Invalid && index<sectionNodesCount; ++index) { + if (QStringRef(&input, pos, separators.at(index).size()) != separators.at(index)) { + QDTPDEBUG << "invalid because" << input.mid(pos, separators.at(index).size()) + << "!=" << separators.at(index) + << index << pos << currentSectionIndex; + state = Invalid; + goto end; + } + pos += separators.at(index).size(); + sectionNodes[index].pos = pos; + int *current = 0; + const SectionNode sn = sectionNodes.at(index); + int used; + + num = parseSection(currentValue, index, input, cursorPosition, pos, tmpstate, &used); + QDTPDEBUG << "sectionValue" << sectionName(sectionType(index)) << input + << "pos" << pos << "used" << used << stateName(tmpstate); + if (fixup && tmpstate == Intermediate && used < sn.count) { + const FieldInfo fi = fieldInfo(index); + if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) { + const QString newText = QString(QLatin1String("%1")).arg(num, sn.count, 10, QLatin1Char('0')); + input.replace(pos, used, newText); + used = sn.count; + } + } + pos += qMax(0, used); + + state = qMin<State>(state, tmpstate); + if (state == Intermediate && context == FromString) { + state = Invalid; + break; + } + + QDTPDEBUG << index << sectionName(sectionType(index)) << "is set to" + << pos << "state is" << stateName(state); + + + if (state != Invalid) { + switch (sn.type) { + case Hour24Section: current = &hour; break; + case Hour12Section: current = &hour12; break; + case MinuteSection: current = &minute; break; + case SecondSection: current = &second; break; + case MSecSection: current = &msec; break; + case YearSection: current = &year; break; + case YearSection2Digits: current = &year2digits; break; + case MonthSection: current = &month; break; + case DayOfWeekSection: current = &dayofweek; break; + case DaySection: current = &day; num = qMax<int>(1, num); break; + case AmPmSection: current = &m; break; + default: + qWarning("QDateTimeParser::parse Internal error (%s)", + qPrintable(sectionName(sn.type))); + break; + } + if (!current) { + qWarning("QDateTimeParser::parse Internal error 2"); + return StateNode(); + } + if (isSet & sn.type && *current != num) { + QDTPDEBUG << "CONFLICT " << sectionName(sn.type) << *current << num; + conflicts = true; + if (index != currentSectionIndex || num == -1) { + continue; + } + } + if (num != -1) + *current = num; + isSet |= sn.type; + } + } + + if (state != Invalid && QStringRef(&input, pos, input.size() - pos) != separators.last()) { + QDTPDEBUG << "invalid because" << input.mid(pos) + << "!=" << separators.last() << pos; + state = Invalid; + } + + if (state != Invalid) { + if (parserType != QVariant::Time) { + if (year % 100 != year2digits) { + switch (isSet & (YearSection2Digits|YearSection)) { + case YearSection2Digits: + year = (year / 100) * 100; + year += year2digits; + break; + case ((uint)YearSection2Digits|(uint)YearSection): { + conflicts = true; + const SectionNode &sn = sectionNode(currentSectionIndex); + if (sn.type == YearSection2Digits) { + year = (year / 100) * 100; + year += year2digits; + } + break; } + default: + break; + } + } + + const QDate date(year, month, day); + const int diff = dayofweek - date.dayOfWeek(); + if (diff != 0 && state == Acceptable && isSet & DayOfWeekSection) { + conflicts = isSet & DaySection; + const SectionNode &sn = sectionNode(currentSectionIndex); + if (sn.type == DayOfWeekSection || currentSectionIndex == -1) { + // dayofweek should be preferred + day += diff; + if (day <= 0) { + day += 7; + } else if (day > date.daysInMonth()) { + day -= 7; + } + QDTPDEBUG << year << month << day << dayofweek + << diff << QDate(year, month, day).dayOfWeek(); + } + } + bool needfixday = false; + if (sectionType(currentSectionIndex) & (DaySection|DayOfWeekSection)) { + cachedDay = day; + } else if (cachedDay > day) { + day = cachedDay; + needfixday = true; + } + + if (!QDate::isValid(year, month, day)) { + if (day < 32) { + cachedDay = day; + } + if (day > 28 && QDate::isValid(year, month, 1)) { + needfixday = true; + } + } + if (needfixday) { + if (context == FromString) { + state = Invalid; + goto end; + } + if (state == Acceptable && fixday) { + day = qMin<int>(day, QDate(year, month, 1).daysInMonth()); + + const QLocale loc = locale(); + for (int i=0; i<sectionNodesCount; ++i) { + if (sectionType(i) & (DaySection|DayOfWeekSection)) { + input.replace(sectionPos(i), sectionSize(i), loc.toString(day)); + } + } + } else { + state = qMin(Intermediate, state); + } + } + } + + if (parserType != QVariant::Date) { + if (isSet & Hour12Section) { + const bool hasHour = isSet & Hour24Section; + if (ampm == -1) { + if (hasHour) { + ampm = (hour < 12 ? 0 : 1); + } else { + ampm = 0; // no way to tell if this is am or pm so I assume am + } + } + hour12 = (ampm == 0 ? hour12 % 12 : (hour12 % 12) + 12); + if (!hasHour) { + hour = hour12; + } else if (hour != hour12) { + conflicts = true; + } + } else if (ampm != -1) { + if (!(isSet & (Hour24Section))) { + hour = (12 * ampm); // special case. Only ap section + } else if ((ampm == 0) != (hour < 12)) { + conflicts = true; + } + } + + } + + newCurrentValue = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec); + QDTPDEBUG << year << month << day << hour << minute << second << msec; + } + QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(), + newCurrentValue.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(), + stateName(state).toLatin1().constData()); + } +end: + if (newCurrentValue.isValid()) { + if (context != FromString && state != Invalid && newCurrentValue < minimum) { + const QLatin1Char space(' '); + if (newCurrentValue >= minimum) + qWarning("QDateTimeParser::parse Internal error 3 (%s %s)", + qPrintable(newCurrentValue.toString()), qPrintable(minimum.toString())); + + bool done = false; + state = Invalid; + for (int i=0; i<sectionNodesCount && !done; ++i) { + const SectionNode &sn = sectionNodes.at(i); + QString t = sectionText(input, i, sn.pos).toLower(); + if ((t.size() < sectionMaxSize(i) && (((int)fieldInfo(i) & (FixedWidth|Numeric)) != Numeric)) + || t.contains(space)) { + switch (sn.type) { + case AmPmSection: + switch (findAmPm(t, i)) { + case AM: + case PM: + state = Acceptable; + done = true; + break; + case Neither: + state = Invalid; + done = true; + break; + case PossibleAM: + case PossiblePM: + case PossibleBoth: { + const QDateTime copy(newCurrentValue.addSecs(12 * 60 * 60)); + if (copy >= minimum && copy <= maximum) { + state = Intermediate; + done = true; + } + break; } + } + case MonthSection: + if (sn.count >= 3) { + int tmp = newCurrentValue.date().month(); + // I know the first possible month makes the date too early + while ((tmp = findMonth(t, tmp + 1, i)) != -1) { + const QDateTime copy(newCurrentValue.addMonths(tmp - newCurrentValue.date().month())); + if (copy >= minimum && copy <= maximum) + break; // break out of while + } + if (tmp == -1) { + break; + } + state = Intermediate; + done = true; + break; + } + // fallthrough + default: { + int toMin; + int toMax; + + if (sn.type & TimeSectionMask) { + if (newCurrentValue.daysTo(minimum) != 0) { + break; + } + toMin = newCurrentValue.time().msecsTo(minimum.time()); + if (newCurrentValue.daysTo(maximum) > 0) { + toMax = -1; // can't get to max + } else { + toMax = newCurrentValue.time().msecsTo(maximum.time()); + } + } else { + toMin = newCurrentValue.daysTo(minimum); + toMax = newCurrentValue.daysTo(maximum); + } + const int maxChange = QDateTimeParser::maxChange(i); + if (toMin > maxChange) { + QDTPDEBUG << "invalid because toMin > maxChange" << toMin + << maxChange << t << newCurrentValue << minimum; + state = Invalid; + done = true; + break; + } else if (toMax > maxChange) { + toMax = -1; // can't get to max + } + + const int min = getDigit(minimum, i); + if (min == -1) { + qWarning("QDateTimeParser::parse Internal error 4 (%s)", + qPrintable(sectionName(sn.type))); + state = Invalid; + done = true; + break; + } + + int max = toMax != -1 ? getDigit(maximum, i) : absoluteMax(i, newCurrentValue); + int pos = cursorPosition - sn.pos; + if (pos < 0 || pos >= t.size()) + pos = -1; + if (!potentialValue(t.simplified(), min, max, i, newCurrentValue, pos)) { + QDTPDEBUG << "invalid because potentialValue(" << t.simplified() << min << max + << sectionName(sn.type) << "returned" << toMax << toMin << pos; + state = Invalid; + done = true; + break; + } + state = Intermediate; + done = true; + break; } + } + } + } + } else { + if (context == FromString) { + // optimization + Q_ASSERT(getMaximum().date().toJulianDay() == 4642999); + if (newCurrentValue.date().toJulianDay() > 4642999) + state = Invalid; + } else { + if (newCurrentValue > getMaximum()) + state = Invalid; + } + + QDTPDEBUG << "not checking intermediate because newCurrentValue is" << newCurrentValue << getMinimum() << getMaximum(); + } + } + StateNode node; + node.input = input; + node.state = state; + node.conflicts = conflicts; + node.value = newCurrentValue.toTimeSpec(spec); + text = input; + return node; +} +#endif // QT_NO_DATESTRING + +#ifndef QT_NO_TEXTDATE +/*! + \internal finds the first possible monthname that \a str1 can + match. Starting from \a index; str should already by lowered +*/ + +int QDateTimeParser::findMonth(const QString &str1, int startMonth, int sectionIndex, + QString *usedMonth, int *used) const +{ + int bestMatch = -1; + int bestCount = 0; + if (!str1.isEmpty()) { + const SectionNode &sn = sectionNode(sectionIndex); + if (sn.type != MonthSection) { + qWarning("QDateTimeParser::findMonth Internal error"); + return -1; + } + + QLocale::FormatType type = sn.count == 3 ? QLocale::ShortFormat : QLocale::LongFormat; + QLocale l = locale(); + + for (int month=startMonth; month<=12; ++month) { + QString str2 = l.monthName(month, type).toLower(); + + if (str1.startsWith(str2)) { + if (used) { + QDTPDEBUG << "used is set to" << str2.size(); + *used = str2.size(); + } + if (usedMonth) + *usedMonth = l.monthName(month, type); + + return month; + } + if (context == FromString) + continue; + + const int limit = qMin(str1.size(), str2.size()); + + QDTPDEBUG << "limit is" << limit << str1 << str2; + bool equal = true; + for (int i=0; i<limit; ++i) { + if (str1.at(i) != str2.at(i)) { + equal = false; + if (i > bestCount) { + bestCount = i; + bestMatch = month; + } + break; + } + } + if (equal) { + if (used) + *used = limit; + if (usedMonth) + *usedMonth = l.monthName(month, type); + return month; + } + } + if (usedMonth && bestMatch != -1) + *usedMonth = l.monthName(bestMatch, type); + } + if (used) { + QDTPDEBUG << "used is set to" << bestCount; + *used = bestCount; + } + return bestMatch; +} + +int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex, QString *usedDay, int *used) const +{ + int bestMatch = -1; + int bestCount = 0; + if (!str1.isEmpty()) { + const SectionNode &sn = sectionNode(sectionIndex); + if (!(sn.type & (DaySection|DayOfWeekSection))) { + qWarning("QDateTimeParser::findDay Internal error"); + return -1; + } + const QLocale l = locale(); + for (int day=startDay; day<=7; ++day) { + const QString str2 = l.dayName(day, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat); + + if (str1.startsWith(str2.toLower())) { + if (used) + *used = str2.size(); + if (usedDay) { + *usedDay = str2; + } + return day; + } + if (context == FromString) + continue; + + const int limit = qMin(str1.size(), str2.size()); + bool found = true; + for (int i=0; i<limit; ++i) { + if (str1.at(i) != str2.at(i) && !str1.at(i).isSpace()) { + if (i > bestCount) { + bestCount = i; + bestMatch = day; + } + found = false; + break; + } + + } + if (found) { + if (used) + *used = limit; + if (usedDay) + *usedDay = str2; + + return day; + } + } + if (usedDay && bestMatch != -1) { + *usedDay = l.dayName(bestMatch, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat); + } + } + if (used) + *used = bestCount; + + return bestMatch; +} +#endif // QT_NO_TEXTDATE + +/*! + \internal + + returns + 0 if str == QDateTimeEdit::tr("AM") + 1 if str == QDateTimeEdit::tr("PM") + 2 if str can become QDateTimeEdit::tr("AM") + 3 if str can become QDateTimeEdit::tr("PM") + 4 if str can become QDateTimeEdit::tr("PM") and can become QDateTimeEdit::tr("AM") + -1 can't become anything sensible + +*/ + +int QDateTimeParser::findAmPm(QString &str, int index, int *used) const +{ + const SectionNode &s = sectionNode(index); + if (s.type != AmPmSection) { + qWarning("QDateTimeParser::findAmPm Internal error"); + return -1; + } + if (used) + *used = str.size(); + if (str.trimmed().isEmpty()) { + return PossibleBoth; + } + const QLatin1Char space(' '); + int size = sectionMaxSize(index); + + enum { + amindex = 0, + pmindex = 1 + }; + QString ampm[2]; + ampm[amindex] = getAmPmText(AmText, s.count == 1 ? UpperCase : LowerCase); + ampm[pmindex] = getAmPmText(PmText, s.count == 1 ? UpperCase : LowerCase); + for (int i=0; i<2; ++i) + ampm[i].truncate(size); + + QDTPDEBUG << "findAmPm" << str << ampm[0] << ampm[1]; + + if (str.indexOf(ampm[amindex], 0, Qt::CaseInsensitive) == 0) { + str = ampm[amindex]; + return AM; + } else if (str.indexOf(ampm[pmindex], 0, Qt::CaseInsensitive) == 0) { + str = ampm[pmindex]; + return PM; + } else if (context == FromString || (str.count(space) == 0 && str.size() >= size)) { + return Neither; + } + size = qMin(size, str.size()); + + bool broken[2] = {false, false}; + for (int i=0; i<size; ++i) { + if (str.at(i) != space) { + for (int j=0; j<2; ++j) { + if (!broken[j]) { + int index = ampm[j].indexOf(str.at(i)); + QDTPDEBUG << "looking for" << str.at(i) + << "in" << ampm[j] << "and got" << index; + if (index == -1) { + if (str.at(i).category() == QChar::Letter_Uppercase) { + index = ampm[j].indexOf(str.at(i).toLower()); + QDTPDEBUG << "trying with" << str.at(i).toLower() + << "in" << ampm[j] << "and got" << index; + } else if (str.at(i).category() == QChar::Letter_Lowercase) { + index = ampm[j].indexOf(str.at(i).toUpper()); + QDTPDEBUG << "trying with" << str.at(i).toUpper() + << "in" << ampm[j] << "and got" << index; + } + if (index == -1) { + broken[j] = true; + if (broken[amindex] && broken[pmindex]) { + QDTPDEBUG << str << "didn't make it"; + return Neither; + } + continue; + } else { + str[i] = ampm[j].at(index); // fix case + } + } + ampm[j].remove(index, 1); + } + } + } + } + if (!broken[pmindex] && !broken[amindex]) + return PossibleBoth; + return (!broken[amindex] ? PossibleAM : PossiblePM); +} + +/*! + \internal + Max number of units that can be changed by this section. +*/ + +int QDateTimeParser::maxChange(int index) const +{ + const SectionNode &sn = sectionNode(index); + switch (sn.type) { + // Time. unit is msec + case MSecSection: return 999; + case SecondSection: return 59 * 1000; + case MinuteSection: return 59 * 60 * 1000; + case Hour24Section: case Hour12Section: return 59 * 60 * 60 * 1000; + + // Date. unit is day + case DayOfWeekSection: return 7; + case DaySection: return 30; + case MonthSection: return 365 - 31; + case YearSection: return 9999 * 365; + case YearSection2Digits: return 100 * 365; + default: + qWarning("QDateTimeParser::maxChange() Internal error (%s)", + qPrintable(sectionName(sectionType(index)))); + } + + return -1; +} + +QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const +{ + FieldInfo ret = 0; + const SectionNode &sn = sectionNode(index); + const Section s = sn.type; + switch (s) { + case MSecSection: + ret |= Fraction; + // fallthrough + case SecondSection: + case MinuteSection: + case Hour24Section: + case Hour12Section: + case YearSection: + case YearSection2Digits: + ret |= Numeric; + if (s != YearSection) { + ret |= AllowPartial; + } + if (sn.count != 1) { + ret |= FixedWidth; + } + break; + case MonthSection: + case DaySection: + switch (sn.count) { + case 2: + ret |= FixedWidth; + // fallthrough + case 1: + ret |= (Numeric|AllowPartial); + break; + } + break; + case DayOfWeekSection: + if (sn.count == 3) + ret |= FixedWidth; + break; + case AmPmSection: + ret |= FixedWidth; + break; + default: + qWarning("QDateTimeParser::fieldInfo Internal error 2 (%d %s %d)", + index, qPrintable(sectionName(sn.type)), sn.count); + break; + } + return ret; +} + +/*! + \internal Get a number that str can become which is between min + and max or -1 if this is not possible. +*/ + + +QString QDateTimeParser::sectionFormat(int index) const +{ + const SectionNode &sn = sectionNode(index); + return sectionFormat(sn.type, sn.count); +} + +QString QDateTimeParser::sectionFormat(Section s, int count) const +{ + QChar fillChar; + switch (s) { + case AmPmSection: return count == 1 ? QLatin1String("AP") : QLatin1String("ap"); + case MSecSection: fillChar = QLatin1Char('z'); break; + case SecondSection: fillChar = QLatin1Char('s'); break; + case MinuteSection: fillChar = QLatin1Char('m'); break; + case Hour24Section: fillChar = QLatin1Char('H'); break; + case Hour12Section: fillChar = QLatin1Char('h'); break; + case DayOfWeekSection: + case DaySection: fillChar = QLatin1Char('d'); break; + case MonthSection: fillChar = QLatin1Char('M'); break; + case YearSection2Digits: + case YearSection: fillChar = QLatin1Char('y'); break; + default: + qWarning("QDateTimeParser::sectionFormat Internal error (%s)", + qPrintable(sectionName(s))); + return QString(); + } + if (fillChar.isNull()) { + qWarning("QDateTimeParser::sectionFormat Internal error 2"); + return QString(); + } + + QString str; + str.fill(fillChar, count); + return str; +} + + +/*! \internal Returns true if str can be modified to represent a + number that is within min and max. +*/ + +bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int index, + const QDateTime ¤tValue, int insert) const +{ + if (str.isEmpty()) { + return true; + } + const int size = sectionMaxSize(index); + int val = (int)locale().toUInt(str); + const SectionNode &sn = sectionNode(index); + if (sn.type == YearSection2Digits) { + val += currentValue.date().year() - (currentValue.date().year() % 100); + } + if (val >= min && val <= max && str.size() == size) { + return true; + } else if (val > max) { + return false; + } else if (str.size() == size && val < min) { + return false; + } + + const int len = size - str.size(); + for (int i=0; i<len; ++i) { + for (int j=0; j<10; ++j) { + if (potentialValue(str + QLatin1Char('0' + j), min, max, index, currentValue, insert)) { + return true; + } else if (insert >= 0) { + QString tmp = str; + tmp.insert(insert, QLatin1Char('0' + j)); + if (potentialValue(tmp, min, max, index, currentValue, insert)) + return true; + } + } + } + + return false; +} + +bool QDateTimeParser::skipToNextSection(int index, const QDateTime ¤t, const QString &text) const +{ + Q_ASSERT(current >= getMinimum() && current <= getMaximum()); + + const SectionNode &node = sectionNode(index); + Q_ASSERT(text.size() < sectionMaxSize(index)); + + const QDateTime maximum = getMaximum(); + const QDateTime minimum = getMinimum(); + QDateTime tmp = current; + int min = absoluteMin(index); + setDigit(tmp, index, min); + if (tmp < minimum) { + min = getDigit(minimum, index); + } + + int max = absoluteMax(index, current); + setDigit(tmp, index, max); + if (tmp > maximum) { + max = getDigit(maximum, index); + } + int pos = cursorPosition() - node.pos; + if (pos < 0 || pos >= text.size()) + pos = -1; + + const bool potential = potentialValue(text, min, max, index, current, pos); + return !potential; + + /* If the value potentially can become another valid entry we + * don't want to skip to the next. E.g. In a M field (month + * without leading 0 if you type 1 we don't want to autoskip but + * if you type 3 we do + */ +} + +/*! + \internal + For debugging. Returns the name of the section \a s. +*/ + +QString QDateTimeParser::sectionName(int s) const +{ + switch (s) { + case QDateTimeParser::AmPmSection: return QLatin1String("AmPmSection"); + case QDateTimeParser::DaySection: return QLatin1String("DaySection"); + case QDateTimeParser::DayOfWeekSection: return QLatin1String("DayOfWeekSection"); + case QDateTimeParser::Hour24Section: return QLatin1String("Hour24Section"); + case QDateTimeParser::Hour12Section: return QLatin1String("Hour12Section"); + case QDateTimeParser::MSecSection: return QLatin1String("MSecSection"); + case QDateTimeParser::MinuteSection: return QLatin1String("MinuteSection"); + case QDateTimeParser::MonthSection: return QLatin1String("MonthSection"); + case QDateTimeParser::SecondSection: return QLatin1String("SecondSection"); + case QDateTimeParser::YearSection: return QLatin1String("YearSection"); + case QDateTimeParser::YearSection2Digits: return QLatin1String("YearSection2Digits"); + case QDateTimeParser::NoSection: return QLatin1String("NoSection"); + case QDateTimeParser::FirstSection: return QLatin1String("FirstSection"); + case QDateTimeParser::LastSection: return QLatin1String("LastSection"); + default: return QLatin1String("Unknown section ") + QString::number(s); + } +} + +/*! + \internal + For debugging. Returns the name of the state \a s. +*/ + +QString QDateTimeParser::stateName(int s) const +{ + switch (s) { + case Invalid: return QLatin1String("Invalid"); + case Intermediate: return QLatin1String("Intermediate"); + case Acceptable: return QLatin1String("Acceptable"); + default: return QLatin1String("Unknown state ") + QString::number(s); + } +} + +#ifndef QT_NO_DATESTRING +bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const +{ + QDateTime val(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN); + QString text = t; + int copy = -1; + const StateNode tmp = parse(text, copy, val, false); + if (tmp.state != Acceptable || tmp.conflicts) { + return false; + } + if (time) { + const QTime t = tmp.value.time(); + if (!t.isValid()) { + return false; + } + *time = t; + } + + if (date) { + const QDate d = tmp.value.date(); + if (!d.isValid()) { + return false; + } + *date = d; + } + return true; +} +#endif // QT_NO_DATESTRING + +QDateTime QDateTimeParser::getMinimum() const +{ + return QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, spec); +} + +QDateTime QDateTimeParser::getMaximum() const +{ + return QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, spec); +} + +QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const +{ + if (ap == AmText) { + return (cs == UpperCase ? QLatin1String("AM") : QLatin1String("am")); + } else { + return (cs == UpperCase ? QLatin1String("PM") : QLatin1String("pm")); + } +} + +/* + \internal + + I give arg2 preference because arg1 is always a QDateTime. +*/ + +bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2) +{ + return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count); +} + + +#endif // QT_BOOTSTRAPPED + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h new file mode 100644 index 0000000..3278297 --- /dev/null +++ b/src/corelib/tools/qdatetime.h @@ -0,0 +1,333 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDATETIME_H +#define QDATETIME_H + +#include <QtCore/qstring.h> +#include <QtCore/qnamespace.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class Q_CORE_EXPORT QDate +{ +public: + enum MonthNameType { + DateFormat = 0, + StandaloneFormat + }; +public: + QDate() { jd = 0; } + QDate(int y, int m, int d); + + bool isNull() const { return jd == 0; } + bool isValid() const; + + int year() const; + int month() const; + int day() const; + int dayOfWeek() const; + int dayOfYear() const; + int daysInMonth() const; + int daysInYear() const; + int weekNumber(int *yearNum = 0) const; + +#ifndef QT_NO_TEXTDATE +#ifdef QT3_SUPPORT + static QT3_SUPPORT QString monthName(int month) { return shortMonthName(month); } + static QT3_SUPPORT QString dayName(int weekday) { return shortDayName(weekday); } +#endif + // ### Qt 5: merge these functions. + static QString shortMonthName(int month); + static QString shortMonthName(int month, MonthNameType type); + static QString shortDayName(int weekday); + static QString shortDayName(int weekday, MonthNameType type); + static QString longMonthName(int month); + static QString longMonthName(int month, MonthNameType type); + static QString longDayName(int weekday); + static QString longDayName(int weekday, MonthNameType type); +#endif // QT_NO_TEXTDATE +#ifndef QT_NO_DATESTRING + QString toString(Qt::DateFormat f = Qt::TextDate) const; + QString toString(const QString &format) const; +#endif + bool setYMD(int y, int m, int d); + bool setDate(int year, int month, int day); + + void getDate(int *year, int *month, int *day); + + QDate addDays(int days) const; + QDate addMonths(int months) const; + QDate addYears(int years) const; + int daysTo(const QDate &) const; + + bool operator==(const QDate &other) const { return jd == other.jd; } + bool operator!=(const QDate &other) const { return jd != other.jd; } + bool operator<(const QDate &other) const { return jd < other.jd; } + bool operator<=(const QDate &other) const { return jd <= other.jd; } + bool operator>(const QDate &other) const { return jd > other.jd; } + bool operator>=(const QDate &other) const { return jd >= other.jd; } + + static QDate currentDate(); +#ifndef QT_NO_DATESTRING + static QDate fromString(const QString &s, Qt::DateFormat f = Qt::TextDate); + static QDate fromString(const QString &s, const QString &format); +#endif + static bool isValid(int y, int m, int d); + static bool isLeapYear(int year); +#ifdef QT3_SUPPORT + inline static QT3_SUPPORT bool leapYear(int year) { return isLeapYear(year); } +#endif + + // ### Qt 5: remove these two functions + static uint gregorianToJulian(int y, int m, int d); + static void julianToGregorian(uint jd, int &y, int &m, int &d); + +#ifdef QT3_SUPPORT + static QT3_SUPPORT QDate currentDate(Qt::TimeSpec spec); +#endif + + static inline QDate fromJulianDay(int jd) { QDate d; d.jd = jd; return d; } + inline int toJulianDay() const { return jd; } + +private: + uint jd; + + friend class QDateTime; + friend class QDateTimePrivate; +#ifndef QT_NO_DATASTREAM + friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDate &); + friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDate &); +#endif +}; +Q_DECLARE_TYPEINFO(QDate, Q_MOVABLE_TYPE); + +class Q_CORE_EXPORT QTime +{ +public: + QTime(): mds(NullTime) +#if defined(Q_OS_WINCE) + , startTick(NullTime) +#endif + {} + QTime(int h, int m, int s = 0, int ms = 0); + + bool isNull() const { return mds == NullTime; } + bool isValid() const; + + int hour() const; + int minute() const; + int second() const; + int msec() const; +#ifndef QT_NO_DATESTRING + QString toString(Qt::DateFormat f = Qt::TextDate) const; + QString toString(const QString &format) const; +#endif + bool setHMS(int h, int m, int s, int ms = 0); + + QTime addSecs(int secs) const; + int secsTo(const QTime &) const; + QTime addMSecs(int ms) const; + int msecsTo(const QTime &) const; + + bool operator==(const QTime &other) const { return mds == other.mds; } + bool operator!=(const QTime &other) const { return mds != other.mds; } + bool operator<(const QTime &other) const { return mds < other.mds; } + bool operator<=(const QTime &other) const { return mds <= other.mds; } + bool operator>(const QTime &other) const { return mds > other.mds; } + bool operator>=(const QTime &other) const { return mds >= other.mds; } + + static QTime currentTime(); +#ifndef QT_NO_DATESTRING + static QTime fromString(const QString &s, Qt::DateFormat f = Qt::TextDate); + static QTime fromString(const QString &s, const QString &format); +#endif + static bool isValid(int h, int m, int s, int ms = 0); + +#ifdef QT3_SUPPORT + static QT3_SUPPORT QTime currentTime(Qt::TimeSpec spec); +#endif + + void start(); + int restart(); + int elapsed() const; +private: + enum TimeFlag { NullTime = -1 }; + inline int ds() const { return mds == -1 ? 0 : mds; } + int mds; +#if defined(Q_OS_WINCE) + int startTick; +#endif + + friend class QDateTime; + friend class QDateTimePrivate; +#ifndef QT_NO_DATASTREAM + friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QTime &); + friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTime &); +#endif +}; +Q_DECLARE_TYPEINFO(QTime, Q_MOVABLE_TYPE); + +class QDateTimePrivate; + +class Q_CORE_EXPORT QDateTime +{ +public: + QDateTime(); + explicit QDateTime(const QDate &); + QDateTime(const QDate &, const QTime &, Qt::TimeSpec spec = Qt::LocalTime); + QDateTime(const QDateTime &other); + ~QDateTime(); + + QDateTime &operator=(const QDateTime &other); + + bool isNull() const; + bool isValid() const; + + QDate date() const; + QTime time() const; + Qt::TimeSpec timeSpec() const; + uint toTime_t() const; + void setDate(const QDate &date); + void setTime(const QTime &time); + void setTimeSpec(Qt::TimeSpec spec); + void setTime_t(uint secsSince1Jan1970UTC); +#ifndef QT_NO_DATESTRING + QString toString(Qt::DateFormat f = Qt::TextDate) const; + QString toString(const QString &format) const; +#endif + QDateTime addDays(int days) const; + QDateTime addMonths(int months) const; + QDateTime addYears(int years) const; + QDateTime addSecs(int secs) const; + QDateTime addMSecs(qint64 msecs) const; + QDateTime toTimeSpec(Qt::TimeSpec spec) const; + inline QDateTime toLocalTime() const { return toTimeSpec(Qt::LocalTime); } + inline QDateTime toUTC() const { return toTimeSpec(Qt::UTC); } + int daysTo(const QDateTime &) const; + int secsTo(const QDateTime &) const; + + bool operator==(const QDateTime &other) const; + inline bool operator!=(const QDateTime &other) const { return !(*this == other); } + bool operator<(const QDateTime &other) const; + inline bool operator<=(const QDateTime &other) const { return !(other < *this); } + inline bool operator>(const QDateTime &other) const { return other < *this; } + inline bool operator>=(const QDateTime &other) const { return !(*this < other); } + + void setUtcOffset(int seconds); + int utcOffset() const; + + static QDateTime currentDateTime(); +#ifndef QT_NO_DATESTRING + static QDateTime fromString(const QString &s, Qt::DateFormat f = Qt::TextDate); + static QDateTime fromString(const QString &s, const QString &format); +#endif + static QDateTime fromTime_t(uint secsSince1Jan1970UTC); + +#ifdef QT3_SUPPORT + inline QT3_SUPPORT void setTime_t(uint secsSince1Jan1970UTC, Qt::TimeSpec spec) { + setTime_t(secsSince1Jan1970UTC); + if (spec == Qt::UTC) + *this = toUTC(); + } + static inline QT3_SUPPORT QDateTime currentDateTime(Qt::TimeSpec spec) { + if (spec == Qt::LocalTime) + return currentDateTime(); + else + return currentDateTime().toUTC(); + } + +#endif + +private: + friend class QDateTimePrivate; + void detach(); + QDateTimePrivate *d; + +#ifndef QT_NO_DATASTREAM + friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &); + friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDateTime &); +#endif +}; +Q_DECLARE_TYPEINFO(QDateTime, Q_MOVABLE_TYPE); + +#ifdef QT3_SUPPORT +inline QDate QDate::currentDate(Qt::TimeSpec spec) +{ + if (spec == Qt::LocalTime) + return currentDate(); + else + return QDateTime::currentDateTime().toUTC().date(); +} + +inline QTime QTime::currentTime(Qt::TimeSpec spec) +{ + if (spec == Qt::LocalTime) + return currentTime(); + else + return QDateTime::currentDateTime().toUTC().time(); +} +#endif + +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDate &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDate &); +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QTime &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTime &); +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QDateTime &); +#endif // QT_NO_DATASTREAM + +#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING) +Q_CORE_EXPORT QDebug operator<<(QDebug, const QDate &); +Q_CORE_EXPORT QDebug operator<<(QDebug, const QTime &); +Q_CORE_EXPORT QDebug operator<<(QDebug, const QDateTime &); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDATETIME_H diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/tools/qdatetime_p.h new file mode 100644 index 0000000..b2fb58d --- /dev/null +++ b/src/corelib/tools/qdatetime_p.h @@ -0,0 +1,285 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDATETIME_P_H +#define QDATETIME_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qplatformdefs.h" +#include "QtCore/qatomic.h" +#include "QtCore/qdatetime.h" +#include "QtCore/qstringlist.h" +#include "QtCore/qlocale.h" +#ifndef QT_BOOTSTRAPPED +# include "QtCore/qvariant.h" +#endif +#include "QtCore/qvector.h" + + +#define QDATETIMEEDIT_TIME_MIN QTime(0, 0, 0, 0) +#define QDATETIMEEDIT_TIME_MAX QTime(23, 59, 59, 999) +#define QDATETIMEEDIT_DATE_MIN QDate(100, 1, 1) +#define QDATETIMEEDIT_COMPAT_DATE_MIN QDate(1752, 9, 14) +#define QDATETIMEEDIT_DATE_MAX QDate(7999, 12, 31) +#define QDATETIMEEDIT_DATETIME_MIN QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN) +#define QDATETIMEEDIT_COMPAT_DATETIME_MIN QDateTime(QDATETIMEEDIT_COMPAT_DATE_MIN, QDATETIMEEDIT_TIME_MIN) +#define QDATETIMEEDIT_DATETIME_MAX QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX) +#define QDATETIMEEDIT_DATE_INITIAL QDate(2000, 1, 1) + +QT_BEGIN_NAMESPACE + +class QDateTimePrivate +{ +public: + enum Spec { LocalUnknown = -1, LocalStandard = 0, LocalDST = 1, UTC = 2, OffsetFromUTC = 3}; + + QDateTimePrivate() : ref(1), spec(LocalUnknown), utcOffset(0) {} + QDateTimePrivate(const QDateTimePrivate &other) + : ref(1), date(other.date), time(other.time), spec(other.spec), utcOffset(other.utcOffset) + {} + + QAtomicInt ref; + QDate date; + QTime time; + Spec spec; + /*! + \internal + \since 4.4 + + The offset in seconds. Applies only when timeSpec() is OffsetFromUTC. + */ + int utcOffset; + + Spec getLocal(QDate &outDate, QTime &outTime) const; + void getUTC(QDate &outDate, QTime &outTime) const; + static QDateTime addMSecs(const QDateTime &dt, qint64 msecs); + static void addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs); +}; + +#ifndef QT_BOOTSTRAPPED + +class Q_CORE_EXPORT QDateTimeParser +{ +public: + enum Context { + FromString, + DateTimeEdit + }; + QDateTimeParser(QVariant::Type t, Context ctx) + : currentSectionIndex(-1), display(0), cachedDay(-1), parserType(t), + fixday(false), spec(Qt::LocalTime), context(ctx) + { + defaultLocale = QLocale::system(); + first.type = FirstSection; + first.pos = -1; + first.count = -1; + last.type = FirstSection; + last.pos = -1; + last.count = -1; + none.type = NoSection; + none.pos = -1; + none.count = -1; + } + virtual ~QDateTimeParser() {} + enum { + Neither = -1, + AM = 0, + PM = 1, + PossibleAM = 2, + PossiblePM = 3, + PossibleBoth = 4 + }; + + enum { + NoSectionIndex = -1, + FirstSectionIndex = -2, + LastSectionIndex = -3, + CalendarPopupIndex = -4 + }; + + enum Section { + NoSection = 0x00000, + AmPmSection = 0x00001, + MSecSection = 0x00002, + SecondSection = 0x00004, + MinuteSection = 0x00008, + Hour12Section = 0x00010, + Hour24Section = 0x00020, + TimeSectionMask = (AmPmSection|MSecSection|SecondSection|MinuteSection|Hour12Section|Hour24Section), + Internal = 0x10000, + DaySection = 0x00100, + MonthSection = 0x00200, + YearSection = 0x00400, + YearSection2Digits = 0x00800, + DayOfWeekSection = 0x01000, + DateSectionMask = (DaySection|MonthSection|YearSection|YearSection2Digits|DayOfWeekSection), + FirstSection = 0x02000|Internal, + LastSection = 0x04000|Internal, + CalendarPopupSection = 0x08000|Internal + }; // duplicated from qdatetimeedit.h + Q_DECLARE_FLAGS(Sections, Section) + + struct SectionNode { + Section type; + mutable int pos; + int count; + }; + + enum State { // duplicated from QValidator + Invalid, + Intermediate, + Acceptable + }; + + struct StateNode { + StateNode() : state(Invalid), conflicts(false) {} + QString input; + State state; + bool conflicts; + QDateTime value; + }; + + enum AmPm { + AmText, + PmText + }; + + enum Case { + UpperCase, + LowerCase + }; + +#ifndef QT_NO_DATESTRING + StateNode parse(QString &input, int &cursorPosition, const QDateTime ¤tValue, bool fixup) const; +#endif + int sectionMaxSize(int index) const; + int sectionSize(int index) const; + int sectionMaxSize(Section s, int count) const; + int sectionPos(int index) const; + int sectionPos(const SectionNode &sn) const; + + const SectionNode §ionNode(int index) const; + Section sectionType(int index) const; + QString sectionText(int sectionIndex) const; + QString sectionText(const QString &text, int sectionIndex, int index) const; + int getDigit(const QDateTime &dt, int index) const; + bool setDigit(QDateTime &t, int index, int newval) const; + int parseSection(const QDateTime ¤tValue, int sectionIndex, QString &txt, int &cursorPosition, + int index, QDateTimeParser::State &state, int *used = 0) const; + int absoluteMax(int index, const QDateTime &value = QDateTime()) const; + int absoluteMin(int index) const; + bool parseFormat(const QString &format); +#ifndef QT_NO_DATESTRING + bool fromString(const QString &text, QDate *date, QTime *time) const; +#endif + +#ifndef QT_NO_TEXTDATE + int findMonth(const QString &str1, int monthstart, int sectionIndex, + QString *monthName = 0, int *used = 0) const; + int findDay(const QString &str1, int intDaystart, int sectionIndex, + QString *dayName = 0, int *used = 0) const; +#endif + int findAmPm(QString &str1, int index, int *used = 0) const; + int maxChange(int s) const; + bool potentialValue(const QString &str, int min, int max, int index, + const QDateTime ¤tValue, int insert) const; + bool skipToNextSection(int section, const QDateTime ¤t, const QString §ionText) const; + QString sectionName(int s) const; + QString stateName(int s) const; + + QString sectionFormat(int index) const; + QString sectionFormat(Section s, int count) const; + + enum FieldInfoFlag { + Numeric = 0x01, + FixedWidth = 0x02, + AllowPartial = 0x04, + Fraction = 0x08 + }; + Q_DECLARE_FLAGS(FieldInfo, FieldInfoFlag) + + FieldInfo fieldInfo(int index) const; + + virtual QDateTime getMinimum() const; + virtual QDateTime getMaximum() const; + virtual int cursorPosition() const { return -1; } + virtual QString displayText() const { return text; } + virtual QString getAmPmText(AmPm ap, Case cs) const; + virtual QLocale locale() const { return defaultLocale; } + + mutable int currentSectionIndex; + Sections display; + mutable int cachedDay; + mutable QString text; + QVector<SectionNode> sectionNodes; + SectionNode first, last, none, popup; + QStringList separators; + QString displayFormat; + QLocale defaultLocale; + QVariant::Type parserType; + + bool fixday; + + Qt::TimeSpec spec; // spec if used by QDateTimeEdit + Context context; +}; + +Q_CORE_EXPORT bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2); + +Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::Sections) +Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimeParser::FieldInfo) + + +#endif // QT_BOOTSTRAPPED + +QT_END_NAMESPACE + +#endif // QDATETIME_P_H diff --git a/src/corelib/tools/qdumper.cpp b/src/corelib/tools/qdumper.cpp new file mode 100644 index 0000000..c3b8524 --- /dev/null +++ b/src/corelib/tools/qdumper.cpp @@ -0,0 +1,1157 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qdatetime.h> +#include <qdebug.h> +#include <qdir.h> +#include <qfileinfo.h> +#include <qhash.h> +#include <qmap.h> +#include <qmetaobject.h> +#include <qobject.h> +#include <qstring.h> +#include <qvariant.h> +#include <qvector.h> + +#if !defined(Q_OS_WINCE) && !defined(QT_NO_DUMPER) + +#include <stdlib.h> +#include <stdio.h> + +#ifdef Q_OS_WIN +# include <windows.h> +#endif + +QT_BEGIN_NAMESPACE + +namespace { + +// This is used to abort evaluation of custom data dumpers in a "coordinated" +// way. Abortion will happen anyway when we try to access a non-initialized +// non-trivial object, so there is no way to prevent this from occuring at all +// conceptionally. Gdb will catch SIGSEGV and return to the calling frame. +// This is just fine provided we only _read_ memory in the custom handlers +// below. + +volatile int qProvokeSegFaultHelper; + +static void qCheckAccess(const void *d) +{ + // provoke segfault when address is not readable + qProvokeSegFaultHelper = *(char*)d; +} + +static void qCheckPointer(const void *d) +{ + if (!d) + return; + qProvokeSegFaultHelper = *(char*)d; +} + +static void qProvokeSegFault() +{ + // provoke segfault unconditionally + qCheckAccess(0); +} + +static char qDumpInBuffer[100]; +static char qDumpBuffer[1000]; +#ifdef Q_OS_WIN +static char qDumpBuffer2[sizeof(qDumpBuffer) + 100]; +#endif + +static char toHex(int n) +{ + return n < 10 ? '0' + n : 'a' - 10 + n; +} + + +struct QDumper +{ + explicit QDumper(); + ~QDumper(); + void flush(); + QDumper &operator<<(long c); + QDumper &operator<<(int i); + QDumper &operator<<(unsigned long c); + QDumper &operator<<(unsigned int i); + QDumper &operator<<(const void *p); + void put(char c); + void addCommaIfNeeded(); + void putEncoded(unsigned c); + QDumper &operator<<(const char *str); + QDumper &operator<<(const QString &str); + void disarm(); + + void beginHash(); // start of data hash output + void endHash(); // start of data hash output + + // the dumper arguments + int protocolVersion; // dumper protocol version + int token; // some token to show on success + const char *outertype; // object type + const char *iname; // object name used for display + const char *exp; // object expression + const char *innertype; // 'inner type' for class templates + const void *data; // pointer to raw data + bool dumpChildren; // do we want to see children? + + // handling of nested templates + void setupTemplateParameters(); + enum { maxTemplateParameters = 10 }; + const char *templateParameters[maxTemplateParameters + 1]; + int templateParametersCount; + + // internal state + bool success; // are we finished? + size_t pos; +}; + + +QDumper::QDumper() +{ + success = false; + pos = 0; +} + +QDumper::~QDumper() +{ + flush(); + put(0); // our end marker +#ifdef Q_OS_WIN + sprintf(qDumpBuffer2, "@@CDD/%d/done\n", token); + OutputDebugStringA(qDumpBuffer2); +#else + fprintf(stderr, "%d/done\n", token); +#endif + qDumpInBuffer[0] = 0; +} + +void QDumper::flush() +{ + qDumpBuffer[pos++] = 0; +#ifdef Q_OS_WIN + sprintf(qDumpBuffer2, "@@CDD#%d#%d,%s\n", token, int(pos - 1), qDumpBuffer); + OutputDebugStringA(qDumpBuffer2); +#else + fprintf(stderr, "%d#%d,%s\n", token, int(pos - 1), qDumpBuffer); +#endif + pos = 0; +} + +void QDumper::setupTemplateParameters() +{ + char *s = const_cast<char *>(innertype); + + templateParametersCount = 1; + templateParameters[0] = s; + for (int i = 1; i != maxTemplateParameters + 1; ++i) + templateParameters[i] = 0; + + while (*s) { + while (*s && *s != '@') + ++s; + if (*s) { + *s = '\0'; + ++s; + templateParameters[templateParametersCount++] = s; + } + } +} + +QDumper &QDumper::operator<<(unsigned long c) +{ + static char buf[100]; + sprintf(buf, "%lu", c); + return (*this) << buf; +} + +QDumper &QDumper::operator<<(unsigned int i) +{ + static char buf[100]; + sprintf(buf, "%u", i); + return (*this) << buf; +} + +QDumper &QDumper::operator<<(long c) +{ + static char buf[100]; + sprintf(buf, "%ld", c); + return (*this) << buf; +} + +QDumper &QDumper::operator<<(int i) +{ + static char buf[100]; + sprintf(buf, "%d", i); + return (*this) << buf; +} + +QDumper &QDumper::operator<<(const void *p) +{ + static char buf[100]; + sprintf(buf, "%p", p); + // we get a '0x' prefix only on some implementations. + // if it isn't there, write it out manually. + if (buf[1] != 'x') { + put('0'); + put('x'); + } + return (*this) << buf; +} + +void QDumper::put(char c) +{ + if (pos >= sizeof(qDumpBuffer) - 100) + flush(); + qDumpBuffer[pos++] = c; +} + +void QDumper::addCommaIfNeeded() +{ + if (pos == 0) + return; + if (qDumpBuffer[pos - 1] == '}' || qDumpBuffer[pos - 1] == '"') + put(','); +} + +void QDumper::putEncoded(unsigned c) +{ + if (c >= 32 && c <= 126 && c != '"' && c != '\\') { + put(c); + } else { + put('\\'); + put('u'); + put(toHex((c >> 12) & 0xf)); + put(toHex((c >> 8) & 0xf)); + put(toHex((c >> 4) & 0xf)); + put(toHex( c & 0xf)); + } +} + +QDumper &QDumper::operator<<(const char *str) +{ + while (*str) + put(*(str++)); + return *this; +} + +QDumper &QDumper::operator<<(const QString &str) +{ + int n = str.size(); + if (n < 0) { + qProvokeSegFault(); + } else { + //(*this) << "[" << n << "]"; + if (n > 1000000) + n = 1000000; + //put(' '); + put('\\'); + put('"'); + for (int i = 0; i != n; ++i) + putEncoded(str[i].unicode()); + put('\\'); + put('"'); + if (n < str.size()) + (*this) << "<incomplete string>"; + } + return *this; +} + +void QDumper::disarm() +{ + flush(); + success = true; +} + +void QDumper::beginHash() +{ + addCommaIfNeeded(); + put('{'); +} + +void QDumper::endHash() +{ + put('}'); +} + + +// +// Some helpers to keep the dumper code short +// + +// dump property=value pair +#undef P +#define P(dumper,name,value) \ + do { \ + dumper.addCommaIfNeeded(); \ + dumper << (name) << "=\"" << value << "\""; \ + } while (0) + +// simple string property +#undef S +#define S(dumper, name, value) \ + dumper.beginHash(); \ + P(dumper, "name", name); \ + P(dumper, "value", value); \ + P(dumper, "type", "QString"); \ + P(dumper, "numchild", "0"); \ + dumper.endHash(); + +// simple integer property +#undef I +#define I(dumper, name, value) \ + dumper.beginHash(); \ + P(dumper, "name", name); \ + P(dumper, "value", value); \ + P(dumper, "type", "int"); \ + P(dumper, "numchild", "0"); \ + dumper.endHash(); + +// simple boolean property +#undef BL +#define BL(dumper, name, value) \ + dumper.beginHash(); \ + P(dumper, "name", name); \ + P(dumper, "value", (value ? "true" : "false")); \ + P(dumper, "type", "bool"); \ + P(dumper, "numchild", "0"); \ + dumper.endHash(); + +#undef TT +#define TT(type, value) \ + "<tr><td>" << type << "</td><td> : </td><td>" << value << "</td></tr>" + +static void qDumpUnknown(QDumper &d) +{ + P(d, "iname", d.iname); + P(d, "addr", d.data); + P(d, "value", "<internal error>"); + P(d, "type", d.outertype); + P(d, "numchild", "0"); + d.disarm(); +} + +static void qDumpQPropertyList(QDumper &d) +{ + const QObject *ob = (const QObject *)d.data; + const QMetaObject *mo = ob->metaObject(); + P(d, "iname", d.iname); + P(d, "addr", "<synthetic>"); + P(d, "type", "QObject"); + P(d, "numchild", mo->propertyCount()); + if (d.dumpChildren) { + d << ",children=["; + for (int i = mo->propertyCount(); --i >= 0; ) { + const QMetaProperty & prop = mo->property(i); + d.beginHash(); + P(d, "name", prop.name()); + if (QLatin1String(prop.typeName()) == QLatin1String("QString")) { + P(d, "value", prop.read(ob).toString()); + P(d, "numchild", "0"); + } else if (QLatin1String(prop.typeName()) == QLatin1String("bool")) { + P(d, "value", (prop.read(ob).toBool() ? "true" : "false")); + P(d, "numchild", "0"); + } else if (QLatin1String(prop.typeName()) == QLatin1String("int")) { + P(d, "value", prop.read(ob).toInt()); + P(d, "numchild", "0"); + } else { + P(d, "exp", "((" << mo->className() << "*)" << ob + << ")->" << prop.name() << "()"); + } + P(d, "type", prop.typeName()); + P(d, "numchild", "1"); + d.endHash(); + } + d << "]"; + } + d.disarm(); +} + +static void qDumpQObject(QDumper &d) +{ + const QObject *ob = reinterpret_cast<const QObject *>(d.data); + P(d, "iname", d.iname); + P(d, "addr", d.data); + P(d, "value", (void*)d.data); + P(d, "type", "QObject"); + P(d, "numchild", 4); + if (d.dumpChildren) { + const QMetaObject *mo = ob->metaObject(); + const QObjectList &children = ob->children(); + d << ",children=["; + S(d, "objectName", ob->objectName()); + d.beginHash(); + P(d, "name", "properties"); + // FIXME: Note that when simply using '(QObject*)' + // in the cast below, Gdb/MI _sometimes misparses + // expressions further down in the tree. + P(d, "exp", "*(class QObject*)" << d.data); + P(d, "type", "QPropertyList"); + P(d, "value", "<" << mo->propertyCount() << " items>"); + P(d, "numchild", mo->propertyCount()); + d.endHash(); + d.beginHash(); + P(d, "name", "children"); + P(d, "exp", "((class QObject*)" << d.data << ")->children()"); + P(d, "type", "QList<QObject *>"); + P(d, "value", "<" << children.size() << " items>"); + P(d, "numchild", children.size()); + d.endHash(); + d.beginHash(); + P(d, "name", "parent"); + P(d, "exp", "((class QObject*)" << d.data << ")->parent()"); + P(d, "type", "QObject *"); + P(d, "numchild", (ob->parent() ? "1" : "0")); + d.endHash(); + d << "]"; + } + d.disarm(); +} + +static void qDumpQDir(QDumper &d) +{ + const QDir &dir = *reinterpret_cast<const QDir *>(d.data); + P(d, "iname", d.iname); + P(d, "addr", d.data); + P(d, "value", dir.path()); + P(d, "type", "QDir"); + P(d, "numchild", "3"); + if (d.dumpChildren) { + d << ",children=["; + S(d, "absolutePath", dir.absolutePath()); + S(d, "canonicalPath", dir.canonicalPath()); + d << "]"; + } + d.disarm(); +} + +static void qDumpQFileInfo(QDumper &d) +{ + const QFileInfo &info = *reinterpret_cast<const QFileInfo *>(d.data); + P(d, "iname", d.iname); + P(d, "addr", d.data); + P(d, "value", info.filePath()); + P(d, "type", "QDir"); + P(d, "numchild", "3"); + if (d.dumpChildren) { + d << ",children=["; + S(d, "absolutePath", info.absolutePath()); + S(d, "absoluteFilePath", info.absoluteFilePath()); + S(d, "canonicalPath", info.canonicalPath()); + S(d, "canonicalFilePath", info.canonicalFilePath()); + S(d, "completeBaseName", info.completeBaseName()); + S(d, "completeSuffix", info.completeSuffix()); + S(d, "baseName", info.baseName()); +#ifdef Q_OS_MACX + BL(d, "isBundle", info.isBundle()); + S(d, "bundleName", info.bundleName()); +#endif + S(d, "completeSuffix", info.completeSuffix()); + S(d, "fileName", info.fileName()); + S(d, "filePath", info.filePath()); + S(d, "group", info.group()); + S(d, "owner", info.owner()); + S(d, "path", info.path()); + + I(d, "groupid", (long)info.groupId()); + I(d, "ownerid", (long)info.ownerId()); + //QFile::Permissions permissions () const + I(d, "permissions", info.permissions()); + + //QDir absoluteDir () const + //QDir dir () const + + BL(d, "caching", info.caching()); + BL(d, "exists", info.exists()); + BL(d, "isAbsolute", info.isAbsolute()); + BL(d, "isDir", info.isDir()); + BL(d, "isExecutable", info.isExecutable()); + BL(d, "isFile", info.isFile()); + BL(d, "isHidden", info.isHidden()); + BL(d, "isReadable", info.isReadable()); + BL(d, "isRelative", info.isRelative()); + BL(d, "isRoot", info.isRoot()); + BL(d, "isSymLink", info.isSymLink()); + BL(d, "isWritable", info.isWritable()); + +#ifndef QT_NO_DATESTRING + d.beginHash(); + P(d, "name", "created"); + P(d, "value", info.created().toString()); + P(d, "exp", "((QFileInfo*)" << d.data << ")->created()"); + P(d, "type", "QDateTime"); + P(d, "numchild", "1"); + d.endHash(); + + d.beginHash(); + P(d, "name", "lastModified"); + P(d, "value", info.lastModified().toString()); + P(d, "exp", "((QFileInfo*)" << d.data << ")->lastModified()"); + P(d, "type", "QDateTime"); + P(d, "numchild", "1"); + d.endHash(); + + d.beginHash(); + P(d, "name", "lastRead"); + P(d, "value", info.lastRead().toString()); + P(d, "exp", "((QFileInfo*)" << d.data << ")->lastRead()"); + P(d, "type", "QDateTime"); + P(d, "numchild", "1"); + d.endHash(); +#endif + + d << "]"; + } + d.disarm(); +} + +static void qDumpQDateTime(QDumper &d) +{ +#ifdef QT_NO_DATESTRING + qDumpUnknown(d); +#else + const QDateTime &date = *reinterpret_cast<const QDateTime *>(d.data); + P(d, "iname", d.iname); + P(d, "addr", d.data); + P(d, "value", date.toString()); + P(d, "type", "QDateTime"); + P(d, "numchild", "3"); + if (d.dumpChildren) { + d << ",children=["; + BL(d, "isNull", date.isNull()); + I(d, "toTime_t", (long)date.toTime_t()); + S(d, "toString", date.toString()); + S(d, "toString_(ISO)", date.toString(Qt::ISODate)); + S(d, "toString_(SystemLocale)", date.toString(Qt::SystemLocaleDate)); + S(d, "toString_(Locale)", date.toString(Qt::LocaleDate)); + S(d, "toString", date.toString()); + + d.beginHash(); + P(d, "name", "toUTC"); + P(d, "exp", "((QDateTime*)" << d.data << ")->toTimeSpec(Qt::UTC)"); + P(d, "type", "QDateTime"); + P(d, "numchild", "1"); + d.endHash(); + + d.beginHash(); + P(d, "name", "toLocalTime"); + P(d, "exp", "((QDateTime*)" << d.data << ")->toTimeSpec(Qt::LocalTime)"); + P(d, "type", "QDateTime"); + P(d, "numchild", "1"); + d.endHash(); + + d << "]"; + } + d.disarm(); +#endif // ifdef QT_NO_DATESTRING +} + +static void qDumpQString(QDumper &d) +{ + const QString &str = *reinterpret_cast<const QString *>(d.data); + + // Try to provoke segfaults early to prevent the frontend + // from asking for unavailable child details + if (!str.isEmpty()) { + volatile ushort dummy = 0; + dummy += str.at(0).unicode(); + dummy += str.at(str.size() - 1).unicode(); + } + + P(d, "iname", d.iname); + P(d, "addr", d.data); + P(d, "value", str); + P(d, "type", "QString"); + P(d, "numchild", "0"); + d.disarm(); +} + +static void qDumpQStringList(QDumper &d) +{ + const QStringList &list = *reinterpret_cast<const QStringList *>(d.data); + int n = list.size(); + if (n < 0) + qProvokeSegFault(); + if (n > 0) { + qCheckAccess(&list.front()); + qCheckAccess(&list.back()); + } + + P(d, "iname", d.iname); + P(d, "addr", d.data); + P(d, "value", "<" << n << " items>"); + P(d, "valuedisabled", "true"); + P(d, "numchild", n); + if (d.dumpChildren) { + if (n > 100) + n = 100; + d << ",children=["; + for (int i = 0; i != n; ++i) { + S(d, "[" << i << "]", list[i]); + } + if (n < list.size()) { + d.beginHash(); + P(d, "value", "<incomplete>"); + P(d, "type", " "); + P(d, "numchild", "0"); + d.endHash(); + } + d << "]"; + } + d.disarm(); +} + +static void qDumpQVariantHelper(const void *data, QString *value, + QString *exp, int *numchild) +{ + const QVariant &v = *reinterpret_cast<const QVariant *>(data); + switch (v.type()) { + case QVariant::Invalid: + *value = QLatin1String("<invalid>"); + *numchild = 0; + break; + case QVariant::String: + *value = QLatin1Char('"') + v.toString() + QLatin1Char('"'); + *numchild = 0; + break; + case QVariant::StringList: + *exp = QString(QLatin1String("((QVariant*)%1)->d.data.c")) + .arg((qulonglong)data); + *numchild = v.toStringList().size(); + break; + case QVariant::Int: + *value = QString::number(v.toInt()); + *numchild= 0; + break; + case QVariant::Double: + *value = QString::number(v.toDouble()); + *numchild = 0; + break; + default: + // FIXME + //*exp = QString("qVariantValue<" << v.typeName() << ">" + // << "(*(QVariant*)" << data << ")"); + break; + } +} + +static void qDumpQVariant(QDumper &d) +{ + const QVariant &v = *reinterpret_cast<const QVariant *>(d.data); + QString value; + QString exp; + int numchild = 0; + qDumpQVariantHelper(d.data, &value, &exp, &numchild); + P(d, "iname", d.iname); + P(d, "addr", d.data); + P(d, "value", "(" << v.typeName() << ") " << qPrintable(value)); + P(d, "type", "QVariant"); + P(d, "numchild", 1); + if (d.dumpChildren) { + d << ",children=["; + d.beginHash(); + P(d, "name", "value"); + if (!exp.isEmpty()) + P(d, "exp", qPrintable(exp)); + if (!value.isEmpty()) + P(d, "value", qPrintable(value)); + P(d, "type", v.typeName()); + P(d, "numchild", numchild); + d.endHash(); + d << "]"; + } + d.disarm(); +} + +static void qDumpQList(QDumper &d) +{ + // This uses the knowledge that QList<T> has only a single member + // of type union { QListData p; QListData::Data *d; }; + const QListData &ldata = *reinterpret_cast<const QListData*>(d.data); + const QListData::Data *pdata = *reinterpret_cast<const QListData::Data* const*>(d.data); + int nn = ldata.size(); + if (nn < 0) + qProvokeSegFault(); + if (nn > 0) { + qCheckAccess(ldata.d->array); + //qCheckAccess(ldata.d->array[0]); + //qCheckAccess(ldata.d->array[nn - 1]); + } + + int n = nn; + P(d, "iname", d.iname); + P(d, "value", "<" << n << " items>"); + P(d, "valuedisabled", "true"); + P(d, "numchild", n); + if (d.dumpChildren) { + if (n > 100) + n = 100; + d << ",children=["; + for (int i = 0; i != n; ++i) { + d.beginHash(); + P(d, "name", "[" << i << "]"); + // The exact condition here is: + // QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic + // but this data is not available in the compiled binary. + // So as first approximation only do the 'isLarge' check: + void *p = &(ldata.d->array[i + pdata->begin]); + unsigned long voidpsize = sizeof(void*); + P(d, "exp", "(sizeof(" << d.innertype << ")>" << voidpsize << + "?(**(" << d.innertype << "**)(" << p << "))" + ":(*(" << d.innertype << "*)(" << p << ")))"); + P(d, "type", d.innertype); + d.endHash(); + } + if (n < nn) { + d << ",{"; + P(d, "value", "<incomplete>"); + d.endHash(); + } + d << "]"; + } + d.disarm(); +} + +static void qDumpQVector(QDumper &d) +{ + // Use 'int' as representative value. No way (and no need) + // to deduce proper type here. + const QVector<int> &vec = *reinterpret_cast<const QVector<int> *>(d.data); + const int nn = vec.size(); + + // Try to provoke segfaults early to prevent the frontend + // from asking for unavailable child details + if (nn < 0) + qProvokeSegFault(); + if (nn > 0) { + qCheckAccess(&vec.front()); + qCheckAccess(&vec.back()); + } + + //int innersize = 0; + //scanf(qDumpInBuffer, "%d", &innersize); + + int n = nn; + P(d, "iname", d.iname); + P(d, "addr", d.data); + P(d, "value", "<" << n << " items>"); + P(d, "valuedisabled", "true"); + P(d, "numchild", n); + if (d.dumpChildren) { + if (n > 100) + n = 100; + d << ",children=["; + for (int i = 0; i != n; ++i) { + if (i) + d << ","; + d.beginHash(); + P(d, "name", "[" << i << "]"); + P(d, "exp", "(" << d.exp << ".d->array[" << i << "])"); + P(d, "type", d.innertype); + d.endHash(); + } + if (n < nn) { + d << ",{"; + P(d, "value", "<incomplete>"); + d.endHash(); + } + d << "]"; + } + d.disarm(); +} + +static void qDumpQHashNode(QDumper &d) +{ + struct NodeOS { void *next; uint k; uint v; } nodeOS; // int-key optimization, small value + struct NodeOL { void *next; uint k; void *v; } nodeOL; // int-key optimiatzion, large value + struct NodeNS { void *next; uint h; uint k; uint v; } nodeNS; // no optimization, small value + struct NodeNL { void *next; uint h; uint k; void *v; } nodeNL; // no optimization, large value + struct NodeL { void *next; uint h; void *k; void *v; } nodeL; // complex key + + // offsetof(...,...) not yet in Standard C++ + const ulong nodeOSk ( (char *)&nodeOS.k - (char *)&nodeOS ); + const ulong nodeOSv ( (char *)&nodeOS.v - (char *)&nodeOS ); + const ulong nodeOLk ( (char *)&nodeOL.k - (char *)&nodeOL ); + const ulong nodeOLv ( (char *)&nodeOL.v - (char *)&nodeOL ); + const ulong nodeNSk ( (char *)&nodeNS.k - (char *)&nodeNS ); + const ulong nodeNSv ( (char *)&nodeNS.v - (char *)&nodeNS ); + const ulong nodeNLk ( (char *)&nodeNL.k - (char *)&nodeNL ); + const ulong nodeNLv ( (char *)&nodeNL.v - (char *)&nodeNL ); + const ulong nodeLk ( (char *)&nodeL.k - (char *)&nodeL ); + const ulong nodeLv ( (char *)&nodeL.v - (char *)&nodeL ); + + const QHashData *h = reinterpret_cast<const QHashData *>(d.data); + const char *keyType = d.templateParameters[0]; + const char *valueType = d.templateParameters[1]; + + P(d, "iname", d.iname); + P(d, "addr", d.data); + P(d, "value", ""); + P(d, "numchild", 2); + if (d.dumpChildren) { + // there is a hash specialization in cast the key are integers or shorts + bool isOptimizedIntKey = qstrcmp(keyType, "int") == 0 +#if defined(Q_BYTE_ORDER) && Q_BYTE_ORDER == Q_LITTLE_ENDIAN + || qstrcmp(keyType, "short") == 0 + || qstrcmp(keyType, "ushort") == 0 +#endif + || qstrcmp(keyType, "uint") == 0; + + d << ",children=["; + d.beginHash(); + P(d, "name", "key"); + P(d, "type", keyType); + unsigned long intsize = sizeof(int); + if (isOptimizedIntKey) { + P(d, "exp", "*(" << keyType << "*)" + "(((sizeof(" << valueType << ")>" << intsize << ")?" + << nodeOLk << ":" << nodeOSk << + ")+(char*)" << h << ")"); + } else { + P(d, "exp", "*(" << keyType << "*)" + "(((sizeof(" << keyType << ")>" << intsize << ")?" + << nodeLk << ":" + "((sizeof(" << valueType << ")>" << intsize << ")?" + << nodeNLk << ":" << nodeNSk << "))+(char*)" << h << ")"); + } + d.endHash(); + d.beginHash(); + P(d, "name", "value"); + P(d, "type", valueType); + if (isOptimizedIntKey) { + P(d, "exp", "*(" << valueType << "*)" + "(((sizeof(" << valueType << ")>" << intsize << ")?" + << nodeOLv << ":" << nodeOSv << ")+(char*)" << h << ")"); + } else { + P(d, "exp", "*(" << valueType << "*)" + "(((sizeof(" << keyType << ")>" << intsize << ")?" << nodeLv << ":" + "((sizeof(" << valueType << ")>" << intsize << ")?" + << nodeNLv << ":" << nodeNSv << "))+(char*)" << h << ")"); + } + d.endHash(); + d << "]"; + } + d.disarm(); +} + +static void qDumpQHash(QDumper &d) +{ + QHashData *h = *reinterpret_cast<QHashData *const*>(d.data); + const char *keyType = d.templateParameters[0]; + const char *valueType = d.templateParameters[1]; + + qCheckPointer(h->fakeNext); + qCheckPointer(h->buckets); + + int n = h->size; + + if (n < 0) + qProvokeSegFault(); + if (n > 0) { + qCheckPointer(h->fakeNext); + qCheckPointer(*h->buckets); + } + + P(d, "iname", d.iname); + P(d, "addr", d.data); + P(d, "value", "<" << n << " items>"); + P(d, "numchild", n); + if (d.dumpChildren) { + if (n > 100) + n = 100; + d << ",children=["; + + QHashData::Node *node = h->firstNode(); + QHashData::Node *end = reinterpret_cast<QHashData::Node *>(h); + int i = 0; + + while (node != end) { + d.beginHash(); + P(d, "name", "[" << i << "]"); + P(d, "type", "QHashNode<" << keyType << "," << valueType << " >"); + P(d, "exp", "*(QHashNode<" << keyType << "," << valueType << " >*)" << node); + d.endHash(); + + ++i; + node = QHashData::nextNode(node); + } + d << "]"; + } + d.disarm(); +} + +static void qDumpQMapNode(QDumper &d) +{ + const QMapData *h = reinterpret_cast<const QMapData *>(d.data); + const char *keyType = d.templateParameters[0]; + const char *valueType = d.templateParameters[1]; + + qCheckAccess(h->backward); + qCheckAccess(h->forward[0]); + + P(d, "iname", d.iname); + P(d, "addr", d.data); + P(d, "value", ""); + P(d, "numchild", 2); + if (d.dumpChildren) { + unsigned long voidpsize = sizeof(void*); + d << ",children=["; + d.beginHash(); + P(d, "name", "key"); + P(d, "type", keyType); + P(d, "exp", "*(" << keyType << "*)" + << "(" + << 2 * voidpsize + << "-sizeof('QMap<" << keyType << "," << valueType << ">::Node')" + << "+(char*)" << h + << ")"); + d.endHash(); + d.beginHash(); + P(d, "name", "value"); + P(d, "type", valueType); + P(d, "exp", "*(" << valueType << "*)" + << "(" + << "(size_t)&(('QMap<" << keyType << "," << valueType << ">::Node'*)0)->value" + << "+" << 2 * voidpsize + << "-sizeof('QMap<" << keyType << "," << valueType << ">::Node')" + << "+(char*)" << h + << ")"); + d.endHash(); + d << "]"; + } + + d.disarm(); +} + +static void qDumpQMap(QDumper &d) +{ + QMapData *h = *reinterpret_cast<QMapData *const*>(d.data); + const char *keyType = d.templateParameters[0]; + const char *valueType = d.templateParameters[1]; + + int n = h->size; + + if (n < 0) + qProvokeSegFault(); + if (n > 0) { + qCheckAccess(h->backward); + qCheckAccess(h->forward[0]); + qCheckPointer(h->backward->backward); + qCheckPointer(h->forward[0]->backward); + } + + P(d, "iname", d.iname); + P(d, "addr", d.data); + P(d, "value", "<" << n << " items>"); + P(d, "numchild", n); + if (d.dumpChildren) { + if (n > 100) + n = 100; + d << ",children=["; + + QMapData::Node *node = reinterpret_cast<QMapData::Node *>(h->forward[0]); + QMapData::Node *end = reinterpret_cast<QMapData::Node *>(h); + int i = 0; + + while (node != end) { + d.beginHash(); + P(d, "name", "[" << i << "]"); + P(d, "type", "QMap<" << keyType << "," << valueType << ">::Node"); + P(d, "exp", "*('QMap<" << keyType << "," << valueType << ">::Node'*)" << node); + d.endHash(); + + ++i; + node = node->forward[0]; + } + d << "]"; + } + + d.disarm(); +} + +static void qDumpQSet(QDumper &d) +{ + // This uses the knowledge that QHash<T> has only a single member + // of union { QHashData *d; QHashNode<Key, T> *e; }; + QHashData *hd = *(QHashData**)d.data; + QHashData::Node *node = hd->firstNode(); + + int n = hd->size; + if (n < 0) + qProvokeSegFault(); + if (n > 0) { + qCheckAccess(node); + qCheckPointer(node->next); + } + + P(d, "iname", d.iname); + P(d, "addr", d.data); + P(d, "value", "<" << n << " items>"); + P(d, "valuedisabled", "true"); + P(d, "numchild", 2 * n); + if (d.dumpChildren) { + if (n > 100) + n = 100; + d << ",children=["; + int i = 0; + for (int bucket = 0; bucket != hd->numBuckets; ++bucket) { + for (node = hd->buckets[bucket]; node->next; node = node->next) { + d.beginHash(); + P(d, "name", "[" << i << "]"); + P(d, "type", d.innertype); + P(d, "exp", "(('QHashNode<" << d.innertype + << ",QHashDummyValue>'*)" + << static_cast<const void*>(node) << ")->key" + ); + d.endHash(); + ++i; + } + } + d << "]"; + } + d.disarm(); +} + +static void handleProtocolVersion2(QDumper & d) +{ + if (!d.outertype[0]) { + qDumpUnknown(d); + return; + } + + d.setupTemplateParameters(); + // d.outertype[0] is usally 'Q', so don't use it + switch (d.outertype[1]) { + case 'D': + if (qstrcmp(d.outertype, "QDateTime") == 0) + qDumpQDateTime(d); + else if (qstrcmp(d.outertype, "QDir") == 0) + qDumpQDir(d); + break; + case 'F': + if (qstrcmp(d.outertype, "QFileInfo") == 0) + qDumpQFileInfo(d); + break; + case 'H': + if (qstrcmp(d.outertype, "QHash") == 0) + qDumpQHash(d); + else if (qstrcmp(d.outertype, "QHashNode") == 0) + qDumpQHashNode(d); + break; + case 'L': + if (qstrcmp(d.outertype, "QList") == 0) + qDumpQList(d); + break; + case 'M': + if (qstrcmp(d.outertype, "QMap") == 0) + qDumpQMap(d); + else if (qstrcmp(d.outertype, "QMap::Node") == 0) + qDumpQMapNode(d); + break; + case 'O': + if (qstrcmp(d.outertype, "QObject") == 0) + qDumpQObject(d); + break; + case 'P': + if (qstrcmp(d.outertype, "QPropertyList") == 0) + qDumpQPropertyList(d); + break; + case 'S': + if (qstrcmp(d.outertype, "QSet") == 0) + qDumpQSet(d); + else if (qstrcmp(d.outertype, "QString") == 0) + qDumpQString(d); + else if (qstrcmp(d.outertype, "QStringList") == 0) + qDumpQStringList(d); + break; + case 'V': + if (qstrcmp(d.outertype, "QVariant") == 0) + qDumpQVariant(d); + else if (qstrcmp(d.outertype, "QVector") == 0) + qDumpQVector(d); + break; + } + + if (!d.success) + qDumpUnknown(d); +} + +} // anonymous namespace + + +extern "C" Q_CORE_EXPORT void qDumpObjectData( + int protocolVersion, + int token, + const char *outertype, + const char *iname, + const char *exp, + const char *innertype, + const void *data, + bool dumpChildren) +{ + if (protocolVersion == 1) { + // used to test whether error output gets through + //fprintf(stderr, "using stderr, qDebug follows: %d\n", token); + //qDebug() << "using qDebug, stderr already used: " << token; + } + + else if (protocolVersion == 2) { + QDumper d; + d.protocolVersion = protocolVersion; + d.token = token; + d.outertype = outertype ? outertype : ""; + d.iname = iname ? iname : ""; + d.exp = exp ? exp : ""; + d.innertype = innertype ? innertype : ""; + d.data = data ? data : ""; + d.dumpChildren = dumpChildren; + handleProtocolVersion2(d); + } + + else { + qDebug() << "Unsupported protocol version" << protocolVersion; + } +} + +QT_END_NAMESPACE + +#endif // !Q_OS_WINCE && !QT_NO_QDUMPER diff --git a/src/corelib/tools/qharfbuzz.cpp b/src/corelib/tools/qharfbuzz.cpp new file mode 100644 index 0000000..1940209 --- /dev/null +++ b/src/corelib/tools/qharfbuzz.cpp @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qharfbuzz_p.h" + +#include "qunicodetables_p.h" +#include "qlibrary.h" +#include "qtextcodec.h" + +QT_USE_NAMESPACE + +extern "C" { + +HB_GraphemeClass HB_GetGraphemeClass(HB_UChar32 ch) +{ + const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ch); + return (HB_GraphemeClass) prop->graphemeBreak; +} + +HB_WordClass HB_GetWordClass(HB_UChar32 ch) +{ + const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ch); + return (HB_WordClass) prop->wordBreak; +} + +HB_SentenceClass HB_GetSentenceClass(HB_UChar32 ch) +{ + const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ch); + return (HB_SentenceClass) prop->sentenceBreak; +} + +HB_LineBreakClass HB_GetLineBreakClass(HB_UChar32 ch) +{ + return (HB_LineBreakClass)QUnicodeTables::lineBreakClass(ch); +} + + +void HB_GetGraphemeAndLineBreakClass(HB_UChar32 ch, HB_GraphemeClass *grapheme, HB_LineBreakClass *lineBreak) +{ + const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ch); + *grapheme = (HB_GraphemeClass) prop->graphemeBreak; + *lineBreak = (HB_LineBreakClass) prop->line_break_class; +} + +void HB_GetUnicodeCharProperties(HB_UChar32 ch, HB_CharCategory *category, int *combiningClass) +{ + const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ch); + *category = (HB_CharCategory)prop->category; + *combiningClass = prop->combiningClass; +} + +HB_CharCategory HB_GetUnicodeCharCategory(HB_UChar32 ch) +{ + return (HB_CharCategory)QChar::category(ch); +} + +int HB_GetUnicodeCharCombiningClass(HB_UChar32 ch) +{ + return QChar::combiningClass(ch); +} + +HB_UChar16 HB_GetMirroredChar(HB_UChar16 ch) +{ + return QChar::mirroredChar(ch); +} + +void *HB_Library_Resolve(const char *library, const char *symbol) +{ +#ifdef QT_NO_LIBRARY + return 0; +#else + return QLibrary::resolve(QLatin1String(library), symbol); +#endif +} + +void *HB_TextCodecForMib(int mib) +{ +#ifndef QT_NO_TEXTCODEC + return QTextCodec::codecForMib(mib); +#else + return 0; +#endif +} + +char *HB_TextCodec_ConvertFromUnicode(void *codec, const HB_UChar16 *unicode, hb_uint32 length, hb_uint32 *outputLength) +{ +#ifndef QT_NO_TEXTCODEC + QByteArray data = reinterpret_cast<QTextCodec *>(codec)->fromUnicode((const QChar *)unicode, length); + // ### suboptimal + char *output = (char *)malloc(data.length() + 1); + memcpy(output, data.constData(), data.length() + 1); + if (outputLength) + *outputLength = data.length(); + return output; +#else + return 0; +#endif +} + +void HB_TextCodec_FreeResult(char *string) +{ + free(string); +} + +} // extern "C" + +QT_BEGIN_NAMESPACE + +HB_Bool qShapeItem(HB_ShaperItem *item) +{ + return HB_ShapeItem(item); +} + +HB_Face qHBNewFace(void *font, HB_GetFontTableFunc tableFunc) +{ + return HB_NewFace(font, tableFunc); +} + +void qHBFreeFace(HB_Face face) +{ + HB_FreeFace(face); +} + +void qGetCharAttributes(const HB_UChar16 *string, hb_uint32 stringLength, + const HB_ScriptItem *items, hb_uint32 numItems, + HB_CharAttributes *attributes) +{ + HB_GetCharAttributes(string, stringLength, items, numItems, attributes); +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qharfbuzz_p.h b/src/corelib/tools/qharfbuzz_p.h new file mode 100644 index 0000000..eaaf0d7 --- /dev/null +++ b/src/corelib/tools/qharfbuzz_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QHARFBUZZ_P_H +#define QHARFBUZZ_P_H + +#include <harfbuzz-shaper.h> +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +// temporary forward until all the textengine code has been moved to QtCore +Q_CORE_EXPORT void qGetCharAttributes(const HB_UChar16 *string, hb_uint32 stringLength, + const HB_ScriptItem *items, hb_uint32 numItems, + HB_CharAttributes *attributes); + +Q_CORE_EXPORT HB_Bool qShapeItem(HB_ShaperItem *item); + +// ### temporary +Q_CORE_EXPORT HB_Face qHBNewFace(void *font, HB_GetFontTableFunc tableFunc); +Q_CORE_EXPORT void qHBFreeFace(HB_Face); + +Q_DECLARE_TYPEINFO(HB_GlyphAttributes, Q_PRIMITIVE_TYPE); +Q_DECLARE_TYPEINFO(HB_FixedPoint, Q_PRIMITIVE_TYPE); + +QT_END_NAMESPACE + +#endif diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp new file mode 100644 index 0000000..540f43d --- /dev/null +++ b/src/corelib/tools/qhash.cpp @@ -0,0 +1,1843 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qhash.h" + +#ifdef truncate +#undef truncate +#endif + +#include <qbitarray.h> +#include <qstring.h> +#include <stdlib.h> +#ifdef QT_QHASH_DEBUG +#include <qstring.h> +#endif + +QT_BEGIN_NAMESPACE + +/* + These functions are based on Peter J. Weinberger's hash function + (from the Dragon Book). The constant 24 in the original function + was replaced with 23 to produce fewer collisions on input such as + "a", "aa", "aaa", "aaaa", ... +*/ + +static uint hash(const uchar *p, int n) +{ + uint h = 0; + uint g; + + while (n--) { + h = (h << 4) + *p++; + if ((g = (h & 0xf0000000)) != 0) + h ^= g >> 23; + h &= ~g; + } + return h; +} + +static uint hash(const QChar *p, int n) +{ + uint h = 0; + uint g; + + while (n--) { + h = (h << 4) + (*p++).unicode(); + if ((g = (h & 0xf0000000)) != 0) + h ^= g >> 23; + h &= ~g; + } + return h; +} + +uint qHash(const QByteArray &key) +{ + return hash(reinterpret_cast<const uchar *>(key.data()), key.size()); +} + +uint qHash(const QString &key) +{ + return hash(key.unicode(), key.size()); +} + +uint qHash(const QStringRef &key) +{ + return hash(key.unicode(), key.size()); +} + +uint qHash(const QBitArray &bitArray) +{ + int m = bitArray.d.size() - 1; + uint result = hash(reinterpret_cast<const uchar *>(bitArray.d.data()), qMax(0, m)); + + // deal with the last 0 to 7 bits manually, because we can't trust that + // the padding is initialized to 0 in bitArray.d + int n = bitArray.size(); + if (n & 0x7) + result = ((result << 4) + bitArray.d.at(m)) & ((1 << n) - 1); + return result; +} + +/* + The prime_deltas array is a table of selected prime values, even + though it doesn't look like one. The primes we are using are 1, + 2, 5, 11, 17, 37, 67, 131, 257, ..., i.e. primes in the immediate + surrounding of a power of two. + + The primeForNumBits() function returns the prime associated to a + power of two. For example, primeForNumBits(8) returns 257. +*/ + +static const uchar prime_deltas[] = { + 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3, + 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0 +}; + +static inline int primeForNumBits(int numBits) +{ + return (1 << numBits) + prime_deltas[numBits]; +} + +/* + Returns the smallest integer n such that + primeForNumBits(n) >= hint. +*/ +static int countBits(int hint) +{ + int numBits = 0; + int bits = hint; + + while (bits > 1) { + bits >>= 1; + numBits++; + } + + if (numBits >= (int)sizeof(prime_deltas)) { + numBits = sizeof(prime_deltas) - 1; + } else if (primeForNumBits(numBits) < hint) { + ++numBits; + } + return numBits; +} + +/* + A QHash has initially around pow(2, MinNumBits) buckets. For + example, if MinNumBits is 4, it has 17 buckets. +*/ +const int MinNumBits = 4; + +QHashData QHashData::shared_null = { + 0, 0, Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, MinNumBits, 0, 0, true +}; + +void *QHashData::allocateNode() +{ + return qMalloc(nodeSize); +} + +void QHashData::freeNode(void *node) +{ + qFree(node); +} + +QHashData *QHashData::detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize) +{ + union { + QHashData *d; + Node *e; + }; + d = new QHashData; + d->fakeNext = 0; + d->buckets = 0; + d->ref = 1; + d->size = size; + d->nodeSize = nodeSize; + d->userNumBits = userNumBits; + d->numBits = numBits; + d->numBuckets = numBuckets; + d->sharable = true; + + if (numBuckets) { + d->buckets = new Node *[numBuckets]; + Node *this_e = reinterpret_cast<Node *>(this); + for (int i = 0; i < numBuckets; ++i) { + Node **nextNode = &d->buckets[i]; + Node *oldNode = buckets[i]; + while (oldNode != this_e) { + Node *dup = static_cast<Node *>(allocateNode()); + node_duplicate(oldNode, dup); + dup->h = oldNode->h; + *nextNode = dup; + nextNode = &dup->next; + oldNode = oldNode->next; + } + *nextNode = e; + } + } + return d; +} + +QHashData::Node *QHashData::nextNode(Node *node) +{ + union { + Node *next; + Node *e; + QHashData *d; + }; + next = node->next; + Q_ASSERT_X(next, "QHash", "Iterating beyond end()"); + if (next->next) + return next; + + int start = (node->h % d->numBuckets) + 1; + Node **bucket = d->buckets + start; + int n = d->numBuckets - start; + while (n--) { + if (*bucket != e) + return *bucket; + ++bucket; + } + return e; +} + +QHashData::Node *QHashData::previousNode(Node *node) +{ + union { + Node *e; + QHashData *d; + }; + + e = node; + while (e->next) + e = e->next; + + int start; + if (node == e) + start = d->numBuckets - 1; + else + start = node->h % d->numBuckets; + + Node *sentinel = node; + Node **bucket = d->buckets + start; + while (start >= 0) { + if (*bucket != sentinel) { + Node *prev = *bucket; + while (prev->next != sentinel) + prev = prev->next; + return prev; + } + + sentinel = e; + --bucket; + --start; + } + Q_ASSERT_X(start >= 0, "QHash", "Iterating backward beyond begin()"); + return e; +} + +/* + If hint is negative, -hint gives the approximate number of + buckets that should be used for the hash table. If hint is + nonnegative, (1 << hint) gives the approximate number + of buckets that should be used. +*/ +void QHashData::rehash(int hint) +{ + if (hint < 0) { + hint = countBits(-hint); + if (hint < MinNumBits) + hint = MinNumBits; + userNumBits = hint; + while (primeForNumBits(hint) < (size >> 1)) + ++hint; + } else if (hint < MinNumBits) { + hint = MinNumBits; + } + + if (numBits != hint) { + Node *e = reinterpret_cast<Node *>(this); + Node **oldBuckets = buckets; + int oldNumBuckets = numBuckets; + + numBits = hint; + numBuckets = primeForNumBits(hint); + buckets = new Node *[numBuckets]; + for (int i = 0; i < numBuckets; ++i) + buckets[i] = e; + + for (int i = 0; i < oldNumBuckets; ++i) { + Node *firstNode = oldBuckets[i]; + while (firstNode != e) { + uint h = firstNode->h; + Node *lastNode = firstNode; + while (lastNode->next != e && lastNode->next->h == h) + lastNode = lastNode->next; + + Node *afterLastNode = lastNode->next; + Node **beforeFirstNode = &buckets[h % numBuckets]; + while (*beforeFirstNode != e) + beforeFirstNode = &(*beforeFirstNode)->next; + lastNode->next = *beforeFirstNode; + *beforeFirstNode = firstNode; + firstNode = afterLastNode; + } + } + delete [] oldBuckets; + } +} + +void QHashData::destroyAndFree() +{ + delete [] buckets; + delete this; +} + +#ifdef QT_QHASH_DEBUG + +void QHashData::dump() +{ + qDebug("Hash data (ref = %d, size = %d, nodeSize = %d, userNumBits = %d, numBits = %d, numBuckets = %d)", + int(ref), size, nodeSize, userNumBits, numBits, + numBuckets); + qDebug(" %p (fakeNode = %p)", this, fakeNext); + for (int i = 0; i < numBuckets; ++i) { + QString line; + Node *n = buckets[i]; + if (n != reinterpret_cast<Node *>(this)) { + line.sprintf("%d:", i); + while (n != reinterpret_cast<Node *>(this)) { + line += QString().sprintf(" -> [%p]", n); + if (!n) { + line += " (CORRUPT)"; + break; + } + n = n->next; + } + qDebug(qPrintable(line)); + } + } +} + +void QHashData::checkSanity() +{ + if (fakeNext) + qFatal("Fake next isn't 0"); + + for (int i = 0; i < numBuckets; ++i) { + Node *n = buckets[i]; + Node *p = n; + if (!n) + qFatal("%d: Bucket entry is 0", i); + if (n != reinterpret_cast<Node *>(this)) { + while (n != reinterpret_cast<Node *>(this)) { + if (!n->next) + qFatal("%d: Next of %p is 0, should be %p", i, n, this); + n = n->next; + } + } + } +} +#endif + +/*! + \class QHash + \brief The QHash class is a template class that provides a hash-table-based dictionary. + + \ingroup tools + \ingroup shared + \mainclass + \reentrant + + QHash\<Key, T\> is one of Qt's generic \l{container classes}. It + stores (key, value) pairs and provides very fast lookup of the + value associated with a key. + + QHash provides very similar functionality to QMap. The + differences are: + + \list + \i QHash provides faster lookups than QMap. (See \l{Algorithmic + Complexity} for details.) + \i When iterating over a QMap, the items are always sorted by + key. With QHash, the items are arbitrarily ordered. + \i The key type of a QMap must provide operator<(). The key + type of a QHash must provide operator==() and a global + \l{qHash()}{qHash}(Key) function. + \endlist + + Here's an example QHash with QString keys and \c int values: + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 0 + + To insert a (key, value) pair into the hash, you can use operator[](): + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 1 + + This inserts the following three (key, value) pairs into the + QHash: ("one", 1), ("three", 3), and ("seven", 7). Another way to + insert items into the hash is to use insert(): + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 2 + + To look up a value, use operator[]() or value(): + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 3 + + If there is no item with the specified key in the hash, these + functions return a \l{default-constructed value}. + + If you want to check whether the hash contains a particular key, + use contains(): + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 4 + + There is also a value() overload that uses its second argument as + a default value if there is no item with the specified key: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 5 + + In general, we recommend that you use contains() and value() + rather than operator[]() for looking up a key in a hash. The + reason is that operator[]() silently inserts an item into the + hash if no item exists with the same key (unless the hash is + const). For example, the following code snippet will create 1000 + items in memory: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 6 + + To avoid this problem, replace \c hash[i] with \c hash.value(i) + in the code above. + + If you want to navigate through all the (key, value) pairs stored + in a QHash, you can use an iterator. QHash provides both + \l{Java-style iterators} (QHashIterator and QMutableHashIterator) + and \l{STL-style iterators} (QHash::const_iterator and + QHash::iterator). Here's how to iterate over a QHash<QString, + int> using a Java-style iterator: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 7 + + Here's the same code, but using an STL-style iterator: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 8 + + QHash is unordered, so an iterator's sequence cannot be assumed + to be predictable. If ordering by key is required, use a QMap. + + Normally, a QHash allows only one value per key. If you call + insert() with a key that already exists in the QHash, the + previous value is erased. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 9 + + However, you can store multiple values per key by using + insertMulti() instead of insert() (or using the convenience + subclass QMultiHash). If you want to retrieve all + the values for a single key, you can use values(const Key &key), + which returns a QList<T>: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 10 + + The items that share the same key are available from most + recently to least recently inserted. A more efficient approach is + to call find() to get the iterator for the first item with a key + and iterate from there: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 11 + + If you only need to extract the values from a hash (not the keys), + you can also use \l{foreach}: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 12 + + Items can be removed from the hash in several ways. One way is to + call remove(); this will remove any item with the given key. + Another way is to use QMutableHashIterator::remove(). In addition, + you can clear the entire hash using clear(). + + QHash's key and value data types must be \l{assignable data + types}. You cannot, for example, store a QWidget as a value; + instead, store a QWidget *. In addition, QHash's key type must + provide operator==(), and there must also be a global qHash() + function that returns a hash value for an argument of the key's + type. + + Here's a list of the C++ and Qt types that can serve as keys in a + QHash: any integer type (char, unsigned long, etc.), any pointer + type, QChar, QString, and QByteArray. For all of these, the \c + <QHash> header defines a qHash() function that computes an + adequate hash value. If you want to use other types as the key, + make sure that you provide operator==() and a qHash() + implementation. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 13 + + The qHash() function computes a numeric value based on a key. It + can use any algorithm imaginable, as long as it always returns + the same value if given the same argument. In other words, if + \c{e1 == e2}, then \c{qHash(e1) == qHash(e2)} must hold as well. + However, to obtain good performance, the qHash() function should + attempt to return different hash values for different keys to the + largest extent possible. + + In the example above, we've relied on Qt's global qHash(const + QString &) to give us a hash value for the employee's name, and + XOR'ed this with the day they were born to help produce unique + hashes for people with the same name. + + Internally, QHash uses a hash table to perform lookups. Unlike Qt + 3's \c QDict class, which needed to be initialized with a prime + number, QHash's hash table automatically grows and shrinks to + provide fast lookups without wasting too much memory. You can + still control the size of the hash table by calling reserve() if + you already know approximately how many items the QHash will + contain, but this isn't necessary to obtain good performance. You + can also call capacity() to retrieve the hash table's size. + + \sa QHashIterator, QMutableHashIterator, QMap, QSet +*/ + +/*! \fn QHash::QHash() + + Constructs an empty hash. + + \sa clear() +*/ + +/*! \fn QHash::QHash(const QHash<Key, T> &other) + + Constructs a copy of \a other. + + This operation occurs in \l{constant time}, because QHash is + \l{implicitly shared}. This makes returning a QHash from a + function very fast. If a shared instance is modified, it will be + copied (copy-on-write), and this takes \l{linear time}. + + \sa operator=() +*/ + +/*! \fn QHash::~QHash() + + Destroys the hash. References to the values in the hash and all + iterators of this hash become invalid. +*/ + +/*! \fn QHash<Key, T> &QHash::operator=(const QHash<Key, T> &other) + + Assigns \a other to this hash and returns a reference to this hash. +*/ + +/*! \fn bool QHash::operator==(const QHash<Key, T> &other) const + + Returns true if \a other is equal to this hash; otherwise returns + false. + + Two hashes are considered equal if they contain the same (key, + value) pairs. + + This function requires the value type to implement \c operator==(). + + \sa operator!=() +*/ + +/*! \fn bool QHash::operator!=(const QHash<Key, T> &other) const + + Returns true if \a other is not equal to this hash; otherwise + returns false. + + Two hashes are considered equal if they contain the same (key, + value) pairs. + + This function requires the value type to implement \c operator==(). + + \sa operator==() +*/ + +/*! \fn int QHash::size() const + + Returns the number of items in the hash. + + \sa isEmpty(), count() +*/ + +/*! \fn bool QHash::isEmpty() const + + Returns true if the hash contains no items; otherwise returns + false. + + \sa size() +*/ + +/*! \fn int QHash::capacity() const + + Returns the number of buckets in the QHash's internal hash table. + + The sole purpose of this function is to provide a means of fine + tuning QHash's memory usage. In general, you will rarely ever + need to call this function. If you want to know how many items are + in the hash, call size(). + + \sa reserve(), squeeze() +*/ + +/*! \fn void QHash::reserve(int size) + + Ensures that the QHash's internal hash table consists of at least + \a size buckets. + + This function is useful for code that needs to build a huge hash + and wants to avoid repeated reallocation. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 14 + + Ideally, \a size should be slightly more than the maximum number + of items expected in the hash. \a size doesn't have to be prime, + because QHash will use a prime number internally anyway. If \a size + is an underestimate, the worst that will happen is that the QHash + will be a bit slower. + + In general, you will rarely ever need to call this function. + QHash's internal hash table automatically shrinks or grows to + provide good performance without wasting too much memory. + + \sa squeeze(), capacity() +*/ + +/*! \fn void QHash::squeeze() + + Reduces the size of the QHash's internal hash table to save + memory. + + The sole purpose of this function is to provide a means of fine + tuning QHash's memory usage. In general, you will rarely ever + need to call this function. + + \sa reserve(), capacity() +*/ + +/*! \fn void QHash::detach() + + \internal + + Detaches this hash from any other hashes with which it may share + data. + + \sa isDetached() +*/ + +/*! \fn bool QHash::isDetached() const + + \internal + + Returns true if the hash's internal data isn't shared with any + other hash object; otherwise returns false. + + \sa detach() +*/ + +/*! \fn void QHash::setSharable(bool sharable) + + \internal +*/ + +/*! \fn void QHash::clear() + + Removes all items from the hash. + + \sa remove() +*/ + +/*! \fn int QHash::remove(const Key &key) + + Removes all the items that have the \a key from the hash. + Returns the number of items removed which is usually 1 but will + be 0 if the key isn't in the hash, or greater than 1 if + insertMulti() has been used with the \a key. + + \sa clear(), take(), QMultiHash::remove() +*/ + +/*! \fn T QHash::take(const Key &key) + + Removes the item with the \a key from the hash and returns + the value associated with it. + + If the item does not exist in the hash, the function simply + returns a \l{default-constructed value}. If there are multiple + items for \a key in the hash, only the most recently inserted one + is removed. + + If you don't use the return value, remove() is more efficient. + + \sa remove() +*/ + +/*! \fn bool QHash::contains(const Key &key) const + + Returns true if the hash contains an item with the \a key; + otherwise returns false. + + \sa count(), QMultiHash::contains() +*/ + +/*! \fn const T QHash::value(const Key &key) const + + Returns the value associated with the \a key. + + If the hash contains no item with the \a key, the function + returns a \l{default-constructed value}. If there are multiple + items for the \a key in the hash, the value of the most recently + inserted one is returned. + + \sa key(), values(), contains(), operator[]() +*/ + +/*! \fn const T QHash::value(const Key &key, const T &defaultValue) const + + \overload + + If the hash contains no item with the given \a key, the function returns + \a defaultValue. +*/ + +/*! \fn T &QHash::operator[](const Key &key) + + Returns the value associated with the \a key as a modifiable + reference. + + If the hash contains no item with the \a key, the function inserts + a \l{default-constructed value} into the hash with the \a key, and + returns a reference to it. If the hash contains multiple items + with the \a key, this function returns a reference to the most + recently inserted value. + + \sa insert(), value() +*/ + +/*! \fn const T QHash::operator[](const Key &key) const + + \overload + + Same as value(). +*/ + +/*! \fn QList<Key> QHash::uniqueKeys() const + \since 4.2 + + Returns a list containing all the keys in the map. Keys that occur multiple + times in the map (because items were inserted with insertMulti(), or + unite() was used) occur only once in the returned list. + + \sa keys(), values() +*/ + +/*! \fn QList<Key> QHash::keys() const + + Returns a list containing all the keys in the hash, in an + arbitrary order. Keys that occur multiple times in the hash + (because items were inserted with insertMulti(), or unite() was + used) also occur multiple times in the list. + + To obtain a list of unique keys, where each key from the map only + occurs once, use uniqueKeys(). + + The order is guaranteed to be the same as that used by values(). + + \sa uniqueKeys(), values(), key() +*/ + +/*! \fn QList<Key> QHash::keys(const T &value) const + + \overload + + Returns a list containing all the keys associated with value \a + value, in an arbitrary order. + + This function can be slow (\l{linear time}), because QHash's + internal data structure is optimized for fast lookup by key, not + by value. +*/ + +/*! \fn QList<T> QHash::values() const + + Returns a list containing all the values in the hash, in an + arbitrary order. If a key is associated multiple values, all of + its values will be in the list, and not just the most recently + inserted one. + + The order is guaranteed to be the same as that used by keys(). + + \sa keys(), value() +*/ + +/*! \fn QList<T> QHash::values(const Key &key) const + + \overload + + Returns a list of all the values associated with the \a key, + from the most recently inserted to the least recently inserted. + + \sa count(), insertMulti() +*/ + +/*! \fn Key QHash::key(const T &value) const + + Returns the first key mapped to \a value. + + If the hash contains no item with the \a value, the function + returns a \link {default-constructed value} default-constructed + key \endlink. + + This function can be slow (\l{linear time}), because QHash's + internal data structure is optimized for fast lookup by key, not + by value. + + \sa value(), keys() +*/ + +/*! + \fn Key QHash::key(const T &value, const Key &defaultKey) const + \since 4.3 + \overload + + Returns the first key mapped to \a value, or \a defaultKey if the + hash contains no item mapped to \a value. + + This function can be slow (\l{linear time}), because QHash's + internal data structure is optimized for fast lookup by key, not + by value. +*/ + +/*! \fn int QHash::count(const Key &key) const + + Returns the number of items associated with the \a key. + + \sa contains(), insertMulti() +*/ + +/*! \fn int QHash::count() const + + \overload + + Same as size(). +*/ + +/*! \fn QHash::iterator QHash::begin() + + Returns an \l{STL-style iterator} pointing to the first item in + the hash. + + \sa constBegin(), end() +*/ + +/*! \fn QHash::const_iterator QHash::begin() const + + \overload +*/ + +/*! \fn QHash::const_iterator QHash::constBegin() const + + Returns a const \l{STL-style iterator} pointing to the first item + in the hash. + + \sa begin(), constEnd() +*/ + +/*! \fn QHash::iterator QHash::end() + + Returns an \l{STL-style iterator} pointing to the imaginary item + after the last item in the hash. + + \sa begin(), constEnd() +*/ + +/*! \fn QHash::const_iterator QHash::end() const + + \overload +*/ + +/*! \fn QHash::const_iterator QHash::constEnd() const + + Returns a const \l{STL-style iterator} pointing to the imaginary + item after the last item in the hash. + + \sa constBegin(), end() +*/ + +/*! \fn QHash::iterator QHash::erase(iterator pos) + + Removes the (key, value) pair associated with the iterator \a pos + from the hash, and returns an iterator to the next item in the + hash. + + Unlike remove() and take(), this function never causes QHash to + rehash its internal data structure. This means that it can safely + be called while iterating, and won't affect the order of items in + the hash. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 15 + + \sa remove(), take(), find() +*/ + +/*! \fn QHash::iterator QHash::find(const Key &key) + + Returns an iterator pointing to the item with the \a key in the + hash. + + If the hash contains no item with the \a key, the function + returns end(). + + If the hash contains multiple items with the \a key, this + function returns an iterator that points to the most recently + inserted value. The other values are accessible by incrementing + the iterator. For example, here's some code that iterates over all + the items with the same key: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 16 + + \sa value(), values(), QMultiHash::find() +*/ + +/*! \fn QHash::const_iterator QHash::find(const Key &key) const + + \overload +*/ + +/*! \fn QHash::iterator QHash::constFind(const Key &key) const + \since 4.1 + + Returns an iterator pointing to the item with the \a key in the + hash. + + If the hash contains no item with the \a key, the function + returns constEnd(). + + \sa find(), QMultiHash::constFind() +*/ + +/*! \fn QHash::iterator QHash::insert(const Key &key, const T &value) + + Inserts a new item with the \a key and a value of \a value. + + If there is already an item with the \a key, that item's value + is replaced with \a value. + + If there are multiple items with the \a key, the most + recently inserted item's value is replaced with \a value. + + \sa insertMulti() +*/ + +/*! \fn QHash::iterator QHash::insertMulti(const Key &key, const T &value) + + Inserts a new item with the \a key and a value of \a value. + + If there is already an item with the same key in the hash, this + function will simply create a new one. (This behavior is + different from insert(), which overwrites the value of an + existing item.) + + \sa insert(), values() +*/ + +/*! \fn QHash<Key, T> &QHash::unite(const QHash<Key, T> &other) + + Inserts all the items in the \a other hash into this hash. If a + key is common to both hashes, the resulting hash will contain the + key multiple times. + + \sa insertMulti() +*/ + +/*! \fn bool QHash::empty() const + + This function is provided for STL compatibility. It is equivalent + to isEmpty(), returning true if the hash is empty; otherwise + returns false. +*/ + +/*! \typedef QHash::ConstIterator + + Qt-style synonym for QHash::const_iterator. +*/ + +/*! \typedef QHash::Iterator + + Qt-style synonym for QHash::iterator. +*/ + +/*! \typedef QHash::difference_type + + Typedef for ptrdiff_t. Provided for STL compatibility. +*/ + +/*! \typedef QHash::key_type + + Typedef for Key. Provided for STL compatibility. +*/ + +/*! \typedef QHash::mapped_type + + Typedef for T. Provided for STL compatibility. +*/ + +/*! \typedef QHash::size_type + + Typedef for int. Provided for STL compatibility. +*/ + +/*! \typedef QHash::iterator::difference_type + \internal +*/ + +/*! \typedef QHash::iterator::iterator_category + \internal +*/ + +/*! \typedef QHash::iterator::pointer + \internal +*/ + +/*! \typedef QHash::iterator::reference + \internal +*/ + +/*! \typedef QHash::iterator::value_type + \internal +*/ + +/*! \typedef QHash::const_iterator::difference_type + \internal +*/ + +/*! \typedef QHash::const_iterator::iterator_category + \internal +*/ + +/*! \typedef QHash::const_iterator::pointer + \internal +*/ + +/*! \typedef QHash::const_iterator::reference + \internal +*/ + +/*! \typedef QHash::const_iterator::value_type + \internal +*/ + +/*! \class QHash::iterator + \brief The QHash::iterator class provides an STL-style non-const iterator for QHash and QMultiHash. + + QHash features both \l{STL-style iterators} and \l{Java-style + iterators}. The STL-style iterators are more low-level and more + cumbersome to use; on the other hand, they are slightly faster + and, for developers who already know STL, have the advantage of + familiarity. + + QHash\<Key, T\>::iterator allows you to iterate over a QHash (or + QMultiHash) and to modify the value (but not the key) associated + with a particular key. If you want to iterate over a const QHash, + you should use QHash::const_iterator. It is generally good + practice to use QHash::const_iterator on a non-const QHash as + well, unless you need to change the QHash through the iterator. + Const iterators are slightly faster, and can improve code + readability. + + The default QHash::iterator constructor creates an uninitialized + iterator. You must initialize it using a QHash function like + QHash::begin(), QHash::end(), or QHash::find() before you can + start iterating. Here's a typical loop that prints all the (key, + value) pairs stored in a hash: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 17 + + Unlike QMap, which orders its items by key, QHash stores its + items in an arbitrary order. The only guarantee is that items that + share the same key (because they were inserted using + QHash::insertMulti()) will appear consecutively, from the most + recently to the least recently inserted value. + + Let's see a few examples of things we can do with a + QHash::iterator that we cannot do with a QHash::const_iterator. + Here's an example that increments every value stored in the QHash + by 2: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 18 + + Here's an example that removes all the items whose key is a + string that starts with an underscore character: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 19 + + The call to QHash::erase() removes the item pointed to by the + iterator from the hash, and returns an iterator to the next item. + Here's another way of removing an item while iterating: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 20 + + It might be tempting to write code like this: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 21 + + However, this will potentially crash in \c{++i}, because \c i is + a dangling iterator after the call to erase(). + + Multiple iterators can be used on the same hash. However, be + aware that any modification performed directly on the QHash has + the potential of dramatically changing the order in which the + items are stored in the hash, as they might cause QHash to rehash + its internal data structure. There is one notable exception: + QHash::erase(). This function can safely be called while + iterating, and won't affect the order of items in the hash. If you + need to keep iterators over a long period of time, we recommend + that you use QMap rather than QHash. + + \sa QHash::const_iterator, QMutableHashIterator +*/ + +/*! \fn QHash::iterator::operator Node *() const + + \internal +*/ + +/*! \fn QHash::iterator::iterator() + + Constructs an uninitialized iterator. + + Functions like key(), value(), and operator++() must not be + called on an uninitialized iterator. Use operator=() to assign a + value to it before using it. + + \sa QHash::begin() QHash::end() +*/ + +/*! \fn QHash::iterator::iterator(void *node) + + \internal +*/ + +/*! \fn const Key &QHash::iterator::key() const + + Returns the current item's key as a const reference. + + There is no direct way of changing an item's key through an + iterator, although it can be done by calling QHash::erase() + followed by QHash::insert() or QHash::insertMulti(). + + \sa value() +*/ + +/*! \fn T &QHash::iterator::value() const + + Returns a modifiable reference to the current item's value. + + You can change the value of an item by using value() on + the left side of an assignment, for example: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 22 + + \sa key(), operator*() +*/ + +/*! \fn T &QHash::iterator::operator*() const + + Returns a modifiable reference to the current item's value. + + Same as value(). + + \sa key() +*/ + +/*! \fn T *QHash::iterator::operator->() const + + Returns a pointer to the current item's value. + + \sa value() +*/ + +/*! + \fn bool QHash::iterator::operator==(const iterator &other) const + \fn bool QHash::iterator::operator==(const const_iterator &other) const + + Returns true if \a other points to the same item as this + iterator; otherwise returns false. + + \sa operator!=() +*/ + +/*! + \fn bool QHash::iterator::operator!=(const iterator &other) const + \fn bool QHash::iterator::operator!=(const const_iterator &other) const + + Returns true if \a other points to a different item than this + iterator; otherwise returns false. + + \sa operator==() +*/ + +/*! + \fn QHash::iterator &QHash::iterator::operator++() + + The prefix ++ operator (\c{++i}) advances the iterator to the + next item in the hash and returns an iterator to the new current + item. + + Calling this function on QHash::end() leads to undefined results. + + \sa operator--() +*/ + +/*! \fn QHash::iterator QHash::iterator::operator++(int) + + \overload + + The postfix ++ operator (\c{i++}) advances the iterator to the + next item in the hash and returns an iterator to the previously + current item. +*/ + +/*! + \fn QHash::iterator &QHash::iterator::operator--() + + The prefix -- operator (\c{--i}) makes the preceding item + current and returns an iterator pointing to the new current item. + + Calling this function on QHash::begin() leads to undefined + results. + + \sa operator++() +*/ + +/*! + \fn QHash::iterator QHash::iterator::operator--(int) + + \overload + + The postfix -- operator (\c{i--}) makes the preceding item + current and returns an iterator pointing to the previously + current item. +*/ + +/*! \fn QHash::iterator QHash::iterator::operator+(int j) const + + Returns an iterator to the item at \a j positions forward from + this iterator. (If \a j is negative, the iterator goes backward.) + + This operation can be slow for large \a j values. + + \sa operator-() + +*/ + +/*! \fn QHash::iterator QHash::iterator::operator-(int j) const + + Returns an iterator to the item at \a j positions backward from + this iterator. (If \a j is negative, the iterator goes forward.) + + This operation can be slow for large \a j values. + + \sa operator+() +*/ + +/*! \fn QHash::iterator &QHash::iterator::operator+=(int j) + + Advances the iterator by \a j items. (If \a j is negative, the + iterator goes backward.) + + \sa operator-=(), operator+() +*/ + +/*! \fn QHash::iterator &QHash::iterator::operator-=(int j) + + Makes the iterator go back by \a j items. (If \a j is negative, + the iterator goes forward.) + + \sa operator+=(), operator-() +*/ + +/*! \class QHash::const_iterator + \brief The QHash::const_iterator class provides an STL-style const iterator for QHash and QMultiHash. + + QHash features both \l{STL-style iterators} and \l{Java-style + iterators}. The STL-style iterators are more low-level and more + cumbersome to use; on the other hand, they are slightly faster + and, for developers who already know STL, have the advantage of + familiarity. + + QHash\<Key, T\>::const_iterator allows you to iterate over a + QHash (or a QMultiHash). If you want to modify the QHash as you + iterate over it, you must use QHash::iterator instead. It is + generally good practice to use QHash::const_iterator on a + non-const QHash as well, unless you need to change the QHash + through the iterator. Const iterators are slightly faster, and + can improve code readability. + + The default QHash::const_iterator constructor creates an + uninitialized iterator. You must initialize it using a QHash + function like QHash::constBegin(), QHash::constEnd(), or + QHash::find() before you can start iterating. Here's a typical + loop that prints all the (key, value) pairs stored in a hash: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 23 + + Unlike QMap, which orders its items by key, QHash stores its + items in an arbitrary order. The only guarantee is that items that + share the same key (because they were inserted using + QHash::insertMulti()) will appear consecutively, from the most + recently to the least recently inserted value. + + Multiple iterators can be used on the same hash. However, be aware + that any modification performed directly on the QHash has the + potential of dramatically changing the order in which the items + are stored in the hash, as they might cause QHash to rehash its + internal data structure. If you need to keep iterators over a long + period of time, we recommend that you use QMap rather than QHash. + + \sa QHash::iterator, QHashIterator +*/ + +/*! \fn QHash::const_iterator::operator Node *() const + + \internal +*/ + +/*! \fn QHash::const_iterator::const_iterator() + + Constructs an uninitialized iterator. + + Functions like key(), value(), and operator++() must not be + called on an uninitialized iterator. Use operator=() to assign a + value to it before using it. + + \sa QHash::constBegin() QHash::constEnd() +*/ + +/*! \fn QHash::const_iterator::const_iterator(void *node) + + \internal +*/ + +/*! \fn QHash::const_iterator::const_iterator(const iterator &other) + + Constructs a copy of \a other. +*/ + +/*! \fn const Key &QHash::const_iterator::key() const + + Returns the current item's key. + + \sa value() +*/ + +/*! \fn const T &QHash::const_iterator::value() const + + Returns the current item's value. + + \sa key(), operator*() +*/ + +/*! \fn const T &QHash::const_iterator::operator*() const + + Returns the current item's value. + + Same as value(). + + \sa key() +*/ + +/*! \fn const T *QHash::const_iterator::operator->() const + + Returns a pointer to the current item's value. + + \sa value() +*/ + +/*! \fn bool QHash::const_iterator::operator==(const const_iterator &other) const + + Returns true if \a other points to the same item as this + iterator; otherwise returns false. + + \sa operator!=() +*/ + +/*! \fn bool QHash::const_iterator::operator!=(const const_iterator &other) const + + Returns true if \a other points to a different item than this + iterator; otherwise returns false. + + \sa operator==() +*/ + +/*! + \fn QHash::const_iterator &QHash::const_iterator::operator++() + + The prefix ++ operator (\c{++i}) advances the iterator to the + next item in the hash and returns an iterator to the new current + item. + + Calling this function on QHash::end() leads to undefined results. + + \sa operator--() +*/ + +/*! \fn QHash::const_iterator QHash::const_iterator::operator++(int) + + \overload + + The postfix ++ operator (\c{i++}) advances the iterator to the + next item in the hash and returns an iterator to the previously + current item. +*/ + +/*! \fn QHash::const_iterator &QHash::const_iterator::operator--() + + The prefix -- operator (\c{--i}) makes the preceding item + current and returns an iterator pointing to the new current item. + + Calling this function on QHash::begin() leads to undefined + results. + + \sa operator++() +*/ + +/*! \fn QHash::const_iterator QHash::const_iterator::operator--(int) + + \overload + + The postfix -- operator (\c{i--}) makes the preceding item + current and returns an iterator pointing to the previously + current item. +*/ + +/*! \fn QHash::const_iterator QHash::const_iterator::operator+(int j) const + + Returns an iterator to the item at \a j positions forward from + this iterator. (If \a j is negative, the iterator goes backward.) + + This operation can be slow for large \a j values. + + \sa operator-() +*/ + +/*! \fn QHash::const_iterator QHash::const_iterator::operator-(int j) const + + Returns an iterator to the item at \a j positions backward from + this iterator. (If \a j is negative, the iterator goes forward.) + + This operation can be slow for large \a j values. + + \sa operator+() +*/ + +/*! \fn QHash::const_iterator &QHash::const_iterator::operator+=(int j) + + Advances the iterator by \a j items. (If \a j is negative, the + iterator goes backward.) + + This operation can be slow for large \a j values. + + \sa operator-=(), operator+() +*/ + +/*! \fn QHash::const_iterator &QHash::const_iterator::operator-=(int j) + + Makes the iterator go back by \a j items. (If \a j is negative, + the iterator goes forward.) + + This operation can be slow for large \a j values. + + \sa operator+=(), operator-() +*/ + +/*! \fn uint qHash(char key) + \relates QHash + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(uchar key) + \relates QHash + \overload + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(signed char key) + \relates QHash + \overload + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(ushort key) + \relates QHash + \overload + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(short key) + \relates QHash + \overload + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(uint key) + \relates QHash + \overload + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(int key) + \relates QHash + \overload + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(ulong key) + \relates QHash + \overload + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(long key) + \relates QHash + \overload + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(quint64 key) + \relates QHash + \overload + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(qint64 key) + \relates QHash + \overload + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(QChar key) + \relates QHash + \overload + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(const QByteArray &key) + \fn uint qHash(const QBitArray &key) + \relates QHash + \overload + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(const QString &key) + \relates QHash + \overload + + Returns the hash value for the \a key. +*/ + +/*! \fn uint qHash(const T *key) + \relates QHash + \overload + + Returns the hash value for the \a key. +*/ + +/*! + \fn uint qHash(const QPair<T1, T2> &key) + \relates QHash + \since 4.3 + + Returns the hash value for the \a key. + + Types \c T1 and \c T2 must be supported by qHash(). +*/ + +/*! \fn QDataStream &operator<<(QDataStream &out, const QHash<Key, T>& hash) + \relates QHash + + Writes the hash \a hash to stream \a out. + + This function requires the key and value types to implement \c + operator<<(). + + \sa {Format of the QDataStream operators} +*/ + +/*! \fn QDataStream &operator>>(QDataStream &in, QHash<Key, T> &hash) + \relates QHash + + Reads a hash from stream \a in into \a hash. + + This function requires the key and value types to implement \c + operator>>(). + + \sa {Format of the QDataStream operators} +*/ + +/*! \class QMultiHash + \brief The QMultiHash class is a convenience QHash subclass that provides multi-valued hashes. + + \ingroup tools + \ingroup shared + \mainclass + \reentrant + + QMultiHash\<Key, T\> is one of Qt's generic \l{container classes}. + It inherits QHash and extends it with a few convenience functions + that make it more suitable than QHash for storing multi-valued + hashes. A multi-valued hash is a hash that allows multiple values + with the same key; QHash normally doesn't allow that, unless you + call QHash::insertMulti(). + + Because QMultiHash inherits QHash, all of QHash's functionality also + applies to QMultiHash. For example, you can use isEmpty() to test + whether the hash is empty, and you can traverse a QMultiHash using + QHash's iterator classes (for example, QHashIterator). But in + addition, it provides an insert() function that corresponds to + QHash::insertMulti(), and a replace() function that corresponds to + QHash::insert(). It also provides convenient operator+() and + operator+=(). + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 24 + + Unlike QHash, QMultiHash provides no operator[]. Use value() or + replace() if you want to access the most recently inserted item + with a certain key. + + If you want to retrieve all the values for a single key, you can + use values(const Key &key), which returns a QList<T>: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 25 + + The items that share the same key are available from most + recently to least recently inserted. + + A more efficient approach is to call find() to get + the STL-style iterator for the first item with a key and iterate from + there: + + \snippet doc/src/snippets/code/src_corelib_tools_qhash.cpp 26 + + QMultiHash's key and value data types must be \l{assignable data + types}. You cannot, for example, store a QWidget as a value; + instead, store a QWidget *. In addition, QMultiHash's key type + must provide operator==(), and there must also be a global + qHash() function that returns a hash value for an argument of the + key's type. See the QHash documentation for details. + + \sa QHash, QHashIterator, QMutableHashIterator, QMultiMap +*/ + +/*! \fn QMultiHash::QMultiHash() + + Constructs an empty hash. +*/ + +/*! \fn QMultiHash::QMultiHash(const QHash<Key, T> &other) + + Constructs a copy of \a other (which can be a QHash or a + QMultiHash). + + \sa operator=() +*/ + +/*! \fn QMultiHash::iterator QMultiHash::replace(const Key &key, const T &value) + + Inserts a new item with the \a key and a value of \a value. + + If there is already an item with the \a key, that item's value + is replaced with \a value. + + If there are multiple items with the \a key, the most + recently inserted item's value is replaced with \a value. + + \sa insert() +*/ + +/*! \fn QMultiHash::iterator QMultiHash::insert(const Key &key, const T &value) + + Inserts a new item with the \a key and a value of \a value. + + If there is already an item with the same key in the hash, this + function will simply create a new one. (This behavior is + different from replace(), which overwrites the value of an + existing item.) + + \sa replace() +*/ + +/*! \fn QMultiHash &QMultiHash::operator+=(const QMultiHash &other) + + Inserts all the items in the \a other hash into this hash + and returns a reference to this hash. + + \sa insert() +*/ + +/*! \fn QMultiHash QMultiHash::operator+(const QMultiHash &other) const + + Returns a hash that contains all the items in this hash in + addition to all the items in \a other. If a key is common to both + hashes, the resulting hash will contain the key multiple times. + + \sa operator+=() +*/ + +/*! + \fn bool QMultiHash::contains(const Key &key, const T &value) const + \since 4.3 + + Returns true if the hash contains an item with the \a key and + \a value; otherwise returns false. + + \sa QHash::contains() +*/ + +/*! + \fn bool QMultiHash::contains(const Key &key) const + \overload + \sa QHash::contains() +*/ + +/*! + \fn int QMultiHash::remove(const Key &key, const T &value) + \since 4.3 + + Removes all the items that have the \a key and the value \a + value from the hash. Returns the number of items removed. + + \sa QHash::remove() +*/ + +/*! + \fn int QMultiHash::remove(const Key &key) + \overload + \sa QHash::remove() +*/ + +/*! + \fn int QMultiHash::count(const Key &key, const T &value) const + \since 4.3 + + Returns the number of items with the \a key and \a value. + + \sa QHash::count() +*/ + +/*! + \fn int QMultiHash::count(const Key &key) const + \overload + \sa QHash::count() +*/ + +/*! + \fn int QMultiHash::count() const + \overload + \sa QHash::count() +*/ + +/*! + \fn typename QHash<Key, T>::iterator QMultiHash::find(const Key &key, const T &value) + \since 4.3 + + Returns an iterator pointing to the item with the \a key and \a value. + If the hash contains no such item, the function returns end(). + + If the hash contains multiple items with the \a key and \a value, the + iterator returned points to the most recently inserted item. + + \sa QHash::find() +*/ + +/*! + \fn typename QHash<Key, T>::iterator QMultiHash::find(const Key &key) + \overload + \sa QHash::find() +*/ + +/*! + \fn typename QHash<Key, T>::const_iterator QMultiHash::find(const Key &key, const T &value) const + \since 4.3 + \overload +*/ + +/*! + \fn typename QHash<Key, T>::const_iterator QMultiHash::find(const Key &key) const + \overload + \sa QHash::find() +*/ + +/*! + \fn typename QHash<Key, T>::const_iterator QMultiHash::constFind(const Key &key, const T &value) const + \since 4.3 + + Returns an iterator pointing to the item with the \a key and the + \a value in the hash. + + If the hash contains no such item, the function returns + constEnd(). + + \sa QHash::constFind() +*/ + +/*! + \fn typename QHash<Key, T>::const_iterator QMultiHash::constFind(const Key &key) const + \overload + \sa QHash::constFind() +*/ + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h new file mode 100644 index 0000000..a18b531 --- /dev/null +++ b/src/corelib/tools/qhash.h @@ -0,0 +1,1017 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHASH_H +#define QHASH_H + +#include <QtCore/qatomic.h> +#include <QtCore/qchar.h> +#include <QtCore/qiterator.h> +#include <QtCore/qlist.h> +#include <QtCore/qpair.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +#undef QT_QHASH_DEBUG +QT_MODULE(Core) + +class QBitArray; +class QByteArray; +class QString; +class QStringRef; + +inline uint qHash(char key) { return uint(key); } +inline uint qHash(uchar key) { return uint(key); } +inline uint qHash(signed char key) { return uint(key); } +inline uint qHash(ushort key) { return uint(key); } +inline uint qHash(short key) { return uint(key); } +inline uint qHash(uint key) { return key; } +inline uint qHash(int key) { return uint(key); } +inline uint qHash(ulong key) +{ + if (sizeof(ulong) > sizeof(uint)) { + return uint((key >> (8 * sizeof(uint) - 1)) ^ key); + } else { + return uint(key); + } +} +inline uint qHash(long key) { return qHash(ulong(key)); } +inline uint qHash(quint64 key) +{ + if (sizeof(quint64) > sizeof(uint)) { + return uint((key >> (8 * sizeof(uint) - 1)) ^ key); + } else { + return uint(key); + } +} +inline uint qHash(qint64 key) { return qHash(quint64(key)); } +inline uint qHash(QChar key) { return qHash(key.unicode()); } +Q_CORE_EXPORT uint qHash(const QByteArray &key); +Q_CORE_EXPORT uint qHash(const QString &key); +Q_CORE_EXPORT uint qHash(const QStringRef &key); +Q_CORE_EXPORT uint qHash(const QBitArray &key); + +#if defined(Q_CC_MSVC) +#pragma warning( push ) +#pragma warning( disable : 4311 ) // disable pointer truncation warning +#endif +template <class T> inline uint qHash(const T *key) +{ + if (sizeof(const T *) > sizeof(uint)) + return qHash(reinterpret_cast<quint64>(key)); + else + return uint(reinterpret_cast<ulong>(key)); +} +#if defined(Q_CC_MSVC) +#pragma warning( pop ) +#endif + +template <typename T1, typename T2> inline uint qHash(const QPair<T1, T2> &key) +{ + uint h1 = qHash(key.first); + uint h2 = qHash(key.second); + return ((h1 << 16) | (h1 >> 16)) ^ h2; +} + +struct Q_CORE_EXPORT QHashData +{ + struct Node { + Node *next; + uint h; + }; + + Node *fakeNext; + Node **buckets; + QBasicAtomicInt ref; + int size; + int nodeSize; + short userNumBits; + short numBits; + int numBuckets; + uint sharable : 1; + + void *allocateNode(); + void freeNode(void *node); + QHashData *detach_helper(void (*node_duplicate)(Node *, void *), int nodeSize); + void mightGrow(); + bool willGrow(); + void hasShrunk(); + void rehash(int hint); + void destroyAndFree(); + Node *firstNode(); +#ifdef QT_QHASH_DEBUG + void dump(); + void checkSanity(); +#endif + static Node *nextNode(Node *node); + static Node *previousNode(Node *node); + + static QHashData shared_null; +}; + +inline void QHashData::mightGrow() // ### Qt 5: eliminate +{ + if (size >= numBuckets) + rehash(numBits + 1); +} + +inline bool QHashData::willGrow() +{ + if (size >= numBuckets) { + rehash(numBits + 1); + return true; + } else { + return false; + } +} + +inline void QHashData::hasShrunk() +{ + if (size <= (numBuckets >> 3) && numBits > userNumBits) + rehash(qMax(int(numBits) - 2, int(userNumBits))); +} + +inline QHashData::Node *QHashData::firstNode() +{ + Node *e = reinterpret_cast<Node *>(this); + Node **bucket = buckets; + int n = numBuckets; + while (n--) { + if (*bucket != e) + return *bucket; + ++bucket; + } + return e; +} + +struct QHashDummyValue +{ +}; + +inline bool operator==(const QHashDummyValue & /* v1 */, const QHashDummyValue & /* v2 */) +{ + return true; +} + +Q_DECLARE_TYPEINFO(QHashDummyValue, Q_MOVABLE_TYPE | Q_DUMMY_TYPE); + +template <class Key, class T> +struct QHashDummyNode +{ + QHashDummyNode *next; + uint h; + Key key; + + inline QHashDummyNode(const Key &key0) : key(key0) {} +}; + +template <class Key, class T> +struct QHashNode +{ + QHashNode *next; + uint h; + Key key; + T value; + + inline QHashNode(const Key &key0) : key(key0) {} // ### remove in 5.0 + inline QHashNode(const Key &key0, const T &value0) : key(key0), value(value0) {} + inline bool same_key(uint h0, const Key &key0) { return h0 == h && key0 == key; } +}; + +#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION +#define Q_HASH_DECLARE_INT_NODES(key_type) \ + template <class T> \ + struct QHashDummyNode<key_type, T> { \ + QHashDummyNode *next; \ + union { uint h; key_type key; }; \ +\ + inline QHashDummyNode(key_type /* key0 */) {} \ + }; \ +\ + template <class T> \ + struct QHashNode<key_type, T> { \ + QHashNode *next; \ + union { uint h; key_type key; }; \ + T value; \ +\ + inline QHashNode(key_type /* key0 */) {} \ + inline QHashNode(key_type /* key0 */, const T &value0) : value(value0) {} \ + inline bool same_key(uint h0, key_type) { return h0 == h; } \ + } + +#if defined(Q_BYTE_ORDER) && Q_BYTE_ORDER == Q_LITTLE_ENDIAN +Q_HASH_DECLARE_INT_NODES(short); +Q_HASH_DECLARE_INT_NODES(ushort); +#endif +Q_HASH_DECLARE_INT_NODES(int); +Q_HASH_DECLARE_INT_NODES(uint); +#undef Q_HASH_DECLARE_INT_NODES +#endif // QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION + +template <class Key, class T> +class QHash +{ + typedef QHashDummyNode<Key, T> DummyNode; + typedef QHashNode<Key, T> Node; + + union { + QHashData *d; + QHashNode<Key, T> *e; + }; + + static inline Node *concrete(QHashData::Node *node) { + return reinterpret_cast<Node *>(node); + } + +public: + inline QHash() : d(&QHashData::shared_null) { d->ref.ref(); } + inline QHash(const QHash<Key, T> &other) : d(other.d) { d->ref.ref(); if (!d->sharable) detach(); } + inline ~QHash() { if (!d->ref.deref()) freeData(d); } + + QHash<Key, T> &operator=(const QHash<Key, T> &other); + + bool operator==(const QHash<Key, T> &other) const; + inline bool operator!=(const QHash<Key, T> &other) const { return !(*this == other); } + + inline int size() const { return d->size; } + + inline bool isEmpty() const { return d->size == 0; } + + inline int capacity() const { return d->numBuckets; } + void reserve(int size); + inline void squeeze() { reserve(1); } + + inline void detach() { if (d->ref != 1) detach_helper(); } + inline bool isDetached() const { return d->ref == 1; } + inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } + + void clear(); + + int remove(const Key &key); + T take(const Key &key); + + bool contains(const Key &key) const; + const Key key(const T &value) const; + const Key key(const T &value, const Key &defaultKey) const; + const T value(const Key &key) const; + const T value(const Key &key, const T &defaultValue) const; + T &operator[](const Key &key); + const T operator[](const Key &key) const; + + QList<Key> uniqueKeys() const; + QList<Key> keys() const; + QList<Key> keys(const T &value) const; + QList<T> values() const; + QList<T> values(const Key &key) const; + int count(const Key &key) const; + + class const_iterator; + + class iterator + { + friend class const_iterator; + QHashData::Node *i; + + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T *pointer; + typedef T &reference; + + // ### Qt 5: get rid of 'operator Node *' + inline operator Node *() const { return concrete(i); } + inline iterator() : i(0) { } + explicit inline iterator(void *node) : i(reinterpret_cast<QHashData::Node *>(node)) { } + + inline const Key &key() const { return concrete(i)->key; } + inline T &value() const { return concrete(i)->value; } + inline T &operator*() const { return concrete(i)->value; } + inline T *operator->() const { return &concrete(i)->value; } + inline bool operator==(const iterator &o) const { return i == o.i; } + inline bool operator!=(const iterator &o) const { return i != o.i; } + + inline iterator &operator++() { + i = QHashData::nextNode(i); + return *this; + } + inline iterator operator++(int) { + iterator r = *this; + i = QHashData::nextNode(i); + return r; + } + inline iterator &operator--() { + i = QHashData::previousNode(i); + return *this; + } + inline iterator operator--(int) { + iterator r = *this; + i = QHashData::previousNode(i); + return r; + } + inline iterator operator+(int j) const + { iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; } + inline iterator operator-(int j) const { return operator+(-j); } + inline iterator &operator+=(int j) { return *this = *this + j; } + inline iterator &operator-=(int j) { return *this = *this - j; } + + // ### Qt 5: not sure this is necessary anymore +#ifdef QT_STRICT_ITERATORS + private: +#else + public: +#endif + inline bool operator==(const const_iterator &o) const + { return i == o.i; } + inline bool operator!=(const const_iterator &o) const + { return i != o.i; } + + private: + // ### Qt 5: remove + inline operator bool() const { return false; } + }; + friend class iterator; + + class const_iterator + { + friend class iterator; + QHashData::Node *i; + + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef const T *pointer; + typedef const T &reference; + + // ### Qt 5: get rid of 'operator Node *' + inline operator Node *() const { return concrete(i); } + inline const_iterator() : i(0) { } + explicit inline const_iterator(void *node) + : i(reinterpret_cast<QHashData::Node *>(node)) { } +#ifdef QT_STRICT_ITERATORS + explicit inline const_iterator(const iterator &o) +#else + inline const_iterator(const iterator &o) +#endif + { i = o.i; } + + inline const Key &key() const { return concrete(i)->key; } + inline const T &value() const { return concrete(i)->value; } + inline const T &operator*() const { return concrete(i)->value; } + inline const T *operator->() const { return &concrete(i)->value; } + inline bool operator==(const const_iterator &o) const { return i == o.i; } + inline bool operator!=(const const_iterator &o) const { return i != o.i; } + + inline const_iterator &operator++() { + i = QHashData::nextNode(i); + return *this; + } + inline const_iterator operator++(int) { + const_iterator r = *this; + i = QHashData::nextNode(i); + return r; + } + inline const_iterator &operator--() { + i = QHashData::previousNode(i); + return *this; + } + inline const_iterator operator--(int) { + const_iterator r = *this; + i = QHashData::previousNode(i); + return r; + } + inline const_iterator operator+(int j) const + { const_iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; } + inline const_iterator operator-(int j) const { return operator+(-j); } + inline const_iterator &operator+=(int j) { return *this = *this + j; } + inline const_iterator &operator-=(int j) { return *this = *this - j; } + + // ### Qt 5: not sure this is necessary anymore +#ifdef QT_STRICT_ITERATORS + private: + inline bool operator==(const iterator &o) const { return operator==(const_iterator(o)); } + inline bool operator!=(const iterator &o) const { return operator!=(const_iterator(o)); } +#endif + + private: + // ### Qt 5: remove + inline operator bool() const { return false; } + }; + friend class const_iterator; + + // STL style + inline iterator begin() { detach(); return iterator(d->firstNode()); } + inline const_iterator begin() const { return const_iterator(d->firstNode()); } + inline const_iterator constBegin() const { return const_iterator(d->firstNode()); } + inline iterator end() { detach(); return iterator(e); } + inline const_iterator end() const { return const_iterator(e); } + inline const_iterator constEnd() const { return const_iterator(e); } + iterator erase(iterator it); + + // more Qt + typedef iterator Iterator; + typedef const_iterator ConstIterator; + inline int count() const { return d->size; } + iterator find(const Key &key); + const_iterator find(const Key &key) const; + const_iterator constFind(const Key &key) const; + iterator insert(const Key &key, const T &value); + iterator insertMulti(const Key &key, const T &value); + QHash<Key, T> &unite(const QHash<Key, T> &other); + + // STL compatibility + typedef T mapped_type; + typedef Key key_type; + typedef ptrdiff_t difference_type; + typedef int size_type; + + inline bool empty() const { return isEmpty(); } + +#ifdef QT_QHASH_DEBUG + inline void dump() const { d->dump(); } + inline void checkSanity() const { d->checkSanity(); } +#endif + +private: + void detach_helper(); + void freeData(QHashData *d); + Node **findNode(const Key &key, uint *hp = 0) const; + Node *createNode(uint h, const Key &key, const T &value, Node **nextNode); + void deleteNode(Node *node); + + static void duplicateNode(QHashData::Node *originalNode, void *newNode); +}; + +template <class Key, class T> +Q_INLINE_TEMPLATE void QHash<Key, T>::deleteNode(Node *node) +{ +#ifdef Q_CC_BOR + node->~QHashNode<Key, T>(); +#elif defined(QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION) + node->~QHashNode(); +#else + node->~Node(); +#endif + d->freeNode(node); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE void QHash<Key, T>::duplicateNode(QHashData::Node *node, void *newNode) +{ + Node *concreteNode = concrete(node); + if (QTypeInfo<T>::isDummy) { + (void) new (newNode) DummyNode(concreteNode->key); + } else { + (void) new (newNode) Node(concreteNode->key, concreteNode->value); + } +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QHash<Key, T>::Node * +QHash<Key, T>::createNode(uint ah, const Key &akey, const T &avalue, Node **anextNode) +{ + Node *node; + + if (QTypeInfo<T>::isDummy) { + node = reinterpret_cast<Node *>(new (d->allocateNode()) DummyNode(akey)); + } else { + node = new (d->allocateNode()) Node(akey, avalue); + } + + node->h = ah; + node->next = *anextNode; + *anextNode = node; + ++d->size; + return node; +} + +template <class Key, class T> +Q_INLINE_TEMPLATE QHash<Key, T> &QHash<Key, T>::unite(const QHash<Key, T> &other) +{ + QHash<Key, T> copy(other); + const_iterator it = copy.constEnd(); + while (it != copy.constBegin()) { + --it; + insertMulti(it.key(), it.value()); + } + return *this; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::freeData(QHashData *x) +{ + Node *e_for_x = reinterpret_cast<Node *>(x); + Node **bucket = reinterpret_cast<Node **>(x->buckets); + int n = x->numBuckets; + while (n--) { + Node *cur = *bucket++; + while (cur != e_for_x) { + Node *next = cur->next; + deleteNode(cur); + cur = next; + } + } + x->destroyAndFree(); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE void QHash<Key, T>::clear() +{ + *this = QHash<Key,T>(); +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE void QHash<Key, T>::detach_helper() +{ + QHashData *x = d->detach_helper(duplicateNode, + QTypeInfo<T>::isDummy ? sizeof(DummyNode) : sizeof(Node)); + if (!d->ref.deref()) + freeData(d); + d = x; +} + +template <class Key, class T> +Q_INLINE_TEMPLATE QHash<Key, T> &QHash<Key, T>::operator=(const QHash<Key, T> &other) +{ + if (d != other.d) { + other.d->ref.ref(); + if (!d->ref.deref()) + freeData(d); + d = other.d; + if (!d->sharable) + detach_helper(); + } + return *this; +} + +template <class Key, class T> +Q_INLINE_TEMPLATE const T QHash<Key, T>::value(const Key &akey) const +{ + Node *node; + if (d->size == 0 || (node = *findNode(akey)) == e) { + return T(); + } else { + return node->value; + } +} + +template <class Key, class T> +Q_INLINE_TEMPLATE const T QHash<Key, T>::value(const Key &akey, const T &adefaultValue) const +{ + Node *node; + if (d->size == 0 || (node = *findNode(akey)) == e) { + return adefaultValue; + } else { + return node->value; + } +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE QList<Key> QHash<Key, T>::uniqueKeys() const +{ + QList<Key> res; + const_iterator i = begin(); + if (i != end()) { + for (;;) { + const Key &aKey = i.key(); + res.append(aKey); + do { + if (++i == end()) + goto break_out_of_outer_loop; + } while (aKey == i.key()); + } + } +break_out_of_outer_loop: + return res; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE QList<Key> QHash<Key, T>::keys() const +{ + QList<Key> res; + const_iterator i = begin(); + while (i != end()) { + res.append(i.key()); + ++i; + } + return res; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE QList<Key> QHash<Key, T>::keys(const T &avalue) const +{ + QList<Key> res; + const_iterator i = begin(); + while (i != end()) { + if (i.value() == avalue) + res.append(i.key()); + ++i; + } + return res; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE const Key QHash<Key, T>::key(const T &avalue) const +{ + return key(avalue, Key()); +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE const Key QHash<Key, T>::key(const T &avalue, const Key &defaultValue) const +{ + const_iterator i = begin(); + while (i != end()) { + if (i.value() == avalue) + return i.key(); + ++i; + } + + return defaultValue; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE QList<T> QHash<Key, T>::values() const +{ + QList<T> res; + const_iterator i = begin(); + while (i != end()) { + res.append(i.value()); + ++i; + } + return res; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE QList<T> QHash<Key, T>::values(const Key &akey) const +{ + QList<T> res; + Node *node = *findNode(akey); + if (node != e) { + do { + res.append(node->value); + } while ((node = node->next) != e && node->key == akey); + } + return res; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::count(const Key &akey) const +{ + int cnt = 0; + Node *node = *findNode(akey); + if (node != e) { + do { + ++cnt; + } while ((node = node->next) != e && node->key == akey); + } + return cnt; +} + +template <class Key, class T> +Q_INLINE_TEMPLATE const T QHash<Key, T>::operator[](const Key &akey) const +{ + return value(akey); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE T &QHash<Key, T>::operator[](const Key &akey) +{ + detach(); + + uint h; + Node **node = findNode(akey, &h); + if (*node == e) { + if (d->willGrow()) + node = findNode(akey, &h); + return createNode(h, akey, T(), node)->value; + } + return (*node)->value; +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QHash<Key, T>::iterator QHash<Key, T>::insert(const Key &akey, + const T &avalue) +{ + detach(); + + uint h; + Node **node = findNode(akey, &h); + if (*node == e) { + if (d->willGrow()) + node = findNode(akey, &h); + return iterator(createNode(h, akey, avalue, node)); + } + + if (!QTypeInfo<T>::isDummy) + (*node)->value = avalue; + return iterator(*node); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QHash<Key, T>::iterator QHash<Key, T>::insertMulti(const Key &akey, + const T &avalue) +{ + detach(); + d->willGrow(); + + uint h; + Node **nextNode = findNode(akey, &h); + return iterator(createNode(h, akey, avalue, nextNode)); +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::remove(const Key &akey) +{ + detach(); + + int oldSize = d->size; + Node **node = findNode(akey); + if (*node != e) { + bool deleteNext = true; + do { + Node *next = (*node)->next; + deleteNext = (next != e && next->key == (*node)->key); + deleteNode(*node); + *node = next; + --d->size; + } while (deleteNext); + d->hasShrunk(); + } + return oldSize - d->size; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE T QHash<Key, T>::take(const Key &akey) +{ + detach(); + + Node **node = findNode(akey); + if (*node != e) { + T t = (*node)->value; + Node *next = (*node)->next; + deleteNode(*node); + *node = next; + --d->size; + d->hasShrunk(); + return t; + } + return T(); +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::iterator QHash<Key, T>::erase(iterator it) +{ + if (it == iterator(e)) + return it; + + iterator ret = it; + ++ret; + + Node *node = it; + Node **node_ptr = reinterpret_cast<Node **>(&d->buckets[node->h % d->numBuckets]); + while (*node_ptr != node) + node_ptr = &(*node_ptr)->next; + *node_ptr = node->next; + deleteNode(node); + --d->size; + return ret; +} + +template <class Key, class T> +Q_INLINE_TEMPLATE void QHash<Key, T>::reserve(int asize) +{ + detach(); + d->rehash(-qMax(asize, 1)); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QHash<Key, T>::const_iterator QHash<Key, T>::find(const Key &akey) const +{ + return const_iterator(*findNode(akey)); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QHash<Key, T>::const_iterator QHash<Key, T>::constFind(const Key &akey) const +{ + return const_iterator(*findNode(akey)); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QHash<Key, T>::iterator QHash<Key, T>::find(const Key &akey) +{ + detach(); + return iterator(*findNode(akey)); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE bool QHash<Key, T>::contains(const Key &akey) const +{ + return *findNode(akey) != e; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE typename QHash<Key, T>::Node **QHash<Key, T>::findNode(const Key &akey, + uint *ahp) const +{ + Node **node; + uint h = qHash(akey); + + if (d->numBuckets) { + node = reinterpret_cast<Node **>(&d->buckets[h % d->numBuckets]); + Q_ASSERT(*node == e || (*node)->next); + while (*node != e && !(*node)->same_key(h, akey)) + node = &(*node)->next; + } else { + node = const_cast<Node **>(reinterpret_cast<const Node * const *>(&e)); + } + if (ahp) + *ahp = h; + return node; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE bool QHash<Key, T>::operator==(const QHash<Key, T> &other) const +{ + if (size() != other.size()) + return false; + if (d == other.d) + return true; + + const_iterator it = begin(); + + while (it != end()) { + const Key &akey = it.key(); + + const_iterator it2 = other.find(akey); + do { + if (it2 == other.end() || !(it2.key() == akey)) + return false; + if (!QTypeInfo<T>::isDummy && !(it.value() == it2.value())) + return false; + ++it; + ++it2; + } while (it != end() && it.key() == akey); + } + return true; +} + +template <class Key, class T> +class QMultiHash : public QHash<Key, T> +{ +public: + QMultiHash() {} + QMultiHash(const QHash<Key, T> &other) : QHash<Key, T>(other) {} + + inline typename QHash<Key, T>::iterator replace(const Key &key, const T &value) + { return QHash<Key, T>::insert(key, value); } + + inline typename QHash<Key, T>::iterator insert(const Key &key, const T &value) + { return QHash<Key, T>::insertMulti(key, value); } + + inline QMultiHash &operator+=(const QMultiHash &other) + { unite(other); return *this; } + inline QMultiHash operator+(const QMultiHash &other) const + { QMultiHash result = *this; result += other; return result; } + +#ifndef Q_NO_USING_KEYWORD + using QHash<Key, T>::contains; + using QHash<Key, T>::remove; + using QHash<Key, T>::count; + using QHash<Key, T>::find; + using QHash<Key, T>::constFind; +#else + inline bool contains(const Key &key) const + { return QHash<Key, T>::contains(key); } + inline int remove(const Key &key) + { return QHash<Key, T>::remove(key); } + inline int count(const Key &key) const + { return QHash<Key, T>::count(key); } + inline int count() const + { return QHash<Key, T>::count(); } + inline typename QHash<Key, T>::iterator find(const Key &key) + { return QHash<Key, T>::find(key); } + inline typename QHash<Key, T>::const_iterator find(const Key &key) const + { return QHash<Key, T>::find(key); } + inline typename QHash<Key, T>::const_iterator constFind(const Key &key) const + { return QHash<Key, T>::constFind(key); } +#endif + + bool contains(const Key &key, const T &value) const; + + int remove(const Key &key, const T &value); + + int count(const Key &key, const T &value) const; + + typename QHash<Key, T>::iterator find(const Key &key, const T &value) { + typename QHash<Key, T>::iterator i(find(key)); + typename QHash<Key, T>::iterator end(this->end()); + while (i != end && i.key() == key) { + if (i.value() == value) + return i; + ++i; + } + return end; + } + typename QHash<Key, T>::const_iterator find(const Key &key, const T &value) const { + typename QHash<Key, T>::const_iterator i(constFind(key)); + typename QHash<Key, T>::const_iterator end(QHash<Key, T>::constEnd()); + while (i != end && i.key() == key) { + if (i.value() == value) + return i; + ++i; + } + return end; + } + typename QHash<Key, T>::const_iterator constFind(const Key &key, const T &value) const + { return find(key, value); } +private: + T &operator[](const Key &key); + const T operator[](const Key &key) const; +}; + +template <class Key, class T> +Q_INLINE_TEMPLATE bool QMultiHash<Key, T>::contains(const Key &key, const T &value) const +{ + return constFind(key, value) != QHash<Key, T>::constEnd(); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE int QMultiHash<Key, T>::remove(const Key &key, const T &value) +{ + int n = 0; + typename QHash<Key, T>::iterator i(find(key)); + typename QHash<Key, T>::iterator end(QHash<Key, T>::end()); + while (i != end && i.key() == key) { + if (i.value() == value) { + i = erase(i); + ++n; + } else { + ++i; + } + } + return n; +} + +template <class Key, class T> +Q_INLINE_TEMPLATE int QMultiHash<Key, T>::count(const Key &key, const T &value) const +{ + int n = 0; + typename QHash<Key, T>::const_iterator i(constFind(key)); + typename QHash<Key, T>::const_iterator end(QHash<Key, T>::constEnd()); + while (i != end && i.key() == key) { + if (i.value() == value) + ++n; + ++i; + } + return n; +} + +Q_DECLARE_ASSOCIATIVE_ITERATOR(Hash) +Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Hash) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QHASH_H diff --git a/src/corelib/tools/qiterator.h b/src/corelib/tools/qiterator.h new file mode 100644 index 0000000..3f050fe --- /dev/null +++ b/src/corelib/tools/qiterator.h @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QITERATOR_H +#define QITERATOR_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_HEADER + +namespace std { + struct bidirectional_iterator_tag; + struct random_access_iterator_tag; +} + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +#define Q_DECLARE_SEQUENTIAL_ITERATOR(C) \ +\ +template <class T> \ +class Q##C##Iterator \ +{ \ + typedef typename Q##C<T>::const_iterator const_iterator; \ + Q##C<T> c; \ + const_iterator i; \ +public: \ + inline Q##C##Iterator(const Q##C<T> &container) \ + : c(container), i(c.constBegin()) {} \ + inline Q##C##Iterator &operator=(const Q##C<T> &container) \ + { c = container; i = c.constBegin(); return *this; } \ + inline void toFront() { i = c.constBegin(); } \ + inline void toBack() { i = c.constEnd(); } \ + inline bool hasNext() const { return i != c.constEnd(); } \ + inline const T &next() { return *i++; } \ + inline const T &peekNext() const { return *i; } \ + inline bool hasPrevious() const { return i != c.constBegin(); } \ + inline const T &previous() { return *--i; } \ + inline const T &peekPrevious() const { const_iterator p = i; return *--p; } \ + inline bool findNext(const T &t) \ + { while (i != c.constEnd()) if (*i++ == t) return true; return false; } \ + inline bool findPrevious(const T &t) \ + { while (i != c.constBegin()) if (*(--i) == t) return true; \ + return false; } \ +}; + +#define Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(C) \ +\ +template <class T> \ +class QMutable##C##Iterator \ +{ \ + typedef typename Q##C<T>::iterator iterator; \ + typedef typename Q##C<T>::const_iterator const_iterator; \ + Q##C<T> *c; \ + iterator i, n; \ + inline bool item_exists() const { return const_iterator(n) != c->constEnd(); } \ +public: \ + inline QMutable##C##Iterator(Q##C<T> &container) \ + : c(&container) \ + { c->setSharable(false); i = c->begin(); n = c->end(); } \ + inline ~QMutable##C##Iterator() \ + { c->setSharable(true); } \ + inline QMutable##C##Iterator &operator=(Q##C<T> &container) \ + { c->setSharable(true); c = &container; c->setSharable(false); \ + i = c->begin(); n = c->end(); return *this; } \ + inline void toFront() { i = c->begin(); n = c->end(); } \ + inline void toBack() { i = c->end(); n = i; } \ + inline bool hasNext() const { return c->constEnd() != const_iterator(i); } \ + inline T &next() { n = i++; return *n; } \ + inline T &peekNext() const { return *i; } \ + inline bool hasPrevious() const { return c->constBegin() != const_iterator(i); } \ + inline T &previous() { n = --i; return *n; } \ + inline T &peekPrevious() const { iterator p = i; return *--p; } \ + inline void remove() \ + { if (c->constEnd() != const_iterator(n)) { i = c->erase(n); n = c->end(); } } \ + inline void setValue(const T &t) const { if (c->constEnd() != const_iterator(n)) *n = t; } \ + inline T &value() { Q_ASSERT(item_exists()); return *n; } \ + inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \ + inline void insert(const T &t) { n = i = c->insert(i, t); ++i; } \ + inline bool findNext(const T &t) \ + { while (c->constEnd() != const_iterator(n = i)) if (*i++ == t) return true; return false; } \ + inline bool findPrevious(const T &t) \ + { while (c->constBegin() != const_iterator(i)) if (*(n = --i) == t) return true; \ + n = c->end(); return false; } \ +}; + +#define Q_DECLARE_ASSOCIATIVE_ITERATOR(C) \ +\ +template <class Key, class T> \ +class Q##C##Iterator \ +{ \ + typedef typename Q##C<Key,T>::const_iterator const_iterator; \ + typedef const_iterator Item; \ + Q##C<Key,T> c; \ + const_iterator i, n; \ + inline bool item_exists() const { return n != c.constEnd(); } \ +public: \ + inline Q##C##Iterator(const Q##C<Key,T> &container) \ + : c(container), i(c.constBegin()), n(c.constEnd()) {} \ + inline Q##C##Iterator &operator=(const Q##C<Key,T> &container) \ + { c = container; i = c.constBegin(); n = c.constEnd(); return *this; } \ + inline void toFront() { i = c.constBegin(); n = c.constEnd(); } \ + inline void toBack() { i = c.constEnd(); n = c.constEnd(); } \ + inline bool hasNext() const { return i != c.constEnd(); } \ + inline Item next() { n = i++; return n; } \ + inline Item peekNext() const { return i; } \ + inline bool hasPrevious() const { return i != c.constBegin(); } \ + inline Item previous() { n = --i; return n; } \ + inline Item peekPrevious() const { const_iterator p = i; return --p; } \ + inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \ + inline const Key &key() const { Q_ASSERT(item_exists()); return n.key(); } \ + inline bool findNext(const T &t) \ + { while ((n = i) != c.constEnd()) if (*i++ == t) return true; return false; } \ + inline bool findPrevious(const T &t) \ + { while (i != c.constBegin()) if (*(n = --i) == t) return true; \ + n = c.constEnd(); return false; } \ +}; + +#define Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(C) \ +\ +template <class Key, class T> \ +class QMutable##C##Iterator \ +{ \ + typedef typename Q##C<Key,T>::iterator iterator; \ + typedef typename Q##C<Key,T>::const_iterator const_iterator; \ + typedef iterator Item; \ + Q##C<Key,T> *c; \ + iterator i, n; \ + inline bool item_exists() const { return const_iterator(n) != c->constEnd(); } \ +public: \ + inline QMutable##C##Iterator(Q##C<Key,T> &container) \ + : c(&container) \ + { c->setSharable(false); i = c->begin(); n = c->end(); } \ + inline ~QMutable##C##Iterator() \ + { c->setSharable(true); } \ + inline QMutable##C##Iterator &operator=(Q##C<Key,T> &container) \ + { c->setSharable(true); c = &container; c->setSharable(false); i = c->begin(); n = c->end(); return *this; } \ + inline void toFront() { i = c->begin(); n = c->end(); } \ + inline void toBack() { i = c->end(); n = c->end(); } \ + inline bool hasNext() const { return const_iterator(i) != c->constEnd(); } \ + inline Item next() { n = i++; return n; } \ + inline Item peekNext() const { return i; } \ + inline bool hasPrevious() const { return const_iterator(i) != c->constBegin(); } \ + inline Item previous() { n = --i; return n; } \ + inline Item peekPrevious() const { iterator p = i; return --p; } \ + inline void remove() \ + { if (const_iterator(n) != c->constEnd()) { i = c->erase(n); n = c->end(); } } \ + inline void setValue(const T &t) { if (const_iterator(n) != c->constEnd()) *n = t; } \ + inline T &value() { Q_ASSERT(item_exists()); return *n; } \ + inline const T &value() const { Q_ASSERT(item_exists()); return *n; } \ + inline const Key &key() const { Q_ASSERT(item_exists()); return n.key(); } \ + inline bool findNext(const T &t) \ + { while (const_iterator(n = i) != c->constEnd()) if (*i++ == t) return true; return false; } \ + inline bool findPrevious(const T &t) \ + { while (const_iterator(i) != c->constBegin()) if (*(n = --i) == t) return true; \ + n = c->end(); return false; } \ +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QITERATOR_H diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp new file mode 100644 index 0000000..f615dcd --- /dev/null +++ b/src/corelib/tools/qline.cpp @@ -0,0 +1,867 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qline.h" +#include "qdebug.h" +#include "qdatastream.h" +#include "qmath.h" +#include <private/qnumeric_p.h> + +QT_BEGIN_NAMESPACE + +/*! + \class QLine + \ingroup multimedia + + \brief The QLine class provides a two-dimensional vector using + integer precision. + + A QLine describes a finite length line (or a line segment) on a + two-dimensional surface. The start and end points of the line are + specified using integer point accuracy for coordinates. Use the + QLineF constructor to retrieve a floating point copy. + + \table + \row + \o \inlineimage qline-point.png + \o \inlineimage qline-coordinates.png + \endtable + + The positions of the line's start and end points can be retrieved + using the p1(), x1(), y1(), p2(), x2(), and y2() functions. The + dx() and dy() functions return the horizontal and vertical + components of the line. Use isNull() to determine whether the + QLine represents a valid line or a null line. + + Finally, the line can be translated a given offset using the + translate() function. + + \sa QLineF, QPolygon, QRect +*/ + +/*! + \fn QLine::QLine() + + Constructs a null line. +*/ + +/*! + \fn QLine::QLine(const QPoint &p1, const QPoint &p2) + + Constructs a line object that represents the line between \a p1 and + \a p2. +*/ + +/*! + \fn QLine::QLine(int x1, int y1, int x2, int y2) + + Constructs a line object that represents the line between (\a x1, \a y1) and + (\a x2, \a y2). +*/ + +/*! + \fn bool QLine::isNull() const + + Returns true if the line is not set up with valid start and end point; + otherwise returns false. +*/ + +/*! + \fn QPoint QLine::p1() const + + Returns the line's start point. + + \sa x1(), y1(), p2() +*/ + +/*! + \fn QPoint QLine::p2() const + + Returns the line's end point. + + \sa x2(), y2(), p1() +*/ + +/*! + \fn int QLine::x1() const + + Returns the x-coordinate of the line's start point. + + \sa p1() +*/ + +/*! + \fn int QLine::y1() const + + Returns the y-coordinate of the line's start point. + + \sa p1() +*/ + +/*! + \fn int QLine::x2() const + + Returns the x-coordinate of the line's end point. + + \sa p2() +*/ + +/*! + \fn int QLine::y2() const + + Returns the y-coordinate of the line's end point. + + \sa p2() +*/ + +/*! + \fn int QLine::dx() const + + Returns the horizontal component of the line's vector. + + \sa dy() +*/ + +/*! + \fn int QLine::dy() const + + Returns the vertical component of the line's vector. + + \sa dx() +*/ + +/*! + \fn bool QLine::operator!=(const QLine &line) const + + Returns true if the given \a line is not the same as \e this line. + + A line is different from another line if any of their start or + end points differ, or the internal order of the points is different. +*/ + +/*! + \fn bool QLine::operator==(const QLine &line) const + + Returns true if the given \a line is the same as \e this line. + + A line is identical to another line if the start and end points + are identical, and the internal order of the points is the same. +*/ + +/*! + \fn void QLine::translate(const QPoint &offset) + + Translates this line by the given \a offset. +*/ + +/*! + \fn void QLine::translate(int dx, int dy) + \overload + + Translates this line the distance specified by \a dx and \a dy. +*/ + +/*! + \fn QLine QLine::translated(const QPoint &offset) const + + \since 4.4 + + Returns this line translated by the given \a offset. +*/ + +/*! + \fn QLine QLine::translated(int dx, int dy) const + \overload + \since 4.4 + + Returns this line translated the distance specified by \a dx and \a dy. +*/ + + +/*! + \fn void QLine::setP1(const QPoint &p1) + \since 4.4 + + Sets the starting point of this line to \a p1. + + \sa setP2(), p1() +*/ + + +/*! + \fn void QLine::setP2(const QPoint &p2) + \since 4.4 + + Sets the end point of this line to \a p2. + + \sa setP1(), p2() +*/ + + +/*! + \fn void QLine::setPoints(const QPoint &p1, const QPoint &p2) + \since 4.4 + + Sets the start point of this line to \a p1 and the end point of this line to \a p2. + + \sa setP1(), setP2(), p1(), p2() +*/ + + +/*! + \fn void QLine::setLine(int x1, int y1, int x2, int y2) + \since 4.4 + + Sets this line to the start in \a x1, \a y1 and end in \a x2, \a y2. + + \sa setP1(), setP2(), p1(), p2() +*/ + + + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const QLine &p) +{ + d << "QLine(" << p.p1() << "," << p.p2() << ")"; + return d; +} +#endif + +#ifndef QT_NO_DATASTREAM +/*! + \relates QLine + + Writes the given \a line to the given \a stream and returns a + reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator<<(QDataStream &stream, const QLine &line) +{ + stream << line.p1() << line.p2(); + return stream; +} + +/*! + \relates QLine + + Reads a line from the given \a stream into the given \a line and + returns a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator>>(QDataStream &stream, QLine &line) +{ + QPoint p1, p2; + stream >> p1; + stream >> p2; + line = QLine(p1, p2); + + return stream; +} + +#endif // QT_NO_DATASTREAM + + +#ifndef M_2PI +#define M_2PI 6.28318530717958647692528676655900576 +#endif + +/*! + \class QLineF + \ingroup multimedia + + \brief The QLineF class provides a two-dimensional vector using + floating point precision. + + A QLineF describes a finite length line (or line segment) on a + two-dimensional surface. QLineF defines the start and end points + of the line using floating point accuracy for coordinates. Use + the toLine() function to retrieve an integer based copy of this + line. + + \table + \row + \o \inlineimage qline-point.png + \o \inlineimage qline-coordinates.png + \endtable + + The positions of the line's start and end points can be retrieved + using the p1(), x1(), y1(), p2(), x2(), and y2() functions. The + dx() and dy() functions return the horizontal and vertical + components of the line, respectively. + + The line's length can be retrieved using the length() function, + and altered using the setLength() function. Similarly, angle() + and setAngle() are respectively used for retrieving and altering + the angle of the line. Use the isNull() + function to determine whether the QLineF represents a valid line + or a null line. + + The intersect() function determines the IntersectType for this + line and a given line, while the angle() function returns the + angle between the lines. In addition, the unitVector() function + returns a line that has the same starting point as this line, but + with a length of only 1, while the normalVector() function returns + a line that is perpendicular to this line with the same starting + point and length. + + Finally, the line can be translated a given offset using the + translate() function, and can be traversed using the pointAt() + function. + + \sa QLine, QPolygonF, QRectF +*/ + +/*! + \enum QLineF::IntersectType + + Describes the intersection between two lines. + + \table + \row + \o \inlineimage qlinef-unbounded.png + \o \inlineimage qlinef-bounded.png + \row + \o QLineF::UnboundedIntersection + \o QLineF::BoundedIntersection + \endtable + + \value NoIntersection Indicates that the lines do not intersect; + i.e. they are parallel. + + \value UnboundedIntersection The two lines intersect, but not + within the range defined by their lengths. This will be the case + if the lines are not parallel. + + intersect() will also return this value if the intersect point is + within the start and end point of only one of the lines. + + \value BoundedIntersection The two lines intersect with each other + within the start and end points of each line. + + \sa intersect() +*/ + +/*! + \fn QLineF::QLineF() + + Constructs a null line. +*/ + +/*! + \fn QLineF::QLineF(const QPointF &p1, const QPointF &p2) + + Constructs a line object that represents the line between \a p1 and + \a p2. +*/ + +/*! + \fn QLineF::QLineF(qreal x1, qreal y1, qreal x2, qreal y2) + + Constructs a line object that represents the line between (\a x1, \a y1) and + (\a x2, \a y2). +*/ + +/*! + \fn QLineF::QLineF(const QLine &line) + + Construct a QLineF object from the given integer-based \a line. + + \sa toLine() +*/ + +/*! + Returns true if the line is not set up with valid start and end point; + otherwise returns false. +*/ + +bool QLineF::isNull() const +{ + return (qFuzzyCompare(pt1.x(), pt2.x()) && qFuzzyCompare(pt1.y(), pt2.y())) ? true : false; +} + + +/*! + \fn QPointF QLineF::p1() const + + Returns the line's start point. + + \sa x1(), y1(), p2() +*/ + +/*! + \fn QPointF QLineF::p2() const + + Returns the line's end point. + + \sa x2(), y2(), p1() +*/ + +/*! + \fn QLine QLineF::toLine() const + + Returns an integer based copy of this line. + + Note that the returned line's start and end points are rounded to + the nearest integer. + + \sa QLineF() +*/ +/*! + \fn qreal QLineF::x1() const + + Returns the x-coordinate of the line's start point. + + \sa p1() +*/ + +/*! + \fn qreal QLineF::y1() const + + Returns the y-coordinate of the line's start point. + + \sa p1() +*/ + +/*! + \fn qreal QLineF::x2() const + + Returns the x-coordinate of the line's end point. + + \sa p2() +*/ + +/*! + \fn qreal QLineF::y2() const + + Returns the y-coordinate of the line's end point. + + \sa p2() +*/ + +/*! + \fn qreal QLineF::dx() const + + Returns the horizontal component of the line's vector. + + \sa dy(), pointAt() +*/ + +/*! + \fn qreal QLineF::dy() const + + Returns the vertical component of the line's vector. + + \sa dx(), pointAt() +*/ + +/*! + \fn QLineF::setLength(qreal length) + + Sets the length of the line to the given \a length. QLineF will + move the end point - p2() - of the line to give the line its new length. + + If the line is a null line, the length will remain zero regardless + of the length specified. + + \sa length(), isNull() +*/ + +/*! + \fn QLineF QLineF::normalVector() const + + Returns a line that is perpendicular to this line with the same starting + point and length. + + \image qlinef-normalvector.png + + \sa unitVector() +*/ + +/*! + \fn bool QLineF::operator!=(const QLineF &line) const + + Returns true if the given \a line is not the same as \e this line. + + A line is different from another line if their start or end points + differ, or the internal order of the points is different. +*/ + +/*! + \fn bool QLineF::operator==(const QLineF &line) const + + Returns true if the given \a line is the same as this line. + + A line is identical to another line if the start and end points + are identical, and the internal order of the points is the same. +*/ + +/*! + \fn qreal QLineF::pointAt(qreal t) const + + Returns the point at the parameterized position specified by \a + t. The function returns the line's start point if t = 0, and its end + point if t = 1. + + \sa dx(), dy() +*/ + +/*! + Returns the length of the line. + + \sa setLength() +*/ +qreal QLineF::length() const +{ + qreal x = pt2.x() - pt1.x(); + qreal y = pt2.y() - pt1.y(); + return qSqrt(x*x + y*y); +} + +/*! + \since 4.4 + + Returns the angle of the line in degrees. + + Positive values for the angles mean counter-clockwise while negative values + mean the clockwise direction. Zero degrees is at the 3 o'clock position. + + \sa setAngle() +*/ +qreal QLineF::angle() const +{ + const qreal dx = pt2.x() - pt1.x(); + const qreal dy = pt2.y() - pt1.y(); + + const qreal theta = atan2(-dy, dx) * 360.0 / M_2PI; + + const qreal theta_normalized = theta < 0 ? theta + 360 : theta; + + if (qFuzzyCompare(theta_normalized, qreal(360))) + return qreal(0); + else + return theta_normalized; +} + +/*! + \since 4.4 + + Sets the angle of the line to the given \a angle (in degrees). + This will change the position of the second point of the line such that + the line has the given angle. + + Positive values for the angles mean counter-clockwise while negative values + mean the clockwise direction. Zero degrees is at the 3 o'clock position. + + \sa angle() +*/ +void QLineF::setAngle(qreal angle) +{ + const qreal angleR = angle * M_2PI / 360.0; + const qreal l = length(); + + const qreal dx = qCos(angleR) * l; + const qreal dy = -qSin(angleR) * l; + + pt2.rx() = pt1.x() + dx; + pt2.ry() = pt1.y() + dy; +} + +/*! + \since 4.4 + + Returns a QLineF with the given \a length and \a angle. + + The first point of the line will be on the origin. + + Positive values for the angles mean counter-clockwise while negative values + mean the clockwise direction. Zero degrees is at the 3 o'clock position. +*/ +QLineF QLineF::fromPolar(qreal length, qreal angle) +{ + const qreal angleR = angle * M_2PI / 360.0; + return QLineF(0, 0, qCos(angleR) * length, -qSin(angleR) * length); +} + +/*! + Returns the unit vector for this line, i.e a line starting at the + same point as \e this line with a length of 1.0. + + \sa normalVector() +*/ +QLineF QLineF::unitVector() const +{ + qreal x = pt2.x() - pt1.x(); + qreal y = pt2.y() - pt1.y(); + + qreal len = qSqrt(x*x + y*y); + QLineF f(p1(), QPointF(pt1.x() + x/len, pt1.y() + y/len)); + +#ifndef QT_NO_DEBUG + if (qAbs(f.length() - 1) >= 0.001) + qWarning("QLine::unitVector: New line does not have unit length"); +#endif + + return f; +} + +/*! + \fn QLineF::IntersectType QLineF::intersect(const QLineF &line, QPointF *intersectionPoint) const + + Returns a value indicating whether or not \e this line intersects + with the given \a line. + + The actual intersection point is extracted to \a intersectionPoint + (if the pointer is valid). If the lines are parallel, the + intersection point is undefined. +*/ + +QLineF::IntersectType QLineF::intersect(const QLineF &l, QPointF *intersectionPoint) const +{ + // ipmlementation is based on Graphics Gems III's "Faster Line Segment Intersection" + const QPointF a = pt2 - pt1; + const QPointF b = l.pt1 - l.pt2; + const QPointF c = pt1 - l.pt1; + + const qreal denominator = a.y() * b.x() - a.x() * b.y(); + if (denominator == 0 || !qt_is_finite(denominator)) + return NoIntersection; + + const qreal reciprocal = 1 / denominator; + const qreal na = (b.y() * c.x() - b.x() * c.y()) * reciprocal; + if (intersectionPoint) + *intersectionPoint = pt1 + a * na; + + if (na < 0 || na > 1) + return UnboundedIntersection; + + const qreal nb = (a.x() * c.y() - a.y() * c.x()) * reciprocal; + if (nb < 0 || nb > 1) + return UnboundedIntersection; + + return BoundedIntersection; +} + +/*! + \fn void QLineF::translate(const QPointF &offset) + + Translates this line by the given \a offset. +*/ + +/*! + \fn void QLineF::translate(qreal dx, qreal dy) + \overload + + Translates this line the distance specified by \a dx and \a dy. +*/ + +/*! + \fn QLineF QLineF::translated(const QPointF &offset) const + + \since 4.4 + + Returns this line translated by the given \a offset. +*/ + +/*! + \fn QLineF QLineF::translated(qreal dx, qreal dy) const + \overload + \since 4.4 + + Returns this line translated the distance specified by \a dx and \a dy. +*/ + +/*! + \fn void QLineF::setP1(const QPointF &p1) + \since 4.4 + + Sets the starting point of this line to \a p1. + + \sa setP2(), p1() +*/ + + +/*! + \fn void QLineF::setP2(const QPointF &p2) + \since 4.4 + + Sets the end point of this line to \a p2. + + \sa setP1(), p2() +*/ + + +/*! + \fn void QLineF::setPoints(const QPointF &p1, const QPointF &p2) + \since 4.4 + + Sets the start point of this line to \a p1 and the end point of this line to \a p2. + + \sa setP1(), setP2(), p1(), p2() +*/ + + +/*! + \fn void QLineF::setLine(qreal x1, qreal y1, qreal x2, qreal y2) + \since 4.4 + + Sets this line to the start in \a x1, \a y1 and end in \a x2, \a y2. + + \sa setP1(), setP2(), p1(), p2() +*/ + +/*! + \fn qreal QLineF::angleTo(const QLineF &line) const + + \since 4.4 + + Returns the angle (in degrees) from this line to the given \a + line, taking the direction of the lines into account. If the lines + do not intersect within their range, it is the intersection point of + the extended lines that serves as origin (see + QLineF::UnboundedIntersection). + + The returned value represents the number of degrees you need to add + to this line to make it have the same angle as the given \a line, + going counter-clockwise. + + \sa intersect() +*/ +qreal QLineF::angleTo(const QLineF &l) const +{ + if (isNull() || l.isNull()) + return 0; + + const qreal a1 = angle(); + const qreal a2 = l.angle(); + + const qreal delta = a2 - a1; + const qreal delta_normalized = delta < 0 ? delta + 360 : delta; + + if (qFuzzyCompare(delta, qreal(360))) + return 0; + else + return delta_normalized; +} + +/*! + \fn qreal QLineF::angle(const QLineF &line) const + + \obsolete + + Returns the angle (in degrees) between this line and the given \a + line, taking the direction of the lines into account. If the lines + do not intersect within their range, it is the intersection point of + the extended lines that serves as origin (see + QLineF::UnboundedIntersection). + + \table + \row + \o \inlineimage qlinef-angle-identicaldirection.png + \o \inlineimage qlinef-angle-oppositedirection.png + \endtable + + When the lines are parallel, this function returns 0 if they have + the same direction; otherwise it returns 180. + + \sa intersect() +*/ +qreal QLineF::angle(const QLineF &l) const +{ + if (isNull() || l.isNull()) + return 0; + qreal cos_line = (dx()*l.dx() + dy()*l.dy()) / (length()*l.length()); + qreal rad = 0; + // only accept cos_line in the range [-1,1], if it is outside, use 0 (we return 0 rather than PI for those cases) + if (cos_line >= -1.0 && cos_line <= 1.0) rad = acos( cos_line ); + return rad * 360 / M_2PI; +} + + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const QLineF &p) +{ + d << "QLineF(" << p.p1() << "," << p.p2() << ")"; + return d; +} +#endif + +#ifndef QT_NO_DATASTREAM +/*! + \relates QLineF + + Writes the given \a line to the given \a stream and returns a + reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator<<(QDataStream &stream, const QLineF &line) +{ + stream << line.p1() << line.p2(); + return stream; +} + +/*! + \relates QLineF + + Reads a line from the given \a stream into the given \a line and + returns a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator>>(QDataStream &stream, QLineF &line) +{ + QPointF start, end; + stream >> start; + stream >> end; + line = QLineF(start, end); + + return stream; +} + +#endif // QT_NO_DATASTREAM + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qline.h b/src/corelib/tools/qline.h new file mode 100644 index 0000000..e4c8c27 --- /dev/null +++ b/src/corelib/tools/qline.h @@ -0,0 +1,424 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLINE_H +#define QLINE_H + +#include <QtCore/qpoint.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +/******************************************************************************* + * class QLine + *******************************************************************************/ + +class Q_CORE_EXPORT QLine +{ +public: + inline QLine(); + inline QLine(const QPoint &pt1, const QPoint &pt2); + inline QLine(int x1, int y1, int x2, int y2); + + inline bool isNull() const; + + inline QPoint p1() const; + inline QPoint p2() const; + + inline int x1() const; + inline int y1() const; + + inline int x2() const; + inline int y2() const; + + inline int dx() const; + inline int dy() const; + + inline void translate(const QPoint &p); + inline void translate(int dx, int dy); + + inline QLine translated(const QPoint &p) const; + inline QLine translated(int dx, int dy) const; + + inline void setP1(const QPoint &p1); + inline void setP2(const QPoint &p2); + inline void setPoints(const QPoint &p1, const QPoint &p2); + inline void setLine(int x1, int y1, int x2, int y2); + + inline bool operator==(const QLine &d) const; + inline bool operator!=(const QLine &d) const { return !(*this == d); } + +private: + QPoint pt1, pt2; +}; +Q_DECLARE_TYPEINFO(QLine, Q_MOVABLE_TYPE); + +/******************************************************************************* + * class QLine inline members + *******************************************************************************/ + +inline QLine::QLine() { } + +inline QLine::QLine(const QPoint &pt1_, const QPoint &pt2_) : pt1(pt1_), pt2(pt2_) { } + +inline QLine::QLine(int x1pos, int y1pos, int x2pos, int y2pos) : pt1(QPoint(x1pos, y1pos)), pt2(QPoint(x2pos, y2pos)) { } + +inline bool QLine::isNull() const +{ + return pt1 == pt2; +} + +inline int QLine::x1() const +{ + return pt1.x(); +} + +inline int QLine::y1() const +{ + return pt1.y(); +} + +inline int QLine::x2() const +{ + return pt2.x(); +} + +inline int QLine::y2() const +{ + return pt2.y(); +} + +inline QPoint QLine::p1() const +{ + return pt1; +} + +inline QPoint QLine::p2() const +{ + return pt2; +} + +inline int QLine::dx() const +{ + return pt2.x() - pt1.x(); +} + +inline int QLine::dy() const +{ + return pt2.y() - pt1.y(); +} + +inline void QLine::translate(const QPoint &point) +{ + pt1 += point; + pt2 += point; +} + +inline void QLine::translate(int adx, int ady) +{ + this->translate(QPoint(adx, ady)); +} + +inline QLine QLine::translated(const QPoint &p) const +{ + return QLine(pt1 + p, pt2 + p); +} + +inline QLine QLine::translated(int adx, int ady) const +{ + return translated(QPoint(adx, ady)); +} + +inline void QLine::setP1(const QPoint &aP1) +{ + pt1 = aP1; +} + +inline void QLine::setP2(const QPoint &aP2) +{ + pt2 = aP2; +} + +inline void QLine::setPoints(const QPoint &aP1, const QPoint &aP2) +{ + pt1 = aP1; + pt2 = aP2; +} + +inline void QLine::setLine(int aX1, int aY1, int aX2, int aY2) +{ + pt1 = QPoint(aX1, aY1); + pt2 = QPoint(aX2, aY2); +} + +inline bool QLine::operator==(const QLine &d) const +{ + return pt1 == d.pt1 && pt2 == d.pt2; +} + +#ifndef QT_NO_DEBUG_STREAM +Q_CORE_EXPORT QDebug operator<<(QDebug d, const QLine &p); +#endif + +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QLine &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QLine &); +#endif + +/******************************************************************************* + * class QLineF + *******************************************************************************/ +class Q_CORE_EXPORT QLineF { +public: + + enum IntersectType { NoIntersection, BoundedIntersection, UnboundedIntersection }; + + inline QLineF(); + inline QLineF(const QPointF &pt1, const QPointF &pt2); + inline QLineF(qreal x1, qreal y1, qreal x2, qreal y2); + inline QLineF(const QLine &line) : pt1(line.p1()), pt2(line.p2()) { } + + static QLineF fromPolar(qreal length, qreal angle); + + bool isNull() const; + + inline QPointF p1() const; + inline QPointF p2() const; + + inline qreal x1() const; + inline qreal y1() const; + + inline qreal x2() const; + inline qreal y2() const; + + inline qreal dx() const; + inline qreal dy() const; + + qreal length() const; + void setLength(qreal len); + + qreal angle() const; + void setAngle(qreal angle); + + qreal angleTo(const QLineF &l) const; + + QLineF unitVector() const; + QLineF normalVector() const; + + // ### Qt 5: rename intersects() or intersection() and rename IntersectType IntersectionType + IntersectType intersect(const QLineF &l, QPointF *intersectionPoint) const; + + qreal angle(const QLineF &l) const; + + QPointF pointAt(qreal t) const; + inline void translate(const QPointF &p); + inline void translate(qreal dx, qreal dy); + + inline QLineF translated(const QPointF &p) const; + inline QLineF translated(qreal dx, qreal dy) const; + + inline void setP1(const QPointF &p1); + inline void setP2(const QPointF &p2); + inline void setPoints(const QPointF &p1, const QPointF &p2); + inline void setLine(qreal x1, qreal y1, qreal x2, qreal y2); + + inline bool operator==(const QLineF &d) const; + inline bool operator!=(const QLineF &d) const { return !(*this == d); } + + QLine toLine() const; + +private: + QPointF pt1, pt2; +}; +Q_DECLARE_TYPEINFO(QLineF, Q_MOVABLE_TYPE); + +/******************************************************************************* + * class QLineF inline members + *******************************************************************************/ + +inline QLineF::QLineF() +{ +} + +inline QLineF::QLineF(const QPointF &apt1, const QPointF &apt2) + : pt1(apt1), pt2(apt2) +{ +} + +inline QLineF::QLineF(qreal x1pos, qreal y1pos, qreal x2pos, qreal y2pos) + : pt1(x1pos, y1pos), pt2(x2pos, y2pos) +{ +} + +inline qreal QLineF::x1() const +{ + return pt1.x(); +} + +inline qreal QLineF::y1() const +{ + return pt1.y(); +} + +inline qreal QLineF::x2() const +{ + return pt2.x(); +} + +inline qreal QLineF::y2() const +{ + return pt2.y(); +} + +inline QPointF QLineF::p1() const +{ + return pt1; +} + +inline QPointF QLineF::p2() const +{ + return pt2; +} + +inline qreal QLineF::dx() const +{ + return pt2.x() - pt1.x(); +} + +inline qreal QLineF::dy() const +{ + return pt2.y() - pt1.y(); +} + +inline QLineF QLineF::normalVector() const +{ + return QLineF(p1(), p1() + QPointF(dy(), -dx())); +} + +inline void QLineF::translate(const QPointF &point) +{ + pt1 += point; + pt2 += point; +} + +inline void QLineF::translate(qreal adx, qreal ady) +{ + this->translate(QPointF(adx, ady)); +} + +inline QLineF QLineF::translated(const QPointF &p) const +{ + return QLineF(pt1 + p, pt2 + p); +} + +inline QLineF QLineF::translated(qreal adx, qreal ady) const +{ + return translated(QPointF(adx, ady)); +} + +inline void QLineF::setLength(qreal len) +{ + if (isNull()) + return; + QLineF v = unitVector(); + pt2 = QPointF(pt1.x() + v.dx() * len, pt1.y() + v.dy() * len); +} + +inline QPointF QLineF::pointAt(qreal t) const +{ + qreal vx = pt2.x() - pt1.x(); + qreal vy = pt2.y() - pt1.y(); + return QPointF(pt1.x() + vx * t, pt1.y() + vy * t); +} + +inline QLine QLineF::toLine() const +{ + return QLine(pt1.toPoint(), pt2.toPoint()); +} + + +inline void QLineF::setP1(const QPointF &aP1) +{ + pt1 = aP1; +} + +inline void QLineF::setP2(const QPointF &aP2) +{ + pt2 = aP2; +} + +inline void QLineF::setPoints(const QPointF &aP1, const QPointF &aP2) +{ + pt1 = aP1; + pt2 = aP2; +} + +inline void QLineF::setLine(qreal aX1, qreal aY1, qreal aX2, qreal aY2) +{ + pt1 = QPointF(aX1, aY1); + pt2 = QPointF(aX2, aY2); +} + + +inline bool QLineF::operator==(const QLineF &d) const +{ + return pt1 == d.pt1 && pt2 == d.pt2; +} + + + +#ifndef QT_NO_DEBUG_STREAM +Q_CORE_EXPORT QDebug operator<<(QDebug d, const QLineF &p); +#endif + +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QLineF &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QLineF &); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QLINE_H diff --git a/src/corelib/tools/qlinkedlist.cpp b/src/corelib/tools/qlinkedlist.cpp new file mode 100644 index 0000000..a3cbecc --- /dev/null +++ b/src/corelib/tools/qlinkedlist.cpp @@ -0,0 +1,1158 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlinkedlist.h" + +QT_BEGIN_NAMESPACE + +QLinkedListData QLinkedListData::shared_null = { + &QLinkedListData::shared_null, &QLinkedListData::shared_null, + Q_BASIC_ATOMIC_INITIALIZER(1), 0, true +}; + +/*! \class QLinkedList + \brief The QLinkedList class is a template class that provides linked lists. + + \ingroup tools + \ingroup shared + \mainclass + \reentrant + + QLinkedList\<T\> is one of Qt's generic \l{container classes}. It + stores a list of values and provides iterator-based access as + well as \l{constant time} insertions and removals. + + QList\<T\>, QLinkedList\<T\>, and QVector\<T\> provide similar + functionality. Here's an overview: + + \list + \i For most purposes, QList is the right class to use. Its + index-based API is more convenient than QLinkedList's + iterator-based API, and it is usually faster than + QVector because of the way it stores its items in + memory (see \l{Algorithmic Complexity} for details). + It also expands to less code in your executable. + \i If you need a real linked list, with guarantees of \l{constant + time} insertions in the middle of the list and iterators to + items rather than indexes, use QLinkedList. + \i If you want the items to occupy adjacent memory positions, + use QVector. + \endlist + + Here's an example of a QLinkedList that stores integers and a + QLinkedList that stores QTime values: + + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 0 + + QLinkedList stores a list of items. The default constructor + creates an empty list. To insert items into the list, you can use + operator<<(): + + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 1 + + If you want to get the first or last item in a linked list, use + first() or last(). If you want to remove an item from either end + of the list, use removeFirst() or removeLast(). If you want to + remove all occurrences of a given value in the list, use + removeAll(). + + A common requirement is to remove the first or last item in the + list and do something with it. For this, QLinkedList provides + takeFirst() and takeLast(). Here's a loop that removes the items + from a list one at a time and calls \c delete on them: + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 2 + + QLinkedList's value type must be an \l {assignable data type}. This + covers most data types that are commonly used, but the compiler + won't let you, for example, store a QWidget as a value; instead, + store a QWidget *. A few functions have additional requirements; + for example, contains() and removeAll() expect the value type to + support \c operator==(). These requirements are documented on a + per-function basis. + + If you want to insert, modify, or remove items in the middle of + the list, you must use an iterator. QLinkedList provides both + \l{Java-style iterators} (QLinkedListIterator and + QMutableLinkedListIterator) and \l{STL-style iterators} + (QLinkedList::const_iterator and QLinkedList::iterator). See the + documentation for these classes for details. + + \sa QLinkedListIterator, QMutableLinkedListIterator, QList, QVector +*/ + +/*! \fn QLinkedList::QLinkedList() + + Constructs an empty list. +*/ + +/*! \fn QLinkedList::QLinkedList(const QLinkedList<T> &other) + + Constructs a copy of \a other. + + This operation occurs in \l{constant time}, because QLinkedList + is \l{implicitly shared}. This makes returning a QLinkedList from + a function very fast. If a shared instance is modified, it will + be copied (copy-on-write), and this takes \l{linear time}. + + \sa operator=() +*/ + +/*! \fn QLinkedList::~QLinkedList() + + Destroys the list. References to the values in the list, and all + iterators over this list, become invalid. +*/ + +/*! \fn QLinkedList<T> &QLinkedList::operator=(const QLinkedList<T> &other) + + Assigns \a other to this list and returns a reference to this + list. +*/ + +/*! \fn bool QLinkedList::operator==(const QLinkedList<T> &other) const + + Returns true if \a other is equal to this list; otherwise returns + false. + + Two lists are considered equal if they contain the same values in + the same order. + + This function requires the value type to implement \c + operator==(). + + \sa operator!=() +*/ + +/*! \fn bool QLinkedList::operator!=(const QLinkedList<T> &other) const + + Returns true if \a other is not equal to this list; otherwise + returns false. + + Two lists are considered equal if they contain the same values in + the same order. + + This function requires the value type to implement \c + operator==(). + + \sa operator==() +*/ + +/*! \fn int QLinkedList::size() const + + Returns the number of items in the list. + + \sa isEmpty(), count() +*/ + +/*! \fn void QLinkedList::detach() + + \internal +*/ + +/*! \fn bool QLinkedList::isDetached() const + + \internal +*/ + +/*! \fn void QLinkedList::setSharable(bool sharable) + + \internal +*/ + +/*! \fn bool QLinkedList::isEmpty() const + + Returns true if the list contains no items; otherwise returns + false. + + \sa size() +*/ + +/*! \fn void QLinkedList::clear() + + Removes all the items in the list. + + \sa removeAll() +*/ + +/*! \fn void QLinkedList::append(const T &value) + + Inserts \a value at the end of the list. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 3 + + This is the same as list.insert(end(), \a value). + + \sa operator<<(), prepend(), insert() +*/ + +/*! \fn void QLinkedList::prepend(const T &value) + + Inserts \a value at the beginning of the list. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 4 + + This is the same as list.insert(begin(), \a value). + + \sa append(), insert() +*/ + +/*! \fn int QLinkedList::removeAll(const T &value) + + Removes all occurrences of \a value in the list. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 5 + + This function requires the value type to have an implementation of + \c operator==(). + + \sa insert() +*/ + +/*! + \fn bool QLinkedList::removeOne(const T &value) + \since 4.4 + + Removes the first occurrences of \a value in the list. Returns true on + success; otherwise returns false. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 6 + + This function requires the value type to have an implementation of + \c operator==(). + + \sa insert() +*/ + +/*! \fn bool QLinkedList::contains(const T &value) const + + Returns true if the list contains an occurrence of \a value; + otherwise returns false. + + This function requires the value type to have an implementation of + \c operator==(). + + \sa QLinkedListIterator::findNext(), QLinkedListIterator::findPrevious() +*/ + +/*! \fn int QLinkedList::count(const T &value) const + + Returns the number of occurrences of \a value in the list. + + This function requires the value type to have an implementation of + \c operator==(). + + \sa contains() +*/ + +/*! \fn bool QLinkedList::startsWith(const T &value) const + \since 4.5 + + Returns true if the list is not empty and its first + item is equal to \a value; otherwise returns false. + + \sa isEmpty(), first() +*/ + +/*! \fn bool QLinkedList::endsWith(const T &value) const + \since 4.5 + + Returns true if the list is not empty and its last + item is equal to \a value; otherwise returns false. + + \sa isEmpty(), last() +*/ + +/*! \fn QLinkedList::iterator QLinkedList::begin() + + Returns an \l{STL-style iterator} pointing to the first item in + the list. + + \sa constBegin(), end() +*/ + +/*! \fn QLinkedList::const_iterator QLinkedList::begin() const + + \overload +*/ + +/*! \fn QLinkedList::const_iterator QLinkedList::constBegin() const + + Returns a const \l{STL-style iterator} pointing to the first item + in the list. + + \sa begin(), constEnd() +*/ + +/*! \fn QLinkedList::iterator QLinkedList::end() + + Returns an \l{STL-style iterator} pointing to the imaginary item + after the last item in the list. + + \sa begin(), constEnd() +*/ + +/*! \fn QLinkedList::const_iterator QLinkedList::end() const + + \overload +*/ + +/*! \fn QLinkedList::const_iterator QLinkedList::constEnd() const + + Returns a const \l{STL-style iterator} pointing to the imaginary + item after the last item in the list. + + \sa constBegin(), end() +*/ + +/*! \fn QLinkedList::iterator QLinkedList::insert(iterator before, const T &value) + + Inserts \a value in front of the item pointed to by the iterator + \a before. Returns an iterator pointing at the inserted item. + + \sa erase() +*/ + +/*! \fn QLinkedList::iterator QLinkedList::erase(iterator pos) + + Removes the item pointed to by the iterator \a pos from the list, + and returns an iterator to the next item in the list (which may be + end()). + + \sa insert() +*/ + +/*! \fn QLinkedList::iterator QLinkedList::erase(iterator begin, iterator end) + + \overload + + Removes all the items from \a begin up to (but not including) \a + end. +*/ + +/*! \typedef QLinkedList::Iterator + + Qt-style synonym for QLinkedList::iterator. +*/ + +/*! \typedef QLinkedList::ConstIterator + + Qt-style synonym for QLinkedList::const_iterator. +*/ + +/*! + \typedef QLinkedList::size_type + + Typedef for int. Provided for STL compatibility. +*/ + +/*! + \typedef QLinkedList::value_type + + Typedef for T. Provided for STL compatibility. +*/ + +/*! + \typedef QLinkedList::pointer + + Typedef for T *. Provided for STL compatibility. +*/ + +/*! + \typedef QLinkedList::const_pointer + + Typedef for const T *. Provided for STL compatibility. +*/ + +/*! + \typedef QLinkedList::reference + + Typedef for T &. Provided for STL compatibility. +*/ + +/*! + \typedef QLinkedList::const_reference + + Typedef for const T &. Provided for STL compatibility. +*/ + +/*! + \typedef QLinkedList::difference_type + + Typedef for ptrdiff_t. Provided for STL compatibility. +*/ + +/*! \fn int QLinkedList::count() const + + Same as size(). +*/ + +/*! \fn T& QLinkedList::first() + + Returns a reference to the first item in the list. This function + assumes that the list isn't empty. + + \sa last(), isEmpty() +*/ + +/*! \fn const T& QLinkedList::first() const + + \overload +*/ + +/*! \fn T& QLinkedList::last() + + Returns a reference to the last item in the list. This function + assumes that the list isn't empty. + + \sa first(), isEmpty() +*/ + +/*! \fn const T& QLinkedList::last() const + + \overload +*/ + +/*! \fn void QLinkedList::removeFirst() + + Removes the first item in the list. + + This is the same as erase(begin()). + + \sa removeLast(), erase() +*/ + +/*! \fn void QLinkedList::removeLast() + + Removes the last item in the list. + + \sa removeFirst(), erase() +*/ + +/*! \fn T QLinkedList::takeFirst() + + Removes the first item in the list and returns it. + + If you don't use the return value, removeFirst() is more + efficient. + + \sa takeLast(), removeFirst() +*/ + +/*! \fn T QLinkedList::takeLast() + + Removes the last item in the list and returns it. + + If you don't use the return value, removeLast() is more + efficient. + + \sa takeFirst(), removeLast() +*/ + +/*! \fn void QLinkedList::push_back(const T &value) + + This function is provided for STL compatibility. It is equivalent + to append(\a value). +*/ + +/*! \fn void QLinkedList::push_front(const T &value) + + This function is provided for STL compatibility. It is equivalent + to prepend(\a value). +*/ + +/*! \fn T& QLinkedList::front() + + This function is provided for STL compatibility. It is equivalent + to first(). +*/ + +/*! \fn const T& QLinkedList::front() const + + \overload +*/ + +/*! \fn T& QLinkedList::back() + + This function is provided for STL compatibility. It is equivalent + to last(). +*/ + +/*! \fn const T& QLinkedList::back() const + + \overload +*/ + +/*! \fn void QLinkedList::pop_front() + + This function is provided for STL compatibility. It is equivalent + to removeFirst(). +*/ + +/*! \fn void QLinkedList::pop_back() + + This function is provided for STL compatibility. It is equivalent + to removeLast(). +*/ + +/*! \fn bool QLinkedList::empty() const + + This function is provided for STL compatibility. It is equivalent + to isEmpty() and returns true if the list is empty. +*/ + +/*! \fn QLinkedList<T> &QLinkedList::operator+=(const QLinkedList<T> &other) + + Appends the items of the \a other list to this list and returns a + reference to this list. + + \sa operator+(), append() +*/ + +/*! \fn void QLinkedList::operator+=(const T &value) + + \overload + + Appends \a value to the list. +*/ + +/*! \fn QLinkedList<T> QLinkedList::operator+(const QLinkedList<T> &other) const + + Returns a list that contains all the items in this list followed + by all the items in the \a other list. + + \sa operator+=() +*/ + +/*! \fn QLinkedList<T> &QLinkedList::operator<<(const QLinkedList<T> &other) + + Appends the items of the \a other list to this list and returns a + reference to this list. + + \sa operator+=(), append() +*/ + +/*! \fn QLinkedList<T> &QLinkedList::operator<<(const T &value) + + \overload + + Appends \a value to the list. +*/ + +/*! \class QLinkedList::iterator + \brief The QLinkedList::iterator class provides an STL-style non-const iterator for QLinkedList. + + QLinkedList features both \l{STL-style iterators} and + \l{Java-style iterators}. The STL-style iterators are more + low-level and more cumbersome to use; on the other hand, they are + slightly faster and, for developers who already know STL, have + the advantage of familiarity. + + QLinkedList\<T\>::iterator allows you to iterate over a + QLinkedList\<T\> and to modify the list item associated with the + iterator. If you want to iterate over a const QLinkedList, use + QLinkedList::const_iterator instead. It is generally good + practice to use QLinkedList::const_iterator on a non-const + QLinkedList as well, unless you need to change the QLinkedList + through the iterator. Const iterators are slightly faster, and + can improve code readability. + + The default QLinkedList::iterator constructor creates an + uninitialized iterator. You must initialize it using a + function like QLinkedList::begin(), QLinkedList::end(), or + QLinkedList::insert() before you can start iterating. Here's a + typical loop that prints all the items stored in a list: + + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 7 + + STL-style iterators can be used as arguments to \l{generic + algorithms}. For example, here's how to find an item in the list + using the qFind() algorithm: + + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 8 + + Let's see a few examples of things we can do with a + QLinkedList::iterator that we cannot do with a QLinkedList::const_iterator. + Here's an example that increments every value stored in a + QLinkedList\<int\> by 2: + + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 9 + + Here's an example that removes all the items that start with an + underscore character in a QLinkedList\<QString\>: + + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 10 + + The call to QLinkedList::erase() removes the item pointed to by + the iterator from the list, and returns an iterator to the next + item. Here's another way of removing an item while iterating: + + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 11 + + It might be tempting to write code like this: + + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 12 + + However, this will potentially crash in \c{++i}, because \c i is + a dangling iterator after the call to erase(). + + Multiple iterators can be used on the same list. If you add items + to the list, existing iterators will remain valid. If you remove + items from the list, iterators that point to the removed items + will become dangling iterators. However, because of how \l{implicit + sharing} works, you must not take a copy of a container while + iterators are active on that container. + + \sa QLinkedList::const_iterator, QMutableLinkedListIterator +*/ + +/*! \fn QLinkedList::iterator::iterator() + + Constructs an uninitialized iterator. + + Functions like operator*() and operator++() should not be called + on an uninitialized iterartor. Use operator=() to assign a value + to it before using it. + + \sa QLinkedList::begin() QLinkedList::end() +*/ + +/*! \fn QLinkedList::iterator::iterator(Node *node) + + \internal +*/ + +/*! \typedef QLinkedList::iterator::iterator_category + + \internal +*/ + +/*! \typedef QLinkedList::iterator::difference_type + + \internal +*/ + +/*! \typedef QLinkedList::iterator::value_type + + \internal +*/ + +/*! \typedef QLinkedList::iterator::pointer + + \internal +*/ + +/*! \typedef QLinkedList::iterator::reference + + \internal +*/ + +/*! \fn QLinkedList::iterator::iterator(const iterator &other) + + Constructs a copy of \a other. +*/ + +/*! \fn QLinkedList::iterator &QLinkedList::iterator::operator=(const iterator &other) + + Assigns \a other to this iterator. +*/ + +/*! \fn T &QLinkedList::iterator::operator*() const + + Returns a modifiable reference to the current item. + + You can change the value of an item by using operator*() on the + left side of an assignment, for example: + + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 13 + + \sa operator->() +*/ + +/*! \fn T *QLinkedList::iterator::operator->() const + + Returns a pointer to the current item. + + \sa operator*() +*/ + +/*! + \fn bool QLinkedList::iterator::operator==(const iterator &other) const + \fn bool QLinkedList::iterator::operator==(const const_iterator &other) const + + Returns true if \a other points to the same item as this + iterator; otherwise returns false. + + \sa operator!=() +*/ + +/*! + \fn bool QLinkedList::iterator::operator!=(const iterator &other) const + \fn bool QLinkedList::iterator::operator!=(const const_iterator &other) const + + Returns true if \a other points to a different item than this + iterator; otherwise returns false. + + \sa operator==() +*/ + +/*! \fn QLinkedList::iterator &QLinkedList::iterator::operator++() + + The prefix ++ operator (\c{++it}) advances the iterator to the + next item in the list and returns an iterator to the new current + item. + + Calling this function on QLinkedList::end() leads to undefined + results. + + \sa operator--() +*/ + +/*! \fn QLinkedList::iterator QLinkedList::iterator::operator++(int) + + \overload + + The postfix ++ operator (\c{it++}) advances the iterator to the + next item in the list and returns an iterator to the previously + current item. +*/ + +/*! \fn QLinkedList::iterator &QLinkedList::iterator::operator--() + + The prefix -- operator (\c{--it}) makes the preceding item + current and returns an iterator to the new current item. + + Calling this function on QLinkedList::begin() leads to undefined + results. + + \sa operator++() +*/ + +/*! \fn QLinkedList::iterator QLinkedList::iterator::operator--(int) + + \overload + + The postfix -- operator (\c{it--}) makes the preceding item + current and returns an iterator to the previously current item. +*/ + +/*! \fn QLinkedList::iterator QLinkedList::iterator::operator+(int j) const + + Returns an iterator to the item at \a j positions forward from + this iterator. (If \a j is negative, the iterator goes backward.) + + This operation can be slow for large \a j values. + + \sa operator-() + +*/ + +/*! \fn QLinkedList::iterator QLinkedList::iterator::operator-(int j) const + + Returns an iterator to the item at \a j positions backward from + this iterator. (If \a j is negative, the iterator goes forward.) + + This operation can be slow for large \a j values. + + \sa operator+() +*/ + +/*! \fn QLinkedList::iterator &QLinkedList::iterator::operator+=(int j) + + Advances the iterator by \a j items. (If \a j is negative, the + iterator goes backward.) + + \sa operator-=(), operator+() +*/ + +/*! \fn QLinkedList::iterator &QLinkedList::iterator::operator-=(int j) + + Makes the iterator go back by \a j items. (If \a j is negative, + the iterator goes forward.) + + \sa operator+=(), operator-() +*/ + +/*! \class QLinkedList::const_iterator + \brief The QLinkedList::const_iterator class provides an STL-style const iterator for QLinkedList. + + QLinkedList features both \l{STL-style iterators} and + \l{Java-style iterators}. The STL-style iterators are more + low-level and more cumbersome to use; on the other hand, they are + slightly faster and, for developers who already know STL, have + the advantage of familiarity. + + QLinkedList\<T\>::const_iterator allows you to iterate over a + QLinkedList\<T\>. If you want modify the QLinkedList as you iterate + over it, you must use QLinkedList::const_iterator instead. It is + generally good practice to use QLinkedList::const_iterator on a + non-const QLinkedList as well, unless you need to change the + QLinkedList through the iterator. Const iterators are slightly + faster, and can improve code readability. + + The default QLinkedList::const_iterator constructor creates an + uninitialized iterator. You must initialize it using a function + like QLinkedList::constBegin(), QLinkedList::constEnd(), or + QLinkedList::insert() before you can start iterating. Here's a + typical loop that prints all the items stored in a list: + + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 14 + + STL-style iterators can be used as arguments to \l{generic + algorithms}. For example, here's how to find an item in the list + using the qFind() algorithm: + + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 15 + + Multiple iterators can be used on the same list. If you add items + to the list, existing iterators will remain valid. If you remove + items from the list, iterators that point to the removed items + will become dangling iterators. + + \sa QLinkedList::iterator, QLinkedListIterator +*/ + +/*! \fn QLinkedList::const_iterator::const_iterator() + + Constructs an uninitialized iterator. + + Functions like operator*() and operator++() should not be called + on an uninitialized iterartor. Use operator=() to assign a value + to it before using it. + + \sa QLinkedList::constBegin() QLinkedList::constEnd() +*/ + +/*! \fn QLinkedList::const_iterator::const_iterator(Node *node) + + \internal +*/ + +/*! \typedef QLinkedList::const_iterator::iterator_category + + \internal +*/ + +/*! \typedef QLinkedList::const_iterator::difference_type + + \internal +*/ + +/*! \typedef QLinkedList::const_iterator::value_type + + \internal +*/ + +/*! \typedef QLinkedList::const_iterator::pointer + + \internal +*/ + +/*! \typedef QLinkedList::const_iterator::reference + + \internal +*/ + +/*! \fn QLinkedList::const_iterator::const_iterator(const const_iterator &other) + + Constructs a copy of \a other. +*/ + +/*! \fn QLinkedList::const_iterator::const_iterator(iterator other) + + Constructs a copy of \a other. +*/ + +/*! \fn QLinkedList::const_iterator &QLinkedList::const_iterator::operator=( \ + const const_iterator &other) + + Assigns \a other to this iterator. +*/ + +/*! \fn const T &QLinkedList::const_iterator::operator*() const + + Returns a reference to the current item. + + \sa operator->() +*/ + +/*! \fn const T *QLinkedList::const_iterator::operator->() const + + Returns a pointer to the current item. + + \sa operator*() +*/ + +/*! \fn bool QLinkedList::const_iterator::operator==(const const_iterator &other) const + + Returns true if \a other points to the same item as this + iterator; otherwise returns false. + + \sa operator!=() +*/ + +/*! \fn bool QLinkedList::const_iterator::operator!=(const const_iterator &other) const + + Returns true if \a other points to a different item than this + iterator; otherwise returns false. + + \sa operator==() +*/ + +/*! \fn QLinkedList::const_iterator &QLinkedList::const_iterator::operator++() + + The prefix ++ operator (\c{++it}) advances the iterator to the + next item in the list and returns an iterator to the new current + item. + + Calling this function on QLinkedList::constEnd() leads to + undefined results. + + \sa operator--() +*/ + +/*! \fn QLinkedList::const_iterator QLinkedList::const_iterator::operator++(int) + + \overload + + The postfix ++ operator (\c{it++}) advances the iterator to the + next item in the list and returns an iterator to the previously + current item. +*/ + +/*! \fn QLinkedList::const_iterator &QLinkedList::const_iterator::operator--() + + The prefix -- operator (\c{--it}) makes the preceding item + current and returns an iterator to the new current item. + + Calling this function on QLinkedList::begin() leads to undefined + results. + + \sa operator++() +*/ + +/*! \fn QLinkedList::const_iterator QLinkedList::const_iterator::operator--(int) + + \overload + + The postfix -- operator (\c{it--}) makes the preceding item + current and returns an iterator to the previously current item. +*/ + +/*! \fn QLinkedList::const_iterator QLinkedList::const_iterator::operator+(int j) const + + Returns an iterator to the item at \a j positions forward from + this iterator. (If \a j is negative, the iterator goes backward.) + + This operation can be slow for large \a j values. + + \sa operator-() +*/ + +/*! \fn QLinkedList::const_iterator QLinkedList::const_iterator::operator-(int j) const + + This function returns an iterator to the item at \a j positions backward from + this iterator. (If \a j is negative, the iterator goes forward.) + + This operation can be slow for large \a j values. + + \sa operator+() +*/ + +/*! \fn QLinkedList::const_iterator &QLinkedList::const_iterator::operator+=(int j) + + Advances the iterator by \a j items. (If \a j is negative, the + iterator goes backward.) + + This operation can be slow for large \a j values. + + \sa operator-=(), operator+() +*/ + +/*! \fn QLinkedList::const_iterator &QLinkedList::const_iterator::operator-=(int j) + + Makes the iterator go back by \a j items. (If \a j is negative, + the iterator goes forward.) + + This operation can be slow for large \a j values. + + \sa operator+=(), operator-() +*/ + +/*! \fn QDataStream &operator<<(QDataStream &out, const QLinkedList<T> &list) + \relates QLinkedList + + Writes the linked list \a list to stream \a out. + + This function requires the value type to implement \c + operator<<(). + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +/*! \fn QDataStream &operator>>(QDataStream &in, QLinkedList<T> &list) + \relates QLinkedList + + Reads a linked list from stream \a in into \a list. + + This function requires the value type to implement \c operator>>(). + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +/*! + \fn iterator QLinkedList::remove(iterator pos) + + Use erase() instead. +*/ + +/*! + \fn int QLinkedList::findIndex(const T& t) const + + If you need indexes then QList or QVector are better choices than + QLinkedList. + + \oldcode + int index = list->findIndex(value); + \newcode + int index = 0; + bool found = false; + for (const_iterator i = list->begin(); i != list->end(); ++i; ++index) + if (*i == value) { + found = true; + break; + } + if (!found) + index = -1; + \endcode +*/ + +/*! + \fn iterator QLinkedList::find(iterator from, const T& t) + + If you need random access to a data structure then QList, QVector, + QMap, or QHash, are all better choices than QLinkedList. + + \oldcode + QLinkedList::iterator i = list->find(from, value); + \newcode + QLinkedList::iterator i = from; + while (i != list->end() && *i != value) + ++i; + \endcode +*/ + +/*! + \fn iterator QLinkedList::find(const T& t) + + If you need random access to a data structure then QList, QVector, + QMap, or QHash, are all better choices than QLinkedList. + + \oldcode + QLinkedList::iterator i = list->find(value); + \newcode + QLinkedList::iterator i = list->begin(); + while (i != list->end() && *i != value) + ++i; + \endcode +*/ + +/*! + \fn const_iterator QLinkedList::find(const_iterator from, const T& t) const + + If you need random access to a data structure then QList, QVector, + QMap, or QHash, are all better choices than QLinkedList. + + \oldcode + QLinkedList::const_iterator i = list->find(from, value); + \newcode + QLinkedList::const_iterator i = from; + while (i != list->end() && *i != value) + ++i; + \endcode +*/ + +/*! + \fn const_iterator QLinkedList::find(const T& t) const + + If you need random access to a data structure then QList, QVector, + QMap, or QHash, are all better choices than QLinkedList. + + \oldcode + QLinkedList::const_iterator i = list->find(value); + \newcode + QLinkedList::const_iterator i = list->begin(); + while (i != list->end() && *i != value) + ++i; + \endcode +*/ + +/*! + \since 4.1 + \fn QLinkedList<T> QLinkedList<T>::fromStdList(const std::list<T> &list) + + Returns a QLinkedList object with the data contained in \a list. + The order of the elements in the QLinkedList is the same as in \a + list. + + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 16 + + \sa toStdList() +*/ + +/*! + \since 4.1 + \fn std::list<T> QLinkedList<T>::toStdList() const + + Returns a std::list object with the data contained in this + QLinkedList. Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qlinkedlist.cpp 17 + + \sa fromStdList() +*/ + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h new file mode 100644 index 0000000..6a85386 --- /dev/null +++ b/src/corelib/tools/qlinkedlist.h @@ -0,0 +1,504 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLINKEDLIST_H +#define QLINKEDLIST_H + +#include <QtCore/qiterator.h> +#include <QtCore/qatomic.h> + +#ifndef QT_NO_STL +#include <iterator> +#include <list> +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +struct Q_CORE_EXPORT QLinkedListData +{ + QLinkedListData *n, *p; + QBasicAtomicInt ref; + int size; + uint sharable : 1; + + static QLinkedListData shared_null; +}; + +template <typename T> +struct QLinkedListNode +{ + inline QLinkedListNode(const T &arg): t(arg) { } + QLinkedListNode *n, *p; + T t; +}; + +template <class T> +class QLinkedList +{ + typedef QLinkedListNode<T> Node; + union { QLinkedListData *d; QLinkedListNode<T> *e; }; + +public: + inline QLinkedList() : d(&QLinkedListData::shared_null) { d->ref.ref(); } + inline QLinkedList(const QLinkedList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach(); } + ~QLinkedList(); + QLinkedList<T> &operator=(const QLinkedList<T> &); + bool operator==(const QLinkedList<T> &l) const; + inline bool operator!=(const QLinkedList<T> &l) const { return !(*this == l); } + + inline int size() const { return d->size; } + inline void detach() + { if (d->ref != 1) detach_helper(); } + inline bool isDetached() const { return d->ref == 1; } + inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } + + inline bool isEmpty() const { return d->size == 0; } + + void clear(); + + void append(const T &); + void prepend(const T &); + T takeFirst(); + T takeLast(); + int removeAll(const T &t); + bool removeOne(const T &t); + bool contains(const T &t) const; + int count(const T &t) const; + + class const_iterator; + + class iterator + { + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T *pointer; + typedef T &reference; + Node *i; + inline iterator() : i(0) {} + inline iterator(Node *n) : i(n) {} + inline iterator(const iterator &o) : i(o.i) {} + inline iterator &operator=(const iterator &o) { i = o.i; return *this; } + inline T &operator*() const { return i->t; } + inline T *operator->() const { return &i->t; } + inline bool operator==(const iterator &o) const { return i == o.i; } + inline bool operator!=(const iterator &o) const { return i != o.i; } + inline bool operator==(const const_iterator &o) const + { return i == o.i; } + inline bool operator!=(const const_iterator &o) const + { return i != o.i; } + inline iterator &operator++() { i = i->n; return *this; } + inline iterator operator++(int) { Node *n = i; i = i->n; return n; } + inline iterator &operator--() { i = i->p; return *this; } + inline iterator operator--(int) { Node *n = i; i = i->p; return n; } + inline iterator operator+(int j) const + { Node *n = i; if (j > 0) while (j--) n = n->n; else while (j++) n = n->p; return n; } + inline iterator operator-(int j) const { return operator+(-j); } + inline iterator &operator+=(int j) { return *this = *this + j; } + inline iterator &operator-=(int j) { return *this = *this - j; } + }; + friend class iterator; + + class const_iterator + { + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef const T *pointer; + typedef const T &reference; + Node *i; + inline const_iterator() : i(0) {} + inline const_iterator(Node *n) : i(n) {} + inline const_iterator(const const_iterator &o) : i(o.i){} + inline const_iterator(iterator ci) : i(ci.i){} + inline const_iterator &operator=(const const_iterator &o) { i = o.i; return *this; } + inline const T &operator*() const { return i->t; } + inline const T *operator->() const { return &i->t; } + inline bool operator==(const const_iterator &o) const { return i == o.i; } + inline bool operator!=(const const_iterator &o) const { return i != o.i; } + inline const_iterator &operator++() { i = i->n; return *this; } + inline const_iterator operator++(int) { Node *n = i; i = i->n; return n; } + inline const_iterator &operator--() { i = i->p; return *this; } + inline const_iterator operator--(int) { Node *n = i; i = i->p; return n; } + inline const_iterator operator+(int j) const + { Node *n = i; if (j > 0) while (j--) n = n->n; else while (j++) n = n->p; return n; } + inline const_iterator operator-(int j) const { return operator+(-j); } + inline const_iterator &operator+=(int j) { return *this = *this + j; } + inline const_iterator &operator-=(int j) { return *this = *this - j; } + }; + friend class const_iterator; + + // stl style + inline iterator begin() { detach(); return e->n; } + inline const_iterator begin() const { return e->n; } + inline const_iterator constBegin() const { return e->n; } + inline iterator end() { detach(); return e; } + inline const_iterator end() const { return e; } + inline const_iterator constEnd() const { return e; } + iterator insert(iterator before, const T &t); + iterator erase(iterator pos); + iterator erase(iterator first, iterator last); + + // more Qt + typedef iterator Iterator; + typedef const_iterator ConstIterator; + inline int count() const { return d->size; } + inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); } + inline const T& first() const { Q_ASSERT(!isEmpty()); return *begin(); } + T& last() { Q_ASSERT(!isEmpty()); return *(--end()); } + const T& last() const { Q_ASSERT(!isEmpty()); return *(--end()); } + inline void removeFirst() { Q_ASSERT(!isEmpty()); erase(begin()); } + inline void removeLast() { Q_ASSERT(!isEmpty()); erase(--end()); } + inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; } + inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; } + + // stl compatibility + inline void push_back(const T &t) { append(t); } + inline void push_front(const T &t) { prepend(t); } + inline T& front() { return first(); } + inline const T& front() const { return first(); } + inline T& back() { return last(); } + inline const T& back() const { return last(); } + inline void pop_front() { removeFirst(); } + inline void pop_back() { removeLast(); } + inline bool empty() const { return isEmpty(); } + typedef int size_type; + typedef T value_type; + typedef value_type *pointer; + typedef const value_type *const_pointer; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef ptrdiff_t difference_type; + +#ifndef QT_NO_STL + static inline QLinkedList<T> fromStdList(const std::list<T> &list) + { QLinkedList<T> tmp; qCopy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; } + inline std::list<T> toStdList() const + { std::list<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; } +#endif + +#ifdef QT3_SUPPORT + // compatibility + inline QT3_SUPPORT iterator remove(iterator pos) { return erase(pos); } + inline QT3_SUPPORT int findIndex(const T& t) const + { int i=0; for (const_iterator it = begin(); it != end(); ++it, ++i) if(*it == t) return i; return -1;} + inline QT3_SUPPORT iterator find(iterator from, const T& t) + { while (from != end() && !(*from == t)) ++from; return from; } + inline QT3_SUPPORT iterator find(const T& t) + { return find(begin(), t); } + inline QT3_SUPPORT const_iterator find(const_iterator from, const T& t) const + { while (from != end() && !(*from == t)) ++from; return from; } + inline QT3_SUPPORT const_iterator find(const T& t) const + { return find(begin(), t); } +#endif + + // comfort + QLinkedList<T> &operator+=(const QLinkedList<T> &l); + QLinkedList<T> operator+(const QLinkedList<T> &l) const; + inline QLinkedList<T> &operator+=(const T &t) { append(t); return *this; } + inline QLinkedList<T> &operator<< (const T &t) { append(t); return *this; } + inline QLinkedList<T> &operator<<(const QLinkedList<T> &l) { *this += l; return *this; } + +private: + void detach_helper(); + void free(QLinkedListData*); +}; + +template <typename T> +inline QLinkedList<T>::~QLinkedList() +{ + if (!d) + return; + if (!d->ref.deref()) + free(d); +} + +template <typename T> +void QLinkedList<T>::detach_helper() +{ + union { QLinkedListData *d; Node *e; } x; + x.d = new QLinkedListData; + x.d->ref = 1; + x.d->size = d->size; + x.d->sharable = true; + Node *i = e->n, *j = x.e; + while (i != e) { + j->n = new Node(i->t); + j->n->p = j; + i = i->n; + j = j->n; + } + j->n = x.e; + x.e->p = j; + if (!d->ref.deref()) + free(d); + d = x.d; +} + +template <typename T> +void QLinkedList<T>::free(QLinkedListData *x) +{ + Node *y = reinterpret_cast<Node*>(x); + Node *i = y->n; + if (x->ref == 0) { + while(i != y) { + Node *n = i; + i = i->n; + delete n; + } + delete x; + } +} + +template <typename T> +void QLinkedList<T>::clear() +{ + *this = QLinkedList<T>(); +} + +template <typename T> +QLinkedList<T> &QLinkedList<T>::operator=(const QLinkedList<T> &l) +{ + if (d != l.d) { + l.d->ref.ref(); + if (!d->ref.deref()) + free(d); + d = l.d; + if (!d->sharable) + detach_helper(); + } + return *this; +} + +template <typename T> +bool QLinkedList<T>::operator== (const QLinkedList<T> &l) const +{ + if (d->size != l.d->size) + return false; + if (e == l.e) + return true; + Node *i = e->n; + Node *il = l.e->n; + while (i != e) { + if (! (i->t == il->t)) + return false; + i = i->n; + il = il->n; + } + return true; +} + +template <typename T> +void QLinkedList<T>::append(const T &t) +{ + detach(); + Node *i = new Node(t); + i->n = e; + i->p = e->p; + i->p->n = i; + e->p = i; + d->size++; +} + +template <typename T> +void QLinkedList<T>::prepend(const T &t) +{ + detach(); + Node *i = new Node(t); + i->n = e->n; + i->p = e; + i->n->p = i; + e->n = i; + d->size++; +} + +template <typename T> +int QLinkedList<T>::removeAll(const T &_t) +{ + detach(); + const T t = _t; + Node *i = e->n; + int c = 0; + while (i != e) { + if (i->t == t) { + Node *n = i; + i->n->p = i->p; + i->p->n = i->n; + i = i->n; + delete n; + c++; + } else { + i = i->n; + } + } + d->size-=c; + return c; +} + +template <typename T> +bool QLinkedList<T>::removeOne(const T &_t) +{ + detach(); + iterator it = qFind(begin(), end(), _t); + if (it != end()) { + erase(it); + return true; + } + return false; +} + +template <typename T> +inline T QLinkedList<T>::takeFirst() +{ + T t = first(); + removeFirst(); + return t; +} + +template <typename T> +inline T QLinkedList<T>::takeLast() +{ + T t = last(); + removeLast(); + return t; +} + +template <typename T> +bool QLinkedList<T>::contains(const T &t) const +{ + Node *i = e; + while ((i = i->n) != e) + if (i->t == t) + return true; + return false; +} + +template <typename T> +int QLinkedList<T>::count(const T &t) const +{ + Node *i = e; + int c = 0; + while ((i = i->n) != e) + if (i->t == t) + c++; + return c; +} + + +template <typename T> +typename QLinkedList<T>::iterator QLinkedList<T>::insert(iterator before, const T &t) +{ + Node *i = before.i; + Node *m = new Node(t); + m->n = i; + m->p = i->p; + m->p->n = m; + i->p = m; + d->size++; + return m; +} + +template <typename T> +typename QLinkedList<T>::iterator QLinkedList<T>::erase(typename QLinkedList<T>::iterator afirst, + typename QLinkedList<T>::iterator alast) +{ + while (afirst != alast) + erase(afirst++); + return alast; +} + + +template <typename T> +typename QLinkedList<T>::iterator QLinkedList<T>::erase(iterator pos) +{ + detach(); + Node *i = pos.i; + if (i != e) { + Node *n = i; + i->n->p = i->p; + i->p->n = i->n; + i = i->n; + delete n; + d->size--; + } + return i; +} + +template <typename T> +QLinkedList<T> &QLinkedList<T>::operator+=(const QLinkedList<T> &l) +{ + detach(); + int n = l.d->size; + d->size += n; + Node *o = l.e->n; + while (n--) { + Node *i = new Node(o->t); + o = o->n; + i->n = e; + i->p = e->p; + i->p->n = i; + e->p = i; + } + return *this; +} + +template <typename T> +QLinkedList<T> QLinkedList<T>::operator+(const QLinkedList<T> &l) const +{ + QLinkedList<T> n = *this; + n += l; + return n; +} + +Q_DECLARE_SEQUENTIAL_ITERATOR(LinkedList) +Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(LinkedList) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QLINKEDLIST_H diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h new file mode 100644 index 0000000..3c21ec1 --- /dev/null +++ b/src/corelib/tools/qlist.h @@ -0,0 +1,691 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLIST_H +#define QLIST_H + +#include <QtCore/qiterator.h> +#include <QtCore/qatomic.h> +#include <QtCore/qalgorithms.h> + +#ifndef QT_NO_STL +#include <iterator> +#include <list> +#endif + +#include <new> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +template <typename T> class QVector; +template <typename T> class QSet; + +struct Q_CORE_EXPORT QListData { + struct Data { + QBasicAtomicInt ref; + int alloc, begin, end; + uint sharable : 1; + void *array[1]; + }; + enum { DataHeaderSize = sizeof(Data) - sizeof(void *) }; + + Data *detach(); // remove in 5.0 + Data *detach2(); + void realloc(int alloc); + static Data shared_null; + Data *d; + void **erase(void **xi); + void **append(); + void **append(const QListData &l); + void **prepend(); + void **insert(int i); + void remove(int i); + void remove(int i, int n); + void move(int from, int to); + inline int size() const { return d->end - d->begin; } + inline bool isEmpty() const { return d->end == d->begin; } + inline void **at(int i) const { return d->array + d->begin + i; } + inline void **begin() const { return d->array + d->begin; } + inline void **end() const { return d->array + d->end; } +}; + +template <typename T> +class QList +{ + struct Node { void *v; +#if defined(Q_CC_BOR) + Q_INLINE_TEMPLATE T &t(); +#else + Q_INLINE_TEMPLATE T &t() + { return *reinterpret_cast<T*>(QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic + ? v : this); } +#endif + }; + + union { QListData p; QListData::Data *d; }; + +public: + inline QList() : d(&QListData::shared_null) { d->ref.ref(); } + inline QList(const QList<T> &l) : d(l.d) { d->ref.ref(); if (!d->sharable) detach_helper(); } + ~QList(); + QList<T> &operator=(const QList<T> &l); + bool operator==(const QList<T> &l) const; + inline bool operator!=(const QList<T> &l) const { return !(*this == l); } + + inline int size() const { return p.size(); } + + inline void detach() { if (d->ref != 1) detach_helper(); } + inline bool isDetached() const { return d->ref == 1; } + inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } + + inline bool isEmpty() const { return p.isEmpty(); } + + void clear(); + + const T &at(int i) const; + const T &operator[](int i) const; + T &operator[](int i); + + void append(const T &t); + void append(const QList<T> &t); + void prepend(const T &t); + void insert(int i, const T &t); + void replace(int i, const T &t); + void removeAt(int i); + int removeAll(const T &t); + bool removeOne(const T &t); + T takeAt(int i); + T takeFirst(); + T takeLast(); + void move(int from, int to); + void swap(int i, int j); + int indexOf(const T &t, int from = 0) const; + int lastIndexOf(const T &t, int from = -1) const; + QBool contains(const T &t) const; + int count(const T &t) const; + + class const_iterator; + + class iterator { + public: + Node *i; + typedef std::random_access_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T *pointer; + typedef T &reference; + + inline iterator() : i(0) {} + inline iterator(Node *n) : i(n) {} + inline iterator(const iterator &o): i(o.i){} + inline T &operator*() const { return i->t(); } + inline T *operator->() const { return &i->t(); } + inline T &operator[](int j) const { return i[j].t(); } + inline bool operator==(const iterator &o) const { return i == o.i; } + inline bool operator!=(const iterator &o) const { return i != o.i; } + inline bool operator<(const iterator& other) const { return i < other.i; } + inline bool operator<=(const iterator& other) const { return i <= other.i; } + inline bool operator>(const iterator& other) const { return i > other.i; } + inline bool operator>=(const iterator& other) const { return i >= other.i; } +#ifndef QT_STRICT_ITERATORS + inline bool operator==(const const_iterator &o) const + { return i == o.i; } + inline bool operator!=(const const_iterator &o) const + { return i != o.i; } + inline bool operator<(const const_iterator& other) const + { return i < other.i; } + inline bool operator<=(const const_iterator& other) const + { return i <= other.i; } + inline bool operator>(const const_iterator& other) const + { return i > other.i; } + inline bool operator>=(const const_iterator& other) const + { return i >= other.i; } +#endif + inline iterator &operator++() { ++i; return *this; } + inline iterator operator++(int) { Node *n = i; ++i; return n; } + inline iterator &operator--() { i--; return *this; } + inline iterator operator--(int) { Node *n = i; i--; return n; } + inline iterator &operator+=(int j) { i+=j; return *this; } + inline iterator &operator-=(int j) { i-=j; return *this; } + inline iterator operator+(int j) const { return iterator(i+j); } + inline iterator operator-(int j) const { return iterator(i-j); } + inline int operator-(iterator j) const { return i - j.i; } + }; + friend class iterator; + + class const_iterator { + public: + Node *i; + typedef std::random_access_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef const T *pointer; + typedef const T &reference; + + inline const_iterator() : i(0) {} + inline const_iterator(Node *n) : i(n) {} + inline const_iterator(const const_iterator &o): i(o.i) {} +#ifdef QT_STRICT_ITERATORS + inline explicit const_iterator(const iterator &o): i(o.i) {} +#else + inline const_iterator(const iterator &o): i(o.i) {} +#endif + inline const T &operator*() const { return i->t(); } + inline const T *operator->() const { return &i->t(); } + inline const T &operator[](int j) const { return i[j].t(); } + inline bool operator==(const const_iterator &o) const { return i == o.i; } + inline bool operator!=(const const_iterator &o) const { return i != o.i; } + inline bool operator<(const const_iterator& other) const { return i < other.i; } + inline bool operator<=(const const_iterator& other) const { return i <= other.i; } + inline bool operator>(const const_iterator& other) const { return i > other.i; } + inline bool operator>=(const const_iterator& other) const { return i >= other.i; } + inline const_iterator &operator++() { ++i; return *this; } + inline const_iterator operator++(int) { Node *n = i; ++i; return n; } + inline const_iterator &operator--() { i--; return *this; } + inline const_iterator operator--(int) { Node *n = i; i--; return n; } + inline const_iterator &operator+=(int j) { i+=j; return *this; } + inline const_iterator &operator-=(int j) { i-=j; return *this; } + inline const_iterator operator+(int j) const { return const_iterator(i+j); } + inline const_iterator operator-(int j) const { return const_iterator(i-j); } + inline int operator-(const_iterator j) const { return i - j.i; } + }; + friend class const_iterator; + + // stl style + inline iterator begin() { detach(); return reinterpret_cast<Node *>(p.begin()); } + inline const_iterator begin() const { return reinterpret_cast<Node *>(p.begin()); } + inline const_iterator constBegin() const { return reinterpret_cast<Node *>(p.begin()); } + inline iterator end() { detach(); return reinterpret_cast<Node *>(p.end()); } + inline const_iterator end() const { return reinterpret_cast<Node *>(p.end()); } + inline const_iterator constEnd() const { return reinterpret_cast<Node *>(p.end()); } + iterator insert(iterator before, const T &t); + iterator erase(iterator pos); + iterator erase(iterator first, iterator last); + + // more Qt + typedef iterator Iterator; + typedef const_iterator ConstIterator; + inline int count() const { return p.size(); } + inline int length() const { return p.size(); } // Same as count() + inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); } + inline const T& first() const { Q_ASSERT(!isEmpty()); return *begin(); } + T& last() { Q_ASSERT(!isEmpty()); return *(--end()); } + const T& last() const { Q_ASSERT(!isEmpty()); return *(--end()); } + inline void removeFirst() { Q_ASSERT(!isEmpty()); erase(begin()); } + inline void removeLast() { Q_ASSERT(!isEmpty()); erase(--end()); } + inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; } + inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; } + QList<T> mid(int pos, int length = -1) const; + + T value(int i) const; + T value(int i, const T &defaultValue) const; + + // stl compatibility + inline void push_back(const T &t) { append(t); } + inline void push_front(const T &t) { prepend(t); } + inline T& front() { return first(); } + inline const T& front() const { return first(); } + inline T& back() { return last(); } + inline const T& back() const { return last(); } + inline void pop_front() { removeFirst(); } + inline void pop_back() { removeLast(); } + inline bool empty() const { return isEmpty(); } + typedef int size_type; + typedef T value_type; + typedef value_type *pointer; + typedef const value_type *const_pointer; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef ptrdiff_t difference_type; + +#ifdef QT3_SUPPORT + inline QT3_SUPPORT iterator remove(iterator pos) { return erase(pos); } + inline QT3_SUPPORT int remove(const T &t) { return removeAll(t); } + inline QT3_SUPPORT int findIndex(const T& t) const { return indexOf(t); } + inline QT3_SUPPORT iterator find(const T& t) + { int i = indexOf(t); return (i == -1 ? end() : (begin()+i)); } + inline QT3_SUPPORT const_iterator find (const T& t) const + { int i = indexOf(t); return (i == -1 ? end() : (begin()+i)); } + inline QT3_SUPPORT iterator find(iterator from, const T& t) + { int i = indexOf(t, from - begin()); return i == -1 ? end() : begin()+i; } + inline QT3_SUPPORT const_iterator find(const_iterator from, const T& t) const + { int i = indexOf(t, from - begin()); return i == -1 ? end() : begin()+i; } +#endif + + // comfort + QList<T> &operator+=(const QList<T> &l); + inline QList<T> operator+(const QList<T> &l) const + { QList n = *this; n += l; return n; } + inline QList<T> &operator+=(const T &t) + { append(t); return *this; } + inline QList<T> &operator<< (const T &t) + { append(t); return *this; } + inline QList<T> &operator<<(const QList<T> &l) + { *this += l; return *this; } + + QVector<T> toVector() const; + QSet<T> toSet() const; + + static QList<T> fromVector(const QVector<T> &vector); + static QList<T> fromSet(const QSet<T> &set); + +#ifndef QT_NO_STL + static inline QList<T> fromStdList(const std::list<T> &list) + { QList<T> tmp; qCopy(list.begin(), list.end(), std::back_inserter(tmp)); return tmp; } + inline std::list<T> toStdList() const + { std::list<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; } +#endif + +private: + void detach_helper(); + void free(QListData::Data *d); + + void node_construct(Node *n, const T &t); + void node_destruct(Node *n); + void node_copy(Node *from, Node *to, Node *src); + void node_destruct(Node *from, Node *to); +}; + +#if defined(Q_CC_BOR) +template <typename T> +Q_INLINE_TEMPLATE T &QList<T>::Node::t() +{ return QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic ? *(T*)v:*(T*)this; } +#endif + +template <typename T> +Q_INLINE_TEMPLATE void QList<T>::node_construct(Node *n, const T &t) +{ + if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) n->v = new T(t); + else if (QTypeInfo<T>::isComplex) new (n) T(t); + else *reinterpret_cast<T*>(n) = t; +} + +template <typename T> +Q_INLINE_TEMPLATE void QList<T>::node_destruct(Node *n) +{ + if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) delete reinterpret_cast<T*>(n->v); + else if (QTypeInfo<T>::isComplex) reinterpret_cast<T*>(n)->~T(); +} + +template <typename T> +Q_INLINE_TEMPLATE void QList<T>::node_copy(Node *from, Node *to, Node *src) +{ + if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) + while(from != to) + (from++)->v = new T(*reinterpret_cast<T*>((src++)->v)); + else if (QTypeInfo<T>::isComplex) + while(from != to) + new (from++) T(*reinterpret_cast<T*>(src++)); +} + +template <typename T> +Q_INLINE_TEMPLATE void QList<T>::node_destruct(Node *from, Node *to) +{ + if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) + while(from != to) --to, delete reinterpret_cast<T*>(to->v); + else if (QTypeInfo<T>::isComplex) + while (from != to) --to, reinterpret_cast<T*>(to)->~T(); +} + +template <typename T> +Q_INLINE_TEMPLATE QList<T> &QList<T>::operator=(const QList<T> &l) +{ + if (d != l.d) { + l.d->ref.ref(); + if (!d->ref.deref()) + free(d); + d = l.d; + if (!d->sharable) + detach_helper(); + } + return *this; +} +template <typename T> +inline typename QList<T>::iterator QList<T>::insert(iterator before, const T &t) +{ Node *n = reinterpret_cast<Node *>(p.insert(before.i-reinterpret_cast<Node *>(p.begin()))); + node_construct(n,t); return n; } +template <typename T> +inline typename QList<T>::iterator QList<T>::erase(iterator it) +{ node_destruct(it.i); + return reinterpret_cast<Node *>(p.erase(reinterpret_cast<void**>(it.i))); } +template <typename T> +inline const T &QList<T>::at(int i) const +{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::at", "index out of range"); + return reinterpret_cast<Node *>(p.at(i))->t(); } +template <typename T> +inline const T &QList<T>::operator[](int i) const +{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::operator[]", "index out of range"); + return reinterpret_cast<Node *>(p.at(i))->t(); } +template <typename T> +inline T &QList<T>::operator[](int i) +{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::operator[]", "index out of range"); + detach(); return reinterpret_cast<Node *>(p.at(i))->t(); } +template <typename T> +inline void QList<T>::removeAt(int i) +{ if(i >= 0 && i < p.size()) { detach(); + node_destruct(reinterpret_cast<Node *>(p.at(i))); p.remove(i); } } +template <typename T> +inline T QList<T>::takeAt(int i) +{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::take", "index out of range"); + detach(); Node *n = reinterpret_cast<Node *>(p.at(i)); T t = n->t(); node_destruct(n); + p.remove(i); return t; } +template <typename T> +inline T QList<T>::takeFirst() +{ T t = first(); removeFirst(); return t; } +template <typename T> +inline T QList<T>::takeLast() +{ T t = last(); removeLast(); return t; } + +template <typename T> +Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t) +{ + detach(); + if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) { + node_construct(reinterpret_cast<Node *>(p.append()), t); + } else { + const T cpy(t); + node_construct(reinterpret_cast<Node *>(p.append()), cpy); + } +} + +template <typename T> +inline void QList<T>::prepend(const T &t) +{ + detach(); + if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) { + node_construct(reinterpret_cast<Node *>(p.prepend()), t); + } else { + const T cpy(t); + node_construct(reinterpret_cast<Node *>(p.prepend()), cpy); + } +} + +template <typename T> +inline void QList<T>::insert(int i, const T &t) +{ + detach(); + if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) { + node_construct(reinterpret_cast<Node *>(p.insert(i)), t); + } else { + const T cpy(t); + node_construct(reinterpret_cast<Node *>(p.insert(i)), cpy); + } +} + +template <typename T> +inline void QList<T>::replace(int i, const T &t) +{ + Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::replace", "index out of range"); + detach(); + if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) { + reinterpret_cast<Node *>(p.at(i))->t() = t; + } else { + const T cpy(t); + reinterpret_cast<Node *>(p.at(i))->t() = cpy; + } +} + +template <typename T> +inline void QList<T>::swap(int i, int j) +{ + Q_ASSERT_X(i >= 0 && i < p.size() && j >= 0 && j < p.size(), + "QList<T>::swap", "index out of range"); + detach(); + void *t = d->array[d->begin + i]; + d->array[d->begin + i] = d->array[d->begin + j]; + d->array[d->begin + j] = t; +} + +template <typename T> +inline void QList<T>::move(int from, int to) +{ + Q_ASSERT_X(from >= 0 && from < p.size() && to >= 0 && to < p.size(), + "QList<T>::move", "index out of range"); + detach(); + p.move(from, to); +} + +template<typename T> +Q_OUTOFLINE_TEMPLATE QList<T> QList<T>::mid(int pos, int alength) const +{ + if (alength < 0) + alength = size() - pos; + if (pos == 0 && alength == size()) + return *this; + QList<T> cpy; + if (pos + alength > size()) + alength = size() - pos; + for (int i = pos; i < pos + alength; ++i) + cpy += at(i); + return cpy; +} + +template<typename T> +Q_OUTOFLINE_TEMPLATE T QList<T>::value(int i) const +{ + if (i < 0 || i >= p.size()) { + return T(); + } + return reinterpret_cast<Node *>(p.at(i))->t(); +} + +template<typename T> +Q_OUTOFLINE_TEMPLATE T QList<T>::value(int i, const T& defaultValue) const +{ + return ((i < 0 || i >= p.size()) ? defaultValue : reinterpret_cast<Node *>(p.at(i))->t()); +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE void QList<T>::detach_helper() +{ + Node *n = reinterpret_cast<Node *>(p.begin()); + QListData::Data *x = p.detach2(); + node_copy(reinterpret_cast<Node *>(p.begin()), reinterpret_cast<Node *>(p.end()), n); + if (!x->ref.deref()) + free(x); +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE QList<T>::~QList() +{ + if (d && !d->ref.deref()) + free(d); +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE bool QList<T>::operator==(const QList<T> &l) const +{ + if (p.size() != l.p.size()) + return false; + if (d == l.d) + return true; + Node *i = reinterpret_cast<Node *>(p.end()); + Node *b = reinterpret_cast<Node *>(p.begin()); + Node *li = reinterpret_cast<Node *>(l.p.end()); + while (i != b) { + --i; --li; + if (!(i->t() == li->t())) + return false; + } + return true; +} + +// ### Qt 5: rename freeData() to avoid confusion with std::free() +template <typename T> +Q_OUTOFLINE_TEMPLATE void QList<T>::free(QListData::Data *data) +{ + node_destruct(reinterpret_cast<Node *>(data->array + data->begin), + reinterpret_cast<Node *>(data->array + data->end)); + if (data->ref == 0) + qFree(data); +} + + +template <typename T> +Q_OUTOFLINE_TEMPLATE void QList<T>::clear() +{ + *this = QList<T>(); +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE int QList<T>::removeAll(const T &_t) +{ + detach(); + const T t = _t; + int removedCount=0, i=0; + Node *n; + while (i < p.size()) + if ((n = reinterpret_cast<Node *>(p.at(i)))->t() == t) { + node_destruct(n); + p.remove(i); + ++removedCount; + } else { + ++i; + } + return removedCount; +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE bool QList<T>::removeOne(const T &_t) +{ + detach(); + int index = indexOf(_t); + if (index != -1) { + removeAt(index); + return true; + } + return false; +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE typename QList<T>::iterator QList<T>::erase(typename QList<T>::iterator afirst, + typename QList<T>::iterator alast) +{ + for (Node *n = afirst.i; n < alast.i; ++n) + node_destruct(n); + int idx = afirst - begin(); + p.remove(idx, alast - afirst); + return begin() + idx; +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE QList<T> &QList<T>::operator+=(const QList<T> &l) +{ + detach(); + Node *n = reinterpret_cast<Node *>(p.append(l.p)); + node_copy(n, reinterpret_cast<Node *>(p.end()), reinterpret_cast<Node *>(l.p.begin())); + return *this; +} + +template <typename T> +inline void QList<T>::append(const QList<T> &t) +{ + *this += t; +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE int QList<T>::indexOf(const T &t, int from) const +{ + if (from < 0) + from = qMax(from + p.size(), 0); + if (from < p.size()) { + Node *n = reinterpret_cast<Node *>(p.at(from -1)); + Node *e = reinterpret_cast<Node *>(p.end()); + while (++n != e) + if (n->t() == t) + return n - reinterpret_cast<Node *>(p.begin()); + } + return -1; +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE int QList<T>::lastIndexOf(const T &t, int from) const +{ + if (from < 0) + from += p.size(); + else if (from >= p.size()) + from = p.size()-1; + if (from >= 0) { + Node *b = reinterpret_cast<Node *>(p.begin()); + Node *n = reinterpret_cast<Node *>(p.at(from + 1)); + while (n-- != b) { + if (n->t() == t) + return n - b; + } + } + return -1; +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE QBool QList<T>::contains(const T &t) const +{ + Node *b = reinterpret_cast<Node *>(p.begin()); + Node *i = reinterpret_cast<Node *>(p.end()); + while (i-- != b) + if (i->t() == t) + return QBool(true); + return QBool(false); +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE int QList<T>::count(const T &t) const +{ + int c = 0; + Node *b = reinterpret_cast<Node *>(p.begin()); + Node *i = reinterpret_cast<Node *>(p.end()); + while (i-- != b) + if (i->t() == t) + ++c; + return c; +} + +Q_DECLARE_SEQUENTIAL_ITERATOR(List) +Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(List) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QLIST_H diff --git a/src/corelib/tools/qlistdata.cpp b/src/corelib/tools/qlistdata.cpp new file mode 100644 index 0000000..2b1c086 --- /dev/null +++ b/src/corelib/tools/qlistdata.cpp @@ -0,0 +1,1742 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qlist.h" +#include "qtools_p.h" +#include <string.h> + +QT_BEGIN_NAMESPACE + +/* + QList as an array-list combines the easy-of-use of a random + access interface with fast list operations and the low memory + management overhead of an array. Accessing elements by index, + appending, prepending, and removing elements from both the front + and the back all happen in constant time O(1). Inserting or + removing elements at random index positions \ai happens in linear + time, or more precisly in O(min{i,n-i}) <= O(n/2), with n being + the number of elements in the list. +*/ + +QListData::Data QListData::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, 0, true, { 0 } }; + +static int grow(int size) +{ + // dear compiler: don't optimize me out. + volatile int x = qAllocMore(size * sizeof(void *), QListData::DataHeaderSize) / sizeof(void *); + return x; +} + +#if QT_VERSION >= 0x050000 +# error "Remove QListData::detach(), it is only required for binary compatibility for 4.0.x to 4.2.x" +#endif +QListData::Data *QListData::detach() +{ + Data *x = static_cast<Data *>(qMalloc(DataHeaderSize + d->alloc * sizeof(void *))); + if (!x) + qFatal("QList: Out of memory"); + + ::memcpy(x, d, DataHeaderSize + d->alloc * sizeof(void *)); + x->alloc = d->alloc; + x->ref = 1; + x->sharable = true; + if (!x->alloc) + x->begin = x->end = 0; + + qSwap(d, x); + if (!x->ref.deref()) + return x; + return 0; +} + +// Returns the old (shared) data, it is up to the caller to deref() and free() +QListData::Data *QListData::detach2() +{ + Data *x = d; + d = static_cast<Data *>(qMalloc(DataHeaderSize + x->alloc * sizeof(void *))); + if (!d) + qFatal("QList: Out of memory"); + + ::memcpy(d, x, DataHeaderSize + x->alloc * sizeof(void *)); + d->alloc = x->alloc; + d->ref = 1; + d->sharable = true; + if (!d->alloc) + d->begin = d->end = 0; + + return x; +} + +void QListData::realloc(int alloc) +{ + Q_ASSERT(d->ref == 1); + Data *x = static_cast<Data *>(qRealloc(d, DataHeaderSize + alloc * sizeof(void *))); + if (!x) + qFatal("QList: Out of memory"); + + d = x; + d->alloc = alloc; + if (!alloc) + d->begin = d->end = 0; +} + +void **QListData::append() +{ + Q_ASSERT(d->ref == 1); + if (d->end == d->alloc) { + int n = d->end - d->begin; + if (d->begin > 2 * d->alloc / 3) { + ::memcpy(d->array + n, d->array + d->begin, n * sizeof(void *)); + d->begin = n; + d->end = n * 2; + } else { + realloc(grow(d->alloc + 1)); + } + } + return d->array + d->end++; +} + +void **QListData::append(const QListData& l) +{ + Q_ASSERT(d->ref == 1); + int e = d->end; + int n = l.d->end - l.d->begin; + if (n) { + if (e + n > d->alloc) + realloc(grow(e + l.d->end - l.d->begin)); + ::memcpy(d->array + d->end, l.d->array + l.d->begin, n * sizeof(void*)); + d->end += n; + } + return d->array + e; +} + +void **QListData::prepend() +{ + Q_ASSERT(d->ref == 1); + if (d->begin == 0) { + if (d->end >= d->alloc / 3) + realloc(grow(d->alloc + 1)); + + if (d->end < d->alloc / 3) + d->begin = d->alloc - 2 * d->end; + else + d->begin = d->alloc - d->end; + + ::memmove(d->array + d->begin, d->array, d->end * sizeof(void *)); + d->end += d->begin; + } + return d->array + --d->begin; +} + +void **QListData::insert(int i) +{ + Q_ASSERT(d->ref == 1); + if (i <= 0) + return prepend(); + if (i >= d->end - d->begin) + return append(); + + bool leftward = false; + int size = d->end - d->begin; + + if (d->begin == 0) { + if (d->end == d->alloc) { + // If the array is full, we expand it and move some items rightward + realloc(grow(d->alloc + 1)); + } else { + // If there is free space at the end of the array, we move some items rightward + } + } else { + if (d->end == d->alloc) { + // If there is free space at the beginning of the array, we move some items leftward + leftward = true; + } else { + // If there is free space at both ends, we move as few items as possible + leftward = (i < size - i); + } + } + + if (leftward) { + --d->begin; + ::memmove(d->array + d->begin, d->array + d->begin + 1, i * sizeof(void *)); + } else { + ::memmove(d->array + d->begin + i + 1, d->array + d->begin + i, + (size - i) * sizeof(void *)); + ++d->end; + } + return d->array + d->begin + i; +} + +void QListData::remove(int i) +{ + Q_ASSERT(d->ref == 1); + i += d->begin; + if (i - d->begin < d->end - i) { + if (int offset = i - d->begin) + ::memmove(d->array + d->begin + 1, d->array + d->begin, offset * sizeof(void *)); + d->begin++; + } else { + if (int offset = d->end - i - 1) + ::memmove(d->array + i, d->array + i + 1, offset * sizeof(void *)); + d->end--; + } +} + +void QListData::remove(int i, int n) +{ + Q_ASSERT(d->ref == 1); + i += d->begin; + int middle = i + n/2; + if (middle - d->begin < d->end - middle) { + ::memmove(d->array + d->begin + n, d->array + d->begin, + (i - d->begin) * sizeof(void*)); + d->begin += n; + } else { + ::memmove(d->array + i, d->array + i + n, + (d->end - i - n) * sizeof(void*)); + d->end -= n; + } +} + +void QListData::move(int from, int to) +{ + Q_ASSERT(d->ref == 1); + if (from == to) + return; + + from += d->begin; + to += d->begin; + void *t = d->array[from]; + + if (from < to) { + if (d->end == d->alloc || 3 * (to - from) < 2 * (d->end - d->begin)) { + ::memmove(d->array + from, d->array + from + 1, (to - from) * sizeof(void *)); + } else { + // optimization + if (int offset = from - d->begin) + ::memmove(d->array + d->begin + 1, d->array + d->begin, offset * sizeof(void *)); + if (int offset = d->end - (to + 1)) + ::memmove(d->array + to + 2, d->array + to + 1, offset * sizeof(void *)); + ++d->begin; + ++d->end; + ++to; + } + } else { + if (d->begin == 0 || 3 * (from - to) < 2 * (d->end - d->begin)) { + ::memmove(d->array + to + 1, d->array + to, (from - to) * sizeof(void *)); + } else { + // optimization + if (int offset = to - d->begin) + ::memmove(d->array + d->begin - 1, d->array + d->begin, offset * sizeof(void *)); + if (int offset = d->end - (from + 1)) + ::memmove(d->array + from, d->array + from + 1, offset * sizeof(void *)); + --d->begin; + --d->end; + --to; + } + } + d->array[to] = t; +} + +void **QListData::erase(void **xi) +{ + Q_ASSERT(d->ref == 1); + int i = xi - (d->array + d->begin); + remove(i); + return d->array + d->begin + i; +} + +/*! \class QList + \brief The QList class is a template class that provides lists. + + \ingroup tools + \ingroup shared + \mainclass + \reentrant + + QList\<T\> is one of Qt's generic \l{container classes}. It + stores a list of values and provides fast index-based access as + well as fast insertions and removals. + + QList\<T\>, QLinkedList\<T\>, and QVector\<T\> provide similar + functionality. Here's an overview: + + \list + \i For most purposes, QList is the right class to use. Its + index-based API is more convenient than QLinkedList's + iterator-based API, and it is usually faster than + QVector because of the way it stores its items in + memory. It also expands to less code in your executable. + \i If you need a real linked list, with guarantees of \l{constant + time} insertions in the middle of the list and iterators to + items rather than indexes, use QLinkedList. + \i If you want the items to occupy adjacent memory positions, + use QVector. + \endlist + + + Internally, QList\<T\> is represented as an array of pointers to + items of type T. If T is itself a pointer type or a basic type + that is no larger than a pointer, or if T is one of Qt's \l{shared + classes}, then QList\<T\> stores the items directly in the pointer + array. For lists under a thousand items, this array representation + allows for very fast insertions in the middle, and it allows + index-based access. Furthermore, operations like prepend() and + append() are very fast, because QList preallocates memory at both + ends of its internal array. (See \l{Algorithmic Complexity} for + details.) Note, however, that for unshared list items that are + larger than a pointer, each append or insert of a new item + requires allocating the new item on the heap, and this per item + allocation might make QVector a better choice in cases that do + lots of appending or inserting, since QVector allocates memory for + its items in a single heap allocation. + + Note that the internal array only ever gets bigger over the life + of the list. It never shrinks. The internal array is deallocated + by the destructor and by the assignment operator, when one list + is assigned to another. + + Here's an example of a QList that stores integers and + a QList that stores QDate values: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 0 + + Qt includes a QStringList class that inherits QList\<QString\> + and adds a few convenience functions, such as QStringList::join() + and QStringList::find(). (QString::split() creates QStringLists + from strings.) + + QList stores a list of items. The default constructor creates an + empty list. To insert items into the list, you can use + operator<<(): + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 1 + + QList provides these basic functions to add, move, and remove + items: insert(), replace(), removeAt(), move(), and swap(). In + addition, it provides the following convenience functions: + append(), prepend(), removeFirst(), and removeLast(). + + QList uses 0-based indexes, just like C++ arrays. To access the + item at a particular index position, you can use operator[](). On + non-const lists, operator[]() returns a reference to the item and + can be used on the left side of an assignment: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 2 + + Because QList is implemented as an array of pointers, this + operation is very fast (\l{constant time}). For read-only access, + an alternative syntax is to use at(): + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 3 + + at() can be faster than operator[](), because it never causes a + \l{deep copy} to occur. + + A common requirement is to remove an item from a list and do + something with it. For this, QList provides takeAt(), takeFirst(), + and takeLast(). Here's a loop that removes the items from a list + one at a time and calls \c delete on them: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 4 + + Inserting and removing items at either ends of the list is very + fast (\l{constant time} in most cases), because QList + preallocates extra space on both sides of its internal buffer to + allow for fast growth at both ends of the list. + + If you want to find all occurrences of a particular value in a + list, use indexOf() or lastIndexOf(). The former searches forward + starting from a given index position, the latter searches + backward. Both return the index of a matching item if they find + it; otherwise, they return -1. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 5 + + If you simply want to check whether a list contains a particular + value, use contains(). If you want to find out how many times a + particular value occurs in the list, use count(). If you want to + replace all occurrences of a particular value with another, use + replace(). + + QList's value type must be an \l{assignable data type}. This + covers most data types that are commonly used, but the compiler + won't let you, for example, store a QWidget as a value; instead, + store a QWidget *. A few functions have additional requirements; + for example, indexOf() and lastIndexOf() expect the value type to + support \c operator==(). These requirements are documented on a + per-function basis. + + Like the other container classes, QList provides \l{Java-style + iterators} (QListIterator and QMutableListIterator) and + \l{STL-style iterators} (QList::const_iterator and + QList::iterator). In practice, these are rarely used, because you + can use indexes into the QList. QList is implemented in such a way + that direct index-based access is just as fast as using iterators. + + QList does \e not support inserting, prepending, appending or + replacing with references to its own values. Doing so will cause + your application to abort with an error message. + + To make QList as efficient as possible, its member functions don't + validate their input before using it. Except for isEmpty(), member + functions always assume the list is \e not empty. Member functions + that take index values as parameters always assume their index + value parameters are in the valid range. This means QList member + functions can fail. If you define QT_NO_DEBUG when you compile, + failures will not be detected. If you \e don't define QT_NO_DEBUG, + failures will be detected using Q_ASSERT() or Q_ASSERT_X() with an + appropriate message. + + To avoid failures when your list can be empty, call isEmpty() + before calling other member functions. If you must pass an index + value that might not be in the valid range, check that it is less + than the value returned by size() but \e not less than 0. + + \sa QListIterator, QMutableListIterator, QLinkedList, QVector +*/ + +/*! + \fn QList<T> QList<T>::mid(int pos, int length) const + + Returns a list whose elements are copied from this list, + starting at position \a pos. If \a length is -1 (the default), all + elements from \a pos are copied; otherwise \a length elements (or + all remaining elements if there are less than \a length elements) + are copied. +*/ + +/*! \fn QList::QList() + + Constructs an empty list. +*/ + +/*! \fn QList::QList(const QList<T> &other) + + Constructs a copy of \a other. + + This operation takes \l{constant time}, because QList is + \l{implicitly shared}. This makes returning a QList from a + function very fast. If a shared instance is modified, it will be + copied (copy-on-write), and that takes \l{linear time}. + + \sa operator=() +*/ + +/*! \fn QList::~QList() + + Destroys the list. References to the values in the list and all + iterators of this list become invalid. +*/ + +/*! \fn QList<T> &QList::operator=(const QList<T> &other) + + Assigns \a other to this list and returns a reference to this + list. +*/ + +/*! \fn bool QList::operator==(const QList<T> &other) const + + Returns true if \a other is equal to this list; otherwise returns + false. + + Two lists are considered equal if they contain the same values in + the same order. + + This function requires the value type to have an implementation of + \c operator==(). + + \sa operator!=() +*/ + +/*! \fn bool QList::operator!=(const QList<T> &other) const + + Returns true if \a other is not equal to this list; otherwise + returns false. + + Two lists are considered equal if they contain the same values in + the same order. + + This function requires the value type to have an implementation of + \c operator==(). + + \sa operator==() +*/ + +/*! + \fn int QList::size() const + + Returns the number of items in the list. + + \sa isEmpty(), count() +*/ + +/*! \fn void QList::detach() + + \internal +*/ + +/*! \fn bool QList::isDetached() const + + \internal +*/ + +/*! \fn void QList::setSharable(bool sharable) + + \internal +*/ + +/*! \fn bool QList::isEmpty() const + + Returns true if the list contains no items; otherwise returns + false. + + \sa size() +*/ + +/*! \fn void QList::clear() + + Removes all items from the list. + + \sa removeAll() +*/ + +/*! \fn const T &QList::at(int i) const + + Returns the item at index position \a i in the list. \a i must be + a valid index position in the list (i.e., 0 <= \a i < size()). + + This function is very fast (\l{constant time}). + + \sa value(), operator[]() +*/ + +/*! \fn T &QList::operator[](int i) + + Returns the item at index position \a i as a modifiable reference. + \a i must be a valid index position in the list (i.e., 0 <= \a i < + size()). + + This function is very fast (\l{constant time}). + + \sa at(), value() +*/ + +/*! \fn const T &QList::operator[](int i) const + + \overload + + Same as at(). +*/ + +/*! \fn void QList::append(const T &value) + + Inserts \a value at the end of the list. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 6 + + This is the same as list.insert(size(), \a value). + + This operation is typically very fast (\l{constant time}), + because QList preallocates extra space on both sides of its + internal buffer to allow for fast growth at both ends of the + list. + + \sa operator<<(), prepend(), insert() +*/ + +/*! \fn void QList::append(const QList<T> &value) + + \overload + + \since 4.5 + + Appends the items of the \a value list to this list. + + \sa operator<<(), operator+=() +*/ + +/*! \fn void QList::prepend(const T &value) + + Inserts \a value at the beginning of the list. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 7 + + This is the same as list.insert(0, \a value). + + This operation is usually very fast (\l{constant time}), because + QList preallocates extra space on both sides of its internal + buffer to allow for fast growth at both ends of the list. + + \sa append(), insert() +*/ + +/*! \fn void QList::insert(int i, const T &value) + + Inserts \a value at index position \a i in the list. If \a i + is 0, the value is prepended to the list. If \a i is size(), the + value is appended to the list. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 8 + + \sa append(), prepend(), replace(), removeAt() +*/ + +/*! \fn QList::iterator QList::insert(iterator before, const T &value) + + \overload + + Inserts \a value in front of the item pointed to by the + iterator \a before. Returns an iterator pointing at the inserted + item. Note that the iterator passed to the function will be + invalid after the call; the returned iterator should be used + instead. +*/ + +/*! \fn void QList::replace(int i, const T &value) + + Replaces the item at index position \a i with \a value. \a i must + be a valid index position in the list (i.e., 0 <= \a i < size()). + + \sa operator[](), removeAt() +*/ + +/*! + \fn int QList::removeAll(const T &value) + + Removes all occurrences of \a value in the list and returns the + number of entries removed. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 9 + + This function requires the value type to have an implementation of + \c operator==(). + + \sa removeOne(), removeAt(), takeAt(), replace() +*/ + +/*! + \fn bool QList::removeOne(const T &value) + \since 4.4 + + Removes the first occurrence of \a value in the list and returns + true on success; otherwise returns false. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 10 + + This function requires the value type to have an implementation of + \c operator==(). + + \sa removeAll(), removeAt(), takeAt(), replace() +*/ + +/*! \fn void QList::removeAt(int i) + + Removes the item at index position \a i. \a i must be a valid + index position in the list (i.e., 0 <= \a i < size()). + + \sa takeAt(), removeFirst(), removeLast(), removeOne() +*/ + +/*! \fn T QList::takeAt(int i) + + Removes the item at index position \a i and returns it. \a i must + be a valid index position in the list (i.e., 0 <= \a i < size()). + + If you don't use the return value, removeAt() is more efficient. + + \sa removeAt(), takeFirst(), takeLast() +*/ + +/*! \fn T QList::takeFirst() + + Removes the first item in the list and returns it. This is the + same as takeAt(0). This function assumes the list is not empty. To + avoid failure, call isEmpty() before calling this function. + + This operation is very fast (\l{constant time}), because QList + preallocates extra space on both sides of its internal buffer to + allow for fast growth at both ends of the list. + + If you don't use the return value, removeFirst() is more + efficient. + + \sa takeLast(), takeAt(), removeFirst() +*/ + +/*! \fn T QList::takeLast() + + Removes the last item in the list and returns it. This is the + same as takeAt(size() - 1). This function assumes the list is + not empty. To avoid failure, call isEmpty() before calling this + function. + + This operation is very fast (\l{constant time}), because QList + preallocates extra space on both sides of its internal buffer to + allow for fast growth at both ends of the list. + + If you don't use the return value, removeLast() is more + efficient. + + \sa takeFirst(), takeAt(), removeLast() +*/ + +/*! \fn void QList::move(int from, int to) + + Moves the item at index position \a from to index position \a to. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 11 + + This is the same as insert(\a{to}, takeAt(\a{from})).This function + assumes that both \a from and \a to are at least 0 but less than + size(). To avoid failure, test that both \a from and \a to are at + least 0 and less than size(). + + \sa swap(), insert(), takeAt() +*/ + +/*! \fn void QList::swap(int i, int j) + + Exchange the item at index position \a i with the item at index + position \a j. This function assumes that both \a i and \a j are + at least 0 but less than size(). To avoid failure, test that both + \a i and \a j are at least 0 and less than size(). + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 12 + + \sa move() +*/ + +/*! \fn int QList::indexOf(const T &value, int from = 0) const + + Returns the index position of the first occurrence of \a value in + the list, searching forward from index position \a from. Returns + -1 if no item matched. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 13 + + This function requires the value type to have an implementation of + \c operator==(). + + \sa lastIndexOf(), contains() +*/ + +/*! \fn int QList::lastIndexOf(const T &value, int from = -1) const + + Returns the index position of the last occurrence of \a value in + the list, searching backward from index position \a from. If \a + from is -1 (the default), the search starts at the last item. + Returns -1 if no item matched. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 14 + + This function requires the value type to have an implementation of + \c operator==(). + + \sa indexOf() +*/ + +/*! \fn QBool QList::contains(const T &value) const + + Returns true if the list contains an occurrence of \a value; + otherwise returns false. + + This function requires the value type to have an implementation of + \c operator==(). + + \sa indexOf(), count() +*/ + +/*! \fn int QList::count(const T &value) const + + Returns the number of occurrences of \a value in the list. + + This function requires the value type to have an implementation of + \c operator==(). + + \sa contains(), indexOf() +*/ + +/*! \fn bool QList::startsWith(const T &value) const + \since 4.5 + + Returns true if this list is not empty and its first + item is equal to \a value; otherwise returns false. + + \sa isEmpty(), contains() +*/ + +/*! \fn bool QList::endsWith(const T &value) const + \since 4.5 + + Returns true if this list is not empty and its last + item is equal to \a value; otherwise returns false. + + \sa isEmpty(), contains() +*/ + +/*! \fn QList::iterator QList::begin() + + Returns an \l{STL-style iterator} pointing to the first item in + the list. + + \sa constBegin(), end() +*/ + +/*! \fn QList::const_iterator QList::begin() const + + \overload +*/ + +/*! \fn QList::const_iterator QList::constBegin() const + + Returns a const \l{STL-style iterator} pointing to the first item + in the list. + + \sa begin(), constEnd() +*/ + +/*! \fn QList::iterator QList::end() + + Returns an \l{STL-style iterator} pointing to the imaginary item + after the last item in the list. + + \sa begin(), constEnd() +*/ + +/*! \fn const_iterator QList::end() const + + \overload +*/ + +/*! \fn QList::const_iterator QList::constEnd() const + + Returns a const \l{STL-style iterator} pointing to the imaginary + item after the last item in the list. + + \sa constBegin(), end() +*/ + +/*! \fn QList::iterator QList::erase(iterator pos) + + Removes the item associated with the iterator \a pos from the + list, and returns an iterator to the next item in the list (which + may be end()). + + \sa insert(), removeAt() +*/ + +/*! \fn QList::iterator QList::erase(iterator begin, iterator end) + + \overload + + Removes all the items from \a begin up to (but not including) \a + end. Returns an iterator to the same item that \a end referred to + before the call. +*/ + +/*! \typedef QList::Iterator + + Qt-style synonym for QList::iterator. +*/ + +/*! \typedef QList::ConstIterator + + Qt-style synonym for QList::const_iterator. +*/ + +/*! + \typedef QList::size_type + + Typedef for int. Provided for STL compatibility. +*/ + +/*! + \typedef QList::value_type + + Typedef for T. Provided for STL compatibility. +*/ + +/*! + \typedef QList::difference_type + + Typedef for ptrdiff_t. Provided for STL compatibility. +*/ + +/*! + \typedef QList::pointer + + Typedef for T *. Provided for STL compatibility. +*/ + +/*! + \typedef QList::const_pointer + + Typedef for const T *. Provided for STL compatibility. +*/ + +/*! + \typedef QList::reference + + Typedef for T &. Provided for STL compatibility. +*/ + +/*! + \typedef QList::const_reference + + Typedef for const T &. Provided for STL compatibility. +*/ + +/*! \fn int QList::count() const + + Returns the number of items in the list. This is effectively the + same as size(). +*/ + +/*! \fn int QList::length() const + \since 4.5 + + This function is identical to count(). + + \sa count() +*/ + +/*! \fn T& QList::first() + + Returns a reference to the first item in the list. The list must + not be empty. If the list can be empty, call isEmpty() before + calling this function. + + \sa last(), isEmpty() +*/ + +/*! \fn const T& QList::first() const + + \overload +*/ + +/*! \fn T& QList::last() + + Returns a reference to the last item in the list. The list must + not be empty. If the list can be empty, call isEmpty() before + calling this function. + + \sa first(), isEmpty() +*/ + +/*! \fn const T& QList::last() const + + \overload +*/ + +/*! \fn void QList::removeFirst() + + Removes the first item in the list. Calling this function is + equivalent to calling removeAt(0). The list must not be empty. If + the list can be empty, call isEmpty() before calling this + function. + + \sa removeAt(), takeFirst() +*/ + +/*! \fn void QList::removeLast() + + Removes the last item in the list. Calling this function is + equivalent to calling removeAt(size() - 1). The list must not be + empty. If the list can be empty, call isEmpty() before calling + this function. + + \sa removeAt(), takeLast() +*/ + +/*! \fn T QList::value(int i) const + + Returns the value at index position \a i in the list. + + If the index \a i is out of bounds, the function returns a + \l{default-constructed value}. If you are certain that the index + is going to be within bounds, you can use at() instead, which is + slightly faster. + + \sa at(), operator[]() +*/ + +/*! \fn T QList::value(int i, const T &defaultValue) const + + \overload + + If the index \a i is out of bounds, the function returns + \a defaultValue. +*/ + +/*! \fn void QList::push_back(const T &value) + + This function is provided for STL compatibility. It is equivalent + to \l{QList::append()}{append(\a value)}. +*/ + +/*! \fn void QList::push_front(const T &value) + + This function is provided for STL compatibility. It is equivalent + to \l{QList::prepend()}{prepend(\a value)}. +*/ + +/*! \fn T& QList::front() + + This function is provided for STL compatibility. It is equivalent + to first(). The list must not be empty. If the list can be empty, + call isEmpty() before calling this function. +*/ + +/*! \fn const T& QList::front() const + + \overload +*/ + +/*! \fn T& QList::back() + + This function is provided for STL compatibility. It is equivalent + to last(). The list must not be empty. If the list can be empty, + call isEmpty() before calling this function. +*/ + +/*! \fn const T& QList::back() const + + \overload +*/ + +/*! \fn void QList::pop_front() + + This function is provided for STL compatibility. It is equivalent + to removeFirst(). The list must not be empty. If the list can be + empty, call isEmpty() before calling this function. +*/ + +/*! \fn void QList::pop_back() + + This function is provided for STL compatibility. It is equivalent + to removeLast(). The list must not be empty. If the list can be + empty, call isEmpty() before calling this function. +*/ + +/*! \fn bool QList::empty() const + + This function is provided for STL compatibility. It is equivalent + to isEmpty() and returns true if the list is empty. +*/ + +/*! \fn QList<T> &QList::operator+=(const QList<T> &other) + + Appends the items of the \a other list to this list and returns a + reference to this list. + + \sa operator+(), append() +*/ + +/*! \fn void QList::operator+=(const T &value) + + \overload + + Appends \a value to the list. + + \sa append(), operator<<() +*/ + +/*! \fn QList<T> QList::operator+(const QList<T> &other) const + + Returns a list that contains all the items in this list followed + by all the items in the \a other list. + + \sa operator+=() +*/ + +/*! \fn QList<T> &QList::operator<<(const QList<T> &other) + + Appends the items of the \a other list to this list and returns a + reference to this list. + + \sa operator+=(), append() +*/ + +/*! \fn void QList::operator<<(const T &value) + + \overload + + Appends \a value to the list. +*/ + +/*! \class QList::iterator + \brief The QList::iterator class provides an STL-style non-const iterator for QList and QQueue. + + QList features both \l{STL-style iterators} and \l{Java-style + iterators}. The STL-style iterators are more low-level and more + cumbersome to use; on the other hand, they are slightly faster + and, for developers who already know STL, have the advantage of + familiarity. + + QList\<T\>::iterator allows you to iterate over a QList\<T\> (or + QQueue\<T\>) and to modify the list item associated with the + iterator. If you want to iterate over a const QList, use + QList::const_iterator instead. It is generally good practice to + use QList::const_iterator on a non-const QList as well, unless + you need to change the QList through the iterator. Const + iterators are slightly faster, and can improve code readability. + + The default QList::iterator constructor creates an uninitialized + iterator. You must initialize it using a QList function like + QList::begin(), QList::end(), or QList::insert() before you can + start iterating. Here's a typical loop that prints all the items + stored in a list: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 15 + + Let's see a few examples of things we can do with a + QList::iterator that we cannot do with a QList::const_iterator. + Here's an example that increments every value stored in a + QList\<int\> by 2: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 16 + + Most QList functions accept an integer index rather than an + iterator. For that reason, iterators are rarely useful in + connection with QList. One place where STL-style iterators do + make sense is as arguments to \l{generic algorithms}. + + For example, here's how to delete all the widgets stored in a + QList\<QWidget *\>: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 17 + + Multiple iterators can be used on the same list. However, be + aware that any non-const function call performed on the QList + will render all existing iterators undefined. If you need to keep + iterators over a long period of time, we recommend that you use + QLinkedList rather than QList. + + \sa QList::const_iterator, QMutableListIterator +*/ + +/*! \typedef QList::iterator::iterator_category + + \internal +*/ + +/*! \typedef QList::iterator::difference_type + + \internal +*/ + +/*! \typedef QList::iterator::value_type + + \internal +*/ + +/*! \typedef QList::iterator::pointer + + \internal +*/ + +/*! \typedef QList::iterator::reference + + \internal +*/ + +/*! \fn QList::iterator::iterator() + + Constructs an uninitialized iterator. + + Functions like operator*() and operator++() should not be called + on an uninitialized iterartor. Use operator=() to assign a value + to it before using it. + + \sa QList::begin() QList::end() +*/ + +/*! \fn QList::iterator::iterator(Node *node) + + \internal +*/ + +/*! \fn QList::iterator::iterator(const iterator &other) + + Constructs a copy of \a other. +*/ + +/*! \fn T &QList::iterator::operator*() const + + Returns a modifiable reference to the current item. + + You can change the value of an item by using operator*() on the + left side of an assignment, for example: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 18 + + \sa operator->() +*/ + +/*! \fn T *QList::iterator::operator->() const + + Returns a pointer to the current item. + + \sa operator*() +*/ + +/*! \fn T &QList::iterator::operator[](int j) const + + Returns a modifiable reference to the item at position *this + + \a{j}. + + This function is provided to make QList iterators behave like C++ + pointers. + + \sa operator+() +*/ + +/*! + \fn bool QList::iterator::operator==(const iterator &other) const + \fn bool QList::iterator::operator==(const const_iterator &other) const + + Returns true if \a other points to the same item as this + iterator; otherwise returns false. + + \sa operator!=() +*/ + +/*! + \fn bool QList::iterator::operator!=(const iterator &other) const + \fn bool QList::iterator::operator!=(const const_iterator &other) const + + Returns true if \a other points to a different item than this + iterator; otherwise returns false. + + \sa operator==() +*/ + +/*! + \fn bool QList::iterator::operator<(const iterator& other) const + \fn bool QList::iterator::operator<(const const_iterator& other) const + + Returns true if the item pointed to by this iterator is less than + the item pointed to by the \a other iterator. +*/ + +/*! + \fn bool QList::iterator::operator<=(const iterator& other) const + \fn bool QList::iterator::operator<=(const const_iterator& other) const + + Returns true if the item pointed to by this iterator is less than + or equal to the item pointed to by the \a other iterator. +*/ + +/*! + \fn bool QList::iterator::operator>(const iterator& other) const + \fn bool QList::iterator::operator>(const const_iterator& other) const + + Returns true if the item pointed to by this iterator is greater + than the item pointed to by the \a other iterator. +*/ + +/*! + \fn bool QList::iterator::operator>=(const iterator& other) const + \fn bool QList::iterator::operator>=(const const_iterator& other) const + + Returns true if the item pointed to by this iterator is greater + than or equal to the item pointed to by the \a other iterator. +*/ + +/*! \fn QList::iterator &QList::iterator::operator++() + + The prefix ++ operator (\c{++it}) advances the iterator to the + next item in the list and returns an iterator to the new current + item. + + Calling this function on QList::end() leads to undefined results. + + \sa operator--() +*/ + +/*! \fn QList::iterator QList::iterator::operator++(int) + + \overload + + The postfix ++ operator (\c{it++}) advances the iterator to the + next item in the list and returns an iterator to the previously + current item. +*/ + +/*! \fn QList::iterator &QList::iterator::operator--() + + The prefix -- operator (\c{--it}) makes the preceding item + current and returns an iterator to the new current item. + + Calling this function on QList::begin() leads to undefined results. + + \sa operator++() +*/ + +/*! \fn QList::iterator QList::iterator::operator--(int) + + \overload + + The postfix -- operator (\c{it--}) makes the preceding item + current and returns an iterator to the previously current item. +*/ + +/*! \fn QList::iterator &QList::iterator::operator+=(int j) + + Advances the iterator by \a j items. (If \a j is negative, the + iterator goes backward.) + + \sa operator-=(), operator+() +*/ + +/*! \fn QList::iterator &QList::iterator::operator-=(int j) + + Makes the iterator go back by \a j items. (If \a j is negative, + the iterator goes forward.) + + \sa operator+=(), operator-() +*/ + +/*! \fn QList::iterator QList::iterator::operator+(int j) const + + Returns an iterator to the item at \a j positions forward from + this iterator. (If \a j is negative, the iterator goes backward.) + + \sa operator-(), operator+=() +*/ + +/*! \fn QList::iterator QList::iterator::operator-(int j) const + + Returns an iterator to the item at \a j positions backward from + this iterator. (If \a j is negative, the iterator goes forward.) + + \sa operator+(), operator-=() +*/ + +/*! \fn int QList::iterator::operator-(iterator other) const + + Returns the number of items between the item pointed to by \a + other and the item pointed to by this iterator. +*/ + +/*! \class QList::const_iterator + \brief The QList::const_iterator class provides an STL-style const iterator for QList and QQueue. + + QList provides both \l{STL-style iterators} and \l{Java-style + iterators}. The STL-style iterators are more low-level and more + cumbersome to use; on the other hand, they are slightly faster + and, for developers who already know STL, have the advantage of + familiarity. + + QList\<T\>::const_iterator allows you to iterate over a + QList\<T\> (or a QQueue\<T\>). If you want to modify the QList as + you iterate over it, use QList::iterator instead. It is generally + good practice to use QList::const_iterator on a non-const QList + as well, unless you need to change the QList through the + iterator. Const iterators are slightly faster, and can improve + code readability. + + The default QList::const_iterator constructor creates an + uninitialized iterator. You must initialize it using a QList + function like QList::constBegin(), QList::constEnd(), or + QList::insert() before you can start iterating. Here's a typical + loop that prints all the items stored in a list: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 19 + + Most QList functions accept an integer index rather than an + iterator. For that reason, iterators are rarely useful in + connection with QList. One place where STL-style iterators do + make sense is as arguments to \l{generic algorithms}. + + For example, here's how to delete all the widgets stored in a + QList\<QWidget *\>: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 20 + + Multiple iterators can be used on the same list. However, be + aware that any non-const function call performed on the QList + will render all existing iterators undefined. If you need to keep + iterators over a long period of time, we recommend that you use + QLinkedList rather than QList. + + \sa QList::iterator, QListIterator +*/ + +/*! \fn QList::const_iterator::const_iterator() + + Constructs an uninitialized iterator. + + Functions like operator*() and operator++() should not be called + on an uninitialized iterartor. Use operator=() to assign a value + to it before using it. + + \sa QList::constBegin() QList::constEnd() +*/ + +/*! \typedef QList::const_iterator::iterator_category + + \internal +*/ + +/*! \typedef QList::const_iterator::difference_type + + \internal +*/ + +/*! \typedef QList::const_iterator::value_type + + \internal +*/ + +/*! \typedef QList::const_iterator::pointer + + \internal +*/ + +/*! \typedef QList::const_iterator::reference + + \internal +*/ + +/*! \fn QList::const_iterator::const_iterator(Node *node) + + \internal +*/ + +/*! \fn QList::const_iterator::const_iterator(const const_iterator &other) + + Constructs a copy of \a other. +*/ + +/*! \fn QList::const_iterator::const_iterator(const iterator &other) + + Constructs a copy of \a other. +*/ + +/*! \fn const T &QList::const_iterator::operator*() const + + Returns the current item. + + \sa operator->() +*/ + +/*! \fn const T *QList::const_iterator::operator->() const + + Returns a pointer to the current item. + + \sa operator*() +*/ + +/*! \fn const T &QList::const_iterator::operator[](int j) const + + Returns the item at position *this + \a{j}. + + This function is provided to make QList iterators behave like C++ + pointers. + + \sa operator+() +*/ + +/*! \fn bool QList::const_iterator::operator==(const const_iterator &other) const + + Returns true if \a other points to the same item as this + iterator; otherwise returns false. + + \sa operator!=() +*/ + +/*! \fn bool QList::const_iterator::operator!=(const const_iterator &other) const + + Returns true if \a other points to a different item than this + iterator; otherwise returns false. + + \sa operator==() +*/ + +/*! + \fn bool QList::const_iterator::operator<(const const_iterator& other) const + + Returns true if the item pointed to by this iterator is less than + the item pointed to by the \a other iterator. +*/ + +/*! + \fn bool QList::const_iterator::operator<=(const const_iterator& other) const + + Returns true if the item pointed to by this iterator is less than + or equal to the item pointed to by the \a other iterator. +*/ + +/*! + \fn bool QList::const_iterator::operator>(const const_iterator& other) const + + Returns true if the item pointed to by this iterator is greater + than the item pointed to by the \a other iterator. +*/ + +/*! + \fn bool QList::const_iterator::operator>=(const const_iterator& other) const + + Returns true if the item pointed to by this iterator is greater + than or equal to the item pointed to by the \a other iterator. +*/ + +/*! \fn QList::const_iterator &QList::const_iterator::operator++() + + The prefix ++ operator (\c{++it}) advances the iterator to the + next item in the list and returns an iterator to the new current + item. + + Calling this function on QList::end() leads to undefined results. + + \sa operator--() +*/ + +/*! \fn QList::const_iterator QList::const_iterator::operator++(int) + + \overload + + The postfix ++ operator (\c{it++}) advances the iterator to the + next item in the list and returns an iterator to the previously + current item. +*/ + +/*! \fn QList::const_iterator &QList::const_iterator::operator--() + + The prefix -- operator (\c{--it}) makes the preceding item + current and returns an iterator to the new current item. + + Calling this function on QList::begin() leads to undefined results. + + \sa operator++() +*/ + +/*! \fn QList::const_iterator QList::const_iterator::operator--(int) + + \overload + + The postfix -- operator (\c{it--}) makes the preceding item + current and returns an iterator to the previously current item. +*/ + +/*! \fn QList::const_iterator &QList::const_iterator::operator+=(int j) + + Advances the iterator by \a j items. (If \a j is negative, the + iterator goes backward.) + + \sa operator-=(), operator+() +*/ + +/*! \fn QList::const_iterator &QList::const_iterator::operator-=(int j) + + Makes the iterator go back by \a j items. (If \a j is negative, + the iterator goes forward.) + + \sa operator+=(), operator-() +*/ + +/*! \fn QList::const_iterator QList::const_iterator::operator+(int j) const + + Returns an iterator to the item at \a j positions forward from + this iterator. (If \a j is negative, the iterator goes backward.) + + \sa operator-(), operator+=() +*/ + +/*! \fn QList::const_iterator QList::const_iterator::operator-(int j) const + + Returns an iterator to the item at \a j positions backward from + this iterator. (If \a j is negative, the iterator goes forward.) + + \sa operator+(), operator-=() +*/ + +/*! \fn int QList::const_iterator::operator-(const_iterator other) const + + Returns the number of items between the item pointed to by \a + other and the item pointed to by this iterator. +*/ + +/*! \fn QDataStream &operator<<(QDataStream &out, const QList<T> &list) + \relates QList + + Writes the list \a list to stream \a out. + + This function requires the value type to implement \c + operator<<(). + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +/*! \fn QDataStream &operator>>(QDataStream &in, QList<T> &list) + \relates QList + + Reads a list from stream \a in into \a list. + + This function requires the value type to implement \c + operator>>(). + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +/*! + \fn iterator QList::remove(iterator pos) + + Use erase() instead. +*/ + +/*! + \fn int QList::remove(const T &t) + + Use removeAll() instead. +*/ + +/*! + \fn int QList::findIndex(const T& t) const + + Use indexOf() instead. +*/ + +/*! + \fn iterator QList::find(const T& t) + + Use indexOf() instead. +*/ + +/*! + \fn const_iterator QList::find (const T& t) const + + Use indexOf() instead. +*/ + +/*! + \fn iterator QList::find(iterator from, const T& t) + + Use indexOf() instead. +*/ + +/*! + \fn const_iterator QList::find(const_iterator from, const T& t) const + + Use indexOf() instead. +*/ + +/*! \fn QList<T> QList<T>::fromVector(const QVector<T> &vector) + + Returns a QList object with the data contained in \a vector. + + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 21 + + \sa fromSet(), toVector(), QVector::toList() +*/ + +/*! \fn QVector<T> QList<T>::toVector() const + + Returns a QVector object with the data contained in this QList. + + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 22 + + \sa toSet(), fromVector(), QVector::fromList() +*/ + +/*! \fn QList<T> QList<T>::fromSet(const QSet<T> &set) + + Returns a QList object with the data contained in \a set. The + order of the elements in the QList is undefined. + + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 23 + + \sa fromVector(), toSet(), QSet::toList(), qSort() +*/ + +/*! \fn QSet<T> QList<T>::toSet() const + + Returns a QSet object with the data contained in this QList. + Since QSet doesn't allow duplicates, the resulting QSet might be + smaller than the original list was. + + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 24 + + \sa toVector(), fromSet(), QSet::fromList() +*/ + +/*! \fn QList<T> QList<T>::fromStdList(const std::list<T> &list) + + Returns a QList object with the data contained in \a list. The + order of the elements in the QList is the same as in \a list. + + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 25 + + \sa toStdList(), QVector::fromStdVector() +*/ + +/*! \fn std::list<T> QList<T>::toStdList() const + + Returns a std::list object with the data contained in this QList. + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qlistdata.cpp 26 + + \sa fromStdList(), QVector::toStdVector() +*/ + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp new file mode 100644 index 0000000..db2fc26 --- /dev/null +++ b/src/corelib/tools/qlocale.cpp @@ -0,0 +1,7220 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qglobal.h" + +#ifndef QT_NO_SYSTEMLOCALE +#define QLOCALE_CPP +QT_BEGIN_NAMESPACE +class QSystemLocale; +static QSystemLocale *QSystemLocale_globalSystemLocale(); +QT_END_NAMESPACE +#endif + +#include "qplatformdefs.h" + +#include "qdatastream.h" +#include "qstring.h" +#include "qlocale.h" +#include "qlocale_p.h" +#include "qdatetime_p.h" +#include "qnamespace.h" +#include "qdatetime.h" +#include "qstringlist.h" +#include "qvariant.h" +#if defined(Q_WS_WIN) +# include "qt_windows.h" +# include <time.h> +#endif +#if !defined(QWS) && defined(Q_OS_MAC) +# include "private/qcore_mac_p.h" +# include <CoreFoundation/CoreFoundation.h> +#endif +#include "private/qnumeric_p.h" + +#include <ctype.h> +#include <float.h> +#include <limits.h> +#include <math.h> +#include <stdlib.h> +#include <qdebug.h> +#include <time.h> + +#if defined(Q_OS_LINUX) && !defined(__UCLIBC__) +# include <fenv.h> +#endif + +#if !defined(QT_QLOCALE_NEEDS_VOLATILE) +# if defined(Q_CC_GNU) +# if __GNUC__ == 4 +# define QT_QLOCALE_NEEDS_VOLATILE +# elif defined(Q_OS_WIN) +# define QT_QLOCALE_NEEDS_VOLATILE +# endif +# endif +#endif + +#if defined(QT_QLOCALE_NEEDS_VOLATILE) +# define NEEDS_VOLATILE volatile +#else +# define NEEDS_VOLATILE +#endif + +// Sizes as defined by the ISO C99 standard - fallback +#ifndef LLONG_MAX +# define LLONG_MAX Q_INT64_C(0x7fffffffffffffff) +#endif +#ifndef LLONG_MIN +# define LLONG_MIN (-LLONG_MAX - Q_INT64_C(1)) +#endif +#ifndef ULLONG_MAX +# define ULLONG_MAX Q_UINT64_C(0xffffffffffffffff) +#endif + +#define CONVERSION_BUFF_SIZE 255 + +QT_BEGIN_NAMESPACE + +#ifndef QT_QLOCALE_USES_FCVT +static char *_qdtoa( NEEDS_VOLATILE double d, int mode, int ndigits, int *decpt, + int *sign, char **rve, char **digits_str); +#endif +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); +Q_CORE_EXPORT qlonglong qstrtoll(const char *nptr, const char **endptr, register int base, bool *ok); +static qulonglong qstrtoull(const char *nptr, const char **endptr, register int base, bool *ok); + +/****************************************************************************** +** Helpers for accessing Qt locale database +*/ + +QT_BEGIN_INCLUDE_NAMESPACE +#include "qlocale_data_p.h" +QT_END_INCLUDE_NAMESPACE + +QLocale::MeasurementSystem QLocalePrivate::measurementSystem() const +{ + for (int i = 0; i < ImperialMeasurementSystemsCount; ++i) { + if (ImperialMeasurementSystems[i].languageId == m_language_id + && ImperialMeasurementSystems[i].countryId == m_country_id) { + return QLocale::ImperialSystem; + } + } + return QLocale::MetricSystem; +} + +// Assumes that code is a +// QChar code[3]; +// If the code is two-digit the third digit must be 0 +static QLocale::Language codeToLanguage(const QChar *code) +{ + ushort uc1 = code[0].unicode(); + ushort uc2 = code[1].unicode(); + ushort uc3 = code[2].unicode(); + + if (uc1 == 'n' && uc2 == 'o' && uc3 == 0) + uc2 = 'b'; + + const unsigned char *c = language_code_list; + for (; *c != 0; c += 3) { + if (uc1 == c[0] && uc2 == c[1] && uc3 == c[2]) + return QLocale::Language((c - language_code_list)/3); + } + + return QLocale::C; +} + +// Assumes that code is a +// QChar code[2]; +static QLocale::Country codeToCountry(const QChar *code) +{ + ushort uc1 = code[0].unicode(); + ushort uc2 = code[1].unicode(); + + const unsigned char *c = country_code_list; + for (; *c != 0; c += 2) { + if (uc1 == c[0] && uc2 == c[1]) + return QLocale::Country((c - country_code_list)/2); + } + + return QLocale::AnyCountry; +} + +static QString languageToCode(QLocale::Language language) +{ + if (language == QLocale::C) + return QLatin1String("C"); + + const unsigned char *c = language_code_list + 3*(uint(language)); + + QString code; + code.resize(c[2] == 0 ? 2 : 3); + + code[0] = ushort(c[0]); + code[1] = ushort(c[1]); + if (c[2] != 0) + code[2] = ushort(c[2]); + + return code; +} + +static QString countryToCode(QLocale::Country country) +{ + if (country == QLocale::AnyCountry) + return QString(); + + QString code; + code.resize(2); + const unsigned char *c = country_code_list + 2*(uint(country)); + code[0] = ushort(c[0]); + code[1] = ushort(c[1]); + return code; +} + +static const QLocalePrivate *findLocale(QLocale::Language language, QLocale::Country country) +{ + unsigned language_id = language; + unsigned country_id = country; + + uint idx = locale_index[language_id]; + + const QLocalePrivate *d = locale_data + idx; + + if (idx == 0) // default language has no associated country + return d; + + if (country == QLocale::AnyCountry) + return d; + + Q_ASSERT(d->languageId() == language_id); + + while (d->languageId() == language_id + && d->countryId() != country_id) + ++d; + + if (d->countryId() == country_id + && d->languageId() == language_id) + return d; + + return locale_data + idx; +} + +static bool splitLocaleName(const QString &name, QChar *lang_begin, QChar *cntry_begin) +{ + for (int i = 0; i < 3; ++i) + lang_begin[i] = 0; + for (int i = 0; i < 2; ++i) + cntry_begin[i] = 0; + + int l = name.length(); + + QChar *lang = lang_begin; + QChar *cntry = cntry_begin; + + int state = 0; + const QChar *uc = name.unicode(); + for (int i = 0; i < l; ++i) { + if (uc->unicode() == '.' || uc->unicode() == '@') + break; + + switch (state) { + case 0: + // parsing language + if (uc->unicode() == '_') { + state = 1; + break; + } + if (lang - lang_begin == 3) + return false; + if (uc->unicode() < 'a' || uc->unicode() > 'z') + return false; + + *lang = *uc; + ++lang; + break; + case 1: + // parsing country + if (cntry - cntry_begin == 2) { + cntry_begin[0] = 0; + break; + } + + *cntry = *uc; + ++cntry; + break; + } + + ++uc; + } + + int lang_len = lang - lang_begin; + + return lang_len == 2 || lang_len == 3; +} + +static void getLangAndCountry(const QString &name, QLocale::Language &lang, QLocale::Country &cntry) +{ + lang = QLocale::C; + cntry = QLocale::AnyCountry; + + QChar lang_code[3]; + QChar cntry_code[2]; + if (!splitLocaleName(name, lang_code, cntry_code)) + return; + + lang = codeToLanguage(lang_code); + if (lang == QLocale::C) + return; + + if (cntry_code[0].unicode() != 0) + cntry = codeToCountry(cntry_code); +} + +static const QLocalePrivate *findLocale(const QString &name) +{ + QLocale::Language lang; + QLocale::Country cntry; + getLangAndCountry(name, lang, cntry); + + return findLocale(lang, cntry); +} +static QString readEscapedFormatString(const QString &format, int *idx) +{ + int &i = *idx; + + Q_ASSERT(format.at(i).unicode() == '\''); + ++i; + if (i == format.size()) + return QString(); + if (format.at(i).unicode() == '\'') { // "''" outside of a quoted stirng + ++i; + return QLatin1String("'"); + } + + QString result; + + while (i < format.size()) { + if (format.at(i).unicode() == '\'') { + if (i + 1 < format.size() && format.at(i + 1).unicode() == '\'') { + // "''" inside of a quoted string + result.append(QLatin1Char('\'')); + i += 2; + } else { + break; + } + } else { + result.append(format.at(i++)); + } + } + if (i < format.size()) + ++i; + + return result; +} + +static int repeatCount(const QString &s, int i) +{ + QChar c = s.at(i); + int j = i + 1; + while (j < s.size() && s.at(j) == c) + ++j; + return j - i; +} + +static const QLocalePrivate *default_lp = 0; +static uint default_number_options = 0; + +#ifndef QT_NO_SYSTEMLOCALE +static QByteArray envVarLocale() +{ + static QByteArray lang = 0; +#ifdef Q_OS_UNIX + lang = qgetenv("LC_ALL"); + if (lang.isNull()) + lang = qgetenv("LC_NUMERIC"); + if (lang.isNull()) +#endif + lang = qgetenv("LANG"); + return lang; +} + + +#if defined(Q_OS_WIN) +/****************************************************************************** +** Wrappers for Windows locale system functions +*/ + +static const char *winLangCodeToIsoName(int code); +static QString winIso639LangName(LCID id = LOCALE_USER_DEFAULT); +static QString winIso3116CtryName(LCID id = LOCALE_USER_DEFAULT); + +static QString getWinLocaleInfo(LCTYPE type) +{ + int cnt = 0; + + LCID id = GetUserDefaultLCID(); + + QT_WA({ + cnt = GetLocaleInfoW(id, type, 0, 0)*2; + } , { + cnt = GetLocaleInfoA(id, type, 0, 0); + }); + + if (cnt == 0) { + qWarning("QLocale: empty windows locale info (%d)", (int)type); + return QString(); + } + + QByteArray buff(cnt, 0); + + QT_WA({ + cnt = GetLocaleInfoW(id, type, + reinterpret_cast<wchar_t*>(buff.data()), + buff.size()/2); + } , { + cnt = GetLocaleInfoA(id, type, + buff.data(), buff.size()); + }); + + if (cnt == 0) { + qWarning("QLocale: empty windows locale info (%d)", (int)type); + return QString(); + } + + QString result; + QT_WA({ + result = QString::fromUtf16(reinterpret_cast<ushort*>(buff.data())); + } , { + result = QString::fromLocal8Bit(buff.data()); + }); + return result; +} + +QByteArray getWinLocaleName(LCID id = LOCALE_USER_DEFAULT) +{ + QByteArray result; + if (id == LOCALE_USER_DEFAULT) { + result = envVarLocale(); + QChar lang[3]; + QChar cntry[2]; + if ( result == "C" || !result.isEmpty() + && splitLocaleName(QString::fromLocal8Bit(result), lang, cntry) ) { + long id = 0; + bool ok = false; + id = qstrtoll(result.data(), 0, 0, &ok); + if ( !ok || id == 0 || id < INT_MIN || id > INT_MAX ) + return result; + else + return winLangCodeToIsoName( (int)id ); + } + } + + if (QSysInfo::WindowsVersion == QSysInfo::WV_95 + || (QSysInfo::WindowsVersion & QSysInfo::WV_CE_based)) { + result = winLangCodeToIsoName(id != LOCALE_USER_DEFAULT ? id : GetUserDefaultLCID()); + } else { + if (id == LOCALE_USER_DEFAULT) + id = GetUserDefaultLCID(); + QString resultuage = winIso639LangName(id); + QString country = winIso3116CtryName(id); + result = resultuage.toLatin1(); + if (!country.isEmpty()) { + result += '_'; + result += country.toLatin1(); + } + } + + return result; +} + +Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id) +{ + return QLocale(QString::fromLatin1(getWinLocaleName(id))); +} + +static QString winToQtFormat(const QString &sys_fmt) +{ + QString result; + int i = 0; + + while (i < sys_fmt.size()) { + if (sys_fmt.at(i).unicode() == QLatin1Char('\'')) { + QString text = readEscapedFormatString(sys_fmt, &i); + if (text == QLatin1String("'")) + result += QLatin1String("''"); + else + result += QLatin1Char('\'') + text + QLatin1Char('\''); + continue; + } + + QChar c = sys_fmt.at(i); + int repeat = repeatCount(sys_fmt, i); + + switch (c.unicode()) { + // Date + case 'y': + if (repeat > 5) + repeat = 5; + else if (repeat == 3) + repeat = 2; + switch (repeat) { + case 1: + result += QLatin1String("yy"); // "y" unsupported by Qt, use "yy" + break; + case 5: + result += QLatin1String("yyyy"); // "yyyyy" same as "yyyy" on Windows + break; + default: + result += QString(repeat, QLatin1Char('y')); + break; + } + break; + case 'g': + if (repeat > 2) + repeat = 2; + switch (repeat) { + case 2: + break; // no equivalent of "gg" in Qt + default: + result += QLatin1Char('g'); + break; + } + break; + case 't': + if (repeat > 2) + repeat = 2; + result += QLatin1String("AP"); // "t" unsupported, use "AP" + break; + default: + result += QString(repeat, c); + break; + } + + i += repeat; + } + + return result; +} + + + +static QString winDateToString(const QDate &date, DWORD flags) +{ + SYSTEMTIME st; + memset(&st, 0, sizeof(SYSTEMTIME)); + st.wYear = date.year(); + st.wMonth = date.month(); + st.wDay = date.day(); + + LCID id = GetUserDefaultLCID(); + + QT_WA({ + TCHAR buf[255]; + if (GetDateFormatW(id, flags, &st, 0, buf, 255)) + return QString::fromUtf16((ushort*)buf); + } , { + char buf[255]; + if (GetDateFormatA(id, flags, &st, 0, (char*)&buf, 255)) + return QString::fromLocal8Bit(buf); + }); + + return QString(); +} + +static QString winTimeToString(const QTime &time) +{ + SYSTEMTIME st; + memset(&st, 0, sizeof(SYSTEMTIME)); + st.wHour = time.hour(); + st.wMinute = time.minute(); + st.wSecond = time.second(); + st.wMilliseconds = 0; + + DWORD flags = 0; + LCID id = GetUserDefaultLCID(); + + QT_WA({ + TCHAR buf[255]; + if (GetTimeFormatW(id, flags, &st, 0, buf, 255)) + return QString::fromUtf16((ushort*)buf); + } , { + char buf[255]; + if (GetTimeFormatA(id, flags, &st, 0, (char*)&buf, 255)) + return QString::fromLocal8Bit(buf); + }); + + return QString(); +} + +static QString winDayName(int day, bool short_format) +{ + static const LCTYPE short_day_map[] + = { LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, + LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5, + LOCALE_SABBREVDAYNAME6, LOCALE_SABBREVDAYNAME7 }; + + static const LCTYPE long_day_map[] + = { LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, + LOCALE_SDAYNAME3, LOCALE_SDAYNAME4, LOCALE_SDAYNAME5, + LOCALE_SDAYNAME6, LOCALE_SDAYNAME7 }; + + day -= 1; + + LCTYPE type = short_format + ? short_day_map[day] : long_day_map[day]; + return getWinLocaleInfo(type); +} + +static QString winMonthName(int month, bool short_format) +{ + static const LCTYPE short_month_map[] + = { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3, + LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6, + LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9, + LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 }; + + static const LCTYPE long_month_map[] + = { LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, + LOCALE_SMONTHNAME4, LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, + LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8, LOCALE_SMONTHNAME9, + LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12 }; + + month -= 1; + if (month < 0 || month > 11) + return QString(); + + LCTYPE type = short_format ? short_month_map[month] : long_month_map[month]; + return getWinLocaleInfo(type); +} + +static QLocale::MeasurementSystem winSystemMeasurementSystem() +{ + LCID id = GetUserDefaultLCID(); + TCHAR output[2]; + + if (GetLocaleInfo(id, LOCALE_IMEASURE, output, 2)) { + QString iMeasure = QT_WA_INLINE( + QString::fromUtf16(reinterpret_cast<ushort*>(output)), + QString::fromLocal8Bit(reinterpret_cast<char*>(output))); + if (iMeasure == QString::fromLatin1("1")) { + return QLocale::ImperialSystem; + } + } + + return QLocale::MetricSystem; +} + +static QString winSystemAMText() +{ + LCID id = GetUserDefaultLCID(); + TCHAR output[15]; // maximum length including terminating zero character for Win2003+ + + if (GetLocaleInfo(id, LOCALE_S1159, output, 15)) { + return QT_WA_INLINE( + QString::fromUtf16(reinterpret_cast<ushort*>(output)), + QString::fromLocal8Bit(reinterpret_cast<char*>(output))); + } + + return QString(); +} + +static QString winSystemPMText() +{ + LCID id = GetUserDefaultLCID(); + TCHAR output[15]; // maximum length including terminating zero character for Win2003+ + + if (GetLocaleInfo(id, LOCALE_S2359, output, 15)) { + return QT_WA_INLINE( + QString::fromUtf16(reinterpret_cast<ushort*>(output)), + QString::fromLocal8Bit(reinterpret_cast<char*>(output))); + } + + return QString(); +} + +QLocale QSystemLocale::fallbackLocale() const +{ + return QLocale(QString::fromLatin1(getWinLocaleName())); +} + +QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const +{ + LCTYPE locale_info = 0; + bool format_string = false; + + switch(type) { +// case Name: +// return getWinLocaleName(); + case DecimalPoint: + locale_info = LOCALE_SDECIMAL; + break; + case GroupSeparator: + locale_info = LOCALE_STHOUSAND; + break; + case NegativeSign: + locale_info = LOCALE_SNEGATIVESIGN; + break; + case PositiveSign: + locale_info = LOCALE_SPOSITIVESIGN; + break; + case DateFormatLong: + locale_info = LOCALE_SLONGDATE; + format_string = true; + break; + case DateFormatShort: + locale_info = LOCALE_SSHORTDATE; + format_string = true; + break; + case TimeFormatLong: + case TimeFormatShort: + locale_info = LOCALE_STIMEFORMAT; + format_string = true; + break; + + case DateTimeFormatLong: + case DateTimeFormatShort: + return query(type == DateTimeFormatLong ? DateFormatLong : DateFormatShort).toString() + + QLatin1Char(' ') + query(type == DateTimeFormatLong ? TimeFormatLong : TimeFormatShort).toString(); + case DayNameLong: + case DayNameShort: + return winDayName(in.toInt(), (type == DayNameShort)); + case MonthNameLong: + case MonthNameShort: + return winMonthName(in.toInt(), (type == MonthNameShort)); + case DateToStringShort: + case DateToStringLong: + return winDateToString(in.toDate(), type == DateToStringShort ? DATE_SHORTDATE : DATE_LONGDATE); + case TimeToStringShort: + case TimeToStringLong: + return winTimeToString(in.toTime()); + case DateTimeToStringShort: + case DateTimeToStringLong: { + const QDateTime dt = in.toDateTime(); + return winDateToString(dt.date(), type == DateTimeToStringShort ? DATE_SHORTDATE : DATE_LONGDATE) + + QLatin1Char(' ') + winTimeToString(dt.time()); } + + case ZeroDigit: + locale_info = LOCALE_SNATIVEDIGITS; + break; + + case LanguageId: + case CountryId: { + QString locale = QString::fromLatin1(getWinLocaleName()); + QLocale::Language lang; + QLocale::Country cntry; + getLangAndCountry(locale, lang, cntry); + if (type == LanguageId) + return lang; + if (cntry == QLocale::AnyCountry) + return fallbackLocale().country(); + return cntry; + } + + case MeasurementSystem: + return QVariant(static_cast<int>(winSystemMeasurementSystem())); + + case AMText: + return QVariant(winSystemAMText()); + case PMText: + return QVariant(winSystemPMText()); + default: + break; + } + if (locale_info) { + QString result = getWinLocaleInfo(locale_info); + if (format_string) + result = winToQtFormat(result); + if (!result.isEmpty()) + return result; + } + return QVariant(); +} + +/* Win95 doesn't have a function to return the ISO lang/country name of the user's locale. + Instead it can return a "Windows code". This maps windows codes to ISO country names. */ + +struct WindowsToISOListElt { + int windows_code; + char iso_name[6]; +}; + +static const WindowsToISOListElt windows_to_iso_list[] = { + { 0x0401, "ar_SA" }, + { 0x0402, "bg\0 " }, + { 0x0403, "ca\0 " }, + { 0x0404, "zh_TW" }, + { 0x0405, "cs\0 " }, + { 0x0406, "da\0 " }, + { 0x0407, "de\0 " }, + { 0x0408, "el\0 " }, + { 0x0409, "en_US" }, + { 0x040a, "es\0 " }, + { 0x040b, "fi\0 " }, + { 0x040c, "fr\0 " }, + { 0x040d, "he\0 " }, + { 0x040e, "hu\0 " }, + { 0x040f, "is\0 " }, + { 0x0410, "it\0 " }, + { 0x0411, "ja\0 " }, + { 0x0412, "ko\0 " }, + { 0x0413, "nl\0 " }, + { 0x0414, "no\0 " }, + { 0x0415, "pl\0 " }, + { 0x0416, "pt_BR" }, + { 0x0418, "ro\0 " }, + { 0x0419, "ru\0 " }, + { 0x041a, "hr\0 " }, + { 0x041c, "sq\0 " }, + { 0x041d, "sv\0 " }, + { 0x041e, "th\0 " }, + { 0x041f, "tr\0 " }, + { 0x0420, "ur\0 " }, + { 0x0421, "in\0 " }, + { 0x0422, "uk\0 " }, + { 0x0423, "be\0 " }, + { 0x0425, "et\0 " }, + { 0x0426, "lv\0 " }, + { 0x0427, "lt\0 " }, + { 0x0429, "fa\0 " }, + { 0x042a, "vi\0 " }, + { 0x042d, "eu\0 " }, + { 0x042f, "mk\0 " }, + { 0x0436, "af\0 " }, + { 0x0438, "fo\0 " }, + { 0x0439, "hi\0 " }, + { 0x043e, "ms\0 " }, + { 0x0458, "mt\0 " }, + { 0x0801, "ar_IQ" }, + { 0x0804, "zh_CN" }, + { 0x0807, "de_CH" }, + { 0x0809, "en_GB" }, + { 0x080a, "es_MX" }, + { 0x080c, "fr_BE" }, + { 0x0810, "it_CH" }, + { 0x0812, "ko\0 " }, + { 0x0813, "nl_BE" }, + { 0x0814, "no\0 " }, + { 0x0816, "pt\0 " }, + { 0x081a, "sr\0 " }, + { 0x081d, "sv_FI" }, + { 0x0c01, "ar_EG" }, + { 0x0c04, "zh_HK" }, + { 0x0c07, "de_AT" }, + { 0x0c09, "en_AU" }, + { 0x0c0a, "es\0 " }, + { 0x0c0c, "fr_CA" }, + { 0x0c1a, "sr\0 " }, + { 0x1001, "ar_LY" }, + { 0x1004, "zh_SG" }, + { 0x1007, "de_LU" }, + { 0x1009, "en_CA" }, + { 0x100a, "es_GT" }, + { 0x100c, "fr_CH" }, + { 0x1401, "ar_DZ" }, + { 0x1407, "de_LI" }, + { 0x1409, "en_NZ" }, + { 0x140a, "es_CR" }, + { 0x140c, "fr_LU" }, + { 0x1801, "ar_MA" }, + { 0x1809, "en_IE" }, + { 0x180a, "es_PA" }, + { 0x1c01, "ar_TN" }, + { 0x1c09, "en_ZA" }, + { 0x1c0a, "es_DO" }, + { 0x2001, "ar_OM" }, + { 0x2009, "en_JM" }, + { 0x200a, "es_VE" }, + { 0x2401, "ar_YE" }, + { 0x2409, "en\0 " }, + { 0x240a, "es_CO" }, + { 0x2801, "ar_SY" }, + { 0x2809, "en_BZ" }, + { 0x280a, "es_PE" }, + { 0x2c01, "ar_JO" }, + { 0x2c09, "en_TT" }, + { 0x2c0a, "es_AR" }, + { 0x3001, "ar_LB" }, + { 0x300a, "es_EC" }, + { 0x3401, "ar_KW" }, + { 0x340a, "es_CL" }, + { 0x3801, "ar_AE" }, + { 0x380a, "es_UY" }, + { 0x3c01, "ar_BH" }, + { 0x3c0a, "es_PY" }, + { 0x4001, "ar_QA" }, + { 0x400a, "es_BO" }, + { 0x440a, "es_SV" }, + { 0x480a, "es_HN" }, + { 0x4c0a, "es_NI" }, + { 0x500a, "es_PR" } +}; + +static const int windows_to_iso_count + = sizeof(windows_to_iso_list)/sizeof(WindowsToISOListElt); + +static const char *winLangCodeToIsoName(int code) +{ + int cmp = code - windows_to_iso_list[0].windows_code; + if (cmp < 0) + return 0; + + if (cmp == 0) + return windows_to_iso_list[0].iso_name; + + int begin = 0; + int end = windows_to_iso_count; + + while (end - begin > 1) { + uint mid = (begin + end)/2; + + const WindowsToISOListElt *elt = windows_to_iso_list + mid; + int cmp = code - elt->windows_code; + if (cmp < 0) + end = mid; + else if (cmp > 0) + begin = mid; + else + return elt->iso_name; + } + + return 0; + +} + +static QString winIso639LangName(LCID id) +{ + QString result; + + // Windows returns the wrong ISO639 for some languages, we need to detect them here using + // the language code + QString lang_code; + QT_WA({ + TCHAR out[256]; + if (GetLocaleInfoW(id, LOCALE_ILANGUAGE, out, 255)) + lang_code = QString::fromUtf16((ushort*)out); + } , { + char out[256]; + if (GetLocaleInfoA(id, LOCALE_ILANGUAGE, out, 255)) + lang_code = QString::fromLocal8Bit(out); + }); + + if (!lang_code.isEmpty()) { + const char *endptr; + bool ok; + QByteArray latin1_lang_code = lang_code.toLatin1(); + int i = qstrtoull(latin1_lang_code, &endptr, 16, &ok); + if (ok && *endptr == '\0') { + switch (i) { + case 0x814: + result = QLatin1String("nn"); // Nynorsk + break; + default: + break; + } + } + } + + if (!result.isEmpty()) + return result; + + // not one of the problematic languages - do the usual lookup + QT_WA({ + TCHAR out[256]; + if (GetLocaleInfoW(id, LOCALE_SISO639LANGNAME , out, 255)) + result = QString::fromUtf16((ushort*)out); + } , { + char out[256]; + if (GetLocaleInfoA(id, LOCALE_SISO639LANGNAME, out, 255)) + result = QString::fromLocal8Bit(out); + }); + + return result; +} + +static QString winIso3116CtryName(LCID id) +{ + QString result; + + QT_WA({ + TCHAR out[256]; + if (GetLocaleInfoW(id, LOCALE_SISO3166CTRYNAME, out, 255)) + result = QString::fromUtf16((ushort*)out); + } , { + char out[256]; + if (GetLocaleInfoA(id, LOCALE_SISO3166CTRYNAME, out, 255)) + result = QString::fromLocal8Bit(out); + }); + + return result; +} + + +#elif defined(Q_OS_MAC) +/****************************************************************************** +** Wrappers for Mac locale system functions +*/ + +static QByteArray getMacLocaleName() +{ + QByteArray result = envVarLocale(); + + QChar lang[3]; + QChar cntry[2]; + if (result.isEmpty() || result != "C" + && !splitLocaleName(QString::fromLocal8Bit(result), lang, cntry)) { + QCFType<CFLocaleRef> l = CFLocaleCopyCurrent(); + CFStringRef locale = CFLocaleGetIdentifier(l); + result = QCFString::toQString(locale).toUtf8(); + } + return result; +} + +static QString macMonthName(int month, bool short_format) +{ + month -= 1; + if (month < 0 || month > 11) + return QString(); + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { + QCFType<CFDateFormatterRef> formatter + = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()), + kCFDateFormatterNoStyle, kCFDateFormatterNoStyle); + QCFType<CFArrayRef> values + = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter, + short_format ? kCFDateFormatterShortMonthSymbols + : kCFDateFormatterMonthSymbols)); + if (values != 0) { + CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, month)); + return QCFString::toQString(cfstring); + } + } +#endif + return QString(); +} + + +static QString macDayName(int day, bool short_format) +{ + if (day < 1 || day > 7) + return QString(); + +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4) + if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { + QCFType<CFDateFormatterRef> formatter + = CFDateFormatterCreate(0, QCFType<CFLocaleRef>(CFLocaleCopyCurrent()), + kCFDateFormatterNoStyle, kCFDateFormatterNoStyle); + QCFType<CFArrayRef> values = static_cast<CFArrayRef>(CFDateFormatterCopyProperty(formatter, + short_format ? kCFDateFormatterShortWeekdaySymbols + : kCFDateFormatterWeekdaySymbols)); + if (values != 0) { + CFStringRef cfstring = static_cast<CFStringRef>(CFArrayGetValueAtIndex(values, day % 7)); + return QCFString::toQString(cfstring); + } + } +#endif + return QString(); +} + +static QString macDateToString(const QDate &date, bool short_format) +{ + CFGregorianDate macGDate; + macGDate.year = date.year(); + macGDate.month = date.month(); + macGDate.day = date.day(); + macGDate.hour = 0; + macGDate.minute = 0; + macGDate.second = 0.0; + QCFType<CFDateRef> myDate + = CFDateCreate(0, CFGregorianDateGetAbsoluteTime(macGDate, + QCFType<CFTimeZoneRef>(CFTimeZoneCopyDefault()))); + QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent(); + CFDateFormatterStyle style = short_format ? kCFDateFormatterShortStyle : kCFDateFormatterLongStyle; + QCFType<CFDateFormatterRef> myFormatter + = CFDateFormatterCreate(kCFAllocatorDefault, + mylocale, style, + kCFDateFormatterNoStyle); + return QCFString(CFDateFormatterCreateStringWithDate(0, myFormatter, myDate)); +} + +static QString macTimeToString(const QTime &time, bool short_format) +{ + CFGregorianDate macGDate; + // Assume this is local time and the current date + QDate dt = QDate::currentDate(); + macGDate.year = dt.year(); + macGDate.month = dt.month(); + macGDate.day = dt.day(); + macGDate.hour = time.hour(); + macGDate.minute = time.minute(); + macGDate.second = time.second(); + QCFType<CFDateRef> myDate + = CFDateCreate(0, CFGregorianDateGetAbsoluteTime(macGDate, + QCFType<CFTimeZoneRef>(CFTimeZoneCopyDefault()))); + + QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent(); + CFDateFormatterStyle style = short_format ? kCFDateFormatterShortStyle : kCFDateFormatterLongStyle; + QCFType<CFDateFormatterRef> myFormatter = CFDateFormatterCreate(kCFAllocatorDefault, + mylocale, + kCFDateFormatterNoStyle, + style); + return QCFString(CFDateFormatterCreateStringWithDate(0, myFormatter, myDate)); +} + +static QString macToQtFormat(const QString &sys_fmt) +{ + QString result; + int i = 0; + + while (i < sys_fmt.size()) { + if (sys_fmt.at(i).unicode() == '\'') { + QString text = readEscapedFormatString(sys_fmt, &i); + if (text == QLatin1String("'")) + result += QLatin1String("''"); + else + result += QLatin1Char('\'') + text + QLatin1Char('\''); + continue; + } + + QChar c = sys_fmt.at(i); + int repeat = repeatCount(sys_fmt, i); + + switch (c.unicode()) { + case 'G': // Qt doesn't support these :( + case 'Y': + case 'D': + case 'F': + case 'w': + case 'W': + case 'g': + break; + + case 'u': // extended year - use 'y' + if (repeat < 4) + result += QLatin1String("yy"); + else + result += QLatin1String("yyyy"); + break; + case 'S': // fractional second + if (repeat < 3) + result += QLatin1String("z"); + else + result += QLatin1String("zzz"); + break; + case 'E': + if (repeat <= 3) + result += QLatin1String("ddd"); + else + result += QLatin1String("dddd"); + break; + case 'e': + if (repeat >= 2) + result += QLatin1String("dd"); + else + result += QLatin1String("d"); + break; + case 'a': + result += QLatin1String("AP"); + break; + case 'k': + result += QString(repeat, QLatin1Char('H')); + break; + case 'K': + result += QString(repeat, QLatin1Char('h')); + break; + case 'z': + case 'Z': + case 'v': + result += QLatin1Char('t'); + break; + default: + result += QString(repeat, c); + break; + } + + i += repeat; + } + + return result; +} + +QString getMacDateFormat(CFDateFormatterStyle style) +{ + QCFType<CFLocaleRef> l = CFLocaleCopyCurrent(); + QCFType<CFDateFormatterRef> formatter = CFDateFormatterCreate(kCFAllocatorDefault, + l, style, kCFDateFormatterNoStyle); + return macToQtFormat(QCFString::toQString(CFDateFormatterGetFormat(formatter))); +} + +static QString getMacTimeFormat(CFDateFormatterStyle style) +{ + QCFType<CFLocaleRef> l = CFLocaleCopyCurrent(); + QCFType<CFDateFormatterRef> formatter = CFDateFormatterCreate(kCFAllocatorDefault, + l, kCFDateFormatterNoStyle, style); + return macToQtFormat(QCFString::toQString(CFDateFormatterGetFormat(formatter))); +} + +static QString getCFLocaleValue(CFStringRef key) +{ + QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent(); + CFTypeRef value = CFLocaleGetValue(locale, key); + return QCFString::toQString(CFStringRef(static_cast<CFTypeRef>(value))); +} + +static QLocale::MeasurementSystem macMeasurementSystem() +{ + QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent(); + CFStringRef system = static_cast<CFStringRef>(CFLocaleGetValue(locale, kCFLocaleMeasurementSystem)); + if (QCFString::toQString(system) == QLatin1String("Metric")) { + return QLocale::MetricSystem; + } else { + return QLocale::ImperialSystem; + } +} + +QLocale QSystemLocale::fallbackLocale() const +{ + return QLocale(QString::fromUtf8(getMacLocaleName().constData())); +} + +QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const +{ + switch(type) { +// case Name: +// return getMacLocaleName(); + case DecimalPoint: { + QString value = getCFLocaleValue(kCFLocaleDecimalSeparator); + return value.isEmpty() ? QVariant() : value; + } + case GroupSeparator: { + QString value = getCFLocaleValue(kCFLocaleGroupingSeparator); + return value.isEmpty() ? QVariant() : value; + } + case DateFormatLong: + case DateFormatShort: + return macToQtFormat(getMacDateFormat(type == DateFormatShort + ? kCFDateFormatterShortStyle + : kCFDateFormatterLongStyle)); + case TimeFormatLong: + case TimeFormatShort: + return macToQtFormat(getMacTimeFormat(type == TimeFormatShort + ? kCFDateFormatterShortStyle + : kCFDateFormatterLongStyle)); + case DayNameLong: + case DayNameShort: + return macDayName(in.toInt(), (type == DayNameShort)); + case MonthNameLong: + case MonthNameShort: + return macMonthName(in.toInt(), (type == MonthNameShort)); + case DateToStringShort: + case DateToStringLong: + return macDateToString(in.toDate(), (type == DateToStringShort)); + case TimeToStringShort: + case TimeToStringLong: + return macTimeToString(in.toTime(), (type == TimeToStringShort)); + + case NegativeSign: + case PositiveSign: + case ZeroDigit: + case LanguageId: + case CountryId: + break; + + case MeasurementSystem: + return QVariant(static_cast<int>(macMeasurementSystem())); + + case AMText: + case PMText: + break; + default: + break; + } + return QVariant(); +} + +#elif defined(Q_OS_UNIX) + +static uint unixGetSystemMeasurementSystem() +{ + QString meas_locale = QString::fromLocal8Bit(qgetenv("LC_ALL")); + if (meas_locale.isEmpty()) { + meas_locale = QString::fromLocal8Bit(qgetenv("LC_MEASUREMENT")); + } + if (meas_locale.isEmpty()) { + meas_locale = QString::fromLocal8Bit(qgetenv("LANG")); + } + if (meas_locale.isEmpty()) { + meas_locale = QString::fromLocal8Bit("C"); + } + + if (meas_locale.compare(QString::fromLocal8Bit("Metric"), Qt::CaseInsensitive) == 0) + return 0; + if (meas_locale.compare(QString::fromLocal8Bit("Other"), Qt::CaseInsensitive) == 0) + return 0; + + const QLocalePrivate* locale = findLocale(meas_locale); + return locale->measurementSystem(); +} + +/*! + \internal +*/ +QLocale QSystemLocale::fallbackLocale() const +{ + return QLocale(QLatin1String(envVarLocale())); +} + +/*! + \internal +*/ +QVariant QSystemLocale::query(QueryType type, QVariant /* in */) const +{ + if (type == MeasurementSystem) { + return QVariant(unixGetSystemMeasurementSystem()); + } else { + return QVariant(); + } +} + +#else + +/*! + Returns a fallback locale, that will get used for everything that + is not explicitly overridden by the system locale. +*/ +QLocale QSystemLocale::fallbackLocale() const +{ + return QLocale(QLatin1String(envVarLocale())); +} + +/*! + Performs a query of the given \a type in the system locale for + customized values or conversion. If the method returns a null + QVariant, the conversion of the fallbackLocale() will be used. + + \a in is unused for some of the query types. + + \sa QSystemLocale::QueryType +*/ +QVariant QSystemLocale::query(QueryType /* type */, QVariant /* in */) const +{ + return QVariant(); +} + +#endif + +#ifndef QT_NO_SYSTEMLOCALE +static QSystemLocale *_systemLocale = 0; +Q_GLOBAL_STATIC_WITH_ARGS(QSystemLocale, QSystemLocale_globalSystemLocale, (true)) +static QLocalePrivate *system_lp = 0; +Q_GLOBAL_STATIC(QLocalePrivate, globalLocalePrivate) +#endif + +/****************************************************************************** +** Default system locale behavior +*/ + +/*! + \class QSystemLocale + \brief The QSystemLocale class can be used to finetune the system locale + of the user. + \since 4.2 + + \ingroup i18n + + \warning This class is only useful in very rare cases. Usually QLocale offers + all the functionality required for application development. + + QSystemLocale allows to override the values provided by the system + locale (QLocale::system()). + + \sa QLocale +*/ + +/*! + \enum QSystemLocale::QueryType + + Specifies the type of information queried by query(). For each value + the type of information to return from the query() method is listed. + + \value LanguageId a uint specifying the language. + \value CountryId a uint specifying the country. + \value DecimalPoint a QString specifying the decimal point. + \value GroupSeparator a QString specifying the group separator. + \value ZeroDigit a QString specifying the zero digit. + \value NegativeSign a QString specifying the minus sign. + \value PositiveSign a QString specifying the plus sign. + \value DateFormatLong a QString specifying the long date format + \value DateFormatShort a QString specifying the short date format + \value TimeFormatLong a QString specifying the long time format + \value TimeFormatShort a QString specifying the short time format + \value DayNameLong a QString specifying the name of a weekday. the in variant contains an integer between 1 and 7 (Monday - Sunday) + \value DayNameShort a QString specifying the short name of a weekday. the in variant contains an integer between 1 and 7 (Monday - Sunday) + \value MonthNameLong a QString specifying the name of a month. the in variant contains an integer between 1 and 12 + \value MonthNameShort a QString specifying the short name of a month. the in variant contains an integer between 1 and 12 + \value DateToStringLong converts the QDate stored in the in variant to a QString using the long date format + \value DateToStringShort converts the QDate stored in the in variant to a QString using the short date format + \value TimeToStringLong converts the QTime stored in the in variant to a QString using the long time format + \value TimeToStringShort converts the QTime stored in the in variant to a QString using the short time format + \value DateTimeFormatLong a QString specifying the long date time format + \value DateTimeFormatShort a QString specifying the short date time format + \value DateTimeToStringLong converts the QDateTime in the in variant to a QString using the long datetime format + \value DateTimeToStringShort converts the QDateTime in the in variant to a QString using the short datetime format + \value MeasurementSystem a QLocale::MeasurementSystem enum specifying the measurement system + \value AMText a string that represents the system AM designator associated with a 12-hour clock. + \value PMText a string that represents the system PM designator associated with a 12-hour clock. +*/ + +/*! + Constructs a QSystemLocale object. The constructor will automatically + install this object as the system locale and remove any earlier installed + system locales. +*/ +QSystemLocale::QSystemLocale() +{ + delete _systemLocale; + _systemLocale = this; + + if (system_lp) + system_lp->m_language_id = 0; +} + +/*! \internal */ +QSystemLocale::QSystemLocale(bool) +{ } + +/*! + Deletes the object. +*/ +QSystemLocale::~QSystemLocale() +{ + if (_systemLocale == this) { + _systemLocale = 0; + + if (system_lp) + system_lp->m_language_id = 0; + } +} + +static const QSystemLocale *systemLocale() +{ + if (_systemLocale) + return _systemLocale; + return QSystemLocale_globalSystemLocale(); +} + +void QLocalePrivate::updateSystemPrivate() +{ + const QSystemLocale *sys_locale = systemLocale(); + if (!system_lp) + system_lp = globalLocalePrivate(); + *system_lp = *sys_locale->fallbackLocale().d(); + + QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant()); + if (!res.isNull()) + system_lp->m_language_id = res.toInt(); + res = sys_locale->query(QSystemLocale::CountryId, QVariant()); + if (!res.isNull()) + system_lp->m_country_id = res.toInt(); + + res = sys_locale->query(QSystemLocale::DecimalPoint, QVariant()); + if (!res.isNull()) + system_lp->m_decimal = res.toString().at(0).unicode(); + + res = sys_locale->query(QSystemLocale::GroupSeparator, QVariant()); + if (!res.isNull()) + system_lp->m_group = res.toString().at(0).unicode(); + + res = sys_locale->query(QSystemLocale::ZeroDigit, QVariant()); + if (!res.isNull()) + system_lp->m_zero = res.toString().at(0).unicode(); + + res = sys_locale->query(QSystemLocale::NegativeSign, QVariant()); + if (!res.isNull()) + system_lp->m_minus = res.toString().at(0).unicode(); + + res = sys_locale->query(QSystemLocale::PositiveSign, QVariant()); + if (!res.isNull()) + system_lp->m_plus = res.toString().at(0).unicode(); +} +#endif + +static const QLocalePrivate *systemPrivate() +{ +#ifndef QT_NO_SYSTEMLOCALE + // copy over the information from the fallback locale and modify + if (!system_lp || system_lp->m_language_id == 0) + QLocalePrivate::updateSystemPrivate(); + + return system_lp; +#else + return locale_data; +#endif +} + +static const QLocalePrivate *defaultPrivate() +{ + if (!default_lp) + default_lp = systemPrivate(); + return default_lp; +} + +static QString getLocaleListData(const ushort *data, int size, int index) +{ + static const ushort separator = ';'; + while (index && size > 0) { + while (*data != separator) + ++data, --size; + --index; + ++data; + --size; + } + const ushort *end = data; + while (size > 0 && *end != separator) + ++end, --size; + return QString::fromRawData(reinterpret_cast<const QChar*>(data), end-data); +} + +static inline QString getLocaleData(const ushort *data, int size) +{ + return QString::fromRawData(reinterpret_cast<const QChar*>(data), size); +} + + +#ifndef QT_NO_DATASTREAM +QDataStream &operator<<(QDataStream &ds, const QLocale &l) +{ + ds << l.name(); + return ds; +} + +QDataStream &operator>>(QDataStream &ds, QLocale &l) +{ + QString s; + ds >> s; + l = QLocale(s); + return ds; +} +#endif + + +/*! + \class QLocale + \brief The QLocale class converts between numbers and their + string representations in various languages. + + \reentrant + \ingroup i18n + \ingroup text + \ingroup shared + \mainclass + + QLocale is initialized with a language/country pair in its + constructor and offers number-to-string and string-to-number + conversion functions similar to those in QString. + + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qlocale.cpp 0 + + QLocale supports the concept of a default locale, which is + determined from the system's locale settings at application + startup. The default locale can be changed by calling the + static member setDefault(). Setting the default locale has the + following effects: + + \list + \i If a QLocale object is constructed with the default constructor, + it will use the default locale's settings. + \i QString::toInt(), QString::toDouble(), etc., interpret the + string according to the default locale. If this fails, it + falls back on the "C" locale. + \i QString::arg() uses the default locale to format a number when + its position specifier in the format string contains an 'L', + e.g. "%L1". + \endlist + + The following example illustrates how to use QLocale directly: + + \snippet doc/src/snippets/code/src_corelib_tools_qlocale.cpp 1 + + When a language/country pair is specified in the constructor, one + of three things can happen: + + \list + \i If the language/country pair is found in the database, it is used. + \i If the language is found but the country is not, or if the country + is \c AnyCountry, the language is used with the most + appropriate available country (for example, Germany for German), + \i If neither the language nor the country are found, QLocale + defaults to the default locale (see setDefault()). + \endlist + + The "C" locale is identical to \l{English}/\l{UnitedStates}. + + Use language() and country() to determine the actual language and + country values used. + + An alternative method for constructing a QLocale object is by + specifying the locale name. + + \snippet doc/src/snippets/code/src_corelib_tools_qlocale.cpp 2 + + This constructor converts the locale name to a language/country + pair; it does not use the system locale database. + + The double-to-string and string-to-double conversion functions are + covered by the following licenses: + + \legalese + Copyright (c) 1991 by AT&T. + + Permission to use, copy, modify, and distribute this software for any + purpose without fee is hereby granted, provided that this entire notice + is included in all copies of any software which is or includes a copy + or modification of this software and in all copies of the supporting + documentation for such software. + + THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED + WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY + REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY + OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + + This product includes software developed by the University of + California, Berkeley and its contributors. + + QLocale's data is based on Common Locale Data Repository v1.6.1. + + \sa QString::arg(), QString::toInt(), QString::toDouble() +*/ + +/*! + \enum QLocale::Language + + This enumerated type is used to specify a language. + + \value C The "C" locale is English/UnitedStates. + \value Abkhazian + \value Afan + \value Afar + \value Afrikaans + \value Albanian + \value Amharic + \value Arabic + \value Armenian + \value Assamese + \value Aymara + \value Azerbaijani + \value Bashkir + \value Basque + \value Bengali + \value Bhutani + \value Bihari + \value Bislama + \value Bosnian + \value Breton + \value Bulgarian + \value Burmese + \value Byelorussian + \value Cambodian + \value Catalan + \value Chinese + \value Cornish + \value Corsican + \value Croatian + \value Czech + \value Danish + \value Divehi + \value Dutch + \value English + \value Esperanto + \value Estonian + \value Faroese + \value FijiLanguage + \value Finnish + \value French + \value Frisian + \value Gaelic + \value Galician + \value Georgian + \value German + \value Greek + \value Greenlandic + \value Guarani + \value Gujarati + \value Hausa + \value Hebrew + \value Hindi + \value Hungarian + \value Icelandic + \value Indonesian + \value Interlingua + \value Interlingue + \value Inuktitut + \value Inupiak + \value Irish + \value Italian + \value Japanese + \value Javanese + \value Kannada + \value Kashmiri + \value Kazakh + \value Kinyarwanda + \value Kirghiz + \value Korean + \value Kurdish + \value Kurundi + \value Laothian + \value Latin + \value Latvian + \value Lingala + \value Lithuanian + \value Macedonian + \value Malagasy + \value Malay + \value Malayalam + \value Maltese + \value Manx + \value Maori + \value Marathi + \value Moldavian + \value Mongolian + \value NauruLanguage + \value Nepali + \value Norwegian + \value NorwegianBokmal + \value Nynorsk Obsolete, please use NorwegianNynorsk + \value NorwegianNynorsk + \value Occitan + \value Oriya + \value Pashto + \value Persian + \value Polish + \value Portuguese + \value Punjabi + \value Quechua + \value RhaetoRomance + \value Romanian + \value Russian + \value Samoan + \value Sangho + \value Sanskrit + \value Serbian + \value SerboCroatian + \value Sesotho + \value Setswana + \value Shona + \value Sindhi + \value Singhalese + \value Siswati + \value Slovak + \value Slovenian + \value Somali + \value Spanish + \value Sundanese + \value Swahili + \value Swedish + \value Tagalog + \value Tajik + \value Tamil + \value Tatar + \value Telugu + \value Thai + \value Tibetan + \value Tigrinya + \value TongaLanguage + \value Tsonga + \value Turkish + \value Turkmen + \value Twi + \value Uigur + \value Ukrainian + \value Urdu + \value Uzbek + \value Vietnamese + \value Volapuk + \value Welsh + \value Wolof + \value Xhosa + \value Yiddish + \value Yoruba + \value Zhuang + \value Zulu + \value Bosnian + \value Divehi + \value Manx + \value Cornish + \value Akan + \value Konkani + \value Ga + \value Igbo + \value Kamba + \value Syriac + \value Blin + \value Geez + \value Koro + \value Sidamo + \value Atsam + \value Tigre + \value Jju + \value Friulian + \value Venda + \value Ewe + \value Walamo + \value Hawaiian + \value Tyap + \value Chewa + \omitvalue LastLanguage + + \sa language() +*/ + +/*! + \enum QLocale::Country + + This enumerated type is used to specify a country. + + \value AnyCountry + \value Afghanistan + \value Albania + \value Algeria + \value AmericanSamoa + \value Andorra + \value Angola + \value Anguilla + \value Antarctica + \value AntiguaAndBarbuda + \value Argentina + \value Armenia + \value Aruba + \value Australia + \value Austria + \value Azerbaijan + \value Bahamas + \value Bahrain + \value Bangladesh + \value Barbados + \value Belarus + \value Belgium + \value Belize + \value Benin + \value Bermuda + \value Bhutan + \value Bolivia + \value BosniaAndHerzegowina + \value Botswana + \value BouvetIsland + \value Brazil + \value BritishIndianOceanTerritory + \value BruneiDarussalam + \value Bulgaria + \value BurkinaFaso + \value Burundi + \value Cambodia + \value Cameroon + \value Canada + \value CapeVerde + \value CaymanIslands + \value CentralAfricanRepublic + \value Chad + \value Chile + \value China + \value ChristmasIsland + \value CocosIslands + \value Colombia + \value Comoros + \value DemocraticRepublicOfCongo + \value PeoplesRepublicOfCongo + \value CookIslands + \value CostaRica + \value IvoryCoast + \value Croatia + \value Cuba + \value Cyprus + \value CzechRepublic + \value Denmark + \value Djibouti + \value Dominica + \value DominicanRepublic + \value EastTimor + \value Ecuador + \value Egypt + \value ElSalvador + \value EquatorialGuinea + \value Eritrea + \value Estonia + \value Ethiopia + \value FalklandIslands + \value FaroeIslands + \value FijiCountry + \value Finland + \value France + \value MetropolitanFrance + \value FrenchGuiana + \value FrenchPolynesia + \value FrenchSouthernTerritories + \value Gabon + \value Gambia + \value Georgia + \value Germany + \value Ghana + \value Gibraltar + \value Greece + \value Greenland + \value Grenada + \value Guadeloupe + \value Guam + \value Guatemala + \value Guinea + \value GuineaBissau + \value Guyana + \value Haiti + \value HeardAndMcDonaldIslands + \value Honduras + \value HongKong + \value Hungary + \value Iceland + \value India + \value Indonesia + \value Iran + \value Iraq + \value Ireland + \value Israel + \value Italy + \value Jamaica + \value Japan + \value Jordan + \value Kazakhstan + \value Kenya + \value Kiribati + \value DemocraticRepublicOfKorea + \value RepublicOfKorea + \value Kuwait + \value Kyrgyzstan + \value Lao + \value Latvia + \value Lebanon + \value Lesotho + \value Liberia + \value LibyanArabJamahiriya + \value Liechtenstein + \value Lithuania + \value Luxembourg + \value Macau + \value Macedonia + \value Madagascar + \value Malawi + \value Malaysia + \value Maldives + \value Mali + \value Malta + \value MarshallIslands + \value Martinique + \value Mauritania + \value Mauritius + \value Mayotte + \value Mexico + \value Micronesia + \value Moldova + \value Monaco + \value Mongolia + \value Montserrat + \value Morocco + \value Mozambique + \value Myanmar + \value Namibia + \value NauruCountry + \value Nepal + \value Netherlands + \value NetherlandsAntilles + \value NewCaledonia + \value NewZealand + \value Nicaragua + \value Niger + \value Nigeria + \value Niue + \value NorfolkIsland + \value NorthernMarianaIslands + \value Norway + \value Oman + \value Pakistan + \value Palau + \value PalestinianTerritory + \value Panama + \value PapuaNewGuinea + \value Paraguay + \value Peru + \value Philippines + \value Pitcairn + \value Poland + \value Portugal + \value PuertoRico + \value Qatar + \value Reunion + \value Romania + \value RussianFederation + \value Rwanda + \value SaintKittsAndNevis + \value StLucia + \value StVincentAndTheGrenadines + \value Samoa + \value SanMarino + \value SaoTomeAndPrincipe + \value SaudiArabia + \value Senegal + \value SerbiaAndMontenegro + \value Seychelles + \value SierraLeone + \value Singapore + \value Slovakia + \value Slovenia + \value SolomonIslands + \value Somalia + \value SouthAfrica + \value SouthGeorgiaAndTheSouthSandwichIslands + \value Spain + \value SriLanka + \value StHelena + \value StPierreAndMiquelon + \value Sudan + \value Suriname + \value SvalbardAndJanMayenIslands + \value Swaziland + \value Sweden + \value Switzerland + \value SyrianArabRepublic + \value Taiwan + \value Tajikistan + \value Tanzania + \value Thailand + \value Togo + \value Tokelau + \value TongaCountry + \value TrinidadAndTobago + \value Tunisia + \value Turkey + \value Turkmenistan + \value TurksAndCaicosIslands + \value Tuvalu + \value Uganda + \value Ukraine + \value UnitedArabEmirates + \value UnitedKingdom + \value UnitedStates + \value UnitedStatesMinorOutlyingIslands + \value Uruguay + \value Uzbekistan + \value Vanuatu + \value VaticanCityState + \value Venezuela + \value VietNam + \value BritishVirginIslands + \value USVirginIslands + \value WallisAndFutunaIslands + \value WesternSahara + \value Yemen + \value Yugoslavia + \value Zambia + \value Zimbabwe + \omitvalue LastCountry + + \sa country() +*/ + +/*! + \enum QLocale::FormatType + + This enum describes the types of format that can be used when + converting QDate and QTime objects to strings. + + \value LongFormat The long version of day and month names; for + example, returning "January" as a month name. + + \value ShortFormat The short version of day and month names; for + example, returning "Jan" as a month name. + + \value NarrowFormat A special version of day and month names for + use when space is limited; for example, returning "J" as a month + name. Note that the narrow format might contain the same text for + different months and days or it can even be an empty string if the + locale doesn't support narrow names, so you should avoid using it + for date formatting. Also, for the system locale this format is + the same as ShortFormat. +*/ + +/*! + \enum QLocale::NumberOption + + This enum defines a set of options for number-to-string and string-to-number + conversions. They can be retrieved with numberOptions() and set with + setNumberOptions(). + + \value OmitGroupSeparator If this option is set, the number-to-string functions + will not insert group separators in their return values. The default + is to insert group separators. + \value RejectGroupSeparator If this option is set, the string-to-number functions + will fail if they encounter group separators in their input. The default + is to accept numbers containing correctly placed group separators. + + \sa setNumberOptions() numberOptions() +*/ + +/*! + \enum QLocale::MeasurementSystem + + This enum defines which units are used for measurement. + + \value MetricSystem This value indicates metric units, such as meters, + centimeters and millimeters. + \value ImperialSystem This value indicates imperial units, such as inches and + miles. There are several distinct imperial systems in the world; this + value stands for the official United States imperial units. + + \since 4.4 +*/ + + +/*! + \fn bool QLocale::operator==(const QLocale &other) const + + Returns true if the QLocale object is the same as the \a other + locale specified; otherwise returns false. +*/ + +/*! + \fn bool QLocale::operator!=(const QLocale &other) const + + Returns true if the QLocale object is not the same as the \a other + locale specified; otherwise returns false. +*/ + +static const int locale_data_size = sizeof(locale_data)/sizeof(QLocalePrivate) - 1; + +static const QLocalePrivate *dataPointerHelper(quint16 index) +{ +#ifndef QT_NO_SYSTEMLOCALE + Q_ASSERT(index <= locale_data_size); + if (index == locale_data_size) + return system_lp; +#else + Q_ASSERT(index < locale_data_size); +#endif + + return &locale_data[index]; +} + +static quint16 localePrivateIndex(const QLocalePrivate *p) +{ +#ifndef QT_NO_SYSTEMLOCALE + Q_ASSERT((p >= locale_data && p - locale_data < locale_data_size) + || (p != 0 && p == system_lp)); + quint16 index = p == system_lp ? locale_data_size : p - locale_data; +#else + Q_ASSERT(p >= locale_data && p - locale_data < locale_data_size); + quint16 index = p - locale_data; +#endif + + return index; +} + +/*! + Constructs a QLocale object with the specified \a name, + which has the format + "language[_country][.codeset][@modifier]" or "C", where: + + \list + \i language is a lowercase, two-letter, ISO 639 language code, + \i territory is an uppercase, two-letter, ISO 3166 country code, + \i and codeset and modifier are ignored. + \endlist + + If the string violates the locale format, or language is not + a valid ISO 369 code, the "C" locale is used instead. If country + is not present, or is not a valid ISO 3166 code, the most + appropriate country is chosen for the specified language. + + The language and country codes are converted to their respective + \c Language and \c Country enums. After this conversion is + performed the constructor behaves exactly like QLocale(Country, + Language). + + This constructor is much slower than QLocale(Country, Language). + + \sa name() +*/ + +QLocale::QLocale(const QString &name) + : v(0) +{ + p.numberOptions = 0; + p.index = localePrivateIndex(findLocale(name)); +} + +/*! + Constructs a QLocale object initialized with the default locale. If + no default locale was set using setDefaultLocale(), this locale will + be the same as the one returned by system(). + + \sa setDefault() +*/ + +QLocale::QLocale() + : v(0) +{ + p.numberOptions = default_number_options; + p.index = localePrivateIndex(defaultPrivate()); +} + +/*! + Constructs a QLocale object with the specified \a language and \a + country. + + \list + \i If the language/country pair is found in the database, it is used. + \i If the language is found but the country is not, or if the country + is \c AnyCountry, the language is used with the most + appropriate available country (for example, Germany for German), + \i If neither the language nor the country are found, QLocale + defaults to the default locale (see setDefault()). + \endlist + + The language and country that are actually used can be queried + using language() and country(). + + \sa setDefault() language() country() +*/ + +QLocale::QLocale(Language language, Country country) + : v(0) +{ + const QLocalePrivate *d = findLocale(language, country); + + // If not found, should default to system + if (d->languageId() == QLocale::C && language != QLocale::C) { + p.numberOptions = default_number_options; + p.index = localePrivateIndex(defaultPrivate()); + } else { + p.numberOptions = 0; + p.index = localePrivateIndex(d); + } +} + +/*! + Constructs a QLocale object as a copy of \a other. +*/ + +QLocale::QLocale(const QLocale &other) +{ + v = other.v; +} + +const QLocalePrivate *QLocale::d() const +{ + return dataPointerHelper(p.index); +} + +/*! + Assigns \a other to this QLocale object and returns a reference + to this QLocale object. +*/ + +QLocale &QLocale::operator=(const QLocale &other) +{ + v = other.v; + return *this; +} + +/*! + \since 4.2 + + Sets the \a options related to number conversions for this + QLocale instance. +*/ +void QLocale::setNumberOptions(NumberOptions options) +{ + p.numberOptions = options; +} + +/*! + \since 4.2 + + Returns the options related to number conversions for this + QLocale instance. + + By default, no options are set for the standard locales. +*/ +QLocale::NumberOptions QLocale::numberOptions() const +{ + return static_cast<NumberOption>(p.numberOptions); +} + +/*! + \nonreentrant + + Sets the global default locale to \a locale. These + values are used when a QLocale object is constructed with + no arguments. If this function is not called, the system's + locale is used. + + \warning In a multithreaded application, the default locale + should be set at application startup, before any non-GUI threads + are created. + + \sa system() c() +*/ + +void QLocale::setDefault(const QLocale &locale) +{ + default_lp = locale.d(); + default_number_options = locale.numberOptions(); +} + +/*! + Returns the language of this locale. + + \sa country(), languageToString(), name() +*/ +QLocale::Language QLocale::language() const +{ + return Language(d()->languageId()); +} + +/*! + Returns the country of this locale. + + \sa language(), countryToString(), name() +*/ +QLocale::Country QLocale::country() const +{ + return Country(d()->countryId()); +} + +/*! + Returns the language and country of this locale as a + string of the form "language_country", where + language is a lowercase, two-letter ISO 639 language code, + and country is an uppercase, two-letter ISO 3166 country code. + + \sa language(), country() +*/ + +QString QLocale::name() const +{ + Language l = language(); + + QString result = languageToCode(l); + + if (l == C) + return result; + + Country c = country(); + if (c == AnyCountry) + return result; + + result.append(QLatin1Char('_')); + result.append(countryToCode(c)); + + return result; +} + +/*! + Returns a QString containing the name of \a language. + + \sa countryToString(), name() +*/ + +QString QLocale::languageToString(Language language) +{ + if (uint(language) > uint(QLocale::LastLanguage)) + return QLatin1String("Unknown"); + return QLatin1String(language_name_list + language_name_index[language]); +} + +/*! + Returns a QString containing the name of \a country. + + \sa country(), name() +*/ + +QString QLocale::countryToString(Country country) +{ + if (uint(country) > uint(QLocale::LastCountry)) + return QLatin1String("Unknown"); + return QLatin1String(country_name_list + country_name_index[country]); +} + +/*! + Returns the short int represented by the localized string \a s, + using base \a base. If \a base is 0 the base is determined + automatically using the following rules: If the string begins with + "0x", it is assumed to be hexadecimal; if it begins with "0", it + is assumed to be octal; otherwise it is assumed to be decimal. + + If the conversion fails the function returns 0. + + If \a ok is not 0, failure is reported by setting *ok to false, and + success by setting *ok to true. + + This function ignores leading and trailing whitespace. + + \sa toUShort(), toString() +*/ + +short QLocale::toShort(const QString &s, bool *ok, int base) const +{ + qlonglong i = toLongLong(s, ok, base); + if (i < SHRT_MIN || i > SHRT_MAX) { + if (ok != 0) + *ok = false; + return 0; + } + return short(i); +} + +/*! + Returns the unsigned short int represented by the localized string + \a s, using base \a base. If \a base is 0 the base is determined + automatically using the following rules: If the string begins with + "0x", it is assumed to be hexadecimal; if it begins with "0", it + is assumed to be octal; otherwise it is assumed to be decimal. + + If the conversion fails the function returns 0. + + If \a ok is not 0, failure is reported by setting *ok to false, and + success by setting *ok to true. + + This function ignores leading and trailing whitespace. + + \sa toShort(), toString() +*/ + +ushort QLocale::toUShort(const QString &s, bool *ok, int base) const +{ + qulonglong i = toULongLong(s, ok, base); + if (i > USHRT_MAX) { + if (ok != 0) + *ok = false; + return 0; + } + return ushort(i); +} + +/*! + Returns the int represented by the localized string \a s, using + base \a base. If \a base is 0 the base is determined automatically + using the following rules: If the string begins with "0x", it is + assumed to be hexadecimal; if it begins with "0", it is assumed to + be octal; otherwise it is assumed to be decimal. + + If the conversion fails the function returns 0. + + If \a ok is not 0, failure is reported by setting *ok to false, and + success by setting *ok to true. + + This function ignores leading and trailing whitespace. + + \sa toUInt(), toString() +*/ + +int QLocale::toInt(const QString &s, bool *ok, int base) const +{ + qlonglong i = toLongLong(s, ok, base); + if (i < INT_MIN || i > INT_MAX) { + if (ok != 0) + *ok = false; + return 0; + } + return int(i); +} + +/*! + Returns the unsigned int represented by the localized string \a s, + using base \a base. If \a base is 0 the base is determined + automatically using the following rules: If the string begins with + "0x", it is assumed to be hexadecimal; if it begins with "0", it + is assumed to be octal; otherwise it is assumed to be decimal. + + If the conversion fails the function returns 0. + + If \a ok is not 0, failure is reported by setting *ok to false, and + success by setting *ok to true. + + This function ignores leading and trailing whitespace. + + \sa toInt(), toString() +*/ + +uint QLocale::toUInt(const QString &s, bool *ok, int base) const +{ + qulonglong i = toULongLong(s, ok, base); + if (i > UINT_MAX) { + if (ok != 0) + *ok = false; + return 0; + } + return uint(i); +} + +/*! + Returns the long long int represented by the localized string \a + s, using base \a base. If \a base is 0 the base is determined + automatically using the following rules: If the string begins with + "0x", it is assumed to be hexadecimal; if it begins with "0", it + is assumed to be octal; otherwise it is assumed to be decimal. + + If the conversion fails the function returns 0. + + If \a ok is not 0, failure is reported by setting *ok to false, and + success by setting *ok to true. + + This function ignores leading and trailing whitespace. + + \sa toInt(), toULongLong(), toDouble(), toString() +*/ + + +qlonglong QLocale::toLongLong(const QString &s, bool *ok, int base) const +{ + QLocalePrivate::GroupSeparatorMode mode + = p.numberOptions & RejectGroupSeparator + ? QLocalePrivate::FailOnGroupSeparators + : QLocalePrivate::ParseGroupSeparators; + + return d()->stringToLongLong(s, base, ok, mode); +} + +// ### Qt5: make the return type for toULongLong() qulonglong. + +/*! + Returns the unsigned long long int represented by the localized + string \a s, using base \a base. If \a base is 0 the base is + determined automatically using the following rules: If the string + begins with "0x", it is assumed to be hexadecimal; if it begins + with "0", it is assumed to be octal; otherwise it is assumed to be + decimal. + + If the conversion fails the function returns 0. + + If \a ok is not 0, failure is reported by setting *ok to false, and + success by setting *ok to true. + + This function ignores leading and trailing whitespace. + + \sa toLongLong(), toInt(), toDouble(), toString() +*/ + +qlonglong QLocale::toULongLong(const QString &s, bool *ok, int base) const +{ + QLocalePrivate::GroupSeparatorMode mode + = p.numberOptions & RejectGroupSeparator + ? QLocalePrivate::FailOnGroupSeparators + : QLocalePrivate::ParseGroupSeparators; + + return d()->stringToUnsLongLong(s, base, ok, mode); +} + +/*! + Returns the float represented by the localized string \a s, or 0.0 + if the conversion failed. + + If \a ok is not 0, reports failure by setting + *ok to false and success by setting *ok to true. + + This function ignores leading and trailing whitespace. + + \sa toDouble(), toInt(), toString() +*/ + +#define QT_MAX_FLOAT 3.4028234663852886e+38 + +float QLocale::toFloat(const QString &s, bool *ok) const +{ + bool myOk; + double d = toDouble(s, &myOk); + if (!myOk || d > QT_MAX_FLOAT || d < -QT_MAX_FLOAT) { + if (ok != 0) + *ok = false; + return 0.0; + } + if (ok != 0) + *ok = true; + return float(d); +} + +/*! + Returns the double represented by the localized string \a s, or + 0.0 if the conversion failed. + + If \a ok is not 0, reports failure by setting + *ok to false and success by setting *ok to true. + + Unlike QString::toDouble(), this function does not fall back to + the "C" locale if the string cannot be interpreted in this + locale. + + \snippet doc/src/snippets/code/src_corelib_tools_qlocale.cpp 3 + + Notice that the last conversion returns 1234.0, because '.' is the + thousands group separator in the German locale. + + This function ignores leading and trailing whitespace. + + \sa toFloat(), toInt(), toString() +*/ + +double QLocale::toDouble(const QString &s, bool *ok) const +{ + QLocalePrivate::GroupSeparatorMode mode + = p.numberOptions & RejectGroupSeparator + ? QLocalePrivate::FailOnGroupSeparators + : QLocalePrivate::ParseGroupSeparators; + + return d()->stringToDouble(s, ok, mode); +} + +/*! + Returns a localized string representation of \a i. + + \sa toLongLong() +*/ + +QString QLocale::toString(qlonglong i) const +{ + int flags = p.numberOptions & OmitGroupSeparator + ? 0 + : QLocalePrivate::ThousandsGroup; + + return d()->longLongToString(i, -1, 10, -1, flags); +} + +/*! + \overload + + \sa toULongLong() +*/ + +QString QLocale::toString(qulonglong i) const +{ + int flags = p.numberOptions & OmitGroupSeparator + ? 0 + : QLocalePrivate::ThousandsGroup; + + return d()->unsLongLongToString(i, -1, 10, -1, flags); +} + +/*! + Returns a localized string representation of the given \a date in the + specified \a format. + If \a format is an empty string, an empty string is returned. +*/ + +QString QLocale::toString(const QDate &date, const QString &format) const +{ + return d()->dateTimeToString(format, &date, 0, this); +} + +/*! + Returns a localized string representation of the given \a date according + to the specified \a format. +*/ + +QString QLocale::toString(const QDate &date, FormatType format) const +{ + if (!date.isValid()) + return QString(); + +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant res = systemLocale()->query(format == LongFormat + ? QSystemLocale::DateToStringLong : QSystemLocale::DateToStringShort, + date); + if (!res.isNull()) + return res.toString(); + } +#endif + + QString format_str = dateFormat(format); + return toString(date, format_str); +} + +static bool timeFormatContainsAP(const QString &format) +{ + int i = 0; + while (i < format.size()) { + if (format.at(i).unicode() == '\'') { + readEscapedFormatString(format, &i); + continue; + } + + if (format.at(i).toLower().unicode() == 'a') + return true; + + ++i; + } + return false; +} + +static QString timeZone() +{ +#if defined(Q_OS_WINCE) + TIME_ZONE_INFORMATION info; + DWORD res = GetTimeZoneInformation(&info); + if (res == TIME_ZONE_ID_UNKNOWN) + return QString(); + return QString::fromUtf16(reinterpret_cast<const ushort *> (info.StandardName)); +#elif defined(Q_OS_WIN) + _tzset(); +# if defined(_MSC_VER) && _MSC_VER >= 1400 + size_t returnSize = 0; + char timeZoneName[512]; + if (_get_tzname(&returnSize, timeZoneName, 512, 1)) + return QString(); + return QString::fromLocal8Bit(timeZoneName); +# else + return QString::fromLocal8Bit(_tzname[1]); +# endif +#else + tzset(); + return QString::fromLocal8Bit(tzname[1]); +#endif +} + +/*! + Returns a localized string representation of the given \a time according + to the specified \a format. + If \a format is an empty string, an empty string is returned. +*/ +QString QLocale::toString(const QTime &time, const QString &format) const +{ + return d()->dateTimeToString(format, 0, &time, this); +} + +/*! + \since 4.4 + + Returns a localized string representation of the given \a dateTime according + to the specified \a format. + If \a format is an empty string, an empty string is returned. +*/ + +QString QLocale::toString(const QDateTime &dateTime, const QString &format) const +{ + const QDate dt = dateTime.date(); + const QTime tm = dateTime.time(); + return d()->dateTimeToString(format, &dt, &tm, this); +} + +/*! + \since 4.4 + + Returns a localized string representation of the given \a dateTime according + to the specified \a format. +*/ + +QString QLocale::toString(const QDateTime &dateTime, FormatType format) const +{ + if (!dateTime.isValid()) + return QString(); + +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant res = systemLocale()->query(format == LongFormat + ? QSystemLocale::DateTimeToStringLong + : QSystemLocale::DateTimeToStringShort, + dateTime); + if (!res.isNull()) + return res.toString(); + } +#endif + + const QString format_str = dateTimeFormat(format); + return toString(dateTime, format_str); +} + + +/*! + Returns a localized string representation of the given \a time in the + specified \a format. +*/ + +QString QLocale::toString(const QTime &time, FormatType format) const +{ + if (!time.isValid()) + return QString(); + +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant res = systemLocale()->query(format == LongFormat + ? QSystemLocale::TimeToStringLong : QSystemLocale::TimeToStringShort, + time); + if (!res.isNull()) + return res.toString(); + } +#endif + + QString format_str = timeFormat(format); + return toString(time, format_str); +} + +/*! + \since 4.1 + + Returns the date format used for the current locale. + + If \a format is LongFormat the format will be a long version. + Otherwise it uses a shorter version. + + \sa QDate::toString(), QDate::fromString() +*/ + +QString QLocale::dateFormat(FormatType format) const +{ +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant res = systemLocale()->query(format == LongFormat + ? QSystemLocale::DateFormatLong : QSystemLocale::DateFormatShort, + QVariant()); + if (!res.isNull()) + return res.toString(); + } +#endif + + quint32 idx, size; + switch (format) { + case LongFormat: + idx = d()->m_long_date_format_idx; + size = d()->m_long_date_format_size; + break; + default: + idx = d()->m_short_date_format_idx; + size = d()->m_short_date_format_size; + break; + } + return getLocaleData(date_format_data + idx, size); +} + +/*! + \since 4.1 + + Returns the time format used for the current locale. + + If \a format is LongFormat the format will be a long version. + Otherwise it uses a shorter version. + + \sa QTime::toString(), QTime::fromString() +*/ + +QString QLocale::timeFormat(FormatType format) const +{ +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant res = systemLocale()->query(format == LongFormat + ? QSystemLocale::TimeFormatLong : QSystemLocale::TimeFormatShort, + QVariant()); + if (!res.isNull()) + return res.toString(); + } +#endif + + quint32 idx, size; + switch (format) { + case LongFormat: + idx = d()->m_long_time_format_idx; + size = d()->m_long_time_format_size; + break; + default: + idx = d()->m_short_time_format_idx; + size = d()->m_short_time_format_size; + break; + } + return getLocaleData(time_format_data + idx, size); +} + +/*! + \since 4.4 + + Returns the date time format used for the current locale. + + If \a format is ShortFormat the format will be a short version. + Otherwise it uses a longer version. + + \sa QDateTime::toString(), QDateTime::fromString() +*/ + +QString QLocale::dateTimeFormat(FormatType format) const +{ +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant res = systemLocale()->query(format == LongFormat + ? QSystemLocale::DateTimeFormatLong + : QSystemLocale::DateTimeFormatShort, + QVariant()); + if (!res.isNull()) { + return res.toString(); + } + } +#endif + return dateFormat(format) + QLatin1Char(' ') + timeFormat(format); +} + +/*! + \since 4.4 + + Parses the time string given in \a string and returns the + time. The format of the time string is chosen according to the + \a format parameter (see timeFormat()). + + If the time could not be parsed, returns an invalid time. + + \sa timeFormat(), toDate(), toDateTime(), QTime::fromString() +*/ +#ifndef QT_NO_DATESTRING +QTime QLocale::toTime(const QString &string, FormatType format) const +{ + return toTime(string, timeFormat(format)); +} +#endif + +/*! + \since 4.4 + + Parses the date string given in \a string and returns the + date. The format of the date string is chosen according to the + \a format parameter (see dateFormat()). + + If the date could not be parsed, returns an invalid date. + + \sa dateFormat(), toTime(), toDateTime(), QDate::fromString() +*/ +#ifndef QT_NO_DATESTRING +QDate QLocale::toDate(const QString &string, FormatType format) const +{ + return toDate(string, dateFormat(format)); +} +#endif + +/*! + \since 4.4 + + Parses the date/time string given in \a string and returns the + time. The format of the date/time string is chosen according to the + \a format parameter (see dateTimeFormat()). + + If the string could not be parsed, returns an invalid QDateTime. + + \sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString() +*/ + +#ifndef QT_NO_DATESTRING +QDateTime QLocale::toDateTime(const QString &string, FormatType format) const +{ + return toDateTime(string, dateFormat(format)); +} +#endif + +/*! + \since 4.4 + + Parses the time string given in \a string and returns the + time. See QTime::fromString() for information on what is a valid + format string. + + If the time could not be parsed, returns an invalid time. + + \sa timeFormat(), toDate(), toDateTime(), QTime::fromString() +*/ +#ifndef QT_NO_DATESTRING +QTime QLocale::toTime(const QString &string, const QString &format) const +{ + QTime time; +#ifndef QT_BOOTSTRAPPED + QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString); + dt.defaultLocale = *this; + if (dt.parseFormat(format)) + dt.fromString(string, 0, &time); +#else + Q_UNUSED(string); + Q_UNUSED(format); +#endif + return time; +} +#endif + +/*! + \since 4.4 + + Parses the date string given in \a string and returns the + date. See QDate::fromString() for information on the expressions + that can be used with this function. + + This function searches month names and the names of the days of + the week in the current locale. + + If the date could not be parsed, returns an invalid date. + + \sa dateFormat(), toTime(), toDateTime(), QDate::fromString() +*/ +#ifndef QT_NO_DATESTRING +QDate QLocale::toDate(const QString &string, const QString &format) const +{ + QDate date; +#ifndef QT_BOOTSTRAPPED + QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString); + dt.defaultLocale = *this; + if (dt.parseFormat(format)) + dt.fromString(string, &date, 0); +#else + Q_UNUSED(string); + Q_UNUSED(format); +#endif + return date; +} +#endif + +/*! + \since 4.4 + + Parses the date/time string given in \a string and returns the + time. See QDateTime::fromString() for information on the expressions + that can be used with this function. + + \note The month and day names used must be given in the user's local + language. + + If the string could not be parsed, returns an invalid QDateTime. + + \sa dateTimeFormat(), toTime(), toDate(), QDateTime::fromString() +*/ +#ifndef QT_NO_DATESTRING +QDateTime QLocale::toDateTime(const QString &string, const QString &format) const +{ +#ifndef QT_BOOTSTRAPPED + QTime time; + QDate date; + + QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString); + dt.defaultLocale = *this; + if (dt.parseFormat(format) && dt.fromString(string, &date, &time)) + return QDateTime(date, time); +#else + Q_UNUSED(string); + Q_UNUSED(format); +#endif + return QDateTime(QDate(), QTime(-1, -1, -1)); +} +#endif + + +/*! + \since 4.1 + + Returns the decimal point character of this locale. +*/ +QChar QLocale::decimalPoint() const +{ + return d()->decimal(); +} + +/*! + \since 4.1 + + Returns the group separator character of this locale. +*/ +QChar QLocale::groupSeparator() const +{ + return d()->group(); +} + +/*! + \since 4.1 + + Returns the percent character of this locale. +*/ +QChar QLocale::percent() const +{ + return d()->percent(); +} + +/*! + \since 4.1 + + Returns the zero digit character of this locale. +*/ +QChar QLocale::zeroDigit() const +{ + return d()->zero(); +} + +/*! + \since 4.1 + + Returns the negative sign character of this locale. +*/ +QChar QLocale::negativeSign() const +{ + return d()->minus(); +} + +/*! + \since 4.5 + + Returns the positive sign character of this locale. +*/ +QChar QLocale::positiveSign() const +{ + return d()->plus(); +} + +/*! + \since 4.1 + + Returns the exponential character of this locale. +*/ +QChar QLocale::exponential() const +{ + return d()->exponential(); +} + +static bool qIsUpper(char c) +{ + return c >= 'A' && c <= 'Z'; +} + +static char qToLower(char c) +{ + if (c >= 'A' && c <= 'Z') + return c - 'A' + 'a'; + else + return c; +} + +/*! + \overload + + \a f and \a prec have the same meaning as in QString::number(double, char, int). + + \sa toDouble() +*/ + +QString QLocale::toString(double i, char f, int prec) const +{ + QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal; + uint flags = 0; + + if (qIsUpper(f)) + flags = QLocalePrivate::CapitalEorX; + f = qToLower(f); + + switch (f) { + case 'f': + form = QLocalePrivate::DFDecimal; + break; + case 'e': + form = QLocalePrivate::DFExponent; + break; + case 'g': + form = QLocalePrivate::DFSignificantDigits; + break; + default: + break; + } + + if (!(p.numberOptions & OmitGroupSeparator)) + flags |= QLocalePrivate::ThousandsGroup; + return d()->doubleToString(i, prec, form, -1, flags); +} + +/*! + \fn QLocale QLocale::c() + + Returns a QLocale object initialized to the "C" locale. + + \sa system() +*/ + +/*! + Returns a QLocale object initialized to the system locale. + + On Windows and Mac, this locale will use the decimal/grouping characters and date/time + formats specified in the system configuration panel. + + \sa QTextCodec::locale() c() +*/ + +QLocale QLocale::system() +{ + QLocale result(C); + result.p.index = localePrivateIndex(systemPrivate()); + return result; +} + +/*! + \since 4.3 + + Returns the list of countries that have entires for \a language in Qt's locale + database. If the result is an empty list, then \a language is not represented in + Qt's locale database. +*/ +QList<QLocale::Country> QLocale::countriesForLanguage(Language language) +{ + QList<Country> result; + + unsigned language_id = language; + uint idx = locale_index[language_id]; + + if (language == C) { + result << AnyCountry; + return result; + } + + const QLocalePrivate *d = locale_data + idx; + + while (d->languageId() == language_id) { + result << static_cast<Country>(d->countryId()); + ++d; + } + + return result; +} + +/*! + \since 4.2 + + Returns the localized name of \a month, in the format specified + by \a type. + + \sa dayName(), standaloneMonthName() +*/ +QString QLocale::monthName(int month, FormatType type) const +{ + if (month < 1 || month > 12) + return QString(); + +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant res = systemLocale()->query(type == LongFormat + ? QSystemLocale::MonthNameLong : QSystemLocale::MonthNameShort, + month); + if (!res.isNull()) + return res.toString(); + } +#endif + + quint32 idx, size; + switch (type) { + case QLocale::LongFormat: + idx = d()->m_long_month_names_idx; + size = d()->m_long_month_names_size; + break; + case QLocale::ShortFormat: + idx = d()->m_short_month_names_idx; + size = d()->m_short_month_names_size; + break; + case QLocale::NarrowFormat: + idx = d()->m_narrow_month_names_idx; + size = d()->m_narrow_month_names_size; + break; + default: + return QString(); + } + return getLocaleListData(months_data + idx, size, month - 1); +} + +/*! + \since 4.5 + + Returns the localized name of \a month that is used as a + standalone text, in the format specified by \a type. + + If the locale information doesn't specify the standalone month + name then return value is the same as in monthName(). + + \sa monthName(), standaloneDayName() +*/ +QString QLocale::standaloneMonthName(int month, FormatType type) const +{ + if (month < 1 || month > 12) + return QString(); + +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant res = systemLocale()->query(type == LongFormat + ? QSystemLocale::MonthNameLong : QSystemLocale::MonthNameShort, + month); + if (!res.isNull()) + return res.toString(); + } +#endif + + quint32 idx, size; + switch (type) { + case QLocale::LongFormat: + idx = d()->m_standalone_long_month_names_idx; + size = d()->m_standalone_long_month_names_size; + break; + case QLocale::ShortFormat: + idx = d()->m_standalone_short_month_names_idx; + size = d()->m_standalone_short_month_names_size; + break; + case QLocale::NarrowFormat: + idx = d()->m_standalone_narrow_month_names_idx; + size = d()->m_standalone_narrow_month_names_size; + break; + default: + return QString(); + } + QString name = getLocaleListData(standalone_months_data + idx, size, month - 1); + if (name.isEmpty()) + return monthName(month, type); + return name; +} + +/*! + \since 4.2 + + Returns the localized name of the \a day (where 1 represents + Monday, 2 represents Tuesday and so on), in the format specified + by \a type. + + \sa monthName(), standaloneDayName() +*/ +QString QLocale::dayName(int day, FormatType type) const +{ + if (day < 1 || day > 7) + return QString(); + +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant res = systemLocale()->query(type == LongFormat + ? QSystemLocale::DayNameLong : QSystemLocale::DayNameShort, + day); + if (!res.isNull()) + return res.toString(); + } +#endif + if (day == 7) + day = 0; + + quint32 idx, size; + switch (type) { + case QLocale::LongFormat: + idx = d()->m_long_day_names_idx; + size = d()->m_long_day_names_size; + break; + case QLocale::ShortFormat: + idx = d()->m_short_day_names_idx; + size = d()->m_short_day_names_size; + break; + case QLocale::NarrowFormat: + idx = d()->m_narrow_day_names_idx; + size = d()->m_narrow_day_names_size; + break; + default: + return QString(); + } + return getLocaleListData(days_data + idx, size, day); +} + +/*! + \since 4.5 + + Returns the localized name of the \a day (where 1 represents + Monday, 2 represents Tuesday and so on) that is used as a + standalone text, in the format specified by \a type. + + If the locale information does not specify the standalone day + name then return value is the same as in dayName(). + + \sa dayName(), standaloneMonthName() +*/ +QString QLocale::standaloneDayName(int day, FormatType type) const +{ + if (day < 1 || day > 7) + return QString(); + +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant res = systemLocale()->query(type == LongFormat + ? QSystemLocale::DayNameLong : QSystemLocale::DayNameShort, + day); + if (!res.isNull()) + return res.toString(); + } +#endif + if (day == 7) + day = 0; + + quint32 idx, size; + switch (type) { + case QLocale::LongFormat: + idx = d()->m_standalone_long_day_names_idx; + size = d()->m_standalone_long_day_names_size; + break; + case QLocale::ShortFormat: + idx = d()->m_standalone_short_day_names_idx; + size = d()->m_standalone_short_day_names_size; + break; + case QLocale::NarrowFormat: + idx = d()->m_standalone_narrow_day_names_idx; + size = d()->m_standalone_narrow_day_names_size; + break; + default: + return QString(); + } + QString name = getLocaleListData(days_data + idx, size, day); + if (name.isEmpty()) + return dayName(day == 0 ? 7 : day, type); + return name; +} + +/*! + \since 4.4 + + Returns the measurement system for the locale. +*/ +QLocale::MeasurementSystem QLocale::measurementSystem() const +{ + MeasurementSystem meas = MetricSystem; + bool found = false; + +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant res = systemLocale()->query(QSystemLocale::MeasurementSystem, QVariant()); + if (!res.isNull()) { + meas = MeasurementSystem(res.toInt()); + found = true; + } + } +#endif + + if (!found) { + meas = d()->measurementSystem(); + found = true; + } + + return meas; +} + +/*! + \since 4.5 + + Returns the localized name of the "AM" suffix for times specified using + the conventions of the 12-hour clock. + + \sa pmText() +*/ +QString QLocale::amText() const +{ +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant res = systemLocale()->query(QSystemLocale::AMText, QVariant()); + if (!res.isNull()) + return res.toString(); + } +#endif + return getLocaleData(am_data + d()->m_am_idx, d()->m_am_size); +} + +/*! + \since 4.5 + + Returns the localized name of the "PM" suffix for times specified using + the conventions of the 12-hour clock. + + \sa amText() +*/ +QString QLocale::pmText() const +{ +#ifndef QT_NO_SYSTEMLOCALE + if (d() == systemPrivate()) { + QVariant res = systemLocale()->query(QSystemLocale::PMText, QVariant()); + if (!res.isNull()) + return res.toString(); + } +#endif + return getLocaleData(pm_data + d()->m_pm_idx, d()->m_pm_size); +} + + +/*! +\fn QString QLocale::toString(short i) const + +\overload + +\sa toShort() +*/ + +/*! +\fn QString QLocale::toString(ushort i) const + +\overload + +\sa toUShort() +*/ + +/*! +\fn QString QLocale::toString(int i) const + +\overload + +\sa toInt() +*/ + +/*! +\fn QString QLocale::toString(uint i) const + +\overload + +\sa toUInt() +*/ + +/* +\fn QString QLocale::toString(long i) const + +\overload + +\sa toLong() +*/ + +/* +\fn QString QLocale::toString(ulong i) const + +\overload + +\sa toULong() +*/ + +/*! +\fn QString QLocale::toString(float i, char f = 'g', int prec = 6) const + +\overload + +\a f and \a prec have the same meaning as in QString::number(double, char, int). + +\sa toDouble() +*/ + + +static QString qulltoa(qulonglong l, int base, const QLocalePrivate &locale) +{ + ushort buff[65]; // length of MAX_ULLONG in base 2 + ushort *p = buff + 65; + const QChar _zero = locale.zero(); + + if (base != 10 || _zero.unicode() == '0') { + while (l != 0) { + int c = l % base; + + --p; + + if (c < 10) + *p = '0' + c; + else + *p = c - 10 + 'a'; + + l /= base; + } + } + else { + while (l != 0) { + int c = l % base; + + *(--p) = _zero.unicode() + c; + + l /= base; + } + } + + return QString(reinterpret_cast<QChar *>(p), 65 - (p - buff)); +} + +static QString qlltoa(qlonglong l, int base, const QLocalePrivate &locale) +{ + return qulltoa(l < 0 ? -l : l, base, locale); +} + +enum PrecisionMode { + PMDecimalDigits = 0x01, + PMSignificantDigits = 0x02, + PMChopTrailingZeros = 0x03 +}; + +static QString &decimalForm(QString &digits, int decpt, uint precision, + PrecisionMode pm, + bool always_show_decpt, + bool thousands_group, + const QLocalePrivate &locale) +{ + if (decpt < 0) { + for (int i = 0; i < -decpt; ++i) + digits.prepend(locale.zero()); + decpt = 0; + } + else if (decpt > digits.length()) { + for (int i = digits.length(); i < decpt; ++i) + digits.append(locale.zero()); + } + + if (pm == PMDecimalDigits) { + uint decimal_digits = digits.length() - decpt; + for (uint i = decimal_digits; i < precision; ++i) + digits.append(locale.zero()); + } + else if (pm == PMSignificantDigits) { + for (uint i = digits.length(); i < precision; ++i) + digits.append(locale.zero()); + } + else { // pm == PMChopTrailingZeros + } + + if (always_show_decpt || decpt < digits.length()) + digits.insert(decpt, locale.decimal()); + + if (thousands_group) { + for (int i = decpt - 3; i > 0; i -= 3) + digits.insert(i, locale.group()); + } + + if (decpt == 0) + digits.prepend(locale.zero()); + + return digits; +} + +static QString &exponentForm(QString &digits, int decpt, uint precision, + PrecisionMode pm, + bool always_show_decpt, + const QLocalePrivate &locale) +{ + int exp = decpt - 1; + + if (pm == PMDecimalDigits) { + for (uint i = digits.length(); i < precision + 1; ++i) + digits.append(locale.zero()); + } + else if (pm == PMSignificantDigits) { + for (uint i = digits.length(); i < precision; ++i) + digits.append(locale.zero()); + } + else { // pm == PMChopTrailingZeros + } + + if (always_show_decpt || digits.length() > 1) + digits.insert(1, locale.decimal()); + + digits.append(locale.exponential()); + digits.append(locale.longLongToString(exp, 2, 10, + -1, QLocalePrivate::AlwaysShowSign)); + + return digits; +} + +static bool isZero(double d) +{ + uchar *ch = (uchar *)&d; +#ifdef QT_ARMFPA + return !(ch[3] & 0x7F || ch[2] || ch[1] || ch[0] || ch[7] || ch[6] || ch[5] || ch[4]); +#else + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { + return !(ch[0] & 0x7F || ch[1] || ch[2] || ch[3] || ch[4] || ch[5] || ch[6] || ch[7]); + } else { + return !(ch[7] & 0x7F || ch[6] || ch[5] || ch[4] || ch[3] || ch[2] || ch[1] || ch[0]); + } +#endif +} + +QString QLocalePrivate::dateTimeToString(const QString &format, const QDate *date, const QTime *time, + const QLocale *q) const +{ + Q_ASSERT(date || time); + if ((date && !date->isValid()) || (time && !time->isValid())) + return QString(); + const bool format_am_pm = time && timeFormatContainsAP(format); + + enum { AM, PM } am_pm = AM; + int hour12 = time ? time->hour() : -1; + if (time) { + if (hour12 == 0) { + am_pm = AM; + hour12 = 12; + } else if (hour12 < 12) { + am_pm = AM; + } else if (hour12 == 12) { + am_pm = PM; + } else { + am_pm = PM; + hour12 -= 12; + } + } + + QString result; + + int i = 0; + while (i < format.size()) { + if (format.at(i).unicode() == '\'') { + result.append(readEscapedFormatString(format, &i)); + continue; + } + + const QChar c = format.at(i); + int repeat = repeatCount(format, i); + bool used = false; + if (date) { + switch (c.unicode()) { + case 'y': + used = true; + if (repeat >= 4) + repeat = 4; + else if (repeat >= 2) + repeat = 2; + + switch (repeat) { + case 4: + result.append(longLongToString(date->year())); + break; + case 2: + result.append(longLongToString(date->year() % 100, -1, 10, 2, + QLocalePrivate::ZeroPadded)); + break; + default: + repeat = 1; + result.append(c); + break; + } + break; + + case 'M': + used = true; + repeat = qMin(repeat, 4); + switch (repeat) { + case 1: + result.append(longLongToString(date->month())); + break; + case 2: + result.append(longLongToString(date->month(), -1, 10, 2, QLocalePrivate::ZeroPadded)); + break; + case 3: + result.append(q->monthName(date->month(), QLocale::ShortFormat)); + break; + case 4: + result.append(q->monthName(date->month(), QLocale::LongFormat)); + break; + } + break; + + case 'd': + used = true; + repeat = qMin(repeat, 4); + switch (repeat) { + case 1: + result.append(longLongToString(date->day())); + break; + case 2: + result.append(longLongToString(date->day(), -1, 10, 2, QLocalePrivate::ZeroPadded)); + break; + case 3: + result.append(q->dayName(date->dayOfWeek(), QLocale::ShortFormat)); + break; + case 4: + result.append(q->dayName(date->dayOfWeek(), QLocale::LongFormat)); + break; + } + break; + + default: + break; + } + } + if (!used && time) { + switch (c.unicode()) { + case 'h': { + used = true; + repeat = qMin(repeat, 2); + const int hour = format_am_pm ? hour12 : time->hour(); + + switch (repeat) { + case 1: + result.append(longLongToString(hour)); + break; + case 2: + result.append(longLongToString(hour, -1, 10, 2, QLocalePrivate::ZeroPadded)); + break; + } + break; + } + case 'H': + used = true; + repeat = qMin(repeat, 2); + switch (repeat) { + case 1: + result.append(longLongToString(time->hour())); + break; + case 2: + result.append(longLongToString(time->hour(), -1, 10, 2, QLocalePrivate::ZeroPadded)); + break; + } + break; + + case 'm': + used = true; + repeat = qMin(repeat, 2); + switch (repeat) { + case 1: + result.append(longLongToString(time->minute())); + break; + case 2: + result.append(longLongToString(time->minute(), -1, 10, 2, QLocalePrivate::ZeroPadded)); + break; + } + break; + + case 's': + used = true; + repeat = qMin(repeat, 2); + switch (repeat) { + case 1: + result.append(longLongToString(time->second())); + break; + case 2: + result.append(longLongToString(time->second(), -1, 10, 2, QLocalePrivate::ZeroPadded)); + break; + } + break; + + case 'a': + used = true; + if (i + 1 < format.length() && format.at(i + 1).unicode() == 'p') { + repeat = 2; + } else { + repeat = 1; + } + result.append(am_pm == AM ? QLatin1String("am") : QLatin1String("pm")); + break; + + case 'A': + used = true; + if (i + 1 < format.length() && format.at(i + 1).unicode() == 'P') { + repeat = 2; + } else { + repeat = 1; + } + result.append(am_pm == AM ? QLatin1String("AM") : QLatin1String("PM")); + break; + + case 'z': + used = true; + if (repeat >= 3) { + repeat = 3; + } else { + repeat = 1; + } + switch (repeat) { + case 1: + result.append(longLongToString(time->msec())); + break; + case 3: + result.append(longLongToString(time->msec(), -1, 10, 3, QLocalePrivate::ZeroPadded)); + break; + } + break; + + case 't': + used = true; + repeat = 1; + result.append(timeZone()); + break; + default: + break; + } + } + if (!used) { + result.append(QString(repeat, c)); + } + i += repeat; + } + + return result; +} + +QString QLocalePrivate::doubleToString(double d, + int precision, + DoubleForm form, + int width, + unsigned flags) const +{ + if (precision == -1) + precision = 6; + if (width == -1) + width = 0; + + bool negative = false; + bool special_number = false; // nan, +/-inf + QString num_str; + + // Detect special numbers (nan, +/-inf) + if (qt_is_inf(d)) { + num_str = QString::fromLatin1("inf"); + special_number = true; + negative = d < 0; + } else if (qt_is_nan(d)) { + num_str = QString::fromLatin1("nan"); + special_number = true; + } + + // Handle normal numbers + if (!special_number) { + int decpt, sign; + QString digits; + +#ifdef QT_QLOCALE_USES_FCVT + // NOT thread safe! + if (form == DFDecimal) { + digits = QLatin1String(fcvt(d, precision, &decpt, &sign)); + } else { + int pr = precision; + if (form == DFExponent) + ++pr; + else if (form == DFSignificantDigits && pr == 0) + pr = 1; + digits = QLatin1String(ecvt(d, pr, &decpt, &sign)); + + // Chop trailing zeros + if (digits.length() > 0) { + int last_nonzero_idx = digits.length() - 1; + while (last_nonzero_idx > 0 + && digits.unicode()[last_nonzero_idx] == QLatin1Char('0')) + --last_nonzero_idx; + digits.truncate(last_nonzero_idx + 1); + } + + } + +#else + int mode; + if (form == DFDecimal) + mode = 3; + else + mode = 2; + + /* This next bit is a bit quirky. In DFExponent form, the precision + is the number of digits after decpt. So that would suggest using + mode=3 for qdtoa. But qdtoa behaves strangely when mode=3 and + precision=0. So we get around this by using mode=2 and reasoning + that we want precision+1 significant digits, since the decimal + point in this mode is always after the first digit. */ + int pr = precision; + if (form == DFExponent) + ++pr; + + char *rve = 0; + char *buff = 0; + digits = QLatin1String(qdtoa(d, mode, pr, &decpt, &sign, &rve, &buff)); + if (buff != 0) + free(buff); +#endif // QT_QLOCALE_USES_FCVT + + const QChar _zero = zero(); + + if (_zero.unicode() != '0') { + ushort z = _zero.unicode() - '0'; + for (int i = 0; i < digits.length(); ++i) + reinterpret_cast<ushort *>(digits.data())[i] += z; + } + + bool always_show_decpt = (flags & Alternate || flags & ForcePoint); + switch (form) { + case DFExponent: { + num_str = exponentForm(digits, decpt, precision, PMDecimalDigits, + always_show_decpt, *this); + break; + } + case DFDecimal: { + num_str = decimalForm(digits, decpt, precision, PMDecimalDigits, + always_show_decpt, flags & ThousandsGroup, + *this); + break; + } + case DFSignificantDigits: { + PrecisionMode mode = (flags & Alternate) ? + PMSignificantDigits : PMChopTrailingZeros; + + if (decpt != digits.length() && (decpt <= -4 || decpt > precision)) + num_str = exponentForm(digits, decpt, precision, mode, + always_show_decpt, *this); + else + num_str = decimalForm(digits, decpt, precision, mode, + always_show_decpt, flags & ThousandsGroup, + *this); + break; + } + } + + negative = sign != 0 && !isZero(d); + } + + // pad with zeros. LeftAdjusted overrides this flag). Also, we don't + // pad special numbers + if (flags & QLocalePrivate::ZeroPadded + && !(flags & QLocalePrivate::LeftAdjusted) + && !special_number) { + int num_pad_chars = width - num_str.length(); + // leave space for the sign + if (negative + || flags & QLocalePrivate::AlwaysShowSign + || flags & QLocalePrivate::BlankBeforePositive) + --num_pad_chars; + + for (int i = 0; i < num_pad_chars; ++i) + num_str.prepend(zero()); + } + + // add sign + if (negative) + num_str.prepend(minus()); + else if (flags & QLocalePrivate::AlwaysShowSign) + num_str.prepend(plus()); + else if (flags & QLocalePrivate::BlankBeforePositive) + num_str.prepend(QLatin1Char(' ')); + + if (flags & QLocalePrivate::CapitalEorX) + num_str = num_str.toUpper(); + + return num_str; +} + +QString QLocalePrivate::longLongToString(qlonglong l, int precision, + int base, int width, + unsigned flags) const +{ + bool precision_not_specified = false; + if (precision == -1) { + precision_not_specified = true; + precision = 1; + } + + bool negative = l < 0; + if (base != 10) { + // these are not supported by sprintf for octal and hex + flags &= ~AlwaysShowSign; + flags &= ~BlankBeforePositive; + negative = false; // neither are negative numbers + } + + QString num_str; + if (base == 10) + num_str = qlltoa(l, base, *this); + else + num_str = qulltoa(l, base, *this); + + uint cnt_thousand_sep = 0; + if (flags & ThousandsGroup && base == 10) { + for (int i = num_str.length() - 3; i > 0; i -= 3) { + num_str.insert(i, group()); + ++cnt_thousand_sep; + } + } + + for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i) + num_str.prepend(base == 10 ? zero() : QChar::fromLatin1('0')); + + if ((flags & Alternate || flags & ShowBase) + && base == 8 + && (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0'))) + num_str.prepend(QLatin1Char('0')); + + // LeftAdjusted overrides this flag ZeroPadded. sprintf only padds + // when precision is not specified in the format string + bool zero_padded = flags & ZeroPadded + && !(flags & LeftAdjusted) + && precision_not_specified; + + if (zero_padded) { + int num_pad_chars = width - num_str.length(); + + // leave space for the sign + if (negative + || flags & AlwaysShowSign + || flags & BlankBeforePositive) + --num_pad_chars; + + // leave space for optional '0x' in hex form + if (base == 16 && (flags & Alternate || flags & ShowBase)) + num_pad_chars -= 2; + // leave space for optional '0b' in binary form + else if (base == 2 && (flags & Alternate || flags & ShowBase)) + num_pad_chars -= 2; + + for (int i = 0; i < num_pad_chars; ++i) + num_str.prepend(base == 10 ? zero() : QChar::fromLatin1('0')); + } + + if (flags & CapitalEorX) + num_str = num_str.toUpper(); + + if (base == 16 && (flags & Alternate || flags & ShowBase)) + num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x")); + if (base == 2 && (flags & Alternate || flags & ShowBase)) + num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b")); + + // add sign + if (negative) + num_str.prepend(minus()); + else if (flags & AlwaysShowSign) + num_str.prepend(plus()); + else if (flags & BlankBeforePositive) + num_str.prepend(QLatin1Char(' ')); + + return num_str; +} + +QString QLocalePrivate::unsLongLongToString(qulonglong l, int precision, + int base, int width, + unsigned flags) const +{ + bool precision_not_specified = false; + if (precision == -1) { + precision_not_specified = true; + precision = 1; + } + + QString num_str = qulltoa(l, base, *this); + + uint cnt_thousand_sep = 0; + if (flags & ThousandsGroup && base == 10) { + for (int i = num_str.length() - 3; i > 0; i -=3) { + num_str.insert(i, group()); + ++cnt_thousand_sep; + } + } + + for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i) + num_str.prepend(base == 10 ? zero() : QChar::fromLatin1('0')); + + if ((flags & Alternate || flags & ShowBase) + && base == 8 + && (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0'))) + num_str.prepend(QLatin1Char('0')); + + // LeftAdjusted overrides this flag ZeroPadded. sprintf only padds + // when precision is not specified in the format string + bool zero_padded = flags & ZeroPadded + && !(flags & LeftAdjusted) + && precision_not_specified; + + if (zero_padded) { + int num_pad_chars = width - num_str.length(); + + // leave space for optional '0x' in hex form + if (base == 16 && flags & Alternate) + num_pad_chars -= 2; + // leave space for optional '0b' in binary form + else if (base == 2 && flags & Alternate) + num_pad_chars -= 2; + + for (int i = 0; i < num_pad_chars; ++i) + num_str.prepend(base == 10 ? zero() : QChar::fromLatin1('0')); + } + + if (flags & CapitalEorX) + num_str = num_str.toUpper(); + + if (base == 16 && (flags & Alternate || flags & ShowBase)) + num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x")); + else if (base == 2 && (flags & Alternate || flags & ShowBase)) + num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b")); + + // add sign + if (flags & AlwaysShowSign) + num_str.prepend(plus()); + else if (flags & BlankBeforePositive) + num_str.prepend(QLatin1Char(' ')); + + return num_str; +} + +// Removes thousand-group separators in "C" locale. +static bool removeGroupSeparators(QLocalePrivate::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 == '-')) // check for negative sign at start of string + return false; + ++i; + } + } + + return true; +} + +/* + Converts a number in locale to its representation in the C locale. + Only has to guarantee that a string that is a correct representation of + a number will be converted. If junk is passed in, junk will be passed + out and the error will be detected during the actual conversion to a + number. We can't detect junk here, since we don't even know the base + of the number. +*/ +bool QLocalePrivate::numberToCLocale(const QString &num, + GroupSeparatorMode group_sep_mode, + CharBuff *result) const +{ + const QChar *uc = num.unicode(); + int l = num.length(); + int idx = 0; + + // Skip whitespace + while (idx < l && uc[idx].isSpace()) + ++idx; + if (idx == l) + return false; + + const QChar _group = group(); + + while (idx < l) { + const QChar &in = uc[idx]; + + char out = digitToCLocale(in); + if (out == 0) { + if (in == list()) + out = ';'; + else if (in == percent()) + out = '%'; + // for handling base-x numbers + else if (in.unicode() >= 'A' && in.unicode() <= 'Z') + out = in.toLower().toLatin1(); + else if (in.unicode() >= 'a' && in.unicode() <= 'z') + out = in.toLatin1(); + else + break; + } + + result->append(out); + + ++idx; + } + + // Check trailing whitespace + for (; idx < l; ++idx) { + if (!uc[idx].isSpace()) + return false; + } + + result->append('\0'); + + // Check separators + if (group_sep_mode == ParseGroupSeparators + && !removeGroupSeparators(result)) + return false; + + + return true; +} + +bool QLocalePrivate::validateChars(const QString &str, NumberMode numMode, QByteArray *buff, + int decDigits) const +{ + buff->clear(); + buff->reserve(str.length()); + + const bool scientific = numMode == DoubleScientificMode; + bool lastWasE = false; + int eCnt = 0; + int decPointCnt = 0; + bool dec = false; + int decDigitCnt = 0; + + for (int i = 0; i < str.length(); ++i) { + char c = digitToCLocale(str.at(i)); + + if (c >= '0' && c <= '9') { + if (numMode != IntegerMode) { + // If a double has too many digits after decpt, it shall be Invalid. + if (dec && decDigits != -1 && decDigits < ++decDigitCnt) + return false; + } + } else { + switch (c) { + case '.': + if (numMode == IntegerMode) { + // If an integer has a decimal point, it shall be Invalid. + return false; + } else { + // If a double has more than one decimal point, it shall be Invalid. + if (++decPointCnt > 1) + return false; +#if 0 + // If a double with no decimal digits has a decimal point, it shall be + // Invalid. + if (decDigits == 0) + return false; +#endif // On second thoughts, it shall be Valid. + + dec = true; + } + break; + + case '+': + case '-': + if (scientific) { + // If a scientific has a sign that's not at the beginning or after + // an 'e', it shall be Invalid. + if (i != 0 && !lastWasE) + return false; + } else { + // If a non-scientific has a sign that's not at the beginning, + // it shall be Invalid. + if (i != 0) + return false; + } + break; + + case ',': + return false; + + case 'e': + if (scientific) { + // If a scientific has more than one 'e', it shall be Invalid. + if (++eCnt > 1) + return false; + dec = false; + } else { + // If a non-scientific has an 'e', it shall be Invalid. + return false; + } + break; + + default: + // If it's not a valid digit, it shall be Invalid. + return false; + } + } + + lastWasE = c == 'e'; + buff->append(c); + } + + return true; +} + +double QLocalePrivate::stringToDouble(const QString &number, bool *ok, + GroupSeparatorMode group_sep_mode) const +{ + CharBuff buff; + if (!numberToCLocale(number, group_sep_mode, &buff)) { + if (ok != 0) + *ok = false; + return 0.0; + } + return bytearrayToDouble(buff.constData(), ok); +} + +qlonglong QLocalePrivate::stringToLongLong(const QString &number, int base, + bool *ok, GroupSeparatorMode group_sep_mode) const +{ + CharBuff buff; + if (!numberToCLocale(number, group_sep_mode, &buff)) { + if (ok != 0) + *ok = false; + return 0; + } + + return bytearrayToLongLong(buff.constData(), base, ok); +} + +qulonglong QLocalePrivate::stringToUnsLongLong(const QString &number, int base, + bool *ok, GroupSeparatorMode group_sep_mode) const +{ + CharBuff buff; + if (!numberToCLocale(number, group_sep_mode, &buff)) { + if (ok != 0) + *ok = false; + return 0; + } + + return bytearrayToUnsLongLong(buff.constData(), base, ok); +} + + +double QLocalePrivate::bytearrayToDouble(const char *num, bool *ok, bool *overflow) +{ + if (ok != 0) + *ok = true; + if (overflow != 0) + *overflow = false; + + if (*num == '\0') { + if (ok != 0) + *ok = false; + return 0.0; + } + + if (qstrcmp(num, "nan") == 0) + return qt_snan(); + + if (qstrcmp(num, "+inf") == 0 || qstrcmp(num, "inf") == 0) + return qt_inf(); + + if (qstrcmp(num, "-inf") == 0) + return -qt_inf(); + + bool _ok; + const char *endptr; + double d = qstrtod(num, &endptr, &_ok); + + if (!_ok) { + // the only way strtod can fail with *endptr != '\0' on a non-empty + // input string is overflow + if (ok != 0) + *ok = false; + if (overflow != 0) + *overflow = *endptr != '\0'; + return 0.0; + } + + if (*endptr != '\0') { + // we stopped at a non-digit character after converting some digits + if (ok != 0) + *ok = false; + if (overflow != 0) + *overflow = false; + return 0.0; + } + + if (ok != 0) + *ok = true; + if (overflow != 0) + *overflow = false; + return d; +} + +qlonglong QLocalePrivate::bytearrayToLongLong(const char *num, int base, bool *ok, bool *overflow) +{ + bool _ok; + const char *endptr; + + if (*num == '\0') { + if (ok != 0) + *ok = false; + if (overflow != 0) + *overflow = false; + return 0; + } + + qlonglong l = qstrtoll(num, &endptr, base, &_ok); + + if (!_ok) { + if (ok != 0) + *ok = false; + if (overflow != 0) { + // the only way qstrtoll can fail with *endptr != '\0' on a non-empty + // input string is overflow + *overflow = *endptr != '\0'; + } + return 0; + } + + if (*endptr != '\0') { + // we stopped at a non-digit character after converting some digits + if (ok != 0) + *ok = false; + if (overflow != 0) + *overflow = false; + return 0; + } + + if (ok != 0) + *ok = true; + if (overflow != 0) + *overflow = false; + return l; +} + +qulonglong QLocalePrivate::bytearrayToUnsLongLong(const char *num, int base, bool *ok) +{ + bool _ok; + const char *endptr; + qulonglong l = qstrtoull(num, &endptr, base, &_ok); + + if (!_ok || *endptr != '\0') { + if (ok != 0) + *ok = false; + return 0; + } + + if (ok != 0) + *ok = true; + return l; +} + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +// static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93"; +// "$FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.5.2.1 2001/03/02 09:45:20 obrien Exp $"; + +/* + * Convert a string to an unsigned long long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +static qulonglong qstrtoull(const char *nptr, const char **endptr, register int base, bool *ok) +{ + register const char *s = nptr; + register qulonglong acc; + register unsigned char c; + register qulonglong qbase, cutoff; + register int any, cutlim; + + if (ok != 0) + *ok = true; + + /* + * See strtoq for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + if (ok != 0) + *ok = false; + if (endptr != 0) + *endptr = s - 1; + return 0; + } else { + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + qbase = unsigned(base); + cutoff = qulonglong(ULLONG_MAX) / qbase; + cutlim = qulonglong(ULLONG_MAX) % qbase; + for (acc = 0, any = 0;; c = *s++) { + if (!isascii(c)) + break; + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= qbase; + acc += c; + } + } + if (any == 0) { + if (ok != 0) + *ok = false; + } else if (any < 0) { + acc = ULLONG_MAX; + if (ok != 0) + *ok = false; + } + if (endptr != 0) + *endptr = (any ? s - 1 : nptr); + return acc; +} + + +// "$FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.5.2.1 2001/03/02 09:45:20 obrien Exp $"; + + +/* + * Convert a string to a long long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +Q_CORE_EXPORT qlonglong qstrtoll(const char *nptr, const char **endptr, register int base, bool *ok) +{ + register const char *s; + register qulonglong acc; + register unsigned char c; + register qulonglong qbase, cutoff; + register int neg, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for quads is + * [-9223372036854775808..9223372036854775807] and the input base + * is 10, cutoff will be set to 922337203685477580 and cutlim to + * either 7 (neg==0) or 8 (neg==1), meaning that if we have + * accumulated a value > 922337203685477580, or equal but the + * next digit is > 7 (or 8), the number is too big, and we will + * return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + qbase = unsigned(base); + cutoff = neg ? qulonglong(0-(LLONG_MIN + LLONG_MAX)) + LLONG_MAX : LLONG_MAX; + cutlim = cutoff % qbase; + cutoff /= qbase; + for (acc = 0, any = 0;; c = *s++) { + if (!isascii(c)) + break; + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= qbase; + acc += c; + } + } + if (any < 0) { + acc = neg ? LLONG_MIN : LLONG_MAX; + if (ok != 0) + *ok = false; + } else if (neg) { + acc = (~acc) + 1; + } + if (endptr != 0) + *endptr = (any >= 0 ? s - 1 : nptr); + + if (ok != 0) + *ok = any > 0; + + return acc; +} + +#ifndef QT_QLOCALE_USES_FCVT + +/* From: NetBSD: strtod.c,v 1.26 1998/02/03 18:44:21 perry Exp */ +/* $FreeBSD: src/lib/libc/stdlib/netbsd_strtod.c,v 1.2.2.2 2001/03/02 17:14:15 tegge Exp $ */ + +/* Please send bug reports to + David M. Gay + AT&T Bell Laboratories, Room 2C-463 + 600 Mountain Avenue + Murray Hill, NJ 07974-2070 + U.S.A. + dmg@research.att.com or research!dmg + */ + +/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. + * + * This strtod returns a nearest machine number to the input decimal + * string (or sets errno to ERANGE). With IEEE arithmetic, ties are + * broken by the IEEE round-even rule. Otherwise ties are broken by + * biased rounding (add half and chop). + * + * Inspired loosely by William D. Clinger's paper "How to Read Floating + * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. + * + * Modifications: + * + * 1. We only require IEEE, IBM, or VAX double-precision + * arithmetic (not IEEE double-extended). + * 2. We get by with floating-point arithmetic in a case that + * Clinger missed -- when we're computing d * 10^n + * for a small integer d and the integer n is not too + * much larger than 22 (the maximum integer k for which + * we can represent 10^k exactly), we may be able to + * compute (d*10^k) * 10^(e-k) with just one roundoff. + * 3. Rather than a bit-at-a-time adjustment of the binary + * result in the hard case, we use floating-point + * arithmetic to determine the adjustment to within + * one bit; only in really hard cases do we need to + * compute a second residual. + * 4. Because of 3., we don't need a large table of powers of 10 + * for ten-to-e (just some small tables, e.g. of 10^k + * for 0 <= k <= 22). + */ + +/* + * #define IEEE_LITTLE_ENDIAN for IEEE-arithmetic machines where the least + * significant byte has the lowest address. + * #define IEEE_BIG_ENDIAN for IEEE-arithmetic machines where the most + * significant byte has the lowest address. + * #define Long int on machines with 32-bit ints and 64-bit longs. + * #define Sudden_Underflow for IEEE-format machines without gradual + * underflow (i.e., that flush to zero on underflow). + * #define IBM for IBM mainframe-style floating-point arithmetic. + * #define VAX for VAX-style floating-point arithmetic. + * #define Unsigned_Shifts if >> does treats its left operand as unsigned. + * #define No_leftright to omit left-right logic in fast floating-point + * computation of dtoa. + * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3. + * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines + * that use extended-precision instructions to compute rounded + * products and quotients) with IBM. + * #define ROUND_BIASED for IEEE-format with biased rounding. + * #define Inaccurate_Divide for IEEE-format with correctly rounded + * products but inaccurate quotients, e.g., for Intel i860. + * #define Just_16 to store 16 bits per 32-bit Long when doing high-precision + * integer arithmetic. Whether this speeds things up or slows things + * down depends on the machine and the number being converted. + * #define KR_headers for old-style C function headers. + * #define Bad_float_h if your system lacks a float.h or if it does not + * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, + * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. + * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) + * if memory is available and otherwise does something you deem + * appropriate. If MALLOC is undefined, malloc will be invoked + * directly -- and assumed always to succeed. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: strtod.c,v 1.26 1998/02/03 18:44:21 perry Exp $"); +#endif /* LIBC_SCCS and not lint */ + +/* +#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \ + defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \ + defined(__powerpc__) || defined(Q_OS_WIN) || defined(Q_OS_DARWIN) || defined(Q_OS_MAC) || \ + defined(mips) || defined(Q_OS_AIX) || defined(Q_OS_SOLARIS) +# define IEEE_BIG_OR_LITTLE_ENDIAN 1 +#endif +*/ + +// *All* of our architectures have IEEE arithmetic, don't they? +#define IEEE_BIG_OR_LITTLE_ENDIAN 1 + +#ifdef __arm32__ +/* + * Although the CPU is little endian the FP has different + * byte and word endianness. The byte order is still little endian + * but the word order is big endian. + */ +#define IEEE_BIG_OR_LITTLE_ENDIAN +#endif + +#ifdef vax +#define VAX +#endif + +#define Long qint32 +#define ULong quint32 + +#define MALLOC malloc + +#ifdef BSD_QDTOA_DEBUG +QT_BEGIN_INCLUDE_NAMESPACE +#include <stdio.h> +QT_END_INCLUDE_NAMESPACE + +#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} +#endif + +#ifdef Unsigned_Shifts +#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000; +#else +#define Sign_Extend(a,b) /*no-op*/ +#endif + +#if (defined(IEEE_BIG_OR_LITTLE_ENDIAN) + defined(VAX) + defined(IBM)) != 1 +#error Exactly one of IEEE_BIG_OR_LITTLE_ENDIAN, VAX, or IBM should be defined. +#endif + +static inline ULong _getWord0(const NEEDS_VOLATILE double x) +{ + const NEEDS_VOLATILE uchar *ptr = reinterpret_cast<const NEEDS_VOLATILE uchar *>(&x); + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { + return (ptr[0]<<24) + (ptr[1]<<16) + (ptr[2]<<8) + ptr[3]; + } else { + return (ptr[7]<<24) + (ptr[6]<<16) + (ptr[5]<<8) + ptr[4]; + } +} + +static inline void _setWord0(NEEDS_VOLATILE double *x, ULong l) +{ + NEEDS_VOLATILE uchar *ptr = reinterpret_cast<NEEDS_VOLATILE uchar *>(x); + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { + ptr[0] = uchar(l>>24); + ptr[1] = uchar(l>>16); + ptr[2] = uchar(l>>8); + ptr[3] = uchar(l); + } else { + ptr[7] = uchar(l>>24); + ptr[6] = uchar(l>>16); + ptr[5] = uchar(l>>8); + ptr[4] = uchar(l); + } +} + +static inline ULong _getWord1(const NEEDS_VOLATILE double x) +{ + const NEEDS_VOLATILE uchar *ptr = reinterpret_cast<const NEEDS_VOLATILE uchar *>(&x); + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { + return (ptr[4]<<24) + (ptr[5]<<16) + (ptr[6]<<8) + ptr[7]; + } else { + return (ptr[3]<<24) + (ptr[2]<<16) + (ptr[1]<<8) + ptr[0]; + } +} +static inline void _setWord1(NEEDS_VOLATILE double *x, ULong l) +{ + NEEDS_VOLATILE uchar *ptr = reinterpret_cast<uchar NEEDS_VOLATILE *>(x); + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { + ptr[4] = uchar(l>>24); + ptr[5] = uchar(l>>16); + ptr[6] = uchar(l>>8); + ptr[7] = uchar(l); + } else { + ptr[3] = uchar(l>>24); + ptr[2] = uchar(l>>16); + ptr[1] = uchar(l>>8); + ptr[0] = uchar(l); + } +} + +static inline ULong getWord0(const NEEDS_VOLATILE double x) +{ +#ifdef QT_ARMFPA + return _getWord1(x); +#else + return _getWord0(x); +#endif +} + +static inline void setWord0(NEEDS_VOLATILE double *x, ULong l) +{ +#ifdef QT_ARMFPA + _setWord1(x, l); +#else + _setWord0(x, l); +#endif +} + +static inline ULong getWord1(const NEEDS_VOLATILE double x) +{ +#ifdef QT_ARMFPA + return _getWord0(x); +#else + return _getWord1(x); +#endif +} + +static inline void setWord1(NEEDS_VOLATILE double *x, ULong l) +{ +#ifdef QT_ARMFPA + _setWord0(x, l); +#else + _setWord1(x, l); +#endif +} + +static inline void Storeinc(ULong *&a, const ULong &b, const ULong &c) +{ + + *a = (ushort(b) << 16) | ushort(c); + ++a; +} + +/* #define P DBL_MANT_DIG */ +/* Ten_pmax = floor(P*log(2)/log(5)) */ +/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ +/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ +/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ + +#if defined(IEEE_BIG_OR_LITTLE_ENDIAN) +#define Exp_shift 20 +#define Exp_shift1 20 +#define Exp_msk1 0x100000 +#define Exp_msk11 0x100000 +#define Exp_mask 0x7ff00000 +#define P 53 +#define Bias 1023 +#define IEEE_Arith +#define Emin (-1022) +#define Exp_1 0x3ff00000 +#define Exp_11 0x3ff00000 +#define Ebits 11 +#define Frac_mask 0xfffff +#define Frac_mask1 0xfffff +#define Ten_pmax 22 +#define Bletch 0x10 +#define Bndry_mask 0xfffff +#define Bndry_mask1 0xfffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 1 +#define Tiny0 0 +#define Tiny1 1 +#define Quick_max 14 +#define Int_max 14 +#define Infinite(x) (getWord0(x) == 0x7ff00000) /* sufficient test for here */ +#else +#undef Sudden_Underflow +#define Sudden_Underflow +#ifdef IBM +#define Exp_shift 24 +#define Exp_shift1 24 +#define Exp_msk1 0x1000000 +#define Exp_msk11 0x1000000 +#define Exp_mask 0x7f000000 +#define P 14 +#define Bias 65 +#define Exp_1 0x41000000 +#define Exp_11 0x41000000 +#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ +#define Frac_mask 0xffffff +#define Frac_mask1 0xffffff +#define Bletch 4 +#define Ten_pmax 22 +#define Bndry_mask 0xefffff +#define Bndry_mask1 0xffffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 4 +#define Tiny0 0x100000 +#define Tiny1 0 +#define Quick_max 14 +#define Int_max 15 +#else /* VAX */ +#define Exp_shift 23 +#define Exp_shift1 7 +#define Exp_msk1 0x80 +#define Exp_msk11 0x800000 +#define Exp_mask 0x7f80 +#define P 56 +#define Bias 129 +#define Exp_1 0x40800000 +#define Exp_11 0x4080 +#define Ebits 8 +#define Frac_mask 0x7fffff +#define Frac_mask1 0xffff007f +#define Ten_pmax 24 +#define Bletch 2 +#define Bndry_mask 0xffff007f +#define Bndry_mask1 0xffff007f +#define LSB 0x10000 +#define Sign_bit 0x8000 +#define Log2P 1 +#define Tiny0 0x80 +#define Tiny1 0 +#define Quick_max 15 +#define Int_max 15 +#endif +#endif + +#ifndef IEEE_Arith +#define ROUND_BIASED +#endif + +#ifdef RND_PRODQUOT +#define rounded_product(a,b) a = rnd_prod(a, b) +#define rounded_quotient(a,b) a = rnd_quot(a, b) +extern double rnd_prod(double, double), rnd_quot(double, double); +#else +#define rounded_product(a,b) a *= b +#define rounded_quotient(a,b) a /= b +#endif + +#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) +#define Big1 0xffffffff + +#ifndef Just_16 +/* When Pack_32 is not defined, we store 16 bits per 32-bit Long. + * This makes some inner loops simpler and sometimes saves work + * during multiplications, but it often seems to make things slightly + * slower. Hence the default is now to store 32 bits per Long. + */ +#ifndef Pack_32 +#define Pack_32 +#endif +#endif + +#define Kmax 15 + +struct +Bigint { + struct Bigint *next; + int k, maxwds, sign, wds; + ULong x[1]; +}; + + typedef struct Bigint Bigint; + +static Bigint *Balloc(int k) +{ + int x; + Bigint *rv; + + x = 1 << k; + rv = static_cast<Bigint *>(MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long))); + rv->k = k; + rv->maxwds = x; + rv->sign = rv->wds = 0; + return rv; +} + +static void Bfree(Bigint *v) +{ + free(v); +} + +#define Bcopy(x,y) memcpy(reinterpret_cast<char *>(&x->sign), reinterpret_cast<char *>(&y->sign), \ +y->wds*sizeof(Long) + 2*sizeof(int)) + +/* multiply by m and add a */ +static Bigint *multadd(Bigint *b, int m, int a) +{ + int i, wds; + ULong *x, y; +#ifdef Pack_32 + ULong xi, z; +#endif + Bigint *b1; + + wds = b->wds; + x = b->x; + i = 0; + do { +#ifdef Pack_32 + xi = *x; + y = (xi & 0xffff) * m + a; + z = (xi >> 16) * m + (y >> 16); + a = (z >> 16); + *x++ = (z << 16) + (y & 0xffff); +#else + y = *x * m + a; + a = (y >> 16); + *x++ = y & 0xffff; +#endif + } + while(++i < wds); + if (a) { + if (wds >= b->maxwds) { + b1 = Balloc(b->k+1); + Bcopy(b1, b); + Bfree(b); + b = b1; + } + b->x[wds++] = a; + b->wds = wds; + } + return b; +} + +static Bigint *s2b(const char *s, int nd0, int nd, ULong y9) +{ + Bigint *b; + int i, k; + Long x, y; + + x = (nd + 8) / 9; + for(k = 0, y = 1; x > y; y <<= 1, k++) ; +#ifdef Pack_32 + b = Balloc(k); + b->x[0] = y9; + b->wds = 1; +#else + b = Balloc(k+1); + b->x[0] = y9 & 0xffff; + b->wds = (b->x[1] = y9 >> 16) ? 2 : 1; +#endif + + i = 9; + if (9 < nd0) { + s += 9; + do b = multadd(b, 10, *s++ - '0'); + while(++i < nd0); + s++; + } + else + s += 10; + for(; i < nd; i++) + b = multadd(b, 10, *s++ - '0'); + return b; +} + +static int hi0bits(ULong x) +{ + int k = 0; + + if (!(x & 0xffff0000)) { + k = 16; + x <<= 16; + } + if (!(x & 0xff000000)) { + k += 8; + x <<= 8; + } + if (!(x & 0xf0000000)) { + k += 4; + x <<= 4; + } + if (!(x & 0xc0000000)) { + k += 2; + x <<= 2; + } + if (!(x & 0x80000000)) { + k++; + if (!(x & 0x40000000)) + return 32; + } + return k; +} + +static int lo0bits(ULong *y) +{ + int k; + ULong x = *y; + + if (x & 7) { + if (x & 1) + return 0; + if (x & 2) { + *y = x >> 1; + return 1; + } + *y = x >> 2; + return 2; + } + k = 0; + if (!(x & 0xffff)) { + k = 16; + x >>= 16; + } + if (!(x & 0xff)) { + k += 8; + x >>= 8; + } + if (!(x & 0xf)) { + k += 4; + x >>= 4; + } + if (!(x & 0x3)) { + k += 2; + x >>= 2; + } + if (!(x & 1)) { + k++; + x >>= 1; + if (!x & 1) + return 32; + } + *y = x; + return k; +} + +static Bigint *i2b(int i) +{ + Bigint *b; + + b = Balloc(1); + b->x[0] = i; + b->wds = 1; + return b; +} + +static Bigint *mult(Bigint *a, Bigint *b) +{ + Bigint *c; + int k, wa, wb, wc; + ULong carry, y, z; + ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0; +#ifdef Pack_32 + ULong z2; +#endif + + if (a->wds < b->wds) { + c = a; + a = b; + b = c; + } + k = a->k; + wa = a->wds; + wb = b->wds; + wc = wa + wb; + if (wc > a->maxwds) + k++; + c = Balloc(k); + for(x = c->x, xa = x + wc; x < xa; x++) + *x = 0; + xa = a->x; + xae = xa + wa; + xb = b->x; + xbe = xb + wb; + xc0 = c->x; +#ifdef Pack_32 + for(; xb < xbe; xb++, xc0++) { + if ((y = *xb & 0xffff) != 0) { + x = xa; + xc = xc0; + carry = 0; + do { + z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; + carry = z >> 16; + z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; + carry = z2 >> 16; + Storeinc(xc, z2, z); + } + while(x < xae); + *xc = carry; + } + if ((y = *xb >> 16) != 0) { + x = xa; + xc = xc0; + carry = 0; + z2 = *xc; + do { + z = (*x & 0xffff) * y + (*xc >> 16) + carry; + carry = z >> 16; + Storeinc(xc, z, z2); + z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; + carry = z2 >> 16; + } + while(x < xae); + *xc = z2; + } + } +#else + for(; xb < xbe; xc0++) { + if (y = *xb++) { + x = xa; + xc = xc0; + carry = 0; + do { + z = *x++ * y + *xc + carry; + carry = z >> 16; + *xc++ = z & 0xffff; + } + while(x < xae); + *xc = carry; + } + } +#endif + for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; + c->wds = wc; + return c; +} + +static Bigint *p5s; + +static Bigint *pow5mult(Bigint *b, int k) +{ + Bigint *b1, *p5, *p51; + int i; + static const int p05[3] = { 5, 25, 125 }; + + if ((i = k & 3) != 0) +#if defined(Q_OS_IRIX) && defined(Q_CC_GNU) + { + // work around a bug on 64 bit IRIX gcc + int *p = (int *) p05; + b = multadd(b, p[i-1], 0); + } +#else + b = multadd(b, p05[i-1], 0); +#endif + + if (!(k >>= 2)) + return b; + if (!(p5 = p5s)) { + /* first time */ + p5 = p5s = i2b(625); + p5->next = 0; + } + for(;;) { + if (k & 1) { + b1 = mult(b, p5); + Bfree(b); + b = b1; + } + if (!(k >>= 1)) + break; + if (!(p51 = p5->next)) { + p51 = p5->next = mult(p5,p5); + p51->next = 0; + } + p5 = p51; + } + return b; +} + +static Bigint *lshift(Bigint *b, int k) +{ + int i, k1, n, n1; + Bigint *b1; + ULong *x, *x1, *xe, z; + +#ifdef Pack_32 + n = k >> 5; +#else + n = k >> 4; +#endif + k1 = b->k; + n1 = n + b->wds + 1; + for(i = b->maxwds; n1 > i; i <<= 1) + k1++; + b1 = Balloc(k1); + x1 = b1->x; + for(i = 0; i < n; i++) + *x1++ = 0; + x = b->x; + xe = x + b->wds; +#ifdef Pack_32 + if (k &= 0x1f) { + k1 = 32 - k; + z = 0; + do { + *x1++ = *x << k | z; + z = *x++ >> k1; + } + while(x < xe); + if ((*x1 = z) != 0) + ++n1; + } +#else + if (k &= 0xf) { + k1 = 16 - k; + z = 0; + do { + *x1++ = *x << k & 0xffff | z; + z = *x++ >> k1; + } + while(x < xe); + if (*x1 = z) + ++n1; + } +#endif + else do + *x1++ = *x++; + while(x < xe); + b1->wds = n1 - 1; + Bfree(b); + return b1; +} + +static int cmp(Bigint *a, Bigint *b) +{ + ULong *xa, *xa0, *xb, *xb0; + int i, j; + + i = a->wds; + j = b->wds; +#ifdef BSD_QDTOA_DEBUG + if (i > 1 && !a->x[i-1]) + Bug("cmp called with a->x[a->wds-1] == 0"); + if (j > 1 && !b->x[j-1]) + Bug("cmp called with b->x[b->wds-1] == 0"); +#endif + if (i -= j) + return i; + xa0 = a->x; + xa = xa0 + j; + xb0 = b->x; + xb = xb0 + j; + for(;;) { + if (*--xa != *--xb) + return *xa < *xb ? -1 : 1; + if (xa <= xa0) + break; + } + return 0; +} + +static Bigint *diff(Bigint *a, Bigint *b) +{ + Bigint *c; + int i, wa, wb; + Long borrow, y; /* We need signed shifts here. */ + ULong *xa, *xae, *xb, *xbe, *xc; +#ifdef Pack_32 + Long z; +#endif + + i = cmp(a,b); + if (!i) { + c = Balloc(0); + c->wds = 1; + c->x[0] = 0; + return c; + } + if (i < 0) { + c = a; + a = b; + b = c; + i = 1; + } + else + i = 0; + c = Balloc(a->k); + c->sign = i; + wa = a->wds; + xa = a->x; + xae = xa + wa; + wb = b->wds; + xb = b->x; + xbe = xb + wb; + xc = c->x; + borrow = 0; +#ifdef Pack_32 + do { + y = (*xa & 0xffff) - (*xb & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*xa++ >> 16) - (*xb++ >> 16) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(xc, z, y); + } + while(xb < xbe); + while(xa < xae) { + y = (*xa & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*xa++ >> 16) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(xc, z, y); + } +#else + do { + y = *xa++ - *xb++ + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + *xc++ = y & 0xffff; + } + while(xb < xbe); + while(xa < xae) { + y = *xa++ + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + *xc++ = y & 0xffff; + } +#endif + while(!*--xc) + wa--; + c->wds = wa; + return c; +} + +static double ulp(double x) +{ + Long L; + double a; + + L = (getWord0(x) & Exp_mask) - (P-1)*Exp_msk1; +#ifndef Sudden_Underflow + if (L > 0) { +#endif +#ifdef IBM + L |= Exp_msk1 >> 4; +#endif + setWord0(&a, L); + setWord1(&a, 0); +#ifndef Sudden_Underflow + } + else { + L = -L >> Exp_shift; + if (L < Exp_shift) { + setWord0(&a, 0x80000 >> L); + setWord1(&a, 0); + } + else { + setWord0(&a, 0); + L -= Exp_shift; + setWord1(&a, L >= 31 ? 1U : 1U << (31 - L)); + } + } +#endif + return a; +} + +static double b2d(Bigint *a, int *e) +{ + ULong *xa, *xa0, w, y, z; + int k; + double d; + + xa0 = a->x; + xa = xa0 + a->wds; + y = *--xa; +#ifdef BSD_QDTOA_DEBUG + if (!y) Bug("zero y in b2d"); +#endif + k = hi0bits(y); + *e = 32 - k; +#ifdef Pack_32 + if (k < Ebits) { + setWord0(&d, Exp_1 | y >> (Ebits - k)); + w = xa > xa0 ? *--xa : 0; + setWord1(&d, y << ((32-Ebits) + k) | w >> (Ebits - k)); + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + if (k -= Ebits) { + setWord0(&d, Exp_1 | y << k | z >> (32 - k)); + y = xa > xa0 ? *--xa : 0; + setWord1(&d, z << k | y >> (32 - k)); + } + else { + setWord0(&d, Exp_1 | y); + setWord1(&d, z); + } +#else + if (k < Ebits + 16) { + z = xa > xa0 ? *--xa : 0; + setWord0(&d, Exp_1 | y << k - Ebits | z >> Ebits + 16 - k); + w = xa > xa0 ? *--xa : 0; + y = xa > xa0 ? *--xa : 0; + setWord1(&d, z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k); + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + w = xa > xa0 ? *--xa : 0; + k -= Ebits + 16; + setWord0(&d, Exp_1 | y << k + 16 | z << k | w >> 16 - k); + y = xa > xa0 ? *--xa : 0; + setWord1(&d, w << k + 16 | y << k); +#endif + ret_d: + return d; +} + +static Bigint *d2b(double d, int *e, int *bits) +{ + Bigint *b; + int de, i, k; + ULong *x, y, z; + +#ifdef Pack_32 + b = Balloc(1); +#else + b = Balloc(2); +#endif + x = b->x; + + z = getWord0(d) & Frac_mask; + setWord0(&d, getWord0(d) & 0x7fffffff); /* clear sign bit, which we ignore */ +#ifdef Sudden_Underflow + de = (int)(getWord0(d) >> Exp_shift); +#ifndef IBM + z |= Exp_msk11; +#endif +#else + if ((de = int(getWord0(d) >> Exp_shift)) != 0) + z |= Exp_msk1; +#endif +#ifdef Pack_32 + if ((y = getWord1(d)) != 0) { + if ((k = lo0bits(&y)) != 0) { + x[0] = y | z << (32 - k); + z >>= k; + } + else + x[0] = y; + i = b->wds = (x[1] = z) ? 2 : 1; + } + else { +#ifdef BSD_QDTOA_DEBUG + if (!z) + Bug("Zero passed to d2b"); +#endif + k = lo0bits(&z); + x[0] = z; + i = b->wds = 1; + k += 32; + } +#else + if (y = getWord1(d)) { + if (k = lo0bits(&y)) + if (k >= 16) { + x[0] = y | z << 32 - k & 0xffff; + x[1] = z >> k - 16 & 0xffff; + x[2] = z >> k; + i = 2; + } + else { + x[0] = y & 0xffff; + x[1] = y >> 16 | z << 16 - k & 0xffff; + x[2] = z >> k & 0xffff; + x[3] = z >> k+16; + i = 3; + } + else { + x[0] = y & 0xffff; + x[1] = y >> 16; + x[2] = z & 0xffff; + x[3] = z >> 16; + i = 3; + } + } + else { +#ifdef BSD_QDTOA_DEBUG + if (!z) + Bug("Zero passed to d2b"); +#endif + k = lo0bits(&z); + if (k >= 16) { + x[0] = z; + i = 0; + } + else { + x[0] = z & 0xffff; + x[1] = z >> 16; + i = 1; + } + k += 32; + } + while(!x[i]) + --i; + b->wds = i + 1; +#endif +#ifndef Sudden_Underflow + if (de) { +#endif +#ifdef IBM + *e = (de - Bias - (P-1) << 2) + k; + *bits = 4*P + 8 - k - hi0bits(getWord0(d) & Frac_mask); +#else + *e = de - Bias - (P-1) + k; + *bits = P - k; +#endif +#ifndef Sudden_Underflow + } + else { + *e = de - Bias - (P-1) + 1 + k; +#ifdef Pack_32 + *bits = 32*i - hi0bits(x[i-1]); +#else + *bits = (i+2)*16 - hi0bits(x[i]); +#endif + } +#endif + return b; +} + +static double ratio(Bigint *a, Bigint *b) +{ + double da, db; + int k, ka, kb; + + da = b2d(a, &ka); + db = b2d(b, &kb); +#ifdef Pack_32 + k = ka - kb + 32*(a->wds - b->wds); +#else + k = ka - kb + 16*(a->wds - b->wds); +#endif +#ifdef IBM + if (k > 0) { + setWord0(&da, getWord0(da) + (k >> 2)*Exp_msk1); + if (k &= 3) + da *= 1 << k; + } + else { + k = -k; + setWord0(&db, getWord0(db) + (k >> 2)*Exp_msk1); + if (k &= 3) + db *= 1 << k; + } +#else + if (k > 0) + setWord0(&da, getWord0(da) + k*Exp_msk1); + else { + k = -k; + setWord0(&db, getWord0(db) + k*Exp_msk1); + } +#endif + return da / db; +} + +static const double tens[] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22 +#ifdef VAX + , 1e23, 1e24 +#endif +}; + +#ifdef IEEE_Arith +static const double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; +static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 }; +#define n_bigtens 5 +#else +#ifdef IBM +static const double bigtens[] = { 1e16, 1e32, 1e64 }; +static const double tinytens[] = { 1e-16, 1e-32, 1e-64 }; +#define n_bigtens 3 +#else +static const double bigtens[] = { 1e16, 1e32 }; +static const double tinytens[] = { 1e-16, 1e-32 }; +#define n_bigtens 2 +#endif +#endif + +/* + The pre-release gcc3.3 shipped with SuSE 8.2 has a bug which causes + the comparison 1e-100 == 0.0 to return true. As a workaround, we + compare it to a global variable containing 0.0, which produces + correct assembler output. + + ### consider detecting the broken compilers and using the static + ### double for these, and use a #define for all working compilers +*/ +static double g_double_zero = 0.0; + +Q_CORE_EXPORT double qstrtod(const char *s00, const char **se, bool *ok) +{ + int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, + e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; + const char *s, *s0, *s1; + double aadj, aadj1, adj, rv, rv0; + Long L; + ULong y, z; + Bigint *bb1, *bd0; + Bigint *bb = NULL, *bd = NULL, *bs = NULL, *delta = NULL;/* pacify gcc */ + + /* + #ifndef KR_headers + const char decimal_point = localeconv()->decimal_point[0]; + #else + const char decimal_point = '.'; + #endif */ + if (ok != 0) + *ok = true; + + const char decimal_point = '.'; + + sign = nz0 = nz = 0; + rv = 0.; + + + for(s = s00; isspace(uchar(*s)); s++) + ; + + if (*s == '-') { + sign = 1; + s++; + } else if (*s == '+') { + s++; + } + + if (*s == '\0') { + s = s00; + goto ret; + } + + if (*s == '0') { + nz0 = 1; + while(*++s == '0') ; + if (!*s) + goto ret; + } + s0 = s; + y = z = 0; + for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) + if (nd < 9) + y = 10*y + c - '0'; + else if (nd < 16) + z = 10*z + c - '0'; + nd0 = nd; + if (c == decimal_point) { + c = *++s; + if (!nd) { + for(; c == '0'; c = *++s) + nz++; + if (c > '0' && c <= '9') { + s0 = s; + nf += nz; + nz = 0; + goto have_dig; + } + goto dig_done; + } + for(; c >= '0' && c <= '9'; c = *++s) { + have_dig: + nz++; + if (c -= '0') { + nf += nz; + for(i = 1; i < nz; i++) + if (nd++ < 9) + y *= 10; + else if (nd <= DBL_DIG + 1) + z *= 10; + if (nd++ < 9) + y = 10*y + c; + else if (nd <= DBL_DIG + 1) + z = 10*z + c; + nz = 0; + } + } + } + dig_done: + e = 0; + if (c == 'e' || c == 'E') { + if (!nd && !nz && !nz0) { + s = s00; + goto ret; + } + s00 = s; + esign = 0; + switch(c = *++s) { + case '-': + esign = 1; + case '+': + c = *++s; + } + if (c >= '0' && c <= '9') { + while(c == '0') + c = *++s; + if (c > '0' && c <= '9') { + L = c - '0'; + s1 = s; + while((c = *++s) >= '0' && c <= '9') + L = 10*L + c - '0'; + if (s - s1 > 8 || L > 19999) + /* Avoid confusion from exponents + * so large that e might overflow. + */ + e = 19999; /* safe for 16 bit ints */ + else + e = int(L); + if (esign) + e = -e; + } + else + e = 0; + } + else + s = s00; + } + if (!nd) { + if (!nz && !nz0) + s = s00; + goto ret; + } + e1 = e -= nf; + + /* Now we have nd0 digits, starting at s0, followed by a + * decimal point, followed by nd-nd0 digits. The number we're + * after is the integer represented by those digits times + * 10**e */ + + if (!nd0) + nd0 = nd; + k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; + rv = y; + if (k > 9) +#if defined(Q_OS_IRIX) && defined(Q_CC_GNU) + { + // work around a bug on 64 bit IRIX gcc + double *t = (double *) tens; + rv = t[k - 9] * rv + z; + } +#else + rv = tens[k - 9] * rv + z; +#endif + + bd0 = 0; + if (nd <= DBL_DIG +#ifndef RND_PRODQUOT + && FLT_ROUNDS == 1 +#endif + ) { + if (!e) + goto ret; + if (e > 0) { + if (e <= Ten_pmax) { +#ifdef VAX + goto vax_ovfl_check; +#else + /* rv = */ rounded_product(rv, tens[e]); + goto ret; +#endif + } + i = DBL_DIG - nd; + if (e <= Ten_pmax + i) { + /* A fancier test would sometimes let us do + * this for larger i values. + */ + e -= i; + rv *= tens[i]; +#ifdef VAX + /* VAX exponent range is so narrow we must + * worry about overflow here... + */ + vax_ovfl_check: + setWord0(&rv, getWord0(rv) - P*Exp_msk1); + /* rv = */ rounded_product(rv, tens[e]); + if ((getWord0(rv) & Exp_mask) + > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) + goto ovfl; + setWord0(&rv, getWord0(rv) + P*Exp_msk1); +#else + /* rv = */ rounded_product(rv, tens[e]); +#endif + goto ret; + } + } +#ifndef Inaccurate_Divide + else if (e >= -Ten_pmax) { + /* rv = */ rounded_quotient(rv, tens[-e]); + goto ret; + } +#endif + } + e1 += nd - k; + + /* Get starting approximation = rv * 10**e1 */ + + if (e1 > 0) { + if ((i = e1 & 15) != 0) + rv *= tens[i]; + if (e1 &= ~15) { + if (e1 > DBL_MAX_10_EXP) { + ovfl: + // errno = ERANGE; + if (ok != 0) + *ok = false; +#ifdef __STDC__ + rv = HUGE_VAL; +#else + /* Can't trust HUGE_VAL */ +#ifdef IEEE_Arith + setWord0(&rv, Exp_mask); + setWord1(&rv, 0); +#else + setWord0(&rv, Big0); + setWord1(&rv, Big1); +#endif +#endif + if (bd0) + goto retfree; + goto ret; + } + if (e1 >>= 4) { + for(j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + rv *= bigtens[j]; + /* The last multiplication could overflow. */ + setWord0(&rv, getWord0(rv) - P*Exp_msk1); + rv *= bigtens[j]; + if ((z = getWord0(rv) & Exp_mask) + > Exp_msk1*(DBL_MAX_EXP+Bias-P)) + goto ovfl; + if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { + /* set to largest number */ + /* (Can't trust DBL_MAX) */ + setWord0(&rv, Big0); + setWord1(&rv, Big1); + } + else + setWord0(&rv, getWord0(rv) + P*Exp_msk1); + } + + } + } + else if (e1 < 0) { + e1 = -e1; + if ((i = e1 & 15) != 0) + rv /= tens[i]; + if (e1 &= ~15) { + e1 >>= 4; + if (e1 >= 1 << n_bigtens) + goto undfl; + for(j = 0; e1 > 1; j++, e1 >>= 1) + if (e1 & 1) + rv *= tinytens[j]; + /* The last multiplication could underflow. */ + rv0 = rv; + rv *= tinytens[j]; + if (rv == g_double_zero) + { + rv = 2.*rv0; + rv *= tinytens[j]; + if (rv == g_double_zero) + { + undfl: + rv = 0.; + // errno = ERANGE; + if (ok != 0) + *ok = false; + if (bd0) + goto retfree; + goto ret; + } + setWord0(&rv, Tiny0); + setWord1(&rv, Tiny1); + /* The refinement below will clean + * this approximation up. + */ + } + } + } + + /* Now the hard part -- adjusting rv to the correct value.*/ + + /* Put digits into bd: true value = bd * 10^e */ + + bd0 = s2b(s0, nd0, nd, y); + + for(;;) { + bd = Balloc(bd0->k); + Bcopy(bd, bd0); + bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */ + bs = i2b(1); + + if (e >= 0) { + bb2 = bb5 = 0; + bd2 = bd5 = e; + } + else { + bb2 = bb5 = -e; + bd2 = bd5 = 0; + } + if (bbe >= 0) + bb2 += bbe; + else + bd2 -= bbe; + bs2 = bb2; +#ifdef Sudden_Underflow +#ifdef IBM + j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3); +#else + j = P + 1 - bbbits; +#endif +#else + i = bbe + bbbits - 1; /* logb(rv) */ + if (i < Emin) /* denormal */ + j = bbe + (P-Emin); + else + j = P + 1 - bbbits; +#endif + bb2 += j; + bd2 += j; + i = bb2 < bd2 ? bb2 : bd2; + if (i > bs2) + i = bs2; + if (i > 0) { + bb2 -= i; + bd2 -= i; + bs2 -= i; + } + if (bb5 > 0) { + bs = pow5mult(bs, bb5); + bb1 = mult(bs, bb); + Bfree(bb); + bb = bb1; + } + if (bb2 > 0) + bb = lshift(bb, bb2); + if (bd5 > 0) + bd = pow5mult(bd, bd5); + if (bd2 > 0) + bd = lshift(bd, bd2); + if (bs2 > 0) + bs = lshift(bs, bs2); + delta = diff(bb, bd); + dsign = delta->sign; + delta->sign = 0; + i = cmp(delta, bs); + if (i < 0) { + /* Error is less than half an ulp -- check for + * special case of mantissa a power of two. + */ + if (dsign || getWord1(rv) || getWord0(rv) & Bndry_mask) + break; + delta = lshift(delta,Log2P); + if (cmp(delta, bs) > 0) + goto drop_down; + break; + } + if (i == 0) { + /* exactly half-way between */ + if (dsign) { + if ((getWord0(rv) & Bndry_mask1) == Bndry_mask1 + && getWord1(rv) == 0xffffffff) { + /*boundary case -- increment exponent*/ + setWord0(&rv, (getWord0(rv) & Exp_mask) + + Exp_msk1 +#ifdef IBM + | Exp_msk1 >> 4 +#endif + ); + setWord1(&rv, 0); + break; + } + } + else if (!(getWord0(rv) & Bndry_mask) && !getWord1(rv)) { + drop_down: + /* boundary case -- decrement exponent */ +#ifdef Sudden_Underflow + L = getWord0(rv) & Exp_mask; +#ifdef IBM + if (L < Exp_msk1) +#else + if (L <= Exp_msk1) +#endif + goto undfl; + L -= Exp_msk1; +#else + L = (getWord0(rv) & Exp_mask) - Exp_msk1; +#endif + setWord0(&rv, L | Bndry_mask1); + setWord1(&rv, 0xffffffff); +#ifdef IBM + goto cont; +#else + break; +#endif + } +#ifndef ROUND_BIASED + if (!(getWord1(rv) & LSB)) + break; +#endif + if (dsign) + rv += ulp(rv); +#ifndef ROUND_BIASED + else { + rv -= ulp(rv); +#ifndef Sudden_Underflow + if (rv == g_double_zero) + goto undfl; +#endif + } +#endif + break; + } + if ((aadj = ratio(delta, bs)) <= 2.) { + if (dsign) + aadj = aadj1 = 1.; + else if (getWord1(rv) || getWord0(rv) & Bndry_mask) { +#ifndef Sudden_Underflow + if (getWord1(rv) == Tiny1 && !getWord0(rv)) + goto undfl; +#endif + aadj = 1.; + aadj1 = -1.; + } + else { + /* special case -- power of FLT_RADIX to be */ + /* rounded down... */ + + if (aadj < 2./FLT_RADIX) + aadj = 1./FLT_RADIX; + else + aadj *= 0.5; + aadj1 = -aadj; + } + } + else { + aadj *= 0.5; + aadj1 = dsign ? aadj : -aadj; +#ifdef Check_FLT_ROUNDS + switch(FLT_ROUNDS) { + case 2: /* towards +infinity */ + aadj1 -= 0.5; + break; + case 0: /* towards 0 */ + case 3: /* towards -infinity */ + aadj1 += 0.5; + } +#else + if (FLT_ROUNDS == 0) + aadj1 += 0.5; +#endif + } + y = getWord0(rv) & Exp_mask; + + /* Check for overflow */ + + if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { + rv0 = rv; + setWord0(&rv, getWord0(rv) - P*Exp_msk1); + adj = aadj1 * ulp(rv); + rv += adj; + if ((getWord0(rv) & Exp_mask) >= + Exp_msk1*(DBL_MAX_EXP+Bias-P)) { + if (getWord0(rv0) == Big0 && getWord1(rv0) == Big1) + goto ovfl; + setWord0(&rv, Big0); + setWord1(&rv, Big1); + goto cont; + } + else + setWord0(&rv, getWord0(rv) + P*Exp_msk1); + } + else { +#ifdef Sudden_Underflow + if ((getWord0(rv) & Exp_mask) <= P*Exp_msk1) { + rv0 = rv; + setWord0(&rv, getWord0(rv) + P*Exp_msk1); + adj = aadj1 * ulp(rv); + rv += adj; +#ifdef IBM + if ((getWord0(rv) & Exp_mask) < P*Exp_msk1) +#else + if ((getWord0(rv) & Exp_mask) <= P*Exp_msk1) +#endif + { + if (getWord0(rv0) == Tiny0 + && getWord1(rv0) == Tiny1) + goto undfl; + setWord0(&rv, Tiny0); + setWord1(&rv, Tiny1); + goto cont; + } + else + setWord0(&rv, getWord0(rv) - P*Exp_msk1); + } + else { + adj = aadj1 * ulp(rv); + rv += adj; + } +#else + /* Compute adj so that the IEEE rounding rules will + * correctly round rv + adj in some half-way cases. + * If rv * ulp(rv) is denormalized (i.e., + * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid + * trouble from bits lost to denormalization; + * example: 1.2e-307 . + */ + if (y <= (P-1)*Exp_msk1 && aadj >= 1.) { + aadj1 = int(aadj + 0.5); + if (!dsign) + aadj1 = -aadj1; + } + adj = aadj1 * ulp(rv); + rv += adj; +#endif + } + z = getWord0(rv) & Exp_mask; + if (y == z) { + /* Can we stop now? */ + L = Long(aadj); + aadj -= L; + /* The tolerances below are conservative. */ + if (dsign || getWord1(rv) || getWord0(rv) & Bndry_mask) { + if (aadj < .4999999 || aadj > .5000001) + break; + } + else if (aadj < .4999999/FLT_RADIX) + break; + } + cont: + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(delta); + } + retfree: + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); + ret: + if (se) + *se = s; + return sign ? -rv : rv; +} + +static int quorem(Bigint *b, Bigint *S) +{ + int n; + Long borrow, y; + ULong carry, q, ys; + ULong *bx, *bxe, *sx, *sxe; +#ifdef Pack_32 + Long z; + ULong si, zs; +#endif + + n = S->wds; +#ifdef BSD_QDTOA_DEBUG + /*debug*/ if (b->wds > n) + /*debug*/ Bug("oversize b in quorem"); +#endif + if (b->wds < n) + return 0; + sx = S->x; + sxe = sx + --n; + bx = b->x; + bxe = bx + n; + q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ +#ifdef BSD_QDTOA_DEBUG + /*debug*/ if (q > 9) + /*debug*/ Bug("oversized quotient in quorem"); +#endif + if (q) { + borrow = 0; + carry = 0; + do { +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) * q + carry; + zs = (si >> 16) * q + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*bx >> 16) - (zs & 0xffff) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(bx, z, y); +#else + ys = *sx++ * q + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + *bx++ = y & 0xffff; +#endif + } + while(sx <= sxe); + if (!*bxe) { + bx = b->x; + while(--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + if (cmp(b, S) >= 0) { + q++; + borrow = 0; + carry = 0; + bx = b->x; + sx = S->x; + do { +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) + carry; + zs = (si >> 16) + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + z = (*bx >> 16) - (zs & 0xffff) + borrow; + borrow = z >> 16; + Sign_Extend(borrow, z); + Storeinc(bx, z, y); +#else + ys = *sx++ + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) + borrow; + borrow = y >> 16; + Sign_Extend(borrow, y); + *bx++ = y & 0xffff; +#endif + } + while(sx <= sxe); + bx = b->x; + bxe = bx + n; + if (!*bxe) { + while(--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + return q; +} + +/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. + * + * Inspired by "How to Print Floating-Point Numbers Accurately" by + * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101]. + * + * Modifications: + * 1. Rather than iterating, we use a simple numeric overestimate + * to determine k = floor(log10(d)). We scale relevant + * quantities using O(log2(k)) rather than O(k) multiplications. + * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't + * try to generate digits strictly left to right. Instead, we + * compute with fewer bits and propagate the carry if necessary + * when rounding the final digit up. This is often faster. + * 3. Under the assumption that input will be rounded nearest, + * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. + * That is, we allow equality in stopping tests when the + * round-nearest rule will give the same floating-point value + * as would satisfaction of the stopping test with strict + * inequality. + * 4. We remove common factors of powers of 2 from relevant + * quantities. + * 5. When converting floating-point integers less than 1e16, + * we use floating-point arithmetic rather than resorting + * to multiple-precision integers. + * 6. When asked to produce fewer than 15 digits, we first try + * to get by with floating-point arithmetic; we resort to + * multiple-precision integer arithmetic only if we cannot + * guarantee that the floating-point calculation has given + * the correctly rounded result. For k requested digits and + * "uniformly" distributed input, the probability is + * something like 10^(k-15) that we must resort to the Long + * calculation. + */ + + +/* This actually sometimes returns a pointer to a string literal + cast to a char*. Do NOT try to modify the return value. */ + +Q_CORE_EXPORT char *qdtoa ( double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **resultp) +{ + // Some values of the floating-point control word can cause _qdtoa to crash with an underflow. + // We set a safe value here. +#ifdef Q_OS_WIN + _clear87(); + unsigned int oldbits = _control87(0, 0); +#ifndef MCW_EM +# ifdef _MCW_EM +# define MCW_EM _MCW_EM +# else +# define MCW_EM 0x0008001F +# endif +#endif + _control87(MCW_EM, MCW_EM); +#endif + +#if defined(Q_OS_LINUX) && !defined(__UCLIBC__) + fenv_t envp; + feholdexcept(&envp); +#endif + + char *s = _qdtoa(d, mode, ndigits, decpt, sign, rve, resultp); + +#ifdef Q_OS_WIN + _clear87(); +#ifndef _M_X64 + _control87(oldbits, 0xFFFFF); +#else + _control87(oldbits, _MCW_EM|_MCW_DN|_MCW_RC); +#endif //_M_X64 +#endif //Q_OS_WIN + +#if defined(Q_OS_LINUX) && !defined(__UCLIBC__) + fesetenv(&envp); +#endif + + return s; +} + +static char *_qdtoa( NEEDS_VOLATILE double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **resultp) +{ + /* + Arguments ndigits, decpt, sign are similar to those + of ecvt and fcvt; trailing zeros are suppressed from + the returned string. If not null, *rve is set to point + to the end of the return value. If d is +-Infinity or NaN, + then *decpt is set to 9999. + + mode: + 0 ==> shortest string that yields d when read in + and rounded to nearest. + 1 ==> like 0, but with Steele & White stopping rule; + e.g. with IEEE P754 arithmetic , mode 0 gives + 1e23 whereas mode 1 gives 9.999999999999999e22. + 2 ==> max(1,ndigits) significant digits. This gives a + return value similar to that of ecvt, except + that trailing zeros are suppressed. + 3 ==> through ndigits past the decimal point. This + gives a return value similar to that from fcvt, + except that trailing zeros are suppressed, and + ndigits can be negative. + 4-9 should give the same return values as 2-3, i.e., + 4 <= mode <= 9 ==> same return as mode + 2 + (mode & 1). These modes are mainly for + debugging; often they run slower but sometimes + faster than modes 2-3. + 4,5,8,9 ==> left-to-right digit generation. + 6-9 ==> don't try fast floating-point estimate + (if applicable). + + Values of mode other than 0-9 are treated as mode 0. + + Sufficient space is allocated to the return value + to hold the suppressed trailing zeros. + */ + + int bbits, b2, b5, be, dig, i, ieps, ilim0, + j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, + try_quick; + int ilim = 0, ilim1 = 0, spec_case = 0; /* pacify gcc */ + Long L; +#ifndef Sudden_Underflow + int denorm; + ULong x; +#endif + Bigint *b, *b1, *delta, *mhi, *S; + Bigint *mlo = NULL; /* pacify gcc */ + double d2; + double ds, eps; + char *s, *s0; + + if (getWord0(d) & Sign_bit) { + /* set sign for everything, including 0's and NaNs */ + *sign = 1; + setWord0(&d, getWord0(d) & ~Sign_bit); /* clear sign bit */ + } + else + *sign = 0; + +#if defined(IEEE_Arith) + defined(VAX) +#ifdef IEEE_Arith + if ((getWord0(d) & Exp_mask) == Exp_mask) +#else + if (getWord0(d) == 0x8000) +#endif + { + /* Infinity or NaN */ + *decpt = 9999; + s = +#ifdef IEEE_Arith + !getWord1(d) && !(getWord0(d) & 0xfffff) ? const_cast<char*>("Infinity") : +#endif + const_cast<char*>("NaN"); + if (rve) + *rve = +#ifdef IEEE_Arith + s[3] ? s + 8 : +#endif + s + 3; + return s; + } +#endif +#ifdef IBM + d += 0; /* normalize */ +#endif + if (d == g_double_zero) + { + *decpt = 1; + s = const_cast<char*>("0"); + if (rve) + *rve = s + 1; + return s; + } + + b = d2b(d, &be, &bbits); +#ifdef Sudden_Underflow + i = (int)(getWord0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); +#else + if ((i = int(getWord0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) { +#endif + d2 = d; + setWord0(&d2, getWord0(d2) & Frac_mask1); + setWord0(&d2, getWord0(d2) | Exp_11); +#ifdef IBM + if (j = 11 - hi0bits(getWord0(d2) & Frac_mask)) + d2 /= 1 << j; +#endif + + /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 + * log10(x) = log(x) / log(10) + * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) + * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) + * + * This suggests computing an approximation k to log10(d) by + * + * k = (i - Bias)*0.301029995663981 + * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); + * + * We want k to be too large rather than too small. + * The error in the first-order Taylor series approximation + * is in our favor, so we just round up the constant enough + * to compensate for any error in the multiplication of + * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, + * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, + * adding 1e-13 to the constant term more than suffices. + * Hence we adjust the constant term to 0.1760912590558. + * (We could get a more accurate k by invoking log10, + * but this is probably not worthwhile.) + */ + + i -= Bias; +#ifdef IBM + i <<= 2; + i += j; +#endif +#ifndef Sudden_Underflow + denorm = 0; + } + else { + /* d is denormalized */ + + i = bbits + be + (Bias + (P-1) - 1); + x = i > 32 ? getWord0(d) << (64 - i) | getWord1(d) >> (i - 32) + : getWord1(d) << (32 - i); + d2 = x; + setWord0(&d2, getWord0(d2) - 31*Exp_msk1); /* adjust exponent */ + i -= (Bias + (P-1) - 1) + 1; + denorm = 1; + } +#endif + ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; + k = int(ds); + if (ds < 0. && ds != k) + k--; /* want k = floor(ds) */ + k_check = 1; + if (k >= 0 && k <= Ten_pmax) { + if (d < tens[k]) + k--; + k_check = 0; + } + j = bbits - i - 1; + if (j >= 0) { + b2 = 0; + s2 = j; + } + else { + b2 = -j; + s2 = 0; + } + if (k >= 0) { + b5 = 0; + s5 = k; + s2 += k; + } + else { + b2 -= k; + b5 = -k; + s5 = 0; + } + if (mode < 0 || mode > 9) + mode = 0; + try_quick = 1; + if (mode > 5) { + mode -= 4; + try_quick = 0; + } + leftright = 1; + switch(mode) { + case 0: + case 1: + ilim = ilim1 = -1; + i = 18; + ndigits = 0; + break; + case 2: + leftright = 0; + /* no break */ + case 4: + if (ndigits <= 0) + ndigits = 1; + ilim = ilim1 = i = ndigits; + break; + case 3: + leftright = 0; + /* no break */ + case 5: + i = ndigits + k + 1; + ilim = i; + ilim1 = i - 1; + if (i <= 0) + i = 1; + } + *resultp = static_cast<char *>(malloc(i + 1)); + s = s0 = *resultp; + + if (ilim >= 0 && ilim <= Quick_max && try_quick) { + + /* Try to get by with floating-point arithmetic. */ + + i = 0; + d2 = d; + k0 = k; + ilim0 = ilim; + ieps = 2; /* conservative */ + if (k > 0) { + ds = tens[k&0xf]; + j = k >> 4; + if (j & Bletch) { + /* prevent overflows */ + j &= Bletch - 1; + d /= bigtens[n_bigtens-1]; + ieps++; + } + for(; j; j >>= 1, i++) + if (j & 1) { + ieps++; + ds *= bigtens[i]; + } + d /= ds; + } + else if ((j1 = -k) != 0) { + d *= tens[j1 & 0xf]; + for(j = j1 >> 4; j; j >>= 1, i++) + if (j & 1) { + ieps++; + d *= bigtens[i]; + } + } + if (k_check && d < 1. && ilim > 0) { + if (ilim1 <= 0) + goto fast_failed; + ilim = ilim1; + k--; + d *= 10.; + ieps++; + } + eps = ieps*d + 7.; + setWord0(&eps, getWord0(eps) - (P-1)*Exp_msk1); + if (ilim == 0) { + S = mhi = 0; + d -= 5.; + if (d > eps) + goto one_digit; + if (d < -eps) + goto no_digits; + goto fast_failed; + } +#ifndef No_leftright + if (leftright) { + /* Use Steele & White method of only + * generating digits needed. + */ + eps = 0.5/tens[ilim-1] - eps; + for(i = 0;;) { + L = Long(d); + d -= L; + *s++ = '0' + int(L); + if (d < eps) + goto ret1; + if (1. - d < eps) + goto bump_up; + if (++i >= ilim) + break; + eps *= 10.; + d *= 10.; + } + } + else { +#endif + /* Generate ilim digits, then fix them up. */ +#if defined(Q_OS_IRIX) && defined(Q_CC_GNU) + // work around a bug on 64 bit IRIX gcc + double *t = (double *) tens; + eps *= t[ilim-1]; +#else + eps *= tens[ilim-1]; +#endif + for(i = 1;; i++, d *= 10.) { + L = Long(d); + d -= L; + *s++ = '0' + int(L); + if (i == ilim) { + if (d > 0.5 + eps) + goto bump_up; + else if (d < 0.5 - eps) { + while(*--s == '0') {} + s++; + goto ret1; + } + break; + } + } +#ifndef No_leftright + } +#endif + fast_failed: + s = s0; + d = d2; + k = k0; + ilim = ilim0; + } + + /* Do we have a "small" integer? */ + + if (be >= 0 && k <= Int_max) { + /* Yes. */ + ds = tens[k]; + if (ndigits < 0 && ilim <= 0) { + S = mhi = 0; + if (ilim < 0 || d <= 5*ds) + goto no_digits; + goto one_digit; + } + for(i = 1;; i++) { + L = Long(d / ds); + d -= L*ds; +#ifdef Check_FLT_ROUNDS + /* If FLT_ROUNDS == 2, L will usually be high by 1 */ + if (d < 0) { + L--; + d += ds; + } +#endif + *s++ = '0' + int(L); + if (i == ilim) { + d += d; + if (d > ds || (d == ds && L & 1)) { + bump_up: + while(*--s == '9') + if (s == s0) { + k++; + *s = '0'; + break; + } + ++*s++; + } + break; + } + if ((d *= 10.) == g_double_zero) + break; + } + goto ret1; + } + + m2 = b2; + m5 = b5; + mhi = mlo = 0; + if (leftright) { + if (mode < 2) { + i = +#ifndef Sudden_Underflow + denorm ? be + (Bias + (P-1) - 1 + 1) : +#endif +#ifdef IBM + 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3); +#else + 1 + P - bbits; +#endif + } + else { + j = ilim - 1; + if (m5 >= j) + m5 -= j; + else { + s5 += j -= m5; + b5 += j; + m5 = 0; + } + if ((i = ilim) < 0) { + m2 -= i; + i = 0; + } + } + b2 += i; + s2 += i; + mhi = i2b(1); + } + if (m2 > 0 && s2 > 0) { + i = m2 < s2 ? m2 : s2; + b2 -= i; + m2 -= i; + s2 -= i; + } + if (b5 > 0) { + if (leftright) { + if (m5 > 0) { + mhi = pow5mult(mhi, m5); + b1 = mult(mhi, b); + Bfree(b); + b = b1; + } + if ((j = b5 - m5) != 0) + b = pow5mult(b, j); + } + else + b = pow5mult(b, b5); + } + S = i2b(1); + if (s5 > 0) + S = pow5mult(S, s5); + + /* Check for special case that d is a normalized power of 2. */ + + if (mode < 2) { + if (!getWord1(d) && !(getWord0(d) & Bndry_mask) +#ifndef Sudden_Underflow + && getWord0(d) & Exp_mask +#endif + ) { + /* The special case */ + b2 += Log2P; + s2 += Log2P; + spec_case = 1; + } + else + spec_case = 0; + } + + /* Arrange for convenient computation of quotients: + * shift left if necessary so divisor has 4 leading 0 bits. + * + * Perhaps we should just compute leading 28 bits of S once + * and for all and pass them and a shift to quorem, so it + * can do shifts and ors to compute the numerator for q. + */ +#ifdef Pack_32 + if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) != 0) + i = 32 - i; +#else + if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) + i = 16 - i; +#endif + if (i > 4) { + i -= 4; + b2 += i; + m2 += i; + s2 += i; + } + else if (i < 4) { + i += 28; + b2 += i; + m2 += i; + s2 += i; + } + if (b2 > 0) + b = lshift(b, b2); + if (s2 > 0) + S = lshift(S, s2); + if (k_check) { + if (cmp(b,S) < 0) { + k--; + b = multadd(b, 10, 0); /* we botched the k estimate */ + if (leftright) + mhi = multadd(mhi, 10, 0); + ilim = ilim1; + } + } + if (ilim <= 0 && mode > 2) { + if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { + /* no digits, fcvt style */ + no_digits: + k = -1 - ndigits; + goto ret; + } + one_digit: + *s++ = '1'; + k++; + goto ret; + } + if (leftright) { + if (m2 > 0) + mhi = lshift(mhi, m2); + + /* Compute mlo -- check for special case + * that d is a normalized power of 2. + */ + + mlo = mhi; + if (spec_case) { + mhi = Balloc(mhi->k); + Bcopy(mhi, mlo); + mhi = lshift(mhi, Log2P); + } + + for(i = 1;;i++) { + dig = quorem(b,S) + '0'; + /* Do we yet have the shortest decimal string + * that will round to d? + */ + j = cmp(b, mlo); + delta = diff(S, mhi); + j1 = delta->sign ? 1 : cmp(b, delta); + Bfree(delta); +#ifndef ROUND_BIASED + if (j1 == 0 && !mode && !(getWord1(d) & 1)) { + if (dig == '9') + goto round_9_up; + if (j > 0) + dig++; + *s++ = dig; + goto ret; + } +#endif + if (j < 0 || (j == 0 && !mode +#ifndef ROUND_BIASED + && !(getWord1(d) & 1) +#endif + )) { + if (j1 > 0) { + b = lshift(b, 1); + j1 = cmp(b, S); + if ((j1 > 0 || (j1 == 0 && dig & 1)) + && dig++ == '9') + goto round_9_up; + } + *s++ = dig; + goto ret; + } + if (j1 > 0) { + if (dig == '9') { /* possible if i == 1 */ + round_9_up: + *s++ = '9'; + goto roundoff; + } + *s++ = dig + 1; + goto ret; + } + *s++ = dig; + if (i == ilim) + break; + b = multadd(b, 10, 0); + if (mlo == mhi) + mlo = mhi = multadd(mhi, 10, 0); + else { + mlo = multadd(mlo, 10, 0); + mhi = multadd(mhi, 10, 0); + } + } + } + else + for(i = 1;; i++) { + *s++ = dig = quorem(b,S) + '0'; + if (i >= ilim) + break; + b = multadd(b, 10, 0); + } + + /* Round off last digit */ + + b = lshift(b, 1); + j = cmp(b, S); + if (j > 0 || (j == 0 && dig & 1)) { + roundoff: + while(*--s == '9') + if (s == s0) { + k++; + *s++ = '1'; + goto ret; + } + ++*s++; + } + else { + while(*--s == '0') {} + s++; + } + ret: + Bfree(S); + if (mhi) { + if (mlo && mlo != mhi) + Bfree(mlo); + Bfree(mhi); + } + ret1: + Bfree(b); + if (s == s0) { /* don't return empty string */ + *s++ = '0'; + k = 0; + } + *s = 0; + *decpt = k + 1; + if (rve) + *rve = s; + return s0; +} +#else +// NOT thread safe! + +#include <errno.h> + +Q_CORE_EXPORT char *qdtoa( double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **resultp) +{ + if(rve) + *rve = 0; + + char *res; + if (mode == 0) + ndigits = 80; + + if (mode == 3) + res = fcvt(d, ndigits, decpt, sign); + else + res = ecvt(d, ndigits, decpt, sign); + + int n = qstrlen(res); + if (mode == 0) { // remove trailing 0's + const int stop = qMax(1, *decpt); + int i; + for (i = n-1; i >= stop; --i) { + if (res[i] != '0') + break; + } + n = i + 1; + } + *resultp = static_cast<char*>(malloc(n + 1)); + qstrncpy(*resultp, res, n + 1); + return *resultp; +} + +Q_CORE_EXPORT double qstrtod(const char *s00, const char **se, bool *ok) +{ + double ret = strtod((char*)s00, (char**)se); + if (ok) { + if((ret == 0.0l && errno == ERANGE) + || ret == HUGE_VAL || ret == -HUGE_VAL) + *ok = false; + else + *ok = true; // the result will be that we don't report underflow in this case + } + return ret; +} +#endif // QT_QLOCALE_USES_FCVT + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h new file mode 100644 index 0000000..5b611eb --- /dev/null +++ b/src/corelib/tools/qlocale.h @@ -0,0 +1,678 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLOCALE_H +#define QLOCALE_H + +#include <QtCore/qstring.h> +#include <QtCore/qobjectdefs.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class QDataStream; +class QDate; +class QDateTime; +class QTime; +class QVariant; +class QTextStream; +class QTextStreamPrivate; + +class QLocale; + +#ifndef QT_NO_SYSTEMLOCALE +class Q_CORE_EXPORT QSystemLocale +{ +public: + QSystemLocale(); + virtual ~QSystemLocale(); + + enum QueryType { + LanguageId, // uint + CountryId, // uint + DecimalPoint, // QString + GroupSeparator, // QString + ZeroDigit, // QString + NegativeSign, // QString + DateFormatLong, // QString + DateFormatShort, // QString + TimeFormatLong, // QString + TimeFormatShort, // QString + DayNameLong, // QString, in: int + DayNameShort, // QString, in: int + MonthNameLong, // QString, in: int + MonthNameShort, // QString, in: int + DateToStringLong, // QString, in: QDate + DateToStringShort, // QString in: QDate + TimeToStringLong, // QString in: QTime + TimeToStringShort, // QString in: QTime + DateTimeFormatLong, // QString + DateTimeFormatShort, // QString + DateTimeToStringLong, // QString in: QDateTime + DateTimeToStringShort, // QString in: QDateTime + MeasurementSystem, // uint + PositiveSign, // QString + AMText, // QString + PMText // QString + }; + virtual QVariant query(QueryType type, QVariant in) const; + virtual QLocale fallbackLocale() const; + +#ifdef QLOCALE_CPP +private: + QSystemLocale(bool); + friend QSystemLocale *QSystemLocale_globalSystemLocale(); +#endif +}; +#endif + +struct QLocalePrivate; +class Q_CORE_EXPORT QLocale +{ + Q_GADGET + Q_ENUMS(Language) + Q_ENUMS(Country) + friend class QString; + friend class QByteArray; + friend class QIntValidator; + friend class QDoubleValidator; + friend class QTextStream; + friend class QTextStreamPrivate; + +public: + enum Language { + C = 1, + Abkhazian = 2, + Afan = 3, + Afar = 4, + Afrikaans = 5, + Albanian = 6, + Amharic = 7, + Arabic = 8, + Armenian = 9, + Assamese = 10, + Aymara = 11, + Azerbaijani = 12, + Bashkir = 13, + Basque = 14, + Bengali = 15, + Bhutani = 16, + Bihari = 17, + Bislama = 18, + Breton = 19, + Bulgarian = 20, + Burmese = 21, + Byelorussian = 22, + Cambodian = 23, + Catalan = 24, + Chinese = 25, + Corsican = 26, + Croatian = 27, + Czech = 28, + Danish = 29, + Dutch = 30, + English = 31, + Esperanto = 32, + Estonian = 33, + Faroese = 34, + FijiLanguage = 35, + Finnish = 36, + French = 37, + Frisian = 38, + Gaelic = 39, + Galician = 40, + Georgian = 41, + German = 42, + Greek = 43, + Greenlandic = 44, + Guarani = 45, + Gujarati = 46, + Hausa = 47, + Hebrew = 48, + Hindi = 49, + Hungarian = 50, + Icelandic = 51, + Indonesian = 52, + Interlingua = 53, + Interlingue = 54, + Inuktitut = 55, + Inupiak = 56, + Irish = 57, + Italian = 58, + Japanese = 59, + Javanese = 60, + Kannada = 61, + Kashmiri = 62, + Kazakh = 63, + Kinyarwanda = 64, + Kirghiz = 65, + Korean = 66, + Kurdish = 67, + Kurundi = 68, + Laothian = 69, + Latin = 70, + Latvian = 71, + Lingala = 72, + Lithuanian = 73, + Macedonian = 74, + Malagasy = 75, + Malay = 76, + Malayalam = 77, + Maltese = 78, + Maori = 79, + Marathi = 80, + Moldavian = 81, + Mongolian = 82, + NauruLanguage = 83, + Nepali = 84, + Norwegian = 85, + NorwegianBokmal = Norwegian, + Occitan = 86, + Oriya = 87, + Pashto = 88, + Persian = 89, + Polish = 90, + Portuguese = 91, + Punjabi = 92, + Quechua = 93, + RhaetoRomance = 94, + Romanian = 95, + Russian = 96, + Samoan = 97, + Sangho = 98, + Sanskrit = 99, + Serbian = 100, + SerboCroatian = 101, + Sesotho = 102, + Setswana = 103, + Shona = 104, + Sindhi = 105, + Singhalese = 106, + Siswati = 107, + Slovak = 108, + Slovenian = 109, + Somali = 110, + Spanish = 111, + Sundanese = 112, + Swahili = 113, + Swedish = 114, + Tagalog = 115, + Tajik = 116, + Tamil = 117, + Tatar = 118, + Telugu = 119, + Thai = 120, + Tibetan = 121, + Tigrinya = 122, + TongaLanguage = 123, + Tsonga = 124, + Turkish = 125, + Turkmen = 126, + Twi = 127, + Uigur = 128, + Ukrainian = 129, + Urdu = 130, + Uzbek = 131, + Vietnamese = 132, + Volapuk = 133, + Welsh = 134, + Wolof = 135, + Xhosa = 136, + Yiddish = 137, + Yoruba = 138, + Zhuang = 139, + Zulu = 140, + NorwegianNynorsk = 141, + Nynorsk = NorwegianNynorsk, // ### obsolete + Bosnian = 142, + Divehi = 143, + Manx = 144, + Cornish = 145, + Akan = 146, + Konkani = 147, + Ga = 148, + Igbo = 149, + Kamba = 150, + Syriac = 151, + Blin = 152, + Geez = 153, + Koro = 154, + Sidamo = 155, + Atsam = 156, + Tigre = 157, + Jju = 158, + Friulian = 159, + Venda = 160, + Ewe = 161, + Walamo = 162, + Hawaiian = 163, + Tyap = 164, + Chewa = 165, + LastLanguage = Chewa + }; + + enum Country { + AnyCountry = 0, + Afghanistan = 1, + Albania = 2, + Algeria = 3, + AmericanSamoa = 4, + Andorra = 5, + Angola = 6, + Anguilla = 7, + Antarctica = 8, + AntiguaAndBarbuda = 9, + Argentina = 10, + Armenia = 11, + Aruba = 12, + Australia = 13, + Austria = 14, + Azerbaijan = 15, + Bahamas = 16, + Bahrain = 17, + Bangladesh = 18, + Barbados = 19, + Belarus = 20, + Belgium = 21, + Belize = 22, + Benin = 23, + Bermuda = 24, + Bhutan = 25, + Bolivia = 26, + BosniaAndHerzegowina = 27, + Botswana = 28, + BouvetIsland = 29, + Brazil = 30, + BritishIndianOceanTerritory = 31, + BruneiDarussalam = 32, + Bulgaria = 33, + BurkinaFaso = 34, + Burundi = 35, + Cambodia = 36, + Cameroon = 37, + Canada = 38, + CapeVerde = 39, + CaymanIslands = 40, + CentralAfricanRepublic = 41, + Chad = 42, + Chile = 43, + China = 44, + ChristmasIsland = 45, + CocosIslands = 46, + Colombia = 47, + Comoros = 48, + DemocraticRepublicOfCongo = 49, + PeoplesRepublicOfCongo = 50, + CookIslands = 51, + CostaRica = 52, + IvoryCoast = 53, + Croatia = 54, + Cuba = 55, + Cyprus = 56, + CzechRepublic = 57, + Denmark = 58, + Djibouti = 59, + Dominica = 60, + DominicanRepublic = 61, + EastTimor = 62, + Ecuador = 63, + Egypt = 64, + ElSalvador = 65, + EquatorialGuinea = 66, + Eritrea = 67, + Estonia = 68, + Ethiopia = 69, + FalklandIslands = 70, + FaroeIslands = 71, + FijiCountry = 72, + Finland = 73, + France = 74, + MetropolitanFrance = 75, + FrenchGuiana = 76, + FrenchPolynesia = 77, + FrenchSouthernTerritories = 78, + Gabon = 79, + Gambia = 80, + Georgia = 81, + Germany = 82, + Ghana = 83, + Gibraltar = 84, + Greece = 85, + Greenland = 86, + Grenada = 87, + Guadeloupe = 88, + Guam = 89, + Guatemala = 90, + Guinea = 91, + GuineaBissau = 92, + Guyana = 93, + Haiti = 94, + HeardAndMcDonaldIslands = 95, + Honduras = 96, + HongKong = 97, + Hungary = 98, + Iceland = 99, + India = 100, + Indonesia = 101, + Iran = 102, + Iraq = 103, + Ireland = 104, + Israel = 105, + Italy = 106, + Jamaica = 107, + Japan = 108, + Jordan = 109, + Kazakhstan = 110, + Kenya = 111, + Kiribati = 112, + DemocraticRepublicOfKorea = 113, + RepublicOfKorea = 114, + Kuwait = 115, + Kyrgyzstan = 116, + Lao = 117, + Latvia = 118, + Lebanon = 119, + Lesotho = 120, + Liberia = 121, + LibyanArabJamahiriya = 122, + Liechtenstein = 123, + Lithuania = 124, + Luxembourg = 125, + Macau = 126, + Macedonia = 127, + Madagascar = 128, + Malawi = 129, + Malaysia = 130, + Maldives = 131, + Mali = 132, + Malta = 133, + MarshallIslands = 134, + Martinique = 135, + Mauritania = 136, + Mauritius = 137, + Mayotte = 138, + Mexico = 139, + Micronesia = 140, + Moldova = 141, + Monaco = 142, + Mongolia = 143, + Montserrat = 144, + Morocco = 145, + Mozambique = 146, + Myanmar = 147, + Namibia = 148, + NauruCountry = 149, + Nepal = 150, + Netherlands = 151, + NetherlandsAntilles = 152, + NewCaledonia = 153, + NewZealand = 154, + Nicaragua = 155, + Niger = 156, + Nigeria = 157, + Niue = 158, + NorfolkIsland = 159, + NorthernMarianaIslands = 160, + Norway = 161, + Oman = 162, + Pakistan = 163, + Palau = 164, + PalestinianTerritory = 165, + Panama = 166, + PapuaNewGuinea = 167, + Paraguay = 168, + Peru = 169, + Philippines = 170, + Pitcairn = 171, + Poland = 172, + Portugal = 173, + PuertoRico = 174, + Qatar = 175, + Reunion = 176, + Romania = 177, + RussianFederation = 178, + Rwanda = 179, + SaintKittsAndNevis = 180, + StLucia = 181, + StVincentAndTheGrenadines = 182, + Samoa = 183, + SanMarino = 184, + SaoTomeAndPrincipe = 185, + SaudiArabia = 186, + Senegal = 187, + Seychelles = 188, + SierraLeone = 189, + Singapore = 190, + Slovakia = 191, + Slovenia = 192, + SolomonIslands = 193, + Somalia = 194, + SouthAfrica = 195, + SouthGeorgiaAndTheSouthSandwichIslands = 196, + Spain = 197, + SriLanka = 198, + StHelena = 199, + StPierreAndMiquelon = 200, + Sudan = 201, + Suriname = 202, + SvalbardAndJanMayenIslands = 203, + Swaziland = 204, + Sweden = 205, + Switzerland = 206, + SyrianArabRepublic = 207, + Taiwan = 208, + Tajikistan = 209, + Tanzania = 210, + Thailand = 211, + Togo = 212, + Tokelau = 213, + TongaCountry = 214, + TrinidadAndTobago = 215, + Tunisia = 216, + Turkey = 217, + Turkmenistan = 218, + TurksAndCaicosIslands = 219, + Tuvalu = 220, + Uganda = 221, + Ukraine = 222, + UnitedArabEmirates = 223, + UnitedKingdom = 224, + UnitedStates = 225, + UnitedStatesMinorOutlyingIslands = 226, + Uruguay = 227, + Uzbekistan = 228, + Vanuatu = 229, + VaticanCityState = 230, + Venezuela = 231, + VietNam = 232, + BritishVirginIslands = 233, + USVirginIslands = 234, + WallisAndFutunaIslands = 235, + WesternSahara = 236, + Yemen = 237, + Yugoslavia = 238, + Zambia = 239, + Zimbabwe = 240, + SerbiaAndMontenegro = 241, + LastCountry = SerbiaAndMontenegro + }; + + enum MeasurementSystem { MetricSystem, ImperialSystem }; + + enum FormatType { LongFormat, ShortFormat, NarrowFormat }; + enum NumberOption { + OmitGroupSeparator = 0x01, + RejectGroupSeparator = 0x02 + }; + Q_DECLARE_FLAGS(NumberOptions, NumberOption) + + QLocale(); + QLocale(const QString &name); + QLocale(Language language, Country country = AnyCountry); + QLocale(const QLocale &other); + + QLocale &operator=(const QLocale &other); + + Language language() const; + Country country() const; + QString name() const; + + short toShort(const QString &s, bool *ok = 0, int base = 0) const; + ushort toUShort(const QString &s, bool *ok = 0, int base = 0) const; + int toInt(const QString &s, bool *ok = 0, int base = 0) const; + uint toUInt(const QString &s, bool *ok = 0, int base = 0) const; + qlonglong toLongLong(const QString &s, bool *ok = 0, int base = 0) const; + qlonglong toULongLong(const QString &s, bool *ok = 0, int base = 0) const; + float toFloat(const QString &s, bool *ok = 0) const; + double toDouble(const QString &s, bool *ok = 0) const; + + QString toString(qlonglong i) const; + QString toString(qulonglong i) const; + inline QString toString(short i) const; + inline QString toString(ushort i) const; + inline QString toString(int i) const; + inline QString toString(uint i) const; + QString toString(double i, char f = 'g', int prec = 6) const; + inline QString toString(float i, char f = 'g', int prec = 6) const; + QString toString(const QDate &date, const QString &formatStr) const; + QString toString(const QDate &date, FormatType format = LongFormat) const; + QString toString(const QTime &time, const QString &formatStr) const; + QString toString(const QTime &time, FormatType format = LongFormat) const; + QString toString(const QDateTime &dateTime, FormatType format = LongFormat) const; + QString toString(const QDateTime &dateTime, const QString &format) const; + + QString dateFormat(FormatType format = LongFormat) const; + QString timeFormat(FormatType format = LongFormat) const; + QString dateTimeFormat(FormatType format = LongFormat) const; +#ifndef QT_NO_DATESTRING + QDate toDate(const QString &string, FormatType = LongFormat) const; + QTime toTime(const QString &string, FormatType = LongFormat) const; + QDateTime toDateTime(const QString &string, FormatType format = LongFormat) const; + QDate toDate(const QString &string, const QString &format) const; + QTime toTime(const QString &string, const QString &format) const; + QDateTime toDateTime(const QString &string, const QString &format) const; +#endif + + // ### Qt 5: We need to return QString from these function since + // unicode data contains several characters for these fields. + QChar decimalPoint() const; + QChar groupSeparator() const; + QChar percent() const; + QChar zeroDigit() const; + QChar negativeSign() const; + QChar positiveSign() const; + QChar exponential() const; + + QString monthName(int, FormatType format = LongFormat) const; + QString standaloneMonthName(int, FormatType format = LongFormat) const; + QString dayName(int, FormatType format = LongFormat) const; + QString standaloneDayName(int, FormatType format = LongFormat) const; + + QString amText() const; + QString pmText() const; + + MeasurementSystem measurementSystem() const; + + inline bool operator==(const QLocale &other) const; + inline bool operator!=(const QLocale &other) const; + + static QString languageToString(Language language); + static QString countryToString(Country country); + static void setDefault(const QLocale &locale); + + static QLocale c() { return QLocale(C); } + static QLocale system(); + + static QList<Country> countriesForLanguage(Language lang); + + void setNumberOptions(NumberOptions options); + NumberOptions numberOptions() const; + +//private: // this should be private, but can't be + struct Data { + quint16 index; + quint16 numberOptions; + } +#if (defined(__arm__) || defined(__ARMEL__)) + Q_PACKED +#endif + ; +private: + friend struct QLocalePrivate; + // ### We now use this field to pack an index into locale_data and NumberOptions. + // ### Qt 5: change to a QLocaleData *d; uint numberOptions. + union { + void *v; + Data p; + }; + const QLocalePrivate *d() const; +}; +Q_DECLARE_TYPEINFO(QLocale, Q_MOVABLE_TYPE); +Q_DECLARE_OPERATORS_FOR_FLAGS(QLocale::NumberOptions) + +inline QString QLocale::toString(short i) const + { return toString(qlonglong(i)); } +inline QString QLocale::toString(ushort i) const + { return toString(qulonglong(i)); } +inline QString QLocale::toString(int i) const + { return toString(qlonglong(i)); } +inline QString QLocale::toString(uint i) const + { return toString(qulonglong(i)); } +inline QString QLocale::toString(float i, char f, int prec) const + { return toString(double(i), f, prec); } +inline bool QLocale::operator==(const QLocale &other) const + { return d() == other.d() && numberOptions() == other.numberOptions(); } +inline bool QLocale::operator!=(const QLocale &other) const + { return d() != other.d() || numberOptions() != other.numberOptions(); } + +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QLocale &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QLocale &); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QLOCALE_H diff --git a/src/corelib/tools/qlocale_data_p.h b/src/corelib/tools/qlocale_data_p.h new file mode 100644 index 0000000..37f59a4 --- /dev/null +++ b/src/corelib/tools/qlocale_data_p.h @@ -0,0 +1,3391 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLOCALE_DATA_P_H +#define QLOCALE_DATA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +/* This part of the file isn't generated, but written by hand since + * Unicode CLDR doesn't contain measurement system information. + */ +struct CountryLanguage +{ + quint32 languageId; + quint32 countryId; +}; +static const CountryLanguage ImperialMeasurementSystems[] = { + { 31, 225 }, + { 31, 226 }, + { 111, 225 }, + { 163, 225 } +}; +static const int ImperialMeasurementSystemsCount = + sizeof(ImperialMeasurementSystems)/sizeof(ImperialMeasurementSystems[0]); + +/* + This part of the file was generated on 2008-08-07 from the + Common Locale Data Repository v1.6.1 + + http://www.unicode.org/cldr/ + + Do not change it, instead edit $QTDIR/util/locale_database/locale.xml and run + qlocalexml2cpp.py. +*/ + + +static const uint locale_index[] = { + 0, // unused + 0, // C + 0, // Abkhazian + 1, // Afan + 3, // Afar + 6, // Afrikaans + 8, // Albanian + 9, // Amharic + 10, // Arabic + 27, // Armenian + 28, // Assamese + 0, // Aymara + 29, // Azerbaijani + 0, // Bashkir + 30, // Basque + 31, // Bengali + 33, // Bhutani + 0, // Bihari + 0, // Bislama + 0, // Breton + 34, // Bulgarian + 35, // Burmese + 36, // Byelorussian + 37, // Cambodian + 38, // Catalan + 39, // Chinese + 0, // Corsican + 44, // Croatian + 45, // Czech + 46, // Danish + 47, // Dutch + 49, // English + 0, // Esperanto + 75, // Estonian + 76, // Faroese + 0, // Fiji + 77, // Finnish + 78, // French + 0, // Frisian + 0, // Gaelic + 85, // Galician + 86, // Georgian + 87, // German + 93, // Greek + 95, // Greenlandic + 0, // Guarani + 96, // Gujarati + 97, // Hausa + 101, // Hebrew + 102, // Hindi + 103, // Hungarian + 104, // Icelandic + 105, // Indonesian + 0, // Interlingua + 0, // Interlingue + 0, // Inuktitut + 0, // Inupiak + 106, // Irish + 107, // Italian + 109, // Japanese + 0, // Javanese + 110, // Kannada + 0, // Kashmiri + 111, // Kazakh + 112, // Kinyarwanda + 113, // Kirghiz + 114, // Korean + 115, // Kurdish + 0, // Kurundi + 116, // Laothian + 0, // Latin + 117, // Latvian + 118, // Lingala + 120, // Lithuanian + 121, // Macedonian + 0, // Malagasy + 122, // Malay + 124, // Malayalam + 125, // Maltese + 0, // Maori + 126, // Marathi + 0, // Moldavian + 127, // Mongolian + 0, // Nauru + 129, // Nepali + 131, // Norwegian + 0, // Occitan + 132, // Oriya + 133, // Pashto + 134, // Persian + 136, // Polish + 137, // Portuguese + 139, // Punjabi + 0, // Quechua + 0, // RhaetoRomance + 141, // Romanian + 143, // Russian + 0, // Samoan + 0, // Sangho + 145, // Sanskrit + 146, // Serbian + 149, // SerboCroatian + 152, // Sesotho + 154, // Setswana + 0, // Shona + 0, // Sindhi + 155, // Singhalese + 156, // Siswati + 158, // Slovak + 159, // Slovenian + 160, // Somali + 164, // Spanish + 0, // Sundanese + 184, // Swahili + 186, // Swedish + 0, // Tagalog + 188, // Tajik + 189, // Tamil + 190, // Tatar + 191, // Telugu + 192, // Thai + 0, // Tibetan + 193, // Tigrinya + 195, // Tonga + 196, // Tsonga + 197, // Turkish + 0, // Turkmen + 0, // Twi + 198, // Uigur + 199, // Ukrainian + 200, // Urdu + 202, // Uzbek + 204, // Vietnamese + 0, // Volapuk + 205, // Welsh + 206, // Wolof + 207, // Xhosa + 0, // Yiddish + 208, // Yoruba + 0, // Zhuang + 209, // Zulu + 210, // Nynorsk + 211, // Bosnian + 212, // Divehi + 213, // Manx + 214, // Cornish + 215, // Akan + 216, // Konkani + 217, // Ga + 218, // Igbo + 219, // Kamba + 220, // Syriac + 221, // Blin + 222, // Geez + 224, // Koro + 225, // Sidamo + 226, // Atsam + 227, // Tigre + 228, // Jju + 229, // Friulian + 230, // Venda + 231, // Ewe + 0, // Walamo + 233, // Hawaiian + 234, // Tyap + 235, // Chewa + 0 // trailing 0 +}; + +static const QLocalePrivate locale_data[] = { +// lang terr dec group list prcnt zero minus plus exp sDtFmt lDtFmt sTmFmt lTmFmt ssMonth slMonth sMonth lMonth sDays lDays am,len pm,len + { 1, 0, 46, 44, 59, 37, 48, 45, 43, 101, 0,10 , 10,17 , 0,8 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,27 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 99,14 , 0,2 , 0,2 }, // C/AnyCountry + { 3, 69, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 35,18 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 161,48 , 209,111 , 320,12 , 113,7 , 113,7 , 85,14 , 120,28 , 148,55 , 113,7 , 2,0 , 2,0 }, // Afan/Ethiopia + { 3, 111, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 35,18 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 161,48 , 209,111 , 320,12 , 113,7 , 113,7 , 85,14 , 120,28 , 148,55 , 113,7 , 2,0 , 2,0 }, // Afan/Kenya + { 4, 59, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 53,19 , 18,7 , 25,11 , 158,12 , 158,12 , 170,24 , 332,48 , 380,129 , 320,12 , 113,7 , 113,7 , 203,14 , 217,28 , 245,52 , 113,7 , 2,0 , 2,0 }, // Afar/Djibouti + { 4, 67, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 53,19 , 18,7 , 25,11 , 158,12 , 158,12 , 170,24 , 332,48 , 509,118 , 320,12 , 113,7 , 113,7 , 203,14 , 217,28 , 245,52 , 113,7 , 2,0 , 2,0 }, // Afar/Eritrea + { 4, 69, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 53,19 , 18,7 , 25,11 , 158,12 , 158,12 , 170,24 , 332,48 , 509,118 , 320,12 , 113,7 , 113,7 , 203,14 , 217,28 , 245,52 , 113,7 , 2,0 , 2,0 }, // Afar/Ethiopia + { 5, 195, 44, 160, 59, 37, 48, 45, 43, 101, 72,10 , 82,17 , 18,7 , 25,11 , 158,12 , 158,12 , 194,27 , 627,48 , 675,92 , 320,12 , 113,7 , 113,7 , 297,14 , 311,21 , 332,58 , 113,7 , 2,3 , 2,3 }, // Afrikaans/SouthAfrica + { 5, 148, 44, 160, 59, 37, 48, 45, 43, 101, 99,10 , 109,16 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 627,48 , 675,92 , 320,12 , 113,7 , 113,7 , 297,14 , 311,21 , 332,58 , 113,7 , 2,3 , 2,3 }, // Afrikaans/Namibia + { 6, 2, 44, 46, 59, 37, 48, 45, 43, 101, 125,8 , 133,18 , 50,7 , 57,11 , 158,12 , 158,12 , 221,24 , 767,48 , 815,78 , 320,12 , 113,7 , 113,7 , 390,14 , 404,28 , 432,58 , 113,7 , 5,2 , 5,2 }, // Albanian/Albania + { 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 151,23 , 18,7 , 68,12 , 158,12 , 158,12 , 245,24 , 893,46 , 939,62 , 320,12 , 113,7 , 113,7 , 490,14 , 504,27 , 531,28 , 113,7 , 2,0 , 2,0 }, // Amharic/Ethiopia + { 8, 186, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1001,75 , 1001,75 , 320,12 , 559,38 , 113,7 , 597,14 , 611,52 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/SaudiArabia + { 8, 3, 1643, 1644, 1563, 1642, 48, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1001,75 , 1001,75 , 320,12 , 559,38 , 113,7 , 597,14 , 597,14 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/Algeria + { 8, 17, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1001,75 , 1001,75 , 320,12 , 559,38 , 113,7 , 597,14 , 597,14 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/Bahrain + { 8, 64, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1001,75 , 1001,75 , 320,12 , 559,38 , 113,7 , 597,14 , 597,14 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/Egypt + { 8, 103, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1001,75 , 1001,75 , 320,12 , 559,38 , 113,7 , 597,14 , 597,14 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/Iraq + { 8, 109, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1076,92 , 1076,92 , 320,12 , 559,38 , 113,7 , 597,14 , 611,52 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/Jordan + { 8, 115, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1001,75 , 1001,75 , 320,12 , 559,38 , 113,7 , 597,14 , 597,14 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/Kuwait + { 8, 119, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1168,92 , 1168,92 , 320,12 , 559,38 , 113,7 , 597,14 , 611,52 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/Lebanon + { 8, 122, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1001,75 , 1001,75 , 320,12 , 559,38 , 113,7 , 597,14 , 597,14 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/LibyanArabJamahiriya + { 8, 145, 1643, 1644, 1563, 1642, 48, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1001,75 , 1001,75 , 320,12 , 559,38 , 113,7 , 597,14 , 597,14 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/Morocco + { 8, 162, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1001,75 , 1001,75 , 320,12 , 559,38 , 113,7 , 597,14 , 597,14 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/Oman + { 8, 175, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1001,75 , 1001,75 , 320,12 , 559,38 , 113,7 , 597,14 , 611,52 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/Qatar + { 8, 201, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1001,75 , 1001,75 , 320,12 , 559,38 , 113,7 , 597,14 , 597,14 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/Sudan + { 8, 207, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1168,92 , 1168,92 , 320,12 , 559,38 , 113,7 , 597,14 , 611,52 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/SyrianArabRepublic + { 8, 216, 1643, 1644, 1563, 1642, 48, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1001,75 , 1001,75 , 320,12 , 559,38 , 113,7 , 597,14 , 611,52 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/Tunisia + { 8, 223, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1001,75 , 1001,75 , 320,12 , 559,38 , 113,7 , 597,14 , 597,14 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/UnitedArabEmirates + { 8, 237, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 174,10 , 184,18 , 18,7 , 80,11 , 158,12 , 158,12 , 269,24 , 1001,75 , 1001,75 , 320,12 , 559,38 , 113,7 , 597,14 , 611,52 , 611,52 , 113,7 , 7,1 , 7,1 }, // Arabic/Yemen + { 9, 11, 44, 46, 59, 37, 48, 45, 43, 101, 202,8 , 35,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 1260,48 , 1308,96 , 320,12 , 113,7 , 113,7 , 297,14 , 663,28 , 691,62 , 113,7 , 8,3 , 8,3 }, // Armenian/Armenia + { 10, 100, 46, 44, 59, 37, 48, 45, 43, 101, 210,8 , 218,18 , 91,8 , 99,11 , 158,12 , 158,12 , 194,27 , 1404,62 , 1466,90 , 320,12 , 113,7 , 113,7 , 297,14 , 753,37 , 790,58 , 113,7 , 11,6 , 11,2 }, // Assamese/India + { 12, 15, 44, 46, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 1556,48 , 1604,77 , 320,12 , 113,7 , 113,7 , 99,14 , 848,26 , 874,67 , 113,7 , 2,0 , 2,0 }, // Azerbaijani/Azerbaijan + { 14, 197, 44, 46, 59, 37, 48, 45, 43, 101, 125,8 , 262,31 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 1681,48 , 1729,93 , 320,12 , 113,7 , 113,7 , 297,14 , 941,21 , 962,68 , 113,7 , 2,0 , 2,0 }, // Basque/Spain + { 15, 18, 46, 44, 59, 37, 2534, 45, 43, 101, 293,6 , 218,18 , 18,7 , 25,11 , 158,12 , 158,12 , 293,33 , 1822,90 , 1822,90 , 320,12 , 113,7 , 113,7 , 1030,18 , 1048,37 , 1085,58 , 113,7 , 17,9 , 13,7 }, // Bengali/Bangladesh + { 15, 100, 46, 44, 59, 37, 2534, 45, 43, 101, 293,6 , 218,18 , 18,7 , 25,11 , 158,12 , 158,12 , 293,33 , 1822,90 , 1822,90 , 320,12 , 113,7 , 113,7 , 1030,18 , 1048,37 , 1085,58 , 113,7 , 17,9 , 13,7 }, // Bengali/India + { 16, 25, 46, 44, 59, 37, 3872, 45, 43, 101, 299,28 , 327,29 , 110,22 , 132,34 , 158,12 , 158,12 , 194,27 , 1912,75 , 1987,205 , 320,12 , 113,7 , 113,7 , 297,14 , 1143,34 , 1177,79 , 113,7 , 2,0 , 2,0 }, // Bhutani/Bhutan + { 20, 33, 44, 160, 59, 37, 48, 45, 43, 101, 356,8 , 364,18 , 36,5 , 41,9 , 158,12 , 158,12 , 326,24 , 2192,59 , 2251,82 , 320,12 , 113,7 , 113,7 , 1256,14 , 1270,21 , 1291,55 , 113,7 , 26,7 , 20,7 }, // Bulgarian/Bulgaria + { 21, 147, 46, 44, 4170, 37, 4160, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 350,24 , 2333,43 , 2376,88 , 320,12 , 113,7 , 113,7 , 1346,14 , 1360,25 , 1385,54 , 113,7 , 2,0 , 2,0 }, // Burmese/Myanmar + { 22, 20, 44, 160, 59, 37, 48, 45, 43, 101, 382,6 , 10,17 , 166,5 , 171,9 , 374,15 , 389,19 , 408,24 , 2464,48 , 2512,95 , 2607,13 , 113,7 , 113,7 , 1439,14 , 1453,21 , 1474,56 , 113,7 , 33,10 , 27,13 }, // Byelorussian/Belarus + { 23, 36, 44, 46, 59, 37, 48, 45, 43, 101, 388,8 , 396,31 , 180,4 , 184,25 , 158,12 , 158,12 , 194,27 , 2620,27 , 2647,71 , 320,12 , 113,7 , 113,7 , 297,14 , 1530,19 , 1549,76 , 113,7 , 43,5 , 40,5 }, // Cambodian/Cambodia + { 24, 197, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 427,26 , 180,4 , 209,8 , 158,12 , 158,12 , 432,24 , 2718,60 , 2778,82 , 320,12 , 1625,21 , 113,7 , 1646,14 , 1660,28 , 1688,60 , 113,7 , 2,0 , 2,0 }, // Catalan/Spain + { 25, 44, 46, 44, 59, 37, 48, 45, 43, 101, 453,6 , 459,13 , 217,6 , 223,11 , 456,38 , 456,38 , 494,39 , 2860,39 , 2860,39 , 320,12 , 113,7 , 113,7 , 1748,14 , 1762,21 , 1783,28 , 113,7 , 48,2 , 45,2 }, // Chinese/China + { 25, 97, 46, 65292, 65307, 37, 48, 45, 43, 101, 472,7 , 459,13 , 217,6 , 223,11 , 456,38 , 456,38 , 494,39 , 2860,39 , 2860,39 , 320,12 , 113,7 , 113,7 , 1748,14 , 1762,21 , 1783,28 , 113,7 , 48,2 , 45,2 }, // Chinese/HongKong + { 25, 126, 46, 44, 59, 37, 48, 45, 43, 101, 472,7 , 479,15 , 217,6 , 223,11 , 456,38 , 456,38 , 494,39 , 2860,39 , 2860,39 , 320,12 , 113,7 , 113,7 , 1748,14 , 1762,21 , 1783,28 , 113,7 , 48,2 , 45,2 }, // Chinese/Macau + { 25, 190, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 459,13 , 234,7 , 223,11 , 456,38 , 456,38 , 494,39 , 2860,39 , 2860,39 , 320,12 , 113,7 , 113,7 , 1748,14 , 1762,21 , 1783,28 , 113,7 , 48,2 , 45,2 }, // Chinese/Singapore + { 25, 208, 46, 44, 59, 37, 48, 45, 43, 101, 453,6 , 459,13 , 217,6 , 223,11 , 456,38 , 456,38 , 494,39 , 2860,39 , 2860,39 , 320,12 , 113,7 , 113,7 , 1748,14 , 1762,21 , 1783,28 , 113,7 , 48,2 , 45,2 }, // Chinese/Taiwan + { 27, 54, 44, 46, 59, 37, 48, 45, 43, 101, 494,11 , 505,19 , 36,5 , 41,9 , 158,12 , 533,94 , 627,24 , 2899,48 , 2947,98 , 320,12 , 113,7 , 113,7 , 1811,14 , 1825,28 , 1853,58 , 113,7 , 0,2 , 0,2 }, // Croatian/Croatia + { 28, 57, 44, 160, 59, 37, 48, 45, 43, 101, 382,6 , 524,18 , 180,4 , 41,9 , 651,39 , 690,82 , 772,24 , 134,27 , 3045,84 , 320,12 , 113,7 , 113,7 , 1911,14 , 1925,21 , 1946,49 , 113,7 , 50,4 , 47,4 }, // Czech/CzechRepublic + { 29, 58, 44, 46, 44, 37, 48, 45, 43, 101, 27,8 , 542,23 , 166,5 , 171,9 , 158,12 , 158,12 , 134,24 , 3129,48 , 3177,84 , 320,12 , 113,7 , 113,7 , 1995,14 , 2009,28 , 2037,51 , 113,7 , 54,4 , 51,4 }, // Danish/Denmark + { 30, 151, 44, 46, 59, 37, 48, 45, 43, 101, 565,8 , 109,16 , 36,5 , 41,9 , 158,12 , 158,12 , 134,24 , 3261,48 , 3309,88 , 320,12 , 113,7 , 113,7 , 2088,14 , 2102,21 , 2123,59 , 113,7 , 2,0 , 2,0 }, // Dutch/Netherlands + { 30, 21, 44, 46, 59, 37, 48, 45, 43, 101, 573,7 , 109,16 , 36,5 , 41,9 , 158,12 , 158,12 , 134,24 , 3261,48 , 3309,88 , 320,12 , 113,7 , 113,7 , 2088,14 , 2102,21 , 2123,59 , 113,7 , 2,0 , 2,0 }, // Dutch/Belgium + { 31, 225, 46, 44, 59, 37, 48, 45, 43, 101, 580,6 , 35,18 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/UnitedStates + { 31, 4, 46, 44, 59, 37, 48, 45, 43, 101, 580,6 , 35,18 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/AmericanSamoa + { 31, 13, 46, 44, 59, 37, 48, 45, 43, 101, 573,7 , 10,17 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/Australia + { 31, 21, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 109,16 , 36,5 , 241,23 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/Belgium + { 31, 22, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 586,12 , 36,5 , 41,9 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/Belize + { 31, 28, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 82,17 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/Botswana + { 31, 38, 46, 44, 59, 37, 48, 45, 43, 101, 125,8 , 35,18 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/Canada + { 31, 89, 46, 44, 59, 37, 48, 45, 43, 101, 580,6 , 35,18 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/Guam + { 31, 97, 46, 44, 59, 37, 48, 45, 43, 101, 598,10 , 10,17 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/HongKong + { 31, 100, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 109,16 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/India + { 31, 104, 46, 44, 59, 37, 48, 45, 43, 101, 598,10 , 109,16 , 36,5 , 41,9 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 58,4 , 55,4 }, // English/Ireland + { 31, 107, 46, 44, 59, 37, 48, 45, 43, 101, 580,6 , 35,18 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/Jamaica + { 31, 133, 46, 44, 59, 37, 48, 45, 43, 101, 598,10 , 10,17 , 36,5 , 41,9 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/Malta + { 31, 134, 46, 44, 59, 37, 48, 45, 43, 101, 580,6 , 35,18 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/MarshallIslands + { 31, 148, 46, 44, 59, 37, 48, 45, 43, 101, 580,6 , 35,18 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/Namibia + { 31, 154, 46, 44, 59, 37, 48, 45, 43, 101, 573,7 , 10,17 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/NewZealand + { 31, 160, 46, 44, 59, 37, 48, 45, 43, 101, 580,6 , 35,18 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/NorthernMarianaIslands + { 31, 163, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 109,16 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/Pakistan + { 31, 170, 46, 44, 59, 37, 48, 45, 43, 101, 580,6 , 35,18 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/Philippines + { 31, 190, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 133,18 , 264,8 , 272,12 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/Singapore + { 31, 195, 44, 160, 59, 37, 48, 45, 43, 101, 72,10 , 82,17 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/SouthAfrica + { 31, 215, 46, 44, 59, 37, 48, 45, 43, 101, 580,6 , 35,18 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/TrinidadAndTobago + { 31, 224, 46, 44, 59, 37, 48, 45, 43, 101, 598,10 , 10,17 , 36,5 , 41,9 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/UnitedKingdom + { 31, 226, 46, 44, 59, 37, 48, 45, 43, 101, 580,6 , 35,18 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/UnitedStatesMinorOutlyingIslands + { 31, 234, 46, 44, 59, 37, 48, 45, 43, 101, 580,6 , 35,18 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/USVirginIslands + { 31, 240, 46, 44, 59, 37, 48, 45, 43, 101, 388,8 , 82,17 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 85,14 , 0,28 , 28,57 , 113,7 , 0,2 , 0,2 }, // English/Zimbabwe + { 33, 68, 44, 160, 59, 37, 48, 45, 43, 101, 356,8 , 608,18 , 180,4 , 209,8 , 158,12 , 158,12 , 194,27 , 3397,59 , 3456,91 , 320,12 , 113,7 , 113,7 , 297,14 , 2182,14 , 2196,63 , 113,7 , 2,0 , 2,0 }, // Estonian/Estonia + { 34, 71, 44, 46, 59, 37, 48, 8722, 43, 101, 565,8 , 82,17 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 3547,48 , 3595,83 , 320,12 , 113,7 , 113,7 , 297,14 , 2259,28 , 2287,74 , 113,7 , 2,0 , 2,0 }, // Faroese/FaroeIslands + { 36, 73, 44, 160, 59, 37, 48, 45, 43, 101, 626,8 , 634,17 , 284,4 , 288,8 , 158,12 , 158,12 , 796,24 , 3678,69 , 3747,129 , 320,12 , 113,7 , 113,7 , 2361,14 , 2375,21 , 2396,81 , 113,7 , 62,3 , 59,3 }, // Finnish/Finland + { 37, 74, 44, 160, 59, 37, 48, 45, 43, 101, 27,8 , 109,16 , 36,5 , 41,9 , 158,12 , 158,12 , 134,24 , 3876,63 , 3939,85 , 320,12 , 113,7 , 113,7 , 2477,14 , 2491,35 , 2526,52 , 113,7 , 0,2 , 0,2 }, // French/France + { 37, 21, 44, 46, 59, 37, 48, 45, 43, 101, 573,7 , 109,16 , 36,5 , 296,22 , 158,12 , 158,12 , 134,24 , 3876,63 , 3939,85 , 320,12 , 113,7 , 113,7 , 2477,14 , 2491,35 , 2526,52 , 113,7 , 0,2 , 0,2 }, // French/Belgium + { 37, 38, 44, 160, 59, 37, 48, 45, 43, 101, 125,8 , 109,16 , 36,5 , 241,23 , 158,12 , 158,12 , 134,24 , 3876,63 , 3939,85 , 320,12 , 113,7 , 113,7 , 2477,14 , 2491,35 , 2526,52 , 113,7 , 0,2 , 0,2 }, // French/Canada + { 37, 125, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 109,16 , 36,5 , 41,9 , 158,12 , 158,12 , 134,24 , 3876,63 , 3939,85 , 320,12 , 113,7 , 113,7 , 2477,14 , 2491,35 , 2526,52 , 113,7 , 0,2 , 0,2 }, // French/Luxembourg + { 37, 142, 44, 160, 59, 37, 48, 45, 43, 101, 27,8 , 109,16 , 36,5 , 41,9 , 158,12 , 158,12 , 134,24 , 3876,63 , 3939,85 , 320,12 , 113,7 , 113,7 , 2477,14 , 2491,35 , 2526,52 , 113,7 , 0,2 , 0,2 }, // French/Monaco + { 37, 187, 44, 160, 59, 37, 48, 45, 43, 101, 27,8 , 109,16 , 36,5 , 41,9 , 158,12 , 158,12 , 134,24 , 3876,63 , 3939,85 , 320,12 , 113,7 , 113,7 , 2477,14 , 2491,35 , 2526,52 , 113,7 , 0,2 , 0,2 }, // French/Senegal + { 37, 206, 46, 39, 59, 37, 48, 45, 43, 101, 356,8 , 10,17 , 36,5 , 318,13 , 158,12 , 158,12 , 134,24 , 3876,63 , 3939,85 , 320,12 , 113,7 , 113,7 , 2477,14 , 2491,35 , 2526,52 , 113,7 , 0,2 , 0,2 }, // French/Switzerland + { 40, 197, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 82,17 , 36,5 , 41,9 , 158,12 , 158,12 , 820,24 , 4024,48 , 4072,87 , 320,12 , 113,7 , 113,7 , 2578,14 , 2592,28 , 2620,49 , 113,7 , 2,0 , 2,0 }, // Galician/Spain + { 41, 81, 44, 46, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 844,24 , 4159,48 , 4207,99 , 320,12 , 113,7 , 113,7 , 2669,14 , 2683,28 , 2711,62 , 113,7 , 2,0 , 2,0 }, // Georgian/Georgia + { 42, 82, 44, 46, 59, 37, 48, 45, 43, 101, 356,8 , 524,18 , 36,5 , 41,9 , 868,33 , 158,12 , 134,24 , 4306,48 , 4354,83 , 320,12 , 113,7 , 113,7 , 2773,14 , 2787,28 , 2815,60 , 113,7 , 65,5 , 62,6 }, // German/Germany + { 42, 14, 44, 46, 59, 37, 48, 45, 43, 101, 356,8 , 651,19 , 36,5 , 41,9 , 868,33 , 158,12 , 134,24 , 4437,48 , 4485,83 , 320,12 , 113,7 , 113,7 , 2773,14 , 2787,28 , 2815,60 , 113,7 , 65,5 , 62,6 }, // German/Austria + { 42, 21, 44, 46, 59, 37, 48, 45, 43, 101, 573,7 , 109,16 , 36,5 , 241,23 , 868,33 , 158,12 , 134,24 , 4568,48 , 4354,83 , 320,12 , 113,7 , 113,7 , 2773,14 , 2875,28 , 2815,60 , 113,7 , 65,5 , 62,6 }, // German/Belgium + { 42, 123, 46, 39, 59, 37, 48, 45, 43, 101, 356,8 , 524,18 , 36,5 , 41,9 , 868,33 , 158,12 , 134,24 , 4306,48 , 4354,83 , 320,12 , 113,7 , 113,7 , 2773,14 , 2787,28 , 2815,60 , 113,7 , 65,5 , 62,6 }, // German/Liechtenstein + { 42, 125, 44, 46, 59, 37, 48, 45, 43, 101, 356,8 , 524,18 , 36,5 , 41,9 , 868,33 , 158,12 , 134,24 , 4306,48 , 4354,83 , 320,12 , 113,7 , 113,7 , 2773,14 , 2787,28 , 2815,60 , 113,7 , 65,5 , 62,6 }, // German/Luxembourg + { 42, 206, 46, 39, 59, 37, 48, 45, 43, 101, 356,8 , 524,18 , 36,5 , 41,9 , 868,33 , 158,12 , 134,24 , 4306,48 , 4354,83 , 320,12 , 113,7 , 113,7 , 2773,14 , 2787,28 , 2815,60 , 113,7 , 65,5 , 62,6 }, // German/Switzerland + { 43, 85, 44, 46, 59, 37, 48, 45, 43, 101, 598,10 , 133,18 , 18,7 , 25,11 , 158,12 , 901,115 , 1016,24 , 4616,50 , 4666,115 , 320,12 , 113,7 , 113,7 , 2903,14 , 2917,28 , 2945,55 , 113,7 , 70,4 , 68,4 }, // Greek/Greece + { 43, 56, 44, 46, 59, 37, 48, 45, 43, 101, 598,10 , 133,18 , 18,7 , 25,11 , 158,12 , 901,115 , 1016,24 , 4616,50 , 4666,115 , 320,12 , 113,7 , 113,7 , 2903,14 , 2917,28 , 2945,55 , 113,7 , 70,4 , 68,4 }, // Greek/Cyprus + { 44, 86, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 82,17 , 18,7 , 25,11 , 158,12 , 158,12 , 194,27 , 3129,48 , 4781,96 , 320,12 , 113,7 , 113,7 , 297,14 , 3000,28 , 3028,98 , 113,7 , 2,0 , 2,0 }, // Greenlandic/Greenland + { 46, 100, 46, 44, 59, 37, 2790, 45, 43, 101, 670,7 , 109,16 , 331,8 , 68,12 , 158,12 , 158,12 , 194,27 , 4877,67 , 4944,87 , 320,12 , 113,7 , 113,7 , 297,14 , 3126,32 , 3158,53 , 113,7 , 74,14 , 72,14 }, // Gujarati/India + { 47, 83, 46, 44, 59, 37, 48, 45, 43, 101, 293,6 , 218,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1040,24 , 5031,48 , 5079,84 , 320,12 , 113,7 , 113,7 , 3211,14 , 3225,28 , 3253,51 , 113,7 , 0,2 , 0,2 }, // Hausa/Ghana + { 47, 156, 46, 44, 59, 37, 48, 45, 43, 101, 293,6 , 218,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1040,24 , 5031,48 , 5079,84 , 320,12 , 113,7 , 113,7 , 3211,14 , 3225,28 , 3253,51 , 113,7 , 0,2 , 0,2 }, // Hausa/Niger + { 47, 157, 46, 44, 59, 37, 48, 45, 43, 101, 293,6 , 218,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1040,24 , 5031,48 , 5079,84 , 320,12 , 113,7 , 113,7 , 3211,14 , 3225,28 , 3253,51 , 113,7 , 0,2 , 0,2 }, // Hausa/Nigeria + { 47, 201, 46, 44, 59, 37, 48, 45, 43, 101, 293,6 , 218,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1040,24 , 5031,48 , 5079,84 , 320,12 , 113,7 , 113,7 , 3211,14 , 3225,28 , 3253,51 , 113,7 , 0,2 , 0,2 }, // Hausa/Sudan + { 48, 105, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 109,16 , 36,5 , 41,9 , 1064,15 , 1064,15 , 194,27 , 5163,48 , 5211,72 , 320,12 , 113,7 , 113,7 , 3304,14 , 3304,14 , 3318,61 , 113,7 , 88,6 , 86,5 }, // Hebrew/Israel + { 49, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 677,6 , 109,16 , 18,7 , 25,11 , 158,12 , 158,12 , 194,27 , 5283,75 , 5283,75 , 320,12 , 113,7 , 113,7 , 3379,16 , 3395,32 , 3427,53 , 113,7 , 94,9 , 91,7 }, // Hindi/India + { 50, 98, 44, 160, 59, 37, 48, 45, 43, 101, 683,11 , 694,13 , 180,4 , 209,8 , 158,12 , 158,12 , 1079,24 , 5358,64 , 5422,98 , 320,12 , 113,7 , 113,7 , 3480,14 , 3494,19 , 3513,52 , 113,7 , 103,3 , 98,3 }, // Hungarian/Hungary + { 51, 99, 44, 46, 59, 37, 48, 8722, 43, 101, 626,8 , 524,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1103,24 , 5520,48 , 5568,82 , 320,12 , 113,7 , 113,7 , 3565,14 , 3579,28 , 3607,81 , 113,7 , 2,0 , 2,0 }, // Icelandic/Iceland + { 52, 101, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 82,17 , 180,4 , 209,8 , 158,12 , 158,12 , 194,27 , 5650,48 , 5698,87 , 320,12 , 113,7 , 113,7 , 297,14 , 3688,28 , 3716,43 , 113,7 , 2,0 , 2,0 }, // Indonesian/Indonesia + { 57, 104, 46, 44, 59, 37, 48, 45, 43, 101, 598,10 , 109,16 , 36,5 , 41,9 , 158,12 , 158,12 , 1127,24 , 5785,62 , 5847,107 , 320,12 , 113,7 , 113,7 , 3759,14 , 3773,37 , 3810,75 , 113,7 , 58,4 , 55,4 }, // Irish/Ireland + { 58, 106, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 109,16 , 166,5 , 171,9 , 158,12 , 1151,56 , 1207,24 , 5954,48 , 6002,94 , 320,12 , 113,7 , 3885,57 , 3942,14 , 3956,28 , 3984,57 , 113,7 , 106,2 , 101,2 }, // Italian/Italy + { 58, 206, 46, 39, 59, 37, 48, 45, 43, 101, 356,8 , 10,17 , 166,5 , 318,13 , 158,12 , 1151,56 , 1207,24 , 5954,48 , 6002,94 , 320,12 , 113,7 , 3885,57 , 3942,14 , 3956,28 , 3984,57 , 113,7 , 106,2 , 101,2 }, // Italian/Switzerland + { 59, 108, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 459,13 , 180,4 , 339,8 , 494,39 , 158,12 , 194,27 , 2860,39 , 2860,39 , 320,12 , 113,7 , 113,7 , 4041,14 , 4041,14 , 4055,28 , 113,7 , 108,2 , 103,2 }, // Japanese/Japan + { 61, 100, 46, 44, 59, 37, 48, 45, 43, 101, 677,6 , 109,16 , 331,8 , 68,12 , 158,12 , 158,12 , 194,27 , 6096,86 , 6096,86 , 320,12 , 113,7 , 113,7 , 297,14 , 4083,28 , 4111,53 , 113,7 , 110,9 , 105,7 }, // Kannada/India + { 63, 110, 44, 160, 59, 37, 48, 45, 43, 101, 356,8 , 707,22 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 6182,61 , 6243,83 , 320,12 , 113,7 , 113,7 , 297,14 , 4164,28 , 4192,54 , 113,7 , 2,0 , 2,0 }, // Kazakh/Kazakhstan + { 64, 179, 44, 46, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 6326,60 , 6386,101 , 320,12 , 113,7 , 113,7 , 297,14 , 4246,35 , 4281,84 , 113,7 , 2,0 , 2,0 }, // Kinyarwanda/Rwanda + { 65, 116, 44, 160, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 134,27 , 134,27 , 320,12 , 113,7 , 113,7 , 297,14 , 297,14 , 297,14 , 113,7 , 2,0 , 2,0 }, // Kirghiz/Kyrgyzstan + { 66, 114, 46, 44, 59, 37, 48, 45, 43, 101, 729,9 , 738,16 , 347,7 , 354,15 , 1231,39 , 1231,39 , 1231,39 , 6487,39 , 6487,39 , 320,12 , 113,7 , 113,7 , 4365,14 , 4365,14 , 4379,28 , 113,7 , 119,2 , 112,2 }, // Korean/RepublicOfKorea + { 67, 217, 46, 44, 59, 37, 48, 45, 43, 101, 99,10 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 320,12 , 134,27 , 320,12 , 113,7 , 113,7 , 297,14 , 113,7 , 297,14 , 113,7 , 2,0 , 2,0 }, // Kurdish/Turkey + { 69, 117, 46, 44, 59, 37, 48, 45, 43, 101, 388,8 , 754,21 , 180,4 , 369,20 , 158,12 , 158,12 , 194,27 , 6526,63 , 6589,75 , 320,12 , 113,7 , 113,7 , 297,14 , 4407,24 , 4431,57 , 113,7 , 2,0 , 2,0 }, // Laothian/Lao + { 71, 118, 44, 160, 59, 37, 48, 45, 43, 101, 775,6 , 781,26 , 36,5 , 41,9 , 158,12 , 158,12 , 134,24 , 6664,48 , 6712,101 , 320,12 , 4488,19 , 113,7 , 4507,14 , 4521,16 , 4537,72 , 113,7 , 2,0 , 2,0 }, // Latvian/Latvia + { 72, 49, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 6813,39 , 6852,203 , 320,12 , 113,7 , 113,7 , 297,14 , 4609,23 , 4632,98 , 113,7 , 2,0 , 2,0 }, // Lingala/DemocraticRepublicOfCongo + { 72, 50, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 6813,39 , 6852,203 , 320,12 , 113,7 , 113,7 , 297,14 , 4609,23 , 4632,98 , 113,7 , 2,0 , 2,0 }, // Lingala/PeoplesRepublicOfCongo + { 73, 124, 44, 46, 59, 37, 48, 8722, 43, 101, 99,10 , 807,26 , 36,5 , 41,9 , 158,12 , 1270,96 , 1366,24 , 7055,48 , 7103,98 , 320,12 , 113,7 , 113,7 , 4730,14 , 4744,21 , 4765,89 , 113,7 , 121,9 , 114,6 }, // Lithuanian/Lithuania + { 74, 127, 44, 46, 59, 37, 48, 45, 43, 101, 833,7 , 133,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1390,24 , 7201,63 , 7264,85 , 7349,14 , 113,7 , 113,7 , 1256,14 , 4854,34 , 4888,54 , 113,7 , 2,0 , 2,0 }, // Macedonian/Macedonia + { 76, 130, 46, 44, 59, 37, 48, 45, 43, 101, 598,10 , 840,16 , 389,4 , 25,11 , 158,12 , 158,12 , 194,27 , 7363,49 , 7412,82 , 320,12 , 113,7 , 113,7 , 297,14 , 4942,28 , 4970,43 , 113,7 , 2,0 , 2,0 }, // Malay/Malaysia + { 76, 32, 44, 46, 59, 37, 48, 45, 43, 101, 598,10 , 586,12 , 180,4 , 393,13 , 158,12 , 158,12 , 194,27 , 7363,49 , 7412,82 , 320,12 , 113,7 , 113,7 , 297,14 , 4942,28 , 4970,43 , 113,7 , 2,0 , 2,0 }, // Malay/BruneiDarussalam + { 77, 100, 46, 44, 59, 37, 48, 45, 43, 101, 565,8 , 856,18 , 18,7 , 25,11 , 158,12 , 158,12 , 1414,30 , 7494,66 , 7560,101 , 320,12 , 113,7 , 5013,17 , 5030,14 , 5044,22 , 5066,47 , 5113,9 , 2,0 , 2,0 }, // Malayalam/India + { 78, 133, 46, 44, 59, 37, 48, 45, 43, 101, 598,10 , 874,23 , 36,5 , 41,9 , 158,12 , 158,12 , 1444,24 , 7661,48 , 7709,85 , 320,12 , 113,7 , 113,7 , 5122,14 , 5136,28 , 5164,63 , 113,7 , 130,2 , 120,2 }, // Maltese/Malta + { 80, 100, 46, 44, 59, 37, 48, 45, 43, 101, 677,6 , 109,16 , 18,7 , 25,11 , 158,12 , 158,12 , 194,27 , 7794,87 , 7794,87 , 320,12 , 113,7 , 113,7 , 297,14 , 5227,32 , 5259,53 , 113,7 , 132,5 , 122,5 }, // Marathi/India + { 82, 44, 44, 160, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 7881,48 , 7929,66 , 320,12 , 113,7 , 113,7 , 297,14 , 5312,21 , 5333,43 , 113,7 , 2,0 , 2,0 }, // Mongolian/China + { 82, 143, 44, 160, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 7881,48 , 7929,66 , 320,12 , 113,7 , 113,7 , 297,14 , 5312,21 , 5333,43 , 113,7 , 2,0 , 2,0 }, // Mongolian/Mongolia + { 84, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1468,27 , 7995,56 , 8051,85 , 320,12 , 113,7 , 113,7 , 5376,14 , 5390,33 , 5423,54 , 113,7 , 2,0 , 2,0 }, // Nepali/India + { 84, 150, 46, 44, 59, 37, 2406, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1468,27 , 7995,56 , 8051,85 , 320,12 , 113,7 , 113,7 , 5376,14 , 5390,33 , 5423,54 , 113,7 , 2,0 , 2,0 }, // Nepali/Nepal + { 85, 161, 44, 160, 59, 37, 48, 45, 43, 101, 356,8 , 634,17 , 166,5 , 406,15 , 158,12 , 158,12 , 134,24 , 8136,59 , 8195,83 , 320,12 , 113,7 , 113,7 , 1995,14 , 5477,35 , 2037,51 , 113,7 , 137,9 , 127,11 }, // Norwegian/Norway + { 87, 100, 46, 44, 59, 37, 2918, 45, 43, 101, 565,8 , 897,17 , 18,7 , 25,11 , 158,12 , 158,12 , 194,27 , 8278,89 , 8278,89 , 320,12 , 113,7 , 113,7 , 297,14 , 5512,33 , 5545,54 , 113,7 , 2,0 , 2,0 }, // Oriya/India + { 88, 1, 1643, 1644, 59, 1642, 1776, 8722, 43, 101, 914,8 , 922,20 , 180,4 , 421,10 , 158,12 , 158,12 , 194,27 , 8367,31 , 8398,68 , 320,12 , 113,7 , 113,7 , 297,14 , 297,14 , 5599,49 , 113,7 , 146,4 , 138,4 }, // Pashto/Afghanistan + { 89, 102, 1643, 1644, 1563, 1642, 1776, 8722, 43, 101, 942,6 , 948,21 , 180,4 , 421,10 , 158,12 , 1495,70 , 1565,24 , 8466,74 , 8466,74 , 320,12 , 113,7 , 113,7 , 5648,14 , 5599,49 , 5599,49 , 113,7 , 150,10 , 142,10 }, // Persian/Iran + { 89, 1, 1643, 1644, 1563, 1642, 1776, 8722, 43, 101, 942,6 , 948,21 , 180,4 , 421,10 , 158,12 , 1495,70 , 1589,24 , 8540,63 , 8603,68 , 320,12 , 113,7 , 113,7 , 5648,14 , 5599,49 , 5599,49 , 113,7 , 150,10 , 142,10 }, // Persian/Afghanistan + { 90, 172, 44, 160, 59, 37, 48, 45, 43, 101, 125,8 , 10,17 , 36,5 , 41,9 , 158,12 , 1613,97 , 1710,24 , 8671,48 , 8719,99 , 320,12 , 113,7 , 113,7 , 5662,14 , 5676,34 , 5710,59 , 113,7 , 0,2 , 0,2 }, // Polish/Poland + { 91, 173, 44, 160, 59, 37, 48, 45, 43, 101, 236,8 , 969,27 , 36,5 , 431,16 , 158,12 , 158,12 , 134,24 , 8818,48 , 8866,89 , 320,12 , 113,7 , 113,7 , 5769,14 , 5783,28 , 5811,79 , 113,7 , 160,17 , 152,18 }, // Portuguese/Portugal + { 91, 30, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 969,27 , 36,5 , 447,18 , 158,12 , 158,12 , 134,24 , 8955,48 , 9003,89 , 320,12 , 113,7 , 113,7 , 5769,14 , 5783,28 , 5811,79 , 113,7 , 0,2 , 0,2 }, // Portuguese/Brazil + { 92, 100, 46, 44, 59, 37, 2662, 45, 43, 101, 996,9 , 133,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1734,27 , 9092,68 , 9092,68 , 320,12 , 113,7 , 113,7 , 5890,23 , 5913,38 , 5951,55 , 113,7 , 177,5 , 170,4 }, // Punjabi/India + { 92, 163, 46, 44, 59, 37, 2662, 45, 43, 101, 996,9 , 133,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1734,27 , 9092,68 , 9092,68 , 320,12 , 113,7 , 113,7 , 5890,23 , 5913,38 , 5951,55 , 113,7 , 177,5 , 170,4 }, // Punjabi/Pakistan + { 95, 141, 44, 46, 59, 37, 48, 45, 43, 101, 1005,10 , 10,17 , 36,5 , 41,9 , 158,12 , 158,12 , 1761,24 , 9160,60 , 9220,98 , 320,12 , 113,7 , 6006,14 , 2477,14 , 6020,16 , 6036,48 , 113,7 , 0,2 , 0,2 }, // Romanian/Moldova + { 95, 177, 44, 46, 59, 37, 48, 45, 43, 101, 1005,10 , 10,17 , 36,5 , 41,9 , 158,12 , 158,12 , 1761,24 , 9160,60 , 9220,98 , 320,12 , 113,7 , 6006,14 , 2477,14 , 6020,16 , 6036,48 , 113,7 , 0,2 , 0,2 }, // Romanian/Romania + { 96, 178, 44, 160, 59, 37, 48, 45, 43, 101, 356,8 , 1015,22 , 180,4 , 209,8 , 1785,62 , 1847,80 , 1927,24 , 9318,63 , 9381,82 , 320,12 , 113,7 , 6084,62 , 6146,14 , 6160,21 , 6181,62 , 113,7 , 0,2 , 0,2 }, // Russian/RussianFederation + { 96, 222, 44, 160, 59, 37, 48, 45, 43, 101, 356,8 , 1015,22 , 36,5 , 41,9 , 1785,62 , 1847,80 , 1927,24 , 9318,63 , 9381,82 , 320,12 , 113,7 , 6084,62 , 6146,14 , 6160,21 , 6181,62 , 113,7 , 0,2 , 0,2 }, // Russian/Ukraine + { 99, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 670,7 , 109,16 , 331,8 , 68,12 , 158,12 , 158,12 , 194,27 , 134,27 , 134,27 , 320,12 , 113,7 , 113,7 , 297,14 , 297,14 , 297,14 , 113,7 , 2,0 , 2,0 }, // Sanskrit/India + { 100, 241, 44, 46, 59, 37, 48, 45, 43, 1077, 1037,7 , 1044,20 , 166,5 , 171,9 , 158,12 , 158,12 , 1390,24 , 9463,48 , 9511,81 , 320,12 , 113,7 , 113,7 , 6243,14 , 6257,28 , 6285,52 , 113,7 , 182,8 , 174,7 }, // Serbian/SerbiaAndMontenegro + { 100, 27, 44, 46, 59, 37, 48, 45, 43, 1077, 125,8 , 1044,20 , 36,5 , 465,39 , 158,12 , 158,12 , 1390,24 , 9463,48 , 9592,83 , 320,12 , 113,7 , 113,7 , 6243,14 , 6337,28 , 6365,54 , 113,7 , 182,8 , 174,7 }, // Serbian/BosniaAndHerzegowina + { 100, 238, 44, 46, 59, 37, 48, 45, 43, 1077, 1037,7 , 1044,20 , 166,5 , 171,9 , 158,12 , 158,12 , 1390,24 , 9463,48 , 9511,81 , 320,12 , 113,7 , 113,7 , 6243,14 , 6257,28 , 6285,52 , 113,7 , 182,8 , 174,7 }, // Serbian/Yugoslavia + { 101, 241, 46, 44, 59, 37, 48, 45, 43, 101, 99,10 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1951,24 , 9675,48 , 9723,81 , 320,12 , 113,7 , 113,7 , 1811,14 , 6419,28 , 6447,54 , 113,7 , 0,2 , 0,2 }, // SerboCroatian/SerbiaAndMontenegro + { 101, 27, 46, 44, 59, 37, 48, 45, 43, 101, 99,10 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1951,24 , 9675,48 , 9723,81 , 320,12 , 113,7 , 113,7 , 1811,14 , 6419,28 , 6447,54 , 113,7 , 0,2 , 0,2 }, // SerboCroatian/BosniaAndHerzegowina + { 101, 238, 46, 44, 59, 37, 48, 45, 43, 101, 99,10 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1951,24 , 9675,48 , 9723,81 , 320,12 , 113,7 , 113,7 , 1811,14 , 6419,28 , 6447,54 , 113,7 , 0,2 , 0,2 }, // SerboCroatian/Yugoslavia + { 102, 120, 44, 160, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 9804,48 , 9852,105 , 320,12 , 113,7 , 113,7 , 297,14 , 6501,27 , 6528,61 , 113,7 , 2,0 , 2,0 }, // Sesotho/Lesotho + { 102, 195, 44, 160, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 9804,48 , 9852,105 , 320,12 , 113,7 , 113,7 , 297,14 , 6501,27 , 6528,61 , 113,7 , 2,0 , 2,0 }, // Sesotho/SouthAfrica + { 103, 195, 44, 160, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 9957,48 , 10005,117 , 320,12 , 113,7 , 113,7 , 297,14 , 6589,27 , 6616,64 , 113,7 , 2,0 , 2,0 }, // Setswana/SouthAfrica + { 106, 198, 46, 44, 59, 37, 48, 45, 43, 101, 72,10 , 1064,17 , 18,7 , 25,11 , 158,12 , 158,12 , 1975,32 , 10122,54 , 10176,92 , 320,12 , 113,7 , 113,7 , 6680,19 , 6699,30 , 6729,62 , 113,7 , 190,5 , 181,4 }, // Singhalese/SriLanka + { 107, 195, 44, 160, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 10268,48 , 10316,114 , 320,12 , 113,7 , 113,7 , 297,14 , 6791,27 , 6818,68 , 113,7 , 2,0 , 2,0 }, // Siswati/SouthAfrica + { 107, 204, 44, 160, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 10268,48 , 10316,114 , 320,12 , 113,7 , 113,7 , 297,14 , 6791,27 , 6818,68 , 113,7 , 2,0 , 2,0 }, // Siswati/Swaziland + { 108, 191, 44, 160, 59, 37, 48, 45, 43, 101, 626,8 , 524,18 , 180,4 , 209,8 , 158,12 , 158,12 , 1951,24 , 10430,48 , 10478,82 , 320,12 , 113,7 , 113,7 , 6886,14 , 6900,21 , 6921,52 , 113,7 , 2,0 , 2,0 }, // Slovak/Slovakia + { 109, 192, 44, 46, 59, 37, 48, 45, 43, 101, 382,6 , 651,19 , 180,4 , 209,8 , 158,12 , 158,12 , 1951,24 , 9675,48 , 10560,86 , 320,12 , 113,7 , 113,7 , 6973,14 , 6987,28 , 7015,52 , 113,7 , 2,0 , 2,0 }, // Slovenian/Slovenia + { 110, 194, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 53,19 , 18,7 , 25,11 , 158,12 , 158,12 , 2007,24 , 10646,48 , 10694,189 , 320,12 , 113,7 , 113,7 , 7067,14 , 7081,28 , 7109,47 , 113,7 , 195,2 , 185,2 }, // Somali/Somalia + { 110, 59, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 53,19 , 18,7 , 25,11 , 158,12 , 158,12 , 2007,24 , 10646,48 , 10694,189 , 320,12 , 113,7 , 113,7 , 7067,14 , 7081,28 , 7109,47 , 113,7 , 195,2 , 185,2 }, // Somali/Djibouti + { 110, 69, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 53,19 , 18,7 , 25,11 , 158,12 , 158,12 , 2007,24 , 10646,48 , 10694,189 , 320,12 , 113,7 , 113,7 , 7067,14 , 7081,28 , 7109,47 , 113,7 , 195,2 , 185,2 }, // Somali/Ethiopia + { 110, 111, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 53,19 , 18,7 , 25,11 , 158,12 , 158,12 , 2007,24 , 10646,48 , 10694,189 , 320,12 , 113,7 , 113,7 , 7067,14 , 7081,28 , 7109,47 , 113,7 , 195,2 , 185,2 }, // Somali/Kenya + { 111, 197, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 427,26 , 36,5 , 68,12 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Spain + { 111, 10, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 427,26 , 36,5 , 504,13 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Argentina + { 111, 26, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 427,26 , 36,5 , 68,12 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Bolivia + { 111, 43, 44, 46, 59, 37, 48, 45, 43, 101, 565,8 , 427,26 , 180,4 , 41,9 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Chile + { 111, 47, 44, 46, 59, 37, 48, 45, 43, 101, 573,7 , 427,26 , 180,4 , 41,9 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Colombia + { 111, 52, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 427,26 , 36,5 , 68,12 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/CostaRica + { 111, 61, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 427,26 , 36,5 , 68,12 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/DominicanRepublic + { 111, 63, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 427,26 , 180,4 , 41,9 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Ecuador + { 111, 65, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 427,26 , 36,5 , 68,12 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/ElSalvador + { 111, 90, 46, 44, 59, 37, 48, 45, 43, 101, 573,7 , 427,26 , 36,5 , 68,12 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Guatemala + { 111, 96, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 1081,27 , 36,5 , 68,12 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Honduras + { 111, 139, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 427,26 , 36,5 , 68,12 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Mexico + { 111, 155, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 427,26 , 36,5 , 68,12 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Nicaragua + { 111, 166, 46, 44, 59, 37, 48, 45, 43, 101, 202,8 , 427,26 , 36,5 , 68,12 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Panama + { 111, 168, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 427,26 , 36,5 , 68,12 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Paraguay + { 111, 169, 46, 44, 59, 37, 48, 45, 43, 101, 573,7 , 427,26 , 36,5 , 517,13 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Peru + { 111, 174, 46, 44, 59, 37, 48, 45, 43, 101, 202,8 , 427,26 , 36,5 , 68,12 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/PuertoRico + { 111, 225, 46, 44, 59, 37, 48, 45, 43, 101, 580,6 , 427,26 , 18,7 , 25,11 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/UnitedStates + { 111, 227, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 427,26 , 36,5 , 68,12 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Uruguay + { 111, 231, 44, 46, 59, 37, 48, 45, 43, 101, 27,8 , 427,26 , 36,5 , 68,12 , 158,12 , 158,12 , 2031,24 , 10883,48 , 10931,89 , 320,12 , 113,7 , 113,7 , 2477,14 , 7156,28 , 7184,53 , 113,7 , 58,4 , 55,4 }, // Spanish/Venezuela + { 113, 111, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 11020,48 , 11068,84 , 320,12 , 113,7 , 113,7 , 297,14 , 7237,28 , 7265,60 , 113,7 , 2,0 , 2,0 }, // Swahili/Kenya + { 113, 210, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 11020,48 , 11068,84 , 320,12 , 113,7 , 113,7 , 297,14 , 7237,28 , 7265,60 , 113,7 , 2,0 , 2,0 }, // Swahili/Tanzania + { 114, 205, 44, 160, 59, 37, 48, 8722, 43, 101, 99,10 , 1108,22 , 166,5 , 406,15 , 158,12 , 158,12 , 134,24 , 3129,48 , 11152,86 , 320,12 , 113,7 , 113,7 , 1995,14 , 7325,29 , 7354,50 , 113,7 , 197,2 , 187,2 }, // Swedish/Sweden + { 114, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 99,10 , 1108,22 , 166,5 , 406,15 , 158,12 , 158,12 , 134,24 , 3129,48 , 11152,86 , 320,12 , 113,7 , 113,7 , 1995,14 , 7325,29 , 7354,50 , 113,7 , 197,2 , 187,2 }, // Swedish/Finland + { 116, 209, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 11238,48 , 11286,71 , 320,12 , 113,7 , 113,7 , 297,14 , 7404,28 , 7432,55 , 113,7 , 2,0 , 2,0 }, // Tajik/Tajikistan + { 117, 100, 46, 44, 59, 37, 48, 45, 43, 101, 677,6 , 109,16 , 18,7 , 25,11 , 158,12 , 158,12 , 194,27 , 11357,58 , 11415,86 , 320,12 , 113,7 , 113,7 , 297,14 , 7487,20 , 7507,49 , 113,7 , 199,4 , 189,4 }, // Tamil/India + { 118, 178, 44, 160, 59, 37, 48, 45, 43, 101, 1005,10 , 1130,11 , 180,4 , 25,11 , 158,12 , 158,12 , 194,27 , 134,27 , 134,27 , 320,12 , 113,7 , 113,7 , 297,14 , 297,14 , 297,14 , 113,7 , 2,0 , 2,0 }, // Tatar/RussianFederation + { 119, 100, 46, 44, 59, 37, 3174, 45, 43, 101, 565,8 , 109,16 , 18,7 , 25,11 , 158,12 , 158,12 , 2055,30 , 11501,86 , 11501,86 , 320,12 , 113,7 , 113,7 , 7556,18 , 7574,32 , 7606,60 , 113,7 , 203,10 , 193,8 }, // Telugu/India + { 120, 211, 46, 44, 59, 37, 48, 45, 43, 101, 388,8 , 1141,21 , 180,4 , 530,26 , 158,12 , 158,12 , 2085,63 , 11587,63 , 11650,98 , 320,12 , 113,7 , 113,7 , 7666,14 , 7680,23 , 7703,68 , 7771,9 , 213,10 , 201,10 }, // Thai/Thailand + { 122, 67, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 1162,25 , 18,7 , 25,11 , 158,12 , 158,12 , 245,24 , 11748,46 , 11794,54 , 320,12 , 113,7 , 113,7 , 7780,14 , 7794,28 , 7822,29 , 113,7 , 223,7 , 211,7 }, // Tigrinya/Eritrea + { 122, 69, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 1187,25 , 18,7 , 25,11 , 158,12 , 158,12 , 245,24 , 893,46 , 939,62 , 320,12 , 113,7 , 113,7 , 7780,14 , 7851,28 , 7879,29 , 113,7 , 223,7 , 211,7 }, // Tigrinya/Ethiopia + { 123, 214, 46, 44, 59, 37, 48, 45, 43, 101, 1212,10 , 109,16 , 36,5 , 41,9 , 158,12 , 158,12 , 2148,24 , 11848,51 , 11899,87 , 320,12 , 113,7 , 113,7 , 7908,14 , 7922,29 , 7951,60 , 113,7 , 2,0 , 2,0 }, // Tonga/Tonga + { 124, 195, 44, 160, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 11986,48 , 12034,122 , 320,12 , 113,7 , 113,7 , 297,14 , 8011,27 , 8038,72 , 113,7 , 2,0 , 2,0 }, // Tsonga/SouthAfrica + { 125, 217, 44, 46, 59, 37, 48, 45, 43, 101, 1005,10 , 1222,17 , 36,5 , 41,9 , 158,12 , 158,12 , 2172,24 , 12156,48 , 12204,75 , 320,12 , 113,7 , 113,7 , 8110,14 , 8124,28 , 8152,54 , 113,7 , 0,2 , 0,2 }, // Turkish/Turkey + { 128, 44, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 134,27 , 134,27 , 320,12 , 113,7 , 113,7 , 297,14 , 297,14 , 297,14 , 113,7 , 2,0 , 2,0 }, // Uigur/China + { 129, 222, 44, 160, 59, 37, 48, 45, 43, 101, 356,8 , 1239,22 , 36,5 , 41,9 , 2196,48 , 2244,95 , 2339,24 , 12279,67 , 12346,87 , 320,12 , 113,7 , 113,7 , 8206,14 , 8220,21 , 8241,56 , 113,7 , 230,2 , 218,2 }, // Ukrainian/Ukraine + { 130, 100, 46, 44, 59, 37, 48, 45, 43, 1602, 293,6 , 608,18 , 18,7 , 25,11 , 158,12 , 158,12 , 1589,24 , 320,12 , 12433,67 , 320,12 , 113,7 , 113,7 , 297,14 , 113,7 , 8297,36 , 8333,14 , 2,0 , 2,0 }, // Urdu/India + { 130, 163, 46, 44, 59, 37, 48, 45, 43, 1602, 293,6 , 608,18 , 18,7 , 25,11 , 158,12 , 158,12 , 1589,24 , 320,12 , 12433,67 , 320,12 , 113,7 , 113,7 , 297,14 , 113,7 , 8297,36 , 8333,14 , 2,0 , 2,0 }, // Urdu/Pakistan + { 131, 228, 44, 160, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1927,24 , 11238,48 , 12500,115 , 320,12 , 113,7 , 113,7 , 8347,14 , 8361,28 , 8389,53 , 113,7 , 2,0 , 2,0 }, // Uzbek/Uzbekistan + { 131, 1, 44, 160, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 1927,24 , 11238,48 , 12500,115 , 320,12 , 113,7 , 113,7 , 8347,14 , 8361,28 , 8389,53 , 113,7 , 2,0 , 2,0 }, // Uzbek/Afghanistan + { 132, 232, 44, 46, 59, 37, 48, 45, 43, 101, 598,10 , 1261,31 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 12615,75 , 12690,130 , 320,12 , 113,7 , 113,7 , 297,14 , 8442,33 , 8475,55 , 113,7 , 232,2 , 220,2 }, // Vietnamese/VietNam + { 134, 224, 46, 44, 59, 37, 48, 45, 43, 101, 598,10 , 133,18 , 18,7 , 25,11 , 2363,25 , 2388,22 , 2410,24 , 12820,62 , 12882,86 , 320,12 , 8530,10 , 113,7 , 8540,14 , 8554,30 , 8584,77 , 113,7 , 2,0 , 2,0 }, // Welsh/UnitedKingdom + { 135, 187, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 134,27 , 134,27 , 320,12 , 113,7 , 113,7 , 297,14 , 297,14 , 297,14 , 113,7 , 2,0 , 2,0 }, // Wolof/Senegal + { 136, 195, 44, 160, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 12968,48 , 13016,91 , 320,12 , 113,7 , 113,7 , 297,14 , 8661,28 , 8689,61 , 113,7 , 2,0 , 2,0 }, // Xhosa/SouthAfrica + { 138, 157, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 13107,73 , 13180,121 , 320,12 , 113,7 , 113,7 , 297,14 , 8750,50 , 8800,80 , 113,7 , 234,5 , 222,5 }, // Yoruba/Nigeria + { 140, 195, 44, 160, 59, 37, 48, 45, 43, 101, 99,10 , 82,17 , 18,7 , 25,11 , 158,12 , 2434,104 , 134,24 , 13301,48 , 13349,90 , 320,12 , 113,7 , 113,7 , 8880,14 , 8894,28 , 8922,68 , 113,7 , 2,0 , 2,0 }, // Zulu/SouthAfrica + { 141, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 356,8 , 634,17 , 166,5 , 406,15 , 158,12 , 158,12 , 134,24 , 3547,48 , 8195,83 , 320,12 , 8990,13 , 113,7 , 1995,14 , 9003,22 , 9025,51 , 113,7 , 137,9 , 127,11 }, // Nynorsk/Norway + { 142, 27, 44, 46, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 13439,48 , 13487,83 , 320,12 , 113,7 , 113,7 , 297,14 , 9076,28 , 9104,58 , 113,7 , 2,0 , 2,0 }, // Bosnian/BosniaAndHerzegowina + { 143, 131, 46, 44, 1548, 37, 1632, 45, 43, 101, 677,6 , 109,16 , 331,8 , 68,12 , 158,12 , 158,12 , 194,27 , 134,27 , 134,27 , 320,12 , 113,7 , 113,7 , 297,14 , 297,14 , 297,14 , 113,7 , 2,0 , 2,0 }, // Divehi/Maldives + { 144, 224, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 82,17 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 13570,102 , 13672,140 , 320,12 , 113,7 , 113,7 , 297,14 , 9162,30 , 9192,57 , 113,7 , 58,4 , 55,4 }, // Manx/UnitedKingdom + { 145, 224, 46, 44, 59, 37, 48, 45, 43, 101, 598,10 , 109,16 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 13812,46 , 13858,124 , 320,12 , 113,7 , 113,7 , 297,14 , 9249,28 , 9277,60 , 113,7 , 58,4 , 55,4 }, // Cornish/UnitedKingdom + { 146, 83, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 13982,48 , 14030,192 , 320,12 , 113,7 , 113,7 , 9337,14 , 9351,28 , 9379,49 , 113,7 , 2,0 , 2,0 }, // Akan/Ghana + { 147, 100, 46, 44, 59, 37, 48, 45, 43, 101, 677,6 , 109,16 , 18,7 , 25,11 , 158,12 , 158,12 , 194,27 , 14222,85 , 7794,87 , 320,12 , 113,7 , 113,7 , 297,14 , 5227,32 , 9428,55 , 113,7 , 132,5 , 122,5 }, // Konkani/India + { 148, 83, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 14307,48 , 14355,94 , 320,12 , 113,7 , 113,7 , 297,14 , 9483,26 , 9509,34 , 113,7 , 2,0 , 2,0 }, // Ga/Ghana + { 149, 157, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 14449,48 , 14497,86 , 320,12 , 113,7 , 113,7 , 297,14 , 9543,29 , 9572,57 , 113,7 , 2,0 , 2,0 }, // Igbo/Nigeria + { 150, 111, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 14583,189 , 14583,189 , 320,12 , 113,7 , 113,7 , 297,14 , 9629,28 , 9657,59 , 113,7 , 2,0 , 2,0 }, // Kamba/Kenya + { 151, 207, 46, 44, 59, 37, 48, 45, 43, 101, 598,10 , 1292,13 , 389,4 , 25,11 , 158,12 , 158,12 , 194,27 , 14772,65 , 14837,65 , 320,12 , 113,7 , 113,7 , 297,14 , 297,14 , 297,14 , 113,7 , 2,0 , 2,0 }, // Syriac/SyrianArabRepublic + { 152, 67, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 1305,24 , 18,7 , 25,11 , 158,12 , 158,12 , 2538,24 , 14902,47 , 14949,77 , 320,12 , 113,7 , 113,7 , 9716,14 , 9730,26 , 9756,43 , 113,7 , 2,0 , 2,0 }, // Blin/Eritrea + { 153, 67, 46, 4808, 59, 37, 48, 45, 43, 101, 27,8 , 1329,25 , 18,7 , 25,11 , 158,12 , 158,12 , 2562,24 , 15026,48 , 15074,49 , 320,12 , 113,7 , 113,7 , 9799,14 , 9813,28 , 9841,29 , 113,7 , 2,0 , 2,0 }, // Geez/Eritrea + { 153, 69, 46, 4808, 59, 37, 48, 45, 43, 101, 27,8 , 1329,25 , 18,7 , 25,11 , 158,12 , 158,12 , 2562,24 , 15026,48 , 15074,49 , 320,12 , 113,7 , 113,7 , 9799,14 , 9813,28 , 9841,29 , 113,7 , 2,0 , 2,0 }, // Geez/Ethiopia + { 154, 53, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 15123,48 , 15171,124 , 320,12 , 113,7 , 113,7 , 297,14 , 9870,28 , 9898,54 , 113,7 , 2,0 , 2,0 }, // Koro/IvoryCoast + { 155, 69, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 53,19 , 18,7 , 25,11 , 158,12 , 158,12 , 134,24 , 0,48 , 48,86 , 320,12 , 113,7 , 113,7 , 9952,14 , 9966,28 , 9994,51 , 113,7 , 2,0 , 2,0 }, // Sidamo/Ethiopia + { 156, 157, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 15295,59 , 15354,129 , 320,12 , 113,7 , 113,7 , 297,14 , 10045,35 , 10080,87 , 113,7 , 2,0 , 2,0 }, // Atsam/Nigeria + { 157, 67, 46, 44, 59, 37, 48, 45, 43, 101, 27,8 , 1354,23 , 18,7 , 25,11 , 158,12 , 158,12 , 245,24 , 893,46 , 939,62 , 320,12 , 113,7 , 113,7 , 10167,14 , 10181,27 , 10208,41 , 113,7 , 2,0 , 2,0 }, // Tigre/Eritrea + { 158, 157, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 15483,57 , 15540,178 , 320,12 , 113,7 , 113,7 , 297,14 , 10249,28 , 10277,44 , 113,7 , 2,0 , 2,0 }, // Jju/Nigeria + { 159, 106, 46, 44, 59, 37, 48, 45, 43, 101, 573,7 , 1377,27 , 36,5 , 41,9 , 158,12 , 158,12 , 2586,24 , 15718,48 , 15766,77 , 320,12 , 113,7 , 113,7 , 2477,14 , 10321,28 , 10349,50 , 113,7 , 2,0 , 2,0 }, // Friulian/Italy + { 160, 195, 44, 160, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 15843,48 , 15891,111 , 320,12 , 113,7 , 113,7 , 297,14 , 10399,27 , 10426,70 , 113,7 , 2,0 , 2,0 }, // Venda/SouthAfrica + { 161, 83, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 2610,24 , 16002,48 , 16050,87 , 320,12 , 113,7 , 113,7 , 10496,14 , 10510,32 , 10542,44 , 113,7 , 2,0 , 2,0 }, // Ewe/Ghana + { 161, 212, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 2610,24 , 16002,48 , 16050,87 , 320,12 , 113,7 , 113,7 , 10496,14 , 10510,32 , 10542,44 , 113,7 , 2,0 , 2,0 }, // Ewe/Togo + { 163, 225, 46, 44, 59, 37, 48, 45, 43, 101, 293,6 , 10,17 , 18,7 , 25,11 , 158,12 , 158,12 , 194,27 , 16137,59 , 16196,95 , 320,12 , 113,7 , 113,7 , 297,14 , 10586,21 , 10607,57 , 113,7 , 2,0 , 2,0 }, // Hawaiian/UnitedStates + { 164, 157, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 16291,48 , 16339,153 , 320,12 , 113,7 , 113,7 , 297,14 , 10664,28 , 10692,42 , 113,7 , 2,0 , 2,0 }, // Tyap/Nigeria + { 165, 129, 46, 44, 59, 37, 48, 45, 43, 101, 236,8 , 244,18 , 36,5 , 41,9 , 158,12 , 158,12 , 194,27 , 16492,48 , 16540,91 , 320,12 , 113,7 , 113,7 , 297,14 , 10734,28 , 10762,67 , 113,7 , 2,0 , 2,0 }, // Chewa/Malawi + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 } // trailing 0s +}; + +static const ushort date_format_data[] = { +0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, +0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, +0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d, +0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2f, 0x4d, 0x4d, 0x2f, +0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, +0x79, 0x79, 0x79, 0x2d, 0x4d, 0x4d, 0x2d, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, +0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2d, 0x4d, 0x4d, 0x2d, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, +0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x1363, 0x20, 0x64, 0x64, 0x20, +0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x1240, 0x1295, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x47, 0x64, 0x200f, 0x2f, 0x4d, 0x200f, 0x2f, +0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x60c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x60c, 0x20, 0x79, 0x79, +0x79, 0x79, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x2f, 0x79, 0x79, 0x64, 0x2d, 0x4d, 0x2d, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, +0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2f, 0x4d, +0x4d, 0x2f, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, +0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x27, 0x65, 0x6b, 0x6f, 0x27, 0x20, 0x4d, 0x4d, +0x4d, 0x4d, 0x27, 0x72, 0x65, 0x6e, 0x27, 0x20, 0x64, 0x64, 0x27, 0x61, 0x27, 0x64, 0x2f, 0x4d, 0x2f, 0x79, 0x79, 0xf66, +0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf63, 0xf7c, 0xf0b, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0xf5f, 0xfb3, 0xf0b, 0x20, 0x4d, 0x4d, 0x20, +0xf5a, 0xf7a, 0xf66, 0xf0b, 0x20, 0x64, 0x64, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf63, 0xf7c, 0xf0b, 0x79, 0x79, 0x79, 0x79, 0x20, +0xf5f, 0xfb3, 0xf0b, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0xf5a, 0xf7a, 0xf66, 0xf0b, 0x20, 0x64, 0x64, 0x64, 0x64, 0x2e, 0x4d, +0x4d, 0x2e, 0x79, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2c, 0x20, 0x64, 0x64, +0x64, 0x64, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x64, 0x2f, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, +0x20, 0x1790, 0x17d2, 0x1784, 0x17c3, 0x20, 0x64, 0x20, 0x1781, 0x17c2, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x1786, 0x17d2, 0x1793, 0x17b6, +0x17c6, 0x20, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x4d, +0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2d, 0x4d, 0x2d, 0x64, 0x79, +0x79, 0x79, 0x79, 0x5e74, 0x4d, 0x6708, 0x64, 0x65e5, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x5e74, 0x4d, 0x6708, 0x64, 0x65e5, 0x79, +0x79, 0x79, 0x79, 0x5e74, 0x4d, 0x4d, 0x6708, 0x64, 0x64, 0x65e5, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, +0x79, 0x79, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, +0x79, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, +0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x27, 0x64, 0x65, 0x6e, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, +0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2d, 0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, +0x4d, 0x2f, 0x64, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, +0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, +0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, +0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x2e, +0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2d, 0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x64, 0x2d, 0x4d, +0x2d, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x4d, 0x4d, 0x2e, 0x64, 0x64, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, +0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, +0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x436, 0x27, 0x2e, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x64, 0x2e, 0x79, 0x79, +0x79, 0x79, 0xb144, 0x20, 0x4d, 0xc6d4, 0x20, 0x64, 0xc77c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0xe97, 0xeb5, +0x20, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x47, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x64, 0x2e, +0x4d, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x27, 0x67, 0x61, 0x64, 0x61, 0x27, 0x20, +0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x6d, 0x27, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, +0x4d, 0x20, 0x64, 0x20, 0x27, 0x64, 0x27, 0x2e, 0x2c, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, +0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, +0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, +0x64, 0x20, 0x27, 0x74, 0x61, 0x27, 0x2019, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x4d, 0x4d, 0x4d, +0x4d, 0x20, 0x64, 0x2c, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2f, 0x4d, +0x2f, 0x64, 0x64, 0x64, 0x64, 0x64, 0x20, 0x62f, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x62f, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, +0x20, 0x64, 0x79, 0x79, 0x2f, 0x4d, 0x2f, 0x64, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, +0x79, 0x79, 0x79, 0x79, 0x20, 0x47, 0x47, 0x47, 0x47, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x64, 0x65, +0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2f, 0x4d, +0x4d, 0x2f, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, +0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x433, 0x27, 0x2e, 0x64, 0x2e, 0x4d, +0x2e, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, +0x79, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, +0x64, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x64, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, +0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x27, 0x64, 0x65, 0x6e, 0x27, 0x20, 0x64, +0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, +0x79, 0x64, 0x64, 0x64, 0x64, 0xe17, 0xe35, 0xe48, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x47, 0x20, 0x79, 0x79, +0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x1361, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x1218, 0x12d3, 0x120d, 0x1272, +0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x47, 0x64, 0x64, 0x64, 0x64, 0x1363, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, +0x20, 0x1218, 0x12d3, 0x120d, 0x1272, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x47, 0x64, 0x64, 0x2d, 0x4d, 0x4d, 0x2d, 0x79, 0x79, +0x79, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, +0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x440, 0x27, +0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x6e, 0x67, 0xe0, 0x79, 0x27, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, +0x4d, 0x20, 0x27, 0x6e, 0x103, 0x6d, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, +0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x1361, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x130d, +0x122d, 0x130b, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x47, 0x64, 0x64, 0x64, 0x64, 0x1365, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, +0x4d, 0x4d, 0x20, 0x1218, 0x12d3, 0x120d, 0x1275, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x47, 0x64, 0x64, 0x64, 0x64, 0x1361, 0x20, +0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x12ee, 0x121d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x47, 0x64, 0x64, 0x64, +0x64, 0x20, 0x64, 0x20, 0x27, 0x64, 0x69, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x61, 0x6c, 0x27, 0x20, +0x79, 0x79, 0x79, 0x79 +}; + +static const ushort time_format_data[] = { +0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x68, 0x3a, +0x6d, 0x6d, 0x20, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x48, 0x48, 0x3a, 0x6d, +0x6d, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x68, 0x2e, 0x6d, 0x6d, 0x2e, 0x41, 0x50, 0x68, 0x2e, 0x6d, +0x6d, 0x2e, 0x73, 0x73, 0x2e, 0x41, 0x50, 0x20, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, +0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x68, 0x2e, 0x6d, 0x6d, 0x2e, 0x20, 0x41, 0x50, 0x68, +0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0xf46, 0xf74, 0xf0b, 0xf5a, 0xf7c, 0xf51, 0xf0b, 0x20, 0x68, 0x20, +0xf66, 0xf90, 0xf62, 0xf0b, 0xf58, 0xf0b, 0x20, 0x6d, 0x6d, 0x20, 0x41, 0x50, 0xf46, 0xf74, 0xf0b, 0xf5a, 0xf7c, 0xf51, 0xf0b, 0x20, +0x68, 0x20, 0xf66, 0xf90, 0xf62, 0xf0b, 0xf58, 0xf0b, 0x20, 0x6d, 0x6d, 0x20, 0xf66, 0xf90, 0xf62, 0xf0b, 0xf46, 0xf71, 0xf0b, 0x20, +0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, +0x48, 0x3a, 0x6d, 0x6d, 0x48, 0x20, 0x1798, 0x17c9, 0x17c4, 0x1784, 0x20, 0x6d, 0x20, 0x1793, 0x17b6, 0x1791, 0x17b8, 0x20, 0x73, 0x73, +0x20, 0x179c, 0x17b7, 0x1793, 0x17b6, 0x1791, 0x17b8, 0x200b, 0x20, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x68, +0x3a, 0x6d, 0x6d, 0x41, 0x50, 0x68, 0x68, 0x65f6, 0x6d, 0x6d, 0x5206, 0x73, 0x73, 0x79d2, 0x41, 0x50, 0x68, 0x68, 0x3a, 0x6d, +0x6d, 0x48, 0x48, 0x20, 0x27, 0x68, 0x27, 0x20, 0x6d, 0x6d, 0x20, 0x27, 0x6d, 0x69, 0x6e, 0x27, 0x20, 0x73, 0x73, 0x20, +0x27, 0x73, 0x27, 0x20, 0x41, 0x50, 0x20, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 0x41, 0x50, 0x20, 0x68, 0x68, 0x3a, 0x6d, 0x6d, +0x3a, 0x73, 0x73, 0x20, 0x48, 0x2e, 0x6d, 0x6d, 0x48, 0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x48, 0x20, 0x27, 0x68, +0x27, 0x20, 0x6d, 0x6d, 0x20, 0x27, 0x6d, 0x69, 0x6e, 0x27, 0x20, 0x73, 0x73, 0x20, 0x27, 0x73, 0x27, 0x20, 0x48, 0x48, +0x2e, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x27, 0x68, 0x27, 0x20, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 0x20, 0x41, 0x50, 0x48, +0x6642, 0x6d, 0x6d, 0x5206, 0x73, 0x73, 0x79d2, 0x41, 0x50, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x41, 0x50, 0x20, 0x68, 0x68, 0xc2dc, +0x20, 0x6d, 0x6d, 0xbd84, 0x20, 0x73, 0x73, 0xcd08, 0x20, 0x48, 0xec2, 0xea1, 0xe87, 0x20, 0x6d, 0xe99, 0xeb2, 0xe97, 0xeb5, 0x20, +0x73, 0x73, 0x20, 0xea7, 0xeb4, 0xe99, 0xeb2, 0xe97, 0xeb5, 0x68, 0x3a, 0x6d, 0x6d, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, +0x20, 0x41, 0x50, 0x41, 0x50, 0x20, 0x27, 0x6b, 0x6c, 0x27, 0x2e, 0x20, 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, +0x20, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x28, 0x29, 0x48, 0x48, 0x27, 0x48, 0x27, 0x6d, 0x6d, 0x27, 0x6d, +0x27, 0x73, 0x73, 0x27, 0x73, 0x27, 0x20, 0x48, 0x48, 0x27, 0x68, 0x27, 0x6d, 0x6d, 0x27, 0x6d, 0x69, 0x6e, 0x27, 0x73, +0x73, 0x27, 0x73, 0x27, 0x20, 0x48, 0x48, 0x20, 0x27, 0x447, 0x430, 0x441, 0x43e, 0x432, 0x430, 0x27, 0x2c, 0x20, 0x6d, 0x6d, +0x20, 0x27, 0x43c, 0x438, 0x43d, 0x443, 0x442, 0x430, 0x27, 0x2c, 0x20, 0x73, 0x73, 0x20, 0x27, 0x441, 0x435, 0x43a, 0x443, 0x43d, +0x434, 0x438, 0x27, 0x20, 0x48, 0x48, 0x27, 0x68, 0x27, 0x27, 0x27, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x48, 0x48, 0x27, +0x48, 0x27, 0x6d, 0x6d, 0x27, 0x27, 0x73, 0x73, 0x22, 0x20, 0x48, 0x20, 0xe19, 0xe32, 0xe2c, 0xe34, 0xe01, 0xe32, 0x20, 0x6d, +0x20, 0xe19, 0xe32, 0xe17, 0xe35, 0x20, 0x73, 0x73, 0x20, 0xe27, 0xe34, 0xe19, 0xe32, 0xe17, 0xe35, 0x20 +}; + +static const ushort months_data[] = { +0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, +0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x63, 0x74, 0x3b, +0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x79, 0x3b, 0x46, 0x65, 0x62, 0x72, +0x75, 0x61, 0x72, 0x79, 0x3b, 0x4d, 0x61, 0x72, 0x63, 0x68, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, +0x3b, 0x4a, 0x75, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6c, 0x79, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, +0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x63, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, +0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x31, 0x3b, 0x32, 0x3b, 0x33, 0x3b, +0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x38, 0x3b, 0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, +0x3b, 0x41, 0x6d, 0x61, 0x3b, 0x47, 0x75, 0x72, 0x3b, 0x42, 0x69, 0x74, 0x3b, 0x45, 0x6c, 0x62, 0x3b, 0x43, 0x61, 0x6d, +0x3b, 0x57, 0x61, 0x78, 0x3b, 0x41, 0x64, 0x6f, 0x3b, 0x48, 0x61, 0x67, 0x3b, 0x46, 0x75, 0x6c, 0x3b, 0x4f, 0x6e, 0x6b, +0x3b, 0x53, 0x61, 0x64, 0x3b, 0x4d, 0x75, 0x64, 0x3b, 0x41, 0x6d, 0x61, 0x6a, 0x6a, 0x69, 0x69, 0x3b, 0x47, 0x75, 0x72, +0x61, 0x61, 0x6e, 0x64, 0x68, 0x61, 0x6c, 0x61, 0x3b, 0x42, 0x69, 0x74, 0x6f, 0x6f, 0x74, 0x65, 0x65, 0x73, 0x73, 0x61, +0x3b, 0x45, 0x6c, 0x62, 0x61, 0x3b, 0x43, 0x61, 0x61, 0x6d, 0x73, 0x61, 0x3b, 0x57, 0x61, 0x78, 0x61, 0x62, 0x61, 0x6a, +0x6a, 0x69, 0x69, 0x3b, 0x41, 0x64, 0x6f, 0x6f, 0x6c, 0x65, 0x65, 0x73, 0x73, 0x61, 0x3b, 0x48, 0x61, 0x67, 0x61, 0x79, +0x79, 0x61, 0x3b, 0x46, 0x75, 0x75, 0x6c, 0x62, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6e, 0x6b, 0x6f, 0x6c, 0x6f, 0x6c, 0x65, +0x65, 0x73, 0x73, 0x61, 0x3b, 0x53, 0x61, 0x64, 0x61, 0x61, 0x73, 0x61, 0x3b, 0x4d, 0x75, 0x64, 0x64, 0x65, 0x65, 0x3b, +0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x51, 0x75, 0x6e, 0x3b, 0x4e, 0x61, 0x68, 0x3b, +0x43, 0x69, 0x67, 0x3b, 0x41, 0x67, 0x64, 0x3b, 0x43, 0x61, 0x78, 0x3b, 0x51, 0x61, 0x73, 0x3b, 0x51, 0x61, 0x64, 0x3b, +0x4c, 0x65, 0x71, 0x3b, 0x57, 0x61, 0x79, 0x3b, 0x44, 0x69, 0x74, 0x3b, 0x58, 0x69, 0x6d, 0x3b, 0x4b, 0x61, 0x78, 0x3b, +0x51, 0x75, 0x6e, 0x78, 0x61, 0x20, 0x47, 0x61, 0x72, 0x61, 0x62, 0x6c, 0x75, 0x3b, 0x4e, 0x61, 0x68, 0x61, 0x72, 0x73, +0x69, 0x20, 0x4b, 0x75, 0x64, 0x6f, 0x3b, 0x43, 0x69, 0x67, 0x67, 0x69, 0x6c, 0x74, 0x61, 0x20, 0x4b, 0x75, 0x64, 0x6f, +0x3b, 0x41, 0x67, 0x64, 0x61, 0x20, 0x42, 0x61, 0x78, 0x69, 0x73, 0x73, 0x6f, 0x3b, 0x43, 0x61, 0x78, 0x61, 0x68, 0x20, +0x41, 0x6c, 0x73, 0x61, 0x3b, 0x51, 0x61, 0x73, 0x61, 0x20, 0x44, 0x69, 0x72, 0x72, 0x69, 0x3b, 0x51, 0x61, 0x64, 0x6f, +0x20, 0x44, 0x69, 0x72, 0x72, 0x69, 0x3b, 0x4c, 0x65, 0x71, 0x65, 0x65, 0x6e, 0x69, 0x3b, 0x57, 0x61, 0x79, 0x73, 0x75, +0x3b, 0x44, 0x69, 0x74, 0x65, 0x6c, 0x69, 0x3b, 0x58, 0x69, 0x6d, 0x6f, 0x6c, 0x69, 0x3b, 0x4b, 0x61, 0x78, 0x78, 0x61, +0x20, 0x47, 0x61, 0x72, 0x61, 0x62, 0x6c, 0x75, 0x3b, 0x51, 0x75, 0x6e, 0x78, 0x61, 0x20, 0x47, 0x61, 0x72, 0x61, 0x62, +0x6c, 0x75, 0x3b, 0x4b, 0x75, 0x64, 0x6f, 0x3b, 0x43, 0x69, 0x67, 0x67, 0x69, 0x6c, 0x74, 0x61, 0x20, 0x4b, 0x75, 0x64, +0x6f, 0x3b, 0x41, 0x67, 0x64, 0x61, 0x20, 0x42, 0x61, 0x78, 0x69, 0x73, 0x3b, 0x43, 0x61, 0x78, 0x61, 0x68, 0x20, 0x41, +0x6c, 0x73, 0x61, 0x3b, 0x51, 0x61, 0x73, 0x61, 0x20, 0x44, 0x69, 0x72, 0x72, 0x69, 0x3b, 0x51, 0x61, 0x64, 0x6f, 0x20, +0x44, 0x69, 0x72, 0x72, 0x69, 0x3b, 0x4c, 0x69, 0x69, 0x71, 0x65, 0x6e, 0x3b, 0x57, 0x61, 0x79, 0x73, 0x75, 0x3b, 0x44, +0x69, 0x74, 0x65, 0x6c, 0x69, 0x3b, 0x58, 0x69, 0x6d, 0x6f, 0x6c, 0x69, 0x3b, 0x4b, 0x61, 0x78, 0x78, 0x61, 0x20, 0x47, +0x61, 0x72, 0x61, 0x62, 0x6c, 0x75, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, +0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, +0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, +0x72, 0x69, 0x65, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x3b, +0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x65, 0x3b, 0x4a, 0x75, 0x6c, 0x69, +0x65, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, +0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, +0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x53, 0x68, 0x6b, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x50, +0x72, 0x69, 0x3b, 0x4d, 0x61, 0x6a, 0x3b, 0x51, 0x65, 0x72, 0x3b, 0x4b, 0x6f, 0x72, 0x3b, 0x47, 0x73, 0x68, 0x3b, 0x53, +0x68, 0x74, 0x3b, 0x54, 0x65, 0x74, 0x3b, 0x4e, 0xeb, 0x6e, 0x3b, 0x44, 0x68, 0x6a, 0x3b, 0x6a, 0x61, 0x6e, 0x61, 0x72, +0x3b, 0x73, 0x68, 0x6b, 0x75, 0x72, 0x74, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x70, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x6d, +0x61, 0x6a, 0x3b, 0x71, 0x65, 0x72, 0x73, 0x68, 0x6f, 0x72, 0x3b, 0x6b, 0x6f, 0x72, 0x72, 0x69, 0x6b, 0x3b, 0x67, 0x75, +0x73, 0x68, 0x74, 0x3b, 0x73, 0x68, 0x74, 0x61, 0x74, 0x6f, 0x72, 0x3b, 0x74, 0x65, 0x74, 0x6f, 0x72, 0x3b, 0x6e, 0xeb, +0x6e, 0x74, 0x6f, 0x72, 0x3b, 0x64, 0x68, 0x6a, 0x65, 0x74, 0x6f, 0x72, 0x3b, 0x1303, 0x1295, 0x12e9, 0x3b, 0x134c, 0x1265, 0x1229, +0x3b, 0x121b, 0x122d, 0x127d, 0x3b, 0x12a4, 0x1355, 0x1228, 0x3b, 0x121c, 0x12ed, 0x3b, 0x1301, 0x1295, 0x3b, 0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, +0x1308, 0x1235, 0x3b, 0x1234, 0x1355, 0x1274, 0x3b, 0x12a6, 0x12ad, 0x1270, 0x3b, 0x1296, 0x126c, 0x121d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x3b, 0x1303, +0x1295, 0x12e9, 0x12c8, 0x122a, 0x3b, 0x134c, 0x1265, 0x1229, 0x12c8, 0x122a, 0x3b, 0x121b, 0x122d, 0x127d, 0x3b, 0x12a4, 0x1355, 0x1228, 0x120d, 0x3b, +0x121c, 0x12ed, 0x3b, 0x1301, 0x1295, 0x3b, 0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308, 0x1235, 0x1275, 0x3b, 0x1234, 0x1355, 0x1274, 0x121d, 0x1260, +0x122d, 0x3b, 0x12a6, 0x12ad, 0x1270, 0x12cd, 0x1260, 0x122d, 0x3b, 0x1296, 0x126c, 0x121d, 0x1260, 0x122d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x1260, 0x122d, +0x3b, 0x64a, 0x646, 0x627, 0x64a, 0x631, 0x3b, 0x641, 0x628, 0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, +0x628, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, +0x648, 0x3b, 0x623, 0x63a, 0x633, 0x637, 0x633, 0x3b, 0x633, 0x628, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, +0x631, 0x3b, 0x646, 0x648, 0x641, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x64a, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x643, 0x627, 0x646, 0x648, +0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x634, 0x628, 0x627, 0x637, 0x3b, 0x622, 0x630, 0x627, 0x631, 0x3b, 0x646, +0x64a, 0x633, 0x627, 0x646, 0x3b, 0x623, 0x64a, 0x627, 0x631, 0x3b, 0x62d, 0x632, 0x64a, 0x631, 0x627, 0x646, 0x3b, 0x62a, 0x645, 0x648, +0x632, 0x3b, 0x622, 0x628, 0x3b, 0x623, 0x64a, 0x644, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0x20, 0x627, 0x644, 0x623, +0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x643, 0x627, 0x646, 0x648, +0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, +0x3b, 0x634, 0x628, 0x627, 0x637, 0x3b, 0x622, 0x630, 0x627, 0x631, 0x3b, 0x646, 0x64a, 0x633, 0x627, 0x646, 0x3b, 0x646, 0x648, 0x627, +0x631, 0x3b, 0x62d, 0x632, 0x64a, 0x631, 0x627, 0x646, 0x3b, 0x62a, 0x645, 0x648, 0x632, 0x3b, 0x622, 0x628, 0x3b, 0x623, 0x64a, 0x644, +0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, +0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, +0x545, 0x576, 0x580, 0x3b, 0x553, 0x57f, 0x580, 0x3b, 0x544, 0x580, 0x57f, 0x3b, 0x531, 0x57a, 0x580, 0x3b, 0x544, 0x575, 0x57d, 0x3b, +0x545, 0x576, 0x57d, 0x3b, 0x545, 0x56c, 0x57d, 0x3b, 0x555, 0x563, 0x57d, 0x3b, 0x54d, 0x565, 0x57a, 0x3b, 0x540, 0x578, 0x56f, 0x3b, +0x546, 0x578, 0x575, 0x3b, 0x534, 0x565, 0x56f, 0x3b, 0x545, 0x578, 0x582, 0x576, 0x578, 0x582, 0x561, 0x580, 0x3b, 0x553, 0x565, 0x57f, +0x580, 0x578, 0x582, 0x561, 0x580, 0x3b, 0x544, 0x561, 0x580, 0x57f, 0x3b, 0x531, 0x57a, 0x580, 0x56b, 0x56c, 0x3b, 0x544, 0x561, 0x575, +0x56b, 0x57d, 0x3b, 0x545, 0x578, 0x582, 0x576, 0x56b, 0x57d, 0x3b, 0x545, 0x578, 0x582, 0x56c, 0x56b, 0x57d, 0x3b, 0x555, 0x563, 0x578, +0x57d, 0x57f, 0x578, 0x57d, 0x3b, 0x54d, 0x565, 0x57a, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x540, 0x578, 0x56f, 0x57f, 0x565, +0x574, 0x562, 0x565, 0x580, 0x3b, 0x546, 0x578, 0x575, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x534, 0x565, 0x56f, 0x57f, 0x565, 0x574, +0x562, 0x565, 0x580, 0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9f0, 0x9c1, 0x3b, 0x9ae, 0x9be, 0x9f0, 0x9cd, +0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9f0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, +0x987, 0x3b, 0x986, 0x997, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x3b, 0x9a8, 0x9ad, 0x9c7, +0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x9af, 0x9bc, 0x9be, 0x9f0, 0x9c0, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, +0x9f0, 0x9c1, 0x9af, 0x9bc, 0x9be, 0x9f0, 0x9c0, 0x3b, 0x9ae, 0x9be, 0x9f0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9f0, 0x9bf, 0x9b2, +0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b7, 0x9cd, 0x99f, 0x3b, +0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9f0, 0x3b, 0x9a8, +0x9ad, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b, 0x79, 0x61, 0x6e, 0x3b, +0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x6e, 0x3b, +0x69, 0x79, 0x6c, 0x3b, 0x61, 0x76, 0x71, 0x3b, 0x73, 0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x79, 0x3b, +0x64, 0x65, 0x6b, 0x3b, 0x59, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x4d, 0x61, +0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x130, 0x79, 0x75, 0x6e, 0x3b, 0x130, 0x79, +0x75, 0x6c, 0x3b, 0x41, 0x76, 0x71, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x6e, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x4f, +0x6b, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x4e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x44, 0x65, 0x6b, 0x61, 0x62, 0x72, +0x3b, 0x75, 0x72, 0x74, 0x3b, 0x6f, 0x74, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x69, 0x3b, 0x6d, 0x61, 0x69, +0x3b, 0x65, 0x6b, 0x61, 0x3b, 0x75, 0x7a, 0x74, 0x3b, 0x61, 0x62, 0x75, 0x3b, 0x69, 0x72, 0x61, 0x3b, 0x75, 0x72, 0x72, +0x3b, 0x61, 0x7a, 0x61, 0x3b, 0x61, 0x62, 0x65, 0x3b, 0x75, 0x72, 0x74, 0x61, 0x72, 0x72, 0x69, 0x6c, 0x61, 0x3b, 0x6f, +0x74, 0x73, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x78, 0x6f, 0x61, 0x3b, 0x61, 0x70, 0x69, 0x72, 0x69, +0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x69, 0x61, 0x74, 0x7a, 0x61, 0x3b, 0x65, 0x6b, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x75, 0x7a, +0x74, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x61, 0x62, 0x75, 0x7a, 0x74, 0x75, 0x61, 0x3b, 0x69, 0x72, 0x61, 0x69, 0x6c, 0x61, +0x3b, 0x75, 0x72, 0x72, 0x69, 0x61, 0x3b, 0x61, 0x7a, 0x61, 0x72, 0x6f, 0x61, 0x3b, 0x61, 0x62, 0x65, 0x6e, 0x64, 0x75, +0x61, 0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x9af, 0x9bc, 0x9be, 0x9b0, 0x9c0, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9b0, 0x9c1, 0x9af, 0x9bc, +0x9be, 0x9b0, 0x9c0, 0x3b, 0x9ae, 0x9be, 0x9b0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b, +0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b8, 0x9cd, 0x99f, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, +0x99f, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9b0, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x9ae, 0x9cd, +0x9ac, 0x9b0, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf21, 0x3b, 0xf5f, 0xfb3, +0xf0b, 0x20, 0xf22, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf23, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf24, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, +0xf25, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf26, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf27, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf28, 0x3b, +0xf5f, 0xfb3, 0xf0b, 0x20, 0xf29, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf21, 0xf20, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x20, 0xf21, 0xf21, 0x3b, +0xf5f, 0xfb3, 0xf0b, 0x20, 0xf21, 0xf22, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf51, 0xf44, 0xf54, 0xf0b, +0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, +0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, +0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, +0xf63, 0xf94, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, +0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, +0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, +0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, +0xfb3, 0xf5d, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, 0xf56, +0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf5d, 0xf0b, +0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0x44f, 0x43d, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x440, +0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x44e, 0x43d, 0x438, 0x3b, +0x44e, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, +0x43d, 0x43e, 0x435, 0x43c, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x3b, 0x44f, 0x43d, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x444, 0x435, +0x432, 0x440, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, +0x439, 0x3b, 0x44e, 0x43d, 0x438, 0x3b, 0x44e, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, +0x442, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43d, 0x43e, 0x435, 0x43c, +0x432, 0x440, 0x438, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x1007, 0x1014, 0x103a, 0x3b, 0x1016, 0x1031, 0x3b, +0x1019, 0x1010, 0x103a, 0x3b, 0x1027, 0x3b, 0x1019, 0x1031, 0x3b, 0x1007, 0x103d, 0x1014, 0x103a, 0x3b, 0x1007, 0x1030, 0x3b, 0x1029, 0x3b, 0x1005, +0x1000, 0x103a, 0x3b, 0x1021, 0x1031, 0x102c, 0x1000, 0x103a, 0x3b, 0x1014, 0x102d, 0x102f, 0x3b, 0x1012, 0x102e, 0x3b, 0x1007, 0x1014, 0x103a, 0x1014, +0x101d, 0x102b, 0x101b, 0x102e, 0x3b, 0x1016, 0x1031, 0x1016, 0x1031, 0x102c, 0x103a, 0x101d, 0x102b, 0x101b, 0x102e, 0x3b, 0x1019, 0x1010, 0x103a, 0x3b, +0x1027, 0x1015, 0x103c, 0x102e, 0x3b, 0x1019, 0x1031, 0x3b, 0x1007, 0x103d, 0x1014, 0x103a, 0x3b, 0x1007, 0x1030, 0x101c, 0x102d, 0x102f, 0x1004, 0x103a, +0x3b, 0x1029, 0x1002, 0x102f, 0x1010, 0x103a, 0x3b, 0x1005, 0x1000, 0x103a, 0x1010, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1021, 0x1031, 0x102c, 0x1000, +0x103a, 0x1010, 0x102d, 0x102f, 0x1018, 0x102c, 0x3b, 0x1014, 0x102d, 0x102f, 0x101d, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1012, 0x102e, 0x1007, 0x1004, +0x103a, 0x1018, 0x102c, 0x3b, 0x441, 0x442, 0x443, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x441, 0x430, 0x43a, 0x3b, 0x43a, 0x440, 0x430, 0x3b, +0x43c, 0x430, 0x439, 0x3b, 0x447, 0x44d, 0x440, 0x3b, 0x43b, 0x456, 0x43f, 0x3b, 0x436, 0x43d, 0x456, 0x3b, 0x432, 0x435, 0x440, 0x3b, +0x43a, 0x430, 0x441, 0x3b, 0x43b, 0x456, 0x441, 0x3b, 0x441, 0x43d, 0x435, 0x3b, 0x441, 0x442, 0x443, 0x434, 0x437, 0x435, 0x43d, 0x44c, +0x3b, 0x43b, 0x44e, 0x442, 0x44b, 0x3b, 0x441, 0x430, 0x43a, 0x430, 0x432, 0x456, 0x43a, 0x3b, 0x43a, 0x440, 0x430, 0x441, 0x430, 0x432, +0x456, 0x43a, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x447, 0x44d, 0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x456, 0x43f, 0x435, 0x43d, +0x44c, 0x3b, 0x436, 0x43d, 0x456, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x432, 0x435, 0x440, 0x430, 0x441, 0x435, 0x43d, 0x44c, 0x3b, 0x43a, +0x430, 0x441, 0x442, 0x440, 0x44b, 0x447, 0x43d, 0x456, 0x43a, 0x3b, 0x43b, 0x456, 0x441, 0x442, 0x430, 0x43f, 0x430, 0x434, 0x3b, 0x441, +0x43d, 0x435, 0x436, 0x430, 0x43d, 0x44c, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x442, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, +0x17e1, 0x3b, 0x17e2, 0x3b, 0x17e3, 0x3b, 0x17e4, 0x3b, 0x17e5, 0x3b, 0x17e6, 0x3b, 0x17e7, 0x3b, 0x17e8, 0x3b, 0x17e9, 0x3b, 0x17e1, 0x17e0, +0x3b, 0x17e1, 0x17e1, 0x3b, 0x17e1, 0x17e2, 0x3b, 0x1798, 0x1780, 0x179a, 0x17b6, 0x3b, 0x1780, 0x17bb, 0x1798, 0x17d2, 0x1797, 0x17c8, 0x3b, 0x1798, +0x17b7, 0x1793, 0x17b6, 0x3b, 0x1798, 0x17c1, 0x179f, 0x17b6, 0x3b, 0x17a7, 0x179f, 0x1797, 0x17b6, 0x3b, 0x1798, 0x17b7, 0x1790, 0x17bb, 0x1793, 0x17b6, +0x3b, 0x1780, 0x1780, 0x17d2, 0x1780, 0x178a, 0x17b6, 0x3b, 0x179f, 0x17b8, 0x17a0, 0x17b6, 0x3b, 0x1780, 0x1789, 0x17d2, 0x1789, 0x17b6, 0x3b, 0x178f, +0x17bb, 0x179b, 0x17b6, 0x3b, 0x179c, 0x17b7, 0x1785, 0x17d2, 0x1786, 0x17b7, 0x1780, 0x17b6, 0x3b, 0x1792, 0x17d2, 0x1793, 0x17bc, 0x3b, 0x67, 0x65, +0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, +0x61, 0x69, 0x67, 0x3b, 0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x2e, 0x3b, 0x73, 0x65, +0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x3b, 0x67, 0x65, +0x6e, 0x65, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x61, 0x62, 0x72, 0x69, +0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x6c, 0x3b, 0x61, +0x67, 0x6f, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, +0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, +0x31, 0x6708, 0x3b, 0x32, 0x6708, 0x3b, 0x33, 0x6708, 0x3b, 0x34, 0x6708, 0x3b, 0x35, 0x6708, 0x3b, 0x36, 0x6708, 0x3b, 0x37, 0x6708, +0x3b, 0x38, 0x6708, 0x3b, 0x39, 0x6708, 0x3b, 0x31, 0x30, 0x6708, 0x3b, 0x31, 0x31, 0x6708, 0x3b, 0x31, 0x32, 0x6708, 0x3b, 0x73, +0x69, 0x6a, 0x3b, 0x76, 0x65, 0x6c, 0x3b, 0x6f, 0x17e, 0x75, 0x3b, 0x74, 0x72, 0x61, 0x3b, 0x73, 0x76, 0x69, 0x3b, 0x6c, +0x69, 0x70, 0x3b, 0x73, 0x72, 0x70, 0x3b, 0x6b, 0x6f, 0x6c, 0x3b, 0x72, 0x75, 0x6a, 0x3b, 0x6c, 0x69, 0x73, 0x3b, 0x73, +0x74, 0x75, 0x3b, 0x70, 0x72, 0x6f, 0x3b, 0x73, 0x69, 0x6a, 0x65, 0x10d, 0x6e, 0x6a, 0x61, 0x3b, 0x76, 0x65, 0x6c, 0x6a, +0x61, 0x10d, 0x65, 0x3b, 0x6f, 0x17e, 0x75, 0x6a, 0x6b, 0x61, 0x3b, 0x74, 0x72, 0x61, 0x76, 0x6e, 0x6a, 0x61, 0x3b, 0x73, +0x76, 0x69, 0x62, 0x6e, 0x6a, 0x61, 0x3b, 0x6c, 0x69, 0x70, 0x6e, 0x6a, 0x61, 0x3b, 0x73, 0x72, 0x70, 0x6e, 0x6a, 0x61, +0x3b, 0x6b, 0x6f, 0x6c, 0x6f, 0x76, 0x6f, 0x7a, 0x61, 0x3b, 0x72, 0x75, 0x6a, 0x6e, 0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, +0x6f, 0x70, 0x61, 0x64, 0x61, 0x3b, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x6f, 0x67, 0x61, 0x3b, 0x70, 0x72, 0x6f, 0x73, +0x69, 0x6e, 0x63, 0x61, 0x3b, 0x6c, 0x65, 0x64, 0x6e, 0x61, 0x3b, 0xfa, 0x6e, 0x6f, 0x72, 0x61, 0x3b, 0x62, 0x159, 0x65, +0x7a, 0x6e, 0x61, 0x3b, 0x64, 0x75, 0x62, 0x6e, 0x61, 0x3b, 0x6b, 0x76, 0x11b, 0x74, 0x6e, 0x61, 0x3b, 0x10d, 0x65, 0x72, +0x76, 0x6e, 0x61, 0x3b, 0x10d, 0x65, 0x72, 0x76, 0x65, 0x6e, 0x63, 0x65, 0x3b, 0x73, 0x72, 0x70, 0x6e, 0x61, 0x3b, 0x7a, +0xe1, 0x159, 0xed, 0x3b, 0x159, 0xed, 0x6a, 0x6e, 0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x75, 0x3b, +0x70, 0x72, 0x6f, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, +0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, +0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, +0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, +0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, +0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, +0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, +0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x65, 0x69, +0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, +0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, +0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x65, +0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, +0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, +0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x61, +0x6e, 0x3b, 0x76, 0x65, 0x65, 0x62, 0x72, 0x3b, 0x6d, 0xe4, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, +0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, +0x70, 0x74, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x74, 0x73, 0x3b, 0x6a, 0x61, 0x61, 0x6e, +0x75, 0x61, 0x72, 0x3b, 0x76, 0x65, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0xe4, 0x72, 0x74, 0x73, 0x3b, 0x61, +0x70, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6c, +0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, +0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x74, +0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, +0x70, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, +0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, +0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, +0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, +0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, +0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x74, 0x61, +0x6d, 0x6d, 0x69, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73, 0x3b, 0x68, 0x75, 0x68, +0x74, 0x69, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x3b, +0x65, 0x6c, 0x6f, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61, 0x73, +0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x3b, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x68, 0x65, +0x6c, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61, +0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x6b, 0x75, 0x75, +0x74, 0x61, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x75, +0x75, 0x74, 0x61, 0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x6b, 0x75, 0x75, +0x74, 0x61, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61, 0x73, 0x6b, +0x75, 0x75, 0x74, 0x61, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6a, 0x61, 0x6e, 0x76, +0x2e, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, +0x69, 0x3b, 0x6a, 0x75, 0x69, 0x6e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x2e, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, +0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9, 0x63, 0x2e, 0x3b, 0x6a, +0x61, 0x6e, 0x76, 0x69, 0x65, 0x72, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x69, 0x65, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, +0x61, 0x76, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69, 0x6e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x6c, +0x65, 0x74, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, +0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0xe9, 0x63, 0x65, 0x6d, +0x62, 0x72, 0x65, 0x3b, 0x58, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, +0x4d, 0x61, 0x69, 0x3b, 0x58, 0x75, 0xf1, 0x3b, 0x58, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, +0x4f, 0x75, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 0x58, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, +0x46, 0x65, 0x62, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, +0x3b, 0x4d, 0x61, 0x69, 0x6f, 0x3b, 0x58, 0x75, 0xf1, 0x6f, 0x3b, 0x58, 0x75, 0x6c, 0x6c, 0x6f, 0x3b, 0x41, 0x67, 0x6f, +0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x4f, 0x75, 0x74, 0x75, 0x62, 0x72, 0x6f, +0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x10d8, +0x10d0, 0x10dc, 0x3b, 0x10d7, 0x10d4, 0x10d1, 0x3b, 0x10db, 0x10d0, 0x10e0, 0x3b, 0x10d0, 0x10de, 0x10e0, 0x3b, 0x10db, 0x10d0, 0x10d8, 0x3b, 0x10d8, +0x10d5, 0x10dc, 0x3b, 0x10d8, 0x10d5, 0x10da, 0x3b, 0x10d0, 0x10d2, 0x10d5, 0x3b, 0x10e1, 0x10d4, 0x10e5, 0x3b, 0x10dd, 0x10e5, 0x10e2, 0x3b, 0x10dc, +0x10dd, 0x10d4, 0x3b, 0x10d3, 0x10d4, 0x10d9, 0x3b, 0x10d8, 0x10d0, 0x10dc, 0x10d5, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x10d7, 0x10d4, 0x10d1, 0x10d4, 0x10e0, +0x10d5, 0x10d0, 0x10da, 0x10d8, 0x3b, 0x10db, 0x10d0, 0x10e0, 0x10e2, 0x10d8, 0x3b, 0x10d0, 0x10de, 0x10e0, 0x10d8, 0x10da, 0x10d8, 0x3b, 0x10db, 0x10d0, +0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10dc, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10da, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d0, 0x10d2, +0x10d5, 0x10d8, 0x10e1, 0x10e2, 0x10dd, 0x3b, 0x10e1, 0x10d4, 0x10e5, 0x10e2, 0x10d4, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10dd, 0x10e5, 0x10e2, +0x10dd, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10dc, 0x10dd, 0x10d4, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10d3, 0x10d4, 0x10d9, 0x10d4, +0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x72, 0x7a, 0x3b, 0x41, 0x70, +0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, +0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, +0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, +0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, +0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, +0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0xe4, 0x6e, +0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, +0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, +0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x4a, 0xe4, 0x6e, 0x6e, 0x65, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, +0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, +0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, +0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, +0x65, 0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, +0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, +0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3b, +0x3a6, 0x3b5, 0x3b2, 0x3b, 0x39c, 0x3b1, 0x3c1, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b, 0x39c, 0x3b1, 0x3ca, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bd, +0x3b, 0x399, 0x3bf, 0x3c5, 0x3bb, 0x3b, 0x391, 0x3c5, 0x3b3, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3b, 0x39d, 0x3bf, +0x3b5, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3bf, 0x3c5, 0x3b1, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x3a6, 0x3b5, 0x3b2, +0x3c1, 0x3bf, 0x3c5, 0x3b1, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39c, 0x3b1, 0x3c1, 0x3c4, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x391, 0x3c0, 0x3c1, +0x3b9, 0x3bb, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39c, 0x3b1, 0x390, 0x3bf, 0x3c5, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bd, 0x3af, 0x3bf, 0x3c5, 0x3b, +0x399, 0x3bf, 0x3c5, 0x3bb, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x391, 0x3c5, 0x3b3, 0x3bf, 0x3cd, 0x3c3, 0x3c4, 0x3bf, 0x3c5, 0x3b, 0x3a3, 0x3b5, +0x3c0, 0x3c4, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3c9, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, +0x39d, 0x3bf, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, +0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, +0x72, 0x74, 0x73, 0x69, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x69, 0x3b, 0x6a, 0x75, 0x6e, +0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x69, 0x3b, 0x73, 0x65, 0x70, +0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x69, 0x3b, 0x6e, 0x6f, 0x76, +0x65, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x3b, 0xa9c, 0xabe, 0xaa8, +0xacd, 0xaaf, 0xac1, 0x3b, 0xaab, 0xac7, 0xaac, 0xacd, 0xab0, 0xac1, 0x3b, 0xaae, 0xabe, 0xab0, 0xacd, 0xa9a, 0x3b, 0xa8f, 0xaaa, 0xacd, +0xab0, 0xabf, 0xab2, 0x3b, 0xaae, 0xac7, 0x3b, 0xa9c, 0xac2, 0xaa8, 0x3b, 0xa9c, 0xac1, 0xab2, 0xabe, 0xa88, 0x3b, 0xa91, 0xa97, 0xab8, +0xacd, 0xa9f, 0x3b, 0xab8, 0xaaa, 0xacd, 0xa9f, 0xac7, 0x3b, 0xa91, 0xa95, 0xacd, 0xa9f, 0xacb, 0x3b, 0xaa8, 0xab5, 0xac7, 0x3b, 0xaa1, +0xabf, 0xab8, 0xac7, 0x3b, 0xa9c, 0xabe, 0xaa8, 0xacd, 0xaaf, 0xac1, 0xa86, 0xab0, 0xac0, 0x3b, 0xaab, 0xac7, 0xaac, 0xacd, 0xab0, 0xac1, +0xa86, 0xab0, 0xac0, 0x3b, 0xaae, 0xabe, 0xab0, 0xacd, 0xa9a, 0x3b, 0xa8f, 0xaaa, 0xacd, 0xab0, 0xabf, 0xab2, 0x3b, 0xaae, 0xac7, 0x3b, +0xa9c, 0xac2, 0xaa8, 0x3b, 0xa9c, 0xac1, 0xab2, 0xabe, 0xa88, 0x3b, 0xa91, 0xa97, 0xab8, 0xacd, 0xa9f, 0x3b, 0xab8, 0xaaa, 0xacd, 0xa9f, +0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0xa91, 0xa95, 0xacd, 0xa9f, 0xacd, 0xaac, 0xab0, 0x3b, 0xaa8, 0xab5, 0xac7, 0xaae, 0xacd, 0xaac, +0xab0, 0x3b, 0xaa1, 0xabf, 0xab8, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x61, 0x62, 0x3b, 0x4d, +0x61, 0x72, 0x3b, 0x41, 0x66, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x41, +0x75, 0x67, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x75, 0x77, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, +0x61, 0x6e, 0x61, 0x69, 0x72, 0x75, 0x3b, 0x46, 0x61, 0x62, 0x72, 0x61, 0x69, 0x72, 0x75, 0x3b, 0x4d, 0x61, 0x72, 0x69, +0x73, 0x3b, 0x41, 0x66, 0x72, 0x69, 0x6c, 0x75, 0x3b, 0x4d, 0x61, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6e, 0x69, 0x3b, 0x59, +0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x61, 0x3b, 0x53, 0x61, 0x74, 0x75, 0x6d, 0x62, 0x61, 0x3b, +0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x75, 0x77, 0x61, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x61, 0x6d, +0x62, 0x61, 0x3b, 0x5d9, 0x5e0, 0x5d5, 0x3b, 0x5e4, 0x5d1, 0x5e8, 0x3b, 0x5de, 0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5e4, 0x5e8, 0x3b, 0x5de, +0x5d0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5e0, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x3b, 0x5d0, 0x5d5, 0x5d2, 0x3b, 0x5e1, 0x5e4, 0x5d8, 0x3b, 0x5d0, +0x5d5, 0x5e7, 0x3b, 0x5e0, 0x5d5, 0x5d1, 0x3b, 0x5d3, 0x5e6, 0x5de, 0x3b, 0x5d9, 0x5e0, 0x5d5, 0x5d0, 0x5e8, 0x3b, 0x5e4, 0x5d1, 0x5e8, +0x5d5, 0x5d0, 0x5e8, 0x3b, 0x5de, 0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5e4, 0x5e8, 0x5d9, 0x5dc, 0x3b, 0x5de, 0x5d0, 0x5d9, 0x3b, 0x5d9, 0x5d5, +0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d2, 0x5d5, 0x5e1, 0x5d8, 0x3b, 0x5e1, 0x5e4, 0x5d8, 0x5de, 0x5d1, +0x5e8, 0x3b, 0x5d0, 0x5d5, 0x5e7, 0x5d8, 0x5d5, 0x5d1, 0x5e8, 0x3b, 0x5e0, 0x5d5, 0x5d1, 0x5de, 0x5d1, 0x5e8, 0x3b, 0x5d3, 0x5e6, 0x5de, +0x5d1, 0x5e8, 0x3b, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x930, 0x935, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, +0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908, +0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x93f, 0x924, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942, +0x92c, 0x930, 0x3b, 0x928, 0x935, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x6a, 0x61, +0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0xe1, 0x72, 0x63, 0x2e, 0x3b, 0xe1, 0x70, 0x72, 0x2e, 0x3b, +0x6d, 0xe1, 0x6a, 0x2e, 0x3b, 0x6a, 0xfa, 0x6e, 0x2e, 0x3b, 0x6a, 0xfa, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, +0x73, 0x7a, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, +0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0xe1, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x3b, 0x6d, 0xe1, 0x72, +0x63, 0x69, 0x75, 0x73, 0x3b, 0xe1, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x73, 0x3b, 0x6d, 0xe1, 0x6a, 0x75, 0x73, 0x3b, 0x6a, +0xfa, 0x6e, 0x69, 0x75, 0x73, 0x3b, 0x6a, 0xfa, 0x6c, 0x69, 0x75, 0x73, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x7a, 0x74, +0x75, 0x73, 0x3b, 0x73, 0x7a, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x65, +0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, +0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0xed, 0x3b, +0x6a, 0xfa, 0x6e, 0x3b, 0x6a, 0xfa, 0x6c, 0x3b, 0xe1, 0x67, 0xfa, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, +0x6e, 0xf3, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x3b, 0x6a, 0x61, 0x6e, 0xfa, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0xfa, +0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0x61, 0xed, 0x3b, 0x6a, 0xfa, +0x6e, 0xed, 0x3b, 0x6a, 0xfa, 0x6c, 0xed, 0x3b, 0xe1, 0x67, 0xfa, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, +0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0xf3, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, +0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, +0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, +0x75, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, +0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x72, 0x65, 0x74, +0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, +0x3b, 0x41, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, +0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x73, 0x65, +0x6d, 0x62, 0x65, 0x72, 0x3b, 0x45, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x61, 0x62, 0x68, 0x3b, 0x4d, 0xe1, 0x72, 0x74, 0x61, +0x3b, 0x41, 0x69, 0x62, 0x3b, 0x42, 0x65, 0x61, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x74, 0x68, 0x3b, 0x49, 0xfa, 0x69, 0x6c, +0x3b, 0x4c, 0xfa, 0x6e, 0x3b, 0x4d, 0x46, 0xf3, 0x6d, 0x68, 0x3b, 0x44, 0x46, 0xf3, 0x6d, 0x68, 0x3b, 0x53, 0x61, 0x6d, +0x68, 0x3b, 0x4e, 0x6f, 0x6c, 0x6c, 0x3b, 0x45, 0x61, 0x6e, 0xe1, 0x69, 0x72, 0x3b, 0x46, 0x65, 0x61, 0x62, 0x68, 0x72, +0x61, 0x3b, 0x4d, 0xe1, 0x72, 0x74, 0x61, 0x3b, 0x41, 0x69, 0x62, 0x72, 0x65, 0xe1, 0x6e, 0x3b, 0x42, 0x65, 0x61, 0x6c, +0x74, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4d, 0x65, 0x69, 0x74, 0x68, 0x65, 0x61, 0x6d, 0x68, 0x3b, 0x49, 0xfa, 0x69, 0x6c, +0x3b, 0x4c, 0xfa, 0x6e, 0x61, 0x73, 0x61, 0x3b, 0x4d, 0x65, 0xe1, 0x6e, 0x20, 0x46, 0xf3, 0x6d, 0x68, 0x61, 0x69, 0x72, +0x3b, 0x44, 0x65, 0x69, 0x72, 0x65, 0x61, 0x64, 0x68, 0x20, 0x46, 0xf3, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x53, 0x61, +0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x4e, 0x6f, 0x6c, 0x6c, 0x61, 0x69, 0x67, 0x3b, 0x67, 0x65, 0x6e, 0x3b, 0x66, 0x65, +0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x67, 0x3b, 0x67, 0x69, 0x75, 0x3b, 0x6c, 0x75, +0x67, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x74, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x69, +0x63, 0x3b, 0x67, 0x65, 0x6e, 0x6e, 0x61, 0x69, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x62, 0x72, 0x61, 0x69, 0x6f, 0x3b, 0x6d, +0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x65, 0x3b, 0x6d, 0x61, 0x67, 0x67, 0x69, 0x6f, 0x3b, 0x67, +0x69, 0x75, 0x67, 0x6e, 0x6f, 0x3b, 0x4c, 0x75, 0x67, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, +0x73, 0x65, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x74, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, +0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0xc9c, 0xca8, 0xcb5, 0xcb0, +0xcc0, 0x3b, 0xcab, 0xcc6, 0xcac, 0xccd, 0xcb0, 0xcb5, 0xcb0, 0xcc0, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8e, 0xcaa, +0xccd, 0xcb0, 0xcbf, 0xcb2, 0xccd, 0x3b, 0xcae, 0xcc6, 0x3b, 0xc9c, 0xcc2, 0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b, 0xc86, +0xc97, 0xcb8, 0xccd, 0xc9f, 0xccd, 0x3b, 0xcb8, 0xcaa, 0xccd, 0xc9f, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0x3b, 0xc85, 0xc95, 0xccd, 0xc9f, +0xccb, 0xcac, 0xcb0, 0xccd, 0x3b, 0xca8, 0xcb5, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0x3b, 0xca1, 0xcbf, 0xcb8, 0xcc6, 0xc82, 0xcac, 0xcb0, +0xccd, 0x3b, 0x49b, 0x430, 0x4a3, 0x2e, 0x3b, 0x430, 0x49b, 0x43f, 0x2e, 0x3b, 0x43d, 0x430, 0x443, 0x2e, 0x3b, 0x441, 0x4d9, 0x443, +0x2e, 0x3b, 0x43c, 0x430, 0x43c, 0x2e, 0x3b, 0x43c, 0x430, 0x443, 0x2e, 0x3b, 0x448, 0x456, 0x43b, 0x2e, 0x3b, 0x442, 0x430, 0x43c, +0x2e, 0x3b, 0x49b, 0x44b, 0x440, 0x2e, 0x3b, 0x49b, 0x430, 0x437, 0x2e, 0x3b, 0x49b, 0x430, 0x440, 0x2e, 0x3b, 0x436, 0x435, 0x43b, +0x442, 0x2e, 0x3b, 0x49b, 0x430, 0x4a3, 0x442, 0x430, 0x440, 0x3b, 0x430, 0x49b, 0x43f, 0x430, 0x43d, 0x3b, 0x43d, 0x430, 0x443, 0x440, +0x44b, 0x437, 0x3b, 0x441, 0x4d9, 0x443, 0x456, 0x440, 0x3b, 0x43c, 0x430, 0x43c, 0x44b, 0x440, 0x3b, 0x43c, 0x430, 0x443, 0x441, 0x44b, +0x43c, 0x3b, 0x448, 0x456, 0x43b, 0x434, 0x435, 0x3b, 0x442, 0x430, 0x43c, 0x44b, 0x437, 0x3b, 0x49b, 0x44b, 0x440, 0x43a, 0x4af, 0x439, +0x435, 0x43a, 0x3b, 0x49b, 0x430, 0x437, 0x430, 0x43d, 0x3b, 0x49b, 0x430, 0x440, 0x430, 0x448, 0x430, 0x3b, 0x436, 0x435, 0x43b, 0x442, +0x43e, 0x49b, 0x441, 0x430, 0x43d, 0x3b, 0x6d, 0x75, 0x74, 0x2e, 0x3b, 0x67, 0x61, 0x73, 0x2e, 0x3b, 0x77, 0x65, 0x72, 0x2e, +0x3b, 0x6d, 0x61, 0x74, 0x2e, 0x3b, 0x67, 0x69, 0x63, 0x2e, 0x3b, 0x6b, 0x61, 0x6d, 0x2e, 0x3b, 0x6e, 0x79, 0x61, 0x2e, +0x3b, 0x6b, 0x61, 0x6e, 0x2e, 0x3b, 0x6e, 0x7a, 0x65, 0x2e, 0x3b, 0x75, 0x6b, 0x77, 0x2e, 0x3b, 0x75, 0x67, 0x75, 0x2e, +0x3b, 0x75, 0x6b, 0x75, 0x2e, 0x3b, 0x4d, 0x75, 0x74, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x3b, 0x47, 0x61, 0x73, 0x68, 0x79, +0x61, 0x6e, 0x74, 0x61, 0x72, 0x65, 0x3b, 0x57, 0x65, 0x72, 0x75, 0x72, 0x77, 0x65, 0x3b, 0x4d, 0x61, 0x74, 0x61, 0x3b, +0x47, 0x69, 0x63, 0x75, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x3b, 0x4b, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x3b, 0x4e, 0x79, 0x61, +0x6b, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x4b, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x3b, 0x4e, 0x7a, 0x65, 0x6c, 0x69, 0x3b, 0x55, +0x6b, 0x77, 0x61, 0x6b, 0x69, 0x72, 0x61, 0x3b, 0x55, 0x67, 0x75, 0x73, 0x68, 0x79, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x55, +0x6b, 0x75, 0x62, 0x6f, 0x7a, 0x61, 0x3b, 0x31, 0xc6d4, 0x3b, 0x32, 0xc6d4, 0x3b, 0x33, 0xc6d4, 0x3b, 0x34, 0xc6d4, 0x3b, 0x35, +0xc6d4, 0x3b, 0x36, 0xc6d4, 0x3b, 0x37, 0xc6d4, 0x3b, 0x38, 0xc6d4, 0x3b, 0x39, 0xc6d4, 0x3b, 0x31, 0x30, 0xc6d4, 0x3b, 0x31, 0x31, +0xc6d4, 0x3b, 0x31, 0x32, 0xc6d4, 0x3b, 0xea1, 0x2e, 0xe81, 0x2e, 0x3b, 0xe81, 0x2e, 0xe9e, 0x2e, 0x3b, 0xea1, 0xeb5, 0x2e, 0xe99, +0x2e, 0x3b, 0xea1, 0x2e, 0xeaa, 0x2e, 0x2e, 0x3b, 0xe9e, 0x2e, 0xe9e, 0x2e, 0x3b, 0xea1, 0xeb4, 0x2e, 0xe96, 0x2e, 0x3b, 0xe81, +0x2e, 0xea5, 0x2e, 0x3b, 0xeaa, 0x2e, 0xeab, 0x2e, 0x3b, 0xe81, 0x2e, 0xe8d, 0x2e, 0x3b, 0xe95, 0x2e, 0xea5, 0x2e, 0x3b, 0xe9e, +0x2e, 0xe88, 0x2e, 0x3b, 0xe97, 0x2e, 0xea7, 0x2e, 0x3b, 0xea1, 0xeb1, 0xe87, 0xe81, 0xead, 0xe99, 0x3b, 0xe81, 0xeb8, 0xea1, 0xe9e, +0xeb2, 0x3b, 0xea1, 0xeb5, 0xe99, 0xeb2, 0x3b, 0xec0, 0xea1, 0xeaa, 0xeb2, 0x3b, 0xe9e, 0xeb6, 0xe94, 0xeaa, 0xeb0, 0xe9e, 0xeb2, 0x3b, +0xea1, 0xeb4, 0xe96, 0xeb8, 0xe99, 0xeb2, 0x3b, 0xe81, 0xecd, 0xea5, 0xeb0, 0xe81, 0xebb, 0xe94, 0x3b, 0xeaa, 0xeb4, 0xe87, 0xeab, 0xeb2, +0x3b, 0xe81, 0xeb1, 0xe99, 0xe8d, 0xeb2, 0x3b, 0xe95, 0xeb8, 0xea5, 0xeb2, 0x3b, 0xe9e, 0xeb0, 0xe88, 0xeb4, 0xe81, 0x3b, 0xe97, 0xeb1, +0xe99, 0xea7, 0xeb2, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, +0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x16b, 0x6e, 0x3b, 0x4a, 0x16b, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, +0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x101, 0x72, 0x69, 0x73, +0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x101, 0x72, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, +0x12b, 0x6c, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b, 0x6e, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b, +0x6c, 0x69, 0x6a, 0x73, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x73, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, +0x72, 0x69, 0x73, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, +0x69, 0x73, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x73, 0x31, 0x3b, 0x73, 0x32, 0x3b, 0x73, +0x33, 0x3b, 0x73, 0x34, 0x3b, 0x73, 0x35, 0x3b, 0x73, 0x36, 0x3b, 0x73, 0x37, 0x3b, 0x73, 0x38, 0x3b, 0x73, 0x39, 0x3b, +0x73, 0x31, 0x30, 0x3b, 0x73, 0x31, 0x31, 0x3b, 0x73, 0x31, 0x32, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, +0x20, 0x79, 0x61, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, +0x6c, 0xe9, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x73, 0xe1, 0x74, 0x6f, 0x3b, 0x73, +0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x6e, 0x65, 0x69, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, +0x79, 0x61, 0x20, 0x6d, 0xed, 0x74, 0xe1, 0x6e, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, +0x6f, 0x74, 0xf3, 0x62, 0xe1, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6e, 0x73, 0x61, 0x6d, 0x62, +0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0x77, 0x61, 0x6d, 0x62, 0x65, 0x3b, 0x73, 0xe1, +0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6c, 0x69, 0x62, 0x77, 0x61, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, +0x61, 0x20, 0x7a, 0xf3, 0x6d, 0x69, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x7a, 0xf3, 0x6d, 0x69, +0x20, 0x6e, 0x61, 0x20, 0x6d, 0x254, 0x30c, 0x6b, 0x254, 0x301, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, +0x7a, 0xf3, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x53, 0x61, 0x75, 0x3b, 0x56, +0x61, 0x73, 0x3b, 0x4b, 0x6f, 0x76, 0x3b, 0x42, 0x61, 0x6c, 0x3b, 0x47, 0x65, 0x67, 0x3b, 0x42, 0x69, 0x72, 0x3b, 0x4c, +0x69, 0x65, 0x3b, 0x52, 0x67, 0x70, 0x3b, 0x52, 0x67, 0x73, 0x3b, 0x53, 0x70, 0x6c, 0x3b, 0x4c, 0x61, 0x70, 0x3b, 0x47, +0x72, 0x64, 0x3b, 0x73, 0x61, 0x75, 0x73, 0x69, 0x6f, 0x3b, 0x76, 0x61, 0x73, 0x61, 0x72, 0x69, 0x6f, 0x3b, 0x6b, 0x6f, +0x76, 0x6f, 0x3b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x17e, 0x69, 0x6f, 0x3b, 0x67, 0x65, 0x67, 0x75, 0x17e, 0x117, 0x73, +0x3b, 0x62, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x6f, 0x3b, 0x6c, 0x69, 0x65, 0x70, 0x6f, 0x73, 0x3b, 0x72, 0x75, 0x67, +0x70, 0x6a, 0x16b, 0x10d, 0x69, 0x6f, 0x3b, 0x72, 0x75, 0x67, 0x73, 0x117, 0x6a, 0x6f, 0x3b, 0x73, 0x70, 0x61, 0x6c, 0x69, +0x6f, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72, 0x69, 0x10d, 0x69, 0x6f, 0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64, 0x17e, 0x69, 0x6f, +0x3b, 0x458, 0x430, 0x43d, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, +0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x2e, 0x3b, 0x458, 0x443, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, +0x441, 0x435, 0x43f, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x2e, 0x3b, 0x434, 0x435, 0x43a, +0x435, 0x43c, 0x2e, 0x3b, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x443, 0x430, 0x440, 0x438, +0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x438, +0x3b, 0x458, 0x443, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x432, +0x440, 0x438, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, +0x434, 0x435, 0x43a, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x441, 0x3b, 0x3b, +0x43d, 0x3b, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, +0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x67, 0x6f, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x3b, +0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, +0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, +0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x4f, 0x67, 0x6f, 0x73, 0x3b, 0x53, 0x65, +0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, +0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0xd1c, 0xd28, 0xd41, 0x3b, 0xd2b, 0xd46, +0xd2c, 0xd4d, 0xd30, 0xd41, 0x3b, 0xd2e, 0xd3e, 0xd30, 0xd4d, 0x200d, 0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd47, 0xd2f, +0xd4d, 0x3b, 0xd1c, 0xd42, 0xd23, 0xd4d, 0x200d, 0x3b, 0xd1c, 0xd42, 0xd32, 0xd48, 0x3b, 0xd06, 0xd17, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, +0xd31, 0xd4d, 0xd31, 0xd02, 0x3b, 0xd12, 0xd15, 0xd4d, 0xd1f, 0xd4b, 0x3b, 0xd28, 0xd35, 0xd02, 0x3b, 0xd21, 0xd3f, 0xd38, 0xd02, 0x3b, +0xd1c, 0xd28, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2b, 0xd46, 0xd2c, 0xd4d, 0xd30, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd3e, 0xd30, +0xd4d, 0x200d, 0xd1a, 0xd4d, 0xd1a, 0xd4d, 0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0xd32, 0xd4d, 0x200d, 0x3b, 0xd2e, 0xd47, 0xd2f, 0xd4d, +0x3b, 0xd1c, 0xd42, 0xd23, 0xd4d, 0x200d, 0x3b, 0xd1c, 0xd42, 0xd32, 0xd48, 0x3b, 0xd13, 0xd17, 0xd38, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd4d, +0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd02, 0xd2c, 0xd30, 0xd4d, 0x200d, 0x3b, 0xd12, 0xd15, 0xd4d, 0xd1f, 0xd4b, 0xd2c, +0xd30, 0xd4d, 0x200d, 0x3b, 0xd28, 0xd35, 0xd02, 0xd2c, 0xd30, 0xd4d, 0x200d, 0x3b, 0xd21, 0xd3f, 0xd38, 0xd02, 0xd2c, 0xd30, 0xd4d, 0x200d, +0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x72, 0x61, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x6a, +0x3b, 0x120, 0x75, 0x6e, 0x3b, 0x4c, 0x75, 0x6c, 0x3b, 0x41, 0x77, 0x69, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x74, +0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x10b, 0x3b, 0x4a, 0x61, 0x6e, 0x6e, 0x61, 0x72, 0x3b, 0x46, 0x72, 0x61, 0x72, +0x3b, 0x4d, 0x61, 0x72, 0x7a, 0x75, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x6a, 0x6a, 0x75, 0x3b, 0x120, +0x75, 0x6e, 0x6a, 0x75, 0x3b, 0x4c, 0x75, 0x6c, 0x6a, 0x75, 0x3b, 0x41, 0x77, 0x69, 0x73, 0x73, 0x75, 0x3b, 0x53, 0x65, +0x74, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x75, 0x3b, 0x4f, 0x74, 0x74, 0x75, 0x62, 0x72, 0x75, 0x3b, 0x4e, 0x6f, 0x76, 0x65, +0x6d, 0x62, 0x72, 0x75, 0x3b, 0x44, 0x69, 0x10b, 0x65, 0x6d, 0x62, 0x72, 0x75, 0x3b, 0x91c, 0x93e, 0x928, 0x947, 0x935, 0x93e, +0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, +0x90f, 0x92a, 0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x948, 0x3b, 0x913, +0x917, 0x938, 0x94d, 0x91f, 0x3b, 0x938, 0x947, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x913, 0x915, 0x94d, 0x91f, 0x94b, +0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x902, 0x92c, 0x930, +0x3b, 0x445, 0x443, 0x43b, 0x3b, 0x4af, 0x445, 0x44d, 0x3b, 0x431, 0x430, 0x440, 0x3b, 0x442, 0x443, 0x443, 0x3b, 0x43b, 0x443, 0x443, +0x3b, 0x43c, 0x43e, 0x433, 0x3b, 0x43c, 0x43e, 0x440, 0x3b, 0x445, 0x43e, 0x43d, 0x3b, 0x431, 0x438, 0x447, 0x3b, 0x442, 0x430, 0x445, +0x3b, 0x43d, 0x43e, 0x445, 0x3b, 0x433, 0x430, 0x445, 0x3b, 0x425, 0x443, 0x43b, 0x433, 0x430, 0x43d, 0x430, 0x3b, 0x4ae, 0x445, 0x44d, +0x440, 0x3b, 0x411, 0x430, 0x440, 0x3b, 0x422, 0x443, 0x443, 0x43b, 0x430, 0x439, 0x3b, 0x41b, 0x443, 0x443, 0x3b, 0x41c, 0x43e, 0x433, +0x43e, 0x439, 0x3b, 0x41c, 0x43e, 0x440, 0x44c, 0x3b, 0x425, 0x43e, 0x43d, 0x44c, 0x3b, 0x411, 0x438, 0x447, 0x3b, 0x422, 0x430, 0x445, +0x438, 0x430, 0x3b, 0x41d, 0x43e, 0x445, 0x43e, 0x439, 0x3b, 0x413, 0x430, 0x445, 0x430, 0x439, 0x3b, 0x91c, 0x928, 0x3b, 0x92b, 0x947, +0x92c, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x93f, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, +0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x3b, 0x905, 0x917, 0x3b, 0x938, 0x947, 0x92a, 0x94d, 0x91f, 0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x94b, +0x3b, 0x928, 0x94b, 0x92d, 0x947, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x3b, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, +0x94d, 0x930, 0x941, 0x905, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x93f, 0x932, 0x3b, +0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, +0x947, 0x92a, 0x94d, 0x91f, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d, 0x91f, 0x94b, 0x92c, 0x930, 0x3b, 0x928, 0x94b, +0x92d, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x92e, 0x94d, 0x92c, 0x930, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, +0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, +0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, +0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, +0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, +0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, +0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, +0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0xb1c, 0xb3e, +0xb28, 0xb41, 0xb06, 0xb30, 0xb40, 0x3b, 0xb2b, 0xb47, 0xb2c, 0xb4d, 0xb30, 0xb41, 0xb5f, 0xb3e, 0xb30, 0xb40, 0x3b, 0xb2e, 0xb3e, 0xb30, +0xb4d, 0xb1a, 0xb4d, 0xb1a, 0x3b, 0xb05, 0xb2a, 0xb4d, 0xb30, 0xb47, 0xb32, 0x3b, 0xb2e, 0xb47, 0x3b, 0xb1c, 0xb41, 0xb28, 0x3b, 0xb1c, +0xb41, 0xb32, 0xb3e, 0xb07, 0x3b, 0xb05, 0xb17, 0xb37, 0xb4d, 0xb1f, 0x3b, 0xb38, 0xb47, 0xb2a, 0xb4d, 0xb1f, 0xb47, 0xb2e, 0xb4d, 0xb2c, +0xb30, 0x3b, 0xb05, 0xb15, 0xb4d, 0xb1f, 0xb4b, 0xb2c, 0xb30, 0x3b, 0xb28, 0xb2d, 0xb47, 0xb2e, 0xb4d, 0xb2c, 0xb30, 0x3b, 0xb21, 0xb3f, +0xb38, 0xb47, 0xb2e, 0xb4d, 0xb2c, 0xb30, 0x3b, 0x31, 0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x645, 0x640, 0x6cc, 0x3b, 0x62c, +0x648, 0x646, 0x3b, 0x37, 0x3b, 0x38, 0x3b, 0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x3b, 0x62c, 0x646, +0x648, 0x631, 0x64a, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, +0x644, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 0x3b, 0x627, 0x6ab, 0x633, 0x62a, 0x3b, +0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, +0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x698, 0x627, 0x646, 0x648, 0x6cc, 0x647, 0x654, 0x3b, 0x641, 0x648, 0x631, 0x6cc, 0x647, 0x654, +0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x647, 0x654, 0x3b, 0x698, 0x648, 0x626, 0x646, +0x3b, 0x698, 0x648, 0x626, 0x6cc, 0x647, 0x654, 0x3b, 0x627, 0x648, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x627, 0x645, 0x628, 0x631, 0x3b, +0x627, 0x6a9, 0x62a, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x627, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x627, 0x645, 0x628, 0x631, 0x3b, +0x62c, 0x646, 0x648, 0x3b, 0x641, 0x648, 0x631, 0x6cc, 0x647, 0x654, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc, +0x644, 0x3b, 0x645, 0x640, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x3b, 0x627, 0x648, 0x62a, 0x3b, 0x633, 0x67e, +0x62a, 0x627, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x627, 0x645, 0x628, 0x631, 0x3b, 0x62f, +0x633, 0x645, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x686, +0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 0x3b, +0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, +0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x73, 0x74, 0x79, 0x3b, 0x6c, 0x75, 0x74, 0x3b, 0x6d, +0x61, 0x72, 0x3b, 0x6b, 0x77, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x63, 0x7a, 0x65, 0x3b, 0x6c, 0x69, 0x70, 0x3b, 0x73, +0x69, 0x65, 0x3b, 0x77, 0x72, 0x7a, 0x3b, 0x70, 0x61, 0x17a, 0x3b, 0x6c, 0x69, 0x73, 0x3b, 0x67, 0x72, 0x75, 0x3b, 0x73, +0x74, 0x79, 0x63, 0x7a, 0x6e, 0x69, 0x61, 0x3b, 0x6c, 0x75, 0x74, 0x65, 0x67, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x63, 0x61, +0x3b, 0x6b, 0x77, 0x69, 0x65, 0x74, 0x6e, 0x69, 0x61, 0x3b, 0x6d, 0x61, 0x6a, 0x61, 0x3b, 0x63, 0x7a, 0x65, 0x72, 0x77, +0x63, 0x61, 0x3b, 0x6c, 0x69, 0x70, 0x63, 0x61, 0x3b, 0x73, 0x69, 0x65, 0x72, 0x70, 0x6e, 0x69, 0x61, 0x3b, 0x77, 0x72, +0x7a, 0x65, 0x15b, 0x6e, 0x69, 0x61, 0x3b, 0x70, 0x61, 0x17a, 0x64, 0x7a, 0x69, 0x65, 0x72, 0x6e, 0x69, 0x6b, 0x61, 0x3b, +0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x61, 0x3b, 0x67, 0x72, 0x75, 0x64, 0x6e, 0x69, 0x61, 0x3b, 0x4a, 0x61, +0x6e, 0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, +0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x75, 0x74, 0x3b, 0x4e, 0x6f, +0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x4a, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46, 0x65, 0x76, 0x65, 0x72, 0x65, +0x69, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0xe7, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x6f, +0x3b, 0x4a, 0x75, 0x6e, 0x68, 0x6f, 0x3b, 0x4a, 0x75, 0x6c, 0x68, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, +0x53, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x4f, 0x75, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b, 0x4e, 0x6f, 0x76, +0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x44, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, +0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, +0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x75, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, +0x65, 0x7a, 0x3b, 0x6a, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x76, 0x65, 0x72, 0x65, 0x69, 0x72, 0x6f, +0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x6a, 0x75, +0x6e, 0x68, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x68, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, +0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, +0x72, 0x6f, 0x3b, 0x64, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0xa1c, 0xa28, 0xa35, 0xa30, 0xa40, 0x3b, 0xa2b, 0xa3c, +0xa30, 0xa35, 0xa30, 0xa40, 0x3b, 0xa2e, 0xa3e, 0xa30, 0xa1a, 0x3b, 0xa05, 0xa2a, 0xa4d, 0xa30, 0xa48, 0xa32, 0x3b, 0xa2e, 0xa08, 0x3b, +0xa1c, 0xa42, 0xa28, 0x3b, 0xa1c, 0xa41, 0xa32, 0xa3e, 0xa08, 0x3b, 0xa05, 0xa17, 0xa38, 0xa24, 0x3b, 0xa38, 0xa24, 0xa70, 0xa2c, 0xa30, +0x3b, 0xa05, 0xa15, 0xa24, 0xa42, 0xa2c, 0xa30, 0x3b, 0xa28, 0xa35, 0xa70, 0xa2c, 0xa30, 0x3b, 0xa26, 0xa38, 0xa70, 0xa2c, 0xa30, 0x3b, +0x69, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, +0x6d, 0x61, 0x69, 0x3b, 0x69, 0x75, 0x6e, 0x2e, 0x3b, 0x69, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, +0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, +0x69, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b, 0x6d, +0x61, 0x72, 0x74, 0x69, 0x65, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x65, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x69, 0x75, +0x6e, 0x69, 0x65, 0x3b, 0x69, 0x75, 0x6c, 0x69, 0x65, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, +0x74, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x6e, 0x6f, +0x69, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x44f, 0x43d, +0x432, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x430, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, +0x43c, 0x430, 0x44f, 0x3b, 0x438, 0x44e, 0x43d, 0x44f, 0x3b, 0x438, 0x44e, 0x43b, 0x44f, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, +0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, +0x3b, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x44f, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44f, 0x3b, 0x43c, 0x430, 0x440, 0x442, +0x430, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44f, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x438, 0x44e, 0x43d, 0x44f, 0x3b, 0x438, 0x44e, +0x43b, 0x44f, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x430, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44f, 0x3b, +0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, +0x440, 0x44f, 0x3b, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435, 0x431, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, +0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x3b, 0x43e, +0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x432, 0x3b, 0x434, 0x435, 0x446, 0x3b, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x3b, 0x444, 0x435, +0x431, 0x440, 0x443, 0x430, 0x440, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x458, +0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, +0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431, 0x430, 0x440, 0x3b, 0x43d, 0x43e, 0x432, 0x435, 0x43c, 0x431, +0x430, 0x440, 0x3b, 0x434, 0x435, 0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x3b, 0x444, +0x435, 0x431, 0x440, 0x443, 0x430, 0x440, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, +0x458, 0x3b, 0x458, 0x443, 0x43d, 0x438, 0x3b, 0x458, 0x443, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, +0x435, 0x43f, 0x442, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431, 0x430, 0x440, 0x3b, 0x43d, 0x43e, 0x432, +0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x434, 0x435, 0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, +0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, +0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, +0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, +0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, +0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6f, 0x6b, +0x74, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, +0x62, 0x61, 0x72, 0x3b, 0x50, 0x68, 0x65, 0x3b, 0x4b, 0x6f, 0x6c, 0x3b, 0x55, 0x62, 0x65, 0x3b, 0x4d, 0x6d, 0x65, 0x3b, +0x4d, 0x6f, 0x74, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x55, 0x70, 0x75, 0x3b, 0x50, 0x68, 0x61, 0x3b, 0x4c, 0x65, 0x6f, 0x3b, +0x4d, 0x70, 0x68, 0x3b, 0x50, 0x75, 0x6e, 0x3b, 0x54, 0x73, 0x68, 0x3b, 0x50, 0x68, 0x65, 0x73, 0x65, 0x6b, 0x67, 0x6f, +0x6e, 0x67, 0x3b, 0x48, 0x6c, 0x61, 0x6b, 0x6f, 0x6c, 0x61, 0x3b, 0x48, 0x6c, 0x61, 0x6b, 0x75, 0x62, 0x65, 0x6c, 0x65, +0x3b, 0x4d, 0x6d, 0x65, 0x73, 0x65, 0x3b, 0x4d, 0x6f, 0x74, 0x73, 0x68, 0x65, 0x61, 0x6e, 0x6f, 0x6e, 0x67, 0x3b, 0x50, +0x68, 0x75, 0x70, 0x6a, 0x61, 0x6e, 0x65, 0x3b, 0x50, 0x68, 0x75, 0x70, 0x75, 0x3b, 0x50, 0x68, 0x61, 0x74, 0x61, 0x3b, +0x4c, 0x65, 0x6f, 0x74, 0x73, 0x68, 0x65, 0x3b, 0x4d, 0x70, 0x68, 0x61, 0x6c, 0x61, 0x6e, 0x65, 0x3b, 0x50, 0x75, 0x6e, +0x64, 0x75, 0x6e, 0x67, 0x77, 0x61, 0x6e, 0x65, 0x3b, 0x54, 0x73, 0x68, 0x69, 0x74, 0x77, 0x65, 0x3b, 0x46, 0x65, 0x72, +0x3b, 0x54, 0x6c, 0x68, 0x3b, 0x4d, 0x6f, 0x70, 0x3b, 0x4d, 0x6f, 0x72, 0x3b, 0x4d, 0x6f, 0x74, 0x3b, 0x53, 0x65, 0x65, +0x3b, 0x50, 0x68, 0x75, 0x3b, 0x50, 0x68, 0x61, 0x3b, 0x4c, 0x77, 0x65, 0x3b, 0x44, 0x69, 0x70, 0x3b, 0x4e, 0x67, 0x77, +0x3b, 0x53, 0x65, 0x64, 0x3b, 0x46, 0x65, 0x72, 0x69, 0x6b, 0x67, 0x6f, 0x6e, 0x67, 0x3b, 0x54, 0x6c, 0x68, 0x61, 0x6b, +0x6f, 0x6c, 0x65, 0x3b, 0x4d, 0x6f, 0x70, 0x69, 0x74, 0x6c, 0x6f, 0x3b, 0x4d, 0x6f, 0x72, 0x61, 0x6e, 0x61, 0x6e, 0x67, +0x3b, 0x4d, 0x6f, 0x74, 0x73, 0x68, 0x65, 0x67, 0x61, 0x6e, 0x61, 0x6e, 0x67, 0x3b, 0x53, 0x65, 0x65, 0x74, 0x65, 0x62, +0x6f, 0x73, 0x69, 0x67, 0x6f, 0x3b, 0x50, 0x68, 0x75, 0x6b, 0x77, 0x69, 0x3b, 0x50, 0x68, 0x61, 0x74, 0x77, 0x65, 0x3b, +0x4c, 0x77, 0x65, 0x74, 0x73, 0x65, 0x3b, 0x44, 0x69, 0x70, 0x68, 0x61, 0x6c, 0x61, 0x6e, 0x65, 0x3b, 0x4e, 0x67, 0x77, +0x61, 0x6e, 0x61, 0x74, 0x73, 0x65, 0x6c, 0x65, 0x3b, 0x53, 0x65, 0x64, 0x69, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x6f, 0x6c, +0x65, 0x3b, 0xda2, 0xdb1, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, +0xdda, 0xdbd, 0x3b, 0xdb8, 0xdd0, 0xdba, 0x3b, 0xda2, 0xdd6, 0xdb1, 0x3b, 0xda2, 0xdd6, 0xdbd, 0x3b, 0xd85, 0xd9c, 0xddd, 0x3b, 0xdc3, +0xdd0, 0xdb4, 0x3b, 0xd94, 0xd9a, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0x3b, 0xda2, 0xdb1, 0xdc0, 0xdcf, +0xdbb, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0xdbb, 0xdc0, 0xdcf, 0xdbb, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, +0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0, 0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0x3b, 0xda2, 0xdd6, 0xdbd, 0xdd2, 0x3b, 0xd85, +0xd9c, 0xddd, 0xdc3, 0xdca, 0xdad, 0xdd4, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0xdad, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xd94, +0xd9a, 0xdca, 0xdad, 0xddd, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xdaf, 0xdd9, +0xdc3, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0x42, 0x68, 0x69, 0x3b, 0x56, 0x61, 0x6e, 0x3b, 0x56, 0x6f, 0x6c, 0x3b, +0x4d, 0x61, 0x62, 0x3b, 0x4e, 0x6b, 0x68, 0x3b, 0x4e, 0x68, 0x6c, 0x3b, 0x4b, 0x68, 0x6f, 0x3b, 0x4e, 0x67, 0x63, 0x3b, +0x4e, 0x79, 0x6f, 0x3b, 0x4d, 0x70, 0x68, 0x3b, 0x4c, 0x77, 0x65, 0x3b, 0x4e, 0x67, 0x6f, 0x3b, 0x42, 0x68, 0x69, 0x6d, +0x62, 0x69, 0x64, 0x76, 0x77, 0x61, 0x6e, 0x65, 0x3b, 0x69, 0x4e, 0x64, 0x6c, 0x6f, 0x76, 0x61, 0x6e, 0x61, 0x3b, 0x69, +0x4e, 0x64, 0x6c, 0x6f, 0x76, 0x75, 0x2d, 0x6c, 0x65, 0x6e, 0x6b, 0x68, 0x75, 0x6c, 0x75, 0x3b, 0x4d, 0x61, 0x62, 0x61, +0x73, 0x61, 0x3b, 0x69, 0x4e, 0x6b, 0x68, 0x77, 0x65, 0x6b, 0x68, 0x77, 0x65, 0x74, 0x69, 0x3b, 0x69, 0x4e, 0x68, 0x6c, +0x61, 0x62, 0x61, 0x3b, 0x4b, 0x68, 0x6f, 0x6c, 0x77, 0x61, 0x6e, 0x65, 0x3b, 0x69, 0x4e, 0x67, 0x63, 0x69, 0x3b, 0x69, +0x4e, 0x79, 0x6f, 0x6e, 0x69, 0x3b, 0x69, 0x4d, 0x70, 0x68, 0x61, 0x6c, 0x61, 0x3b, 0x4c, 0x77, 0x65, 0x74, 0x69, 0x3b, +0x69, 0x4e, 0x67, 0x6f, 0x6e, 0x67, 0x6f, 0x6e, 0x69, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, +0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0xe1, 0x6a, 0x3b, 0x6a, 0xfa, 0x6e, 0x3b, 0x6a, 0xfa, 0x6c, 0x3b, 0x61, 0x75, +0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, +0x6e, 0x75, 0xe1, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x65, 0x63, 0x3b, 0x61, +0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0xe1, 0x6a, 0x3b, 0x6a, 0xfa, 0x6e, 0x3b, 0x6a, 0xfa, 0x6c, 0x3b, 0x61, 0x75, 0x67, +0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x65, +0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, +0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x65, 0x63, +0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x3b, 0x6a, 0x75, 0x6c, +0x69, 0x6a, 0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, +0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, +0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4b, 0x6f, 0x62, 0x3b, 0x4c, 0x61, 0x62, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x41, 0x66, +0x72, 0x3b, 0x53, 0x68, 0x61, 0x3b, 0x4c, 0x69, 0x78, 0x3b, 0x54, 0x6f, 0x64, 0x3b, 0x53, 0x69, 0x64, 0x3b, 0x53, 0x61, +0x67, 0x3b, 0x54, 0x6f, 0x62, 0x3b, 0x4b, 0x49, 0x54, 0x3b, 0x4c, 0x49, 0x54, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, +0x4b, 0x6f, 0x6f, 0x62, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x61, 0x64, +0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x61, 0x64, 0x64, 0x65, 0x78, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, +0x68, 0x61, 0x20, 0x41, 0x66, 0x72, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x68, 0x61, 0x6e, +0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c, 0x69, 0x78, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, +0x68, 0x61, 0x20, 0x54, 0x6f, 0x64, 0x6f, 0x62, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x69, +0x64, 0x65, 0x65, 0x64, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x61, 0x67, 0x61, 0x61, 0x6c, +0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, +0x73, 0x68, 0x61, 0x20, 0x4b, 0x6f, 0x77, 0x20, 0x69, 0x79, 0x6f, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, +0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x20, 0x69, 0x79, 0x6f, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, +0x61, 0x64, 0x3b, 0x65, 0x6e, 0x65, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, +0x61, 0x79, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, +0x63, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x69, 0x63, 0x3b, 0x65, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x62, +0x72, 0x65, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x79, +0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, +0x3b, 0x73, 0x65, 0x70, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, +0x6e, 0x6f, 0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, +0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, +0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, +0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, +0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x65, +0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x69, 0x3b, +0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, +0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, +0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, +0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, +0x69, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, +0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x42f, 0x43d, +0x432, 0x3b, 0x424, 0x435, 0x432, 0x3b, 0x41c, 0x430, 0x440, 0x3b, 0x410, 0x43f, 0x440, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e, +0x43d, 0x3b, 0x418, 0x44e, 0x43b, 0x3b, 0x410, 0x432, 0x433, 0x3b, 0x421, 0x435, 0x43d, 0x3b, 0x41e, 0x43a, 0x442, 0x3b, 0x41d, 0x43e, +0x44f, 0x3b, 0x414, 0x435, 0x43a, 0x3b, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x41c, +0x430, 0x440, 0x442, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x3b, 0x418, 0x44e, +0x43b, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x41e, 0x43a, 0x442, +0x44f, 0x431, 0x440, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440, 0x3b, 0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x3b, 0xb9c, 0xba9, 0x2e, +0x3b, 0xbaa, 0xbbf, 0xbaa, 0xbcd, 0x2e, 0x3b, 0xbae, 0xbbe, 0xbb0, 0xbcd, 0x2e, 0x3b, 0xb8f, 0xbaa, 0xbcd, 0x2e, 0x3b, 0xbae, 0xbc7, +0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd, 0x3b, 0xb9c, 0xbc2, 0xbb2, 0xbc8, 0x3b, 0xb86, 0xb95, 0x2e, 0x3b, 0xb9a, 0xbc6, 0xbaa, 0xbcd, 0x2e, +0x3b, 0xb85, 0xb95, 0xbcd, 0x2e, 0x3b, 0xba8, 0xbb5, 0x2e, 0x3b, 0xb9f, 0xbbf, 0xb9a, 0x2e, 0x3b, 0xb9c, 0xba9, 0xbb5, 0xbb0, 0xbbf, +0x3b, 0xbaa, 0xbbf, 0xbaa, 0xbcd, 0xbb0, 0xbb5, 0xbb0, 0xbbf, 0x3b, 0xbae, 0xbbe, 0xbb0, 0xbcd, 0xb9a, 0xbcd, 0x3b, 0xb8f, 0xbaa, 0xbcd, +0xbb0, 0xbb2, 0xbcd, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd, 0x3b, 0xb9c, 0xbc2, 0xbb2, 0xbc8, 0x3b, 0xb86, 0xb95, 0xbb8, +0xbcd, 0xb9f, 0xbcd, 0x3b, 0xb9a, 0xbc6, 0xbaa, 0xbcd, 0xb9f, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb85, 0xb95, 0xbcd, 0xb9f, 0xbcb, +0xbaa, 0xbb0, 0xbcd, 0x3b, 0xba8, 0xbb5, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb9f, 0xbbf, 0xb9a, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, +0x3b, 0xc1c, 0xc28, 0xc35, 0xc30, 0xc3f, 0x3b, 0xc2b, 0xc3f, 0xc2c, 0xc4d, 0xc30, 0xc35, 0xc30, 0xc3f, 0x3b, 0xc2e, 0xc3e, 0xc30, 0xc4d, +0xc1a, 0xc3f, 0x3b, 0xc0f, 0xc2a, 0xc4d, 0xc30, 0xc3f, 0xc32, 0xc4d, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42, 0xc28, 0xc4d, 0x3b, 0xc1c, +0xc42, 0xc32, 0xc48, 0x3b, 0xc06, 0xc17, 0xc38, 0xc4d, 0xc1f, 0xc41, 0x3b, 0xc38, 0xc46, 0xc2a, 0xc4d, 0xc1f, 0xc46, 0xc02, 0xc2c, 0xc30, +0xc4d, 0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f, 0xc4b, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc28, 0xc35, 0xc02, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc21, 0xc3f, +0xc38, 0xc46, 0xc02, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xe21, 0x2e, 0xe04, 0x2e, 0x3b, 0xe01, 0x2e, 0xe1e, 0x2e, 0x3b, 0xe21, 0xe35, 0x2e, +0xe04, 0x2e, 0x3b, 0xe40, 0xe21, 0x2e, 0xe22, 0x2e, 0x3b, 0xe1e, 0x2e, 0xe04, 0x2e, 0x3b, 0xe21, 0xe34, 0x2e, 0xe22, 0x2e, 0x3b, +0xe01, 0x2e, 0xe04, 0x2e, 0x3b, 0xe2a, 0x2e, 0xe04, 0x2e, 0x3b, 0xe01, 0x2e, 0xe22, 0x2e, 0x3b, 0xe15, 0x2e, 0xe04, 0x2e, 0x3b, +0xe1e, 0x2e, 0xe22, 0x2e, 0x3b, 0xe18, 0x2e, 0xe04, 0x2e, 0x3b, 0xe21, 0xe01, 0xe23, 0xe32, 0xe04, 0xe21, 0x3b, 0xe01, 0xe38, 0xe21, +0xe20, 0xe32, 0xe1e, 0xe31, 0xe19, 0xe18, 0xe4c, 0x3b, 0xe21, 0xe35, 0xe19, 0xe32, 0xe04, 0xe21, 0x3b, 0xe40, 0xe21, 0xe29, 0xe32, 0xe22, +0xe19, 0x3b, 0xe1e, 0xe24, 0xe29, 0xe20, 0xe32, 0xe04, 0xe21, 0x3b, 0xe21, 0xe34, 0xe16, 0xe38, 0xe19, 0xe32, 0xe22, 0xe19, 0x3b, 0xe01, +0xe23, 0xe01, 0xe0e, 0xe32, 0xe04, 0xe21, 0x3b, 0xe2a, 0xe34, 0xe07, 0xe2b, 0xe32, 0xe04, 0xe21, 0x3b, 0xe01, 0xe31, 0xe19, 0xe22, 0xe32, +0xe22, 0xe19, 0x3b, 0xe15, 0xe38, 0xe25, 0xe32, 0xe04, 0xe21, 0x3b, 0xe1e, 0xe24, 0xe28, 0xe08, 0xe34, 0xe01, 0xe32, 0xe22, 0xe19, 0x3b, +0xe18, 0xe31, 0xe19, 0xe27, 0xe32, 0xe04, 0xe21, 0x3b, 0x1325, 0x122a, 0x3b, 0x1208, 0x12ab, 0x1272, 0x3b, 0x1218, 0x130b, 0x1262, 0x3b, 0x121a, +0x12eb, 0x12dd, 0x3b, 0x130d, 0x1295, 0x1266, 0x3b, 0x1230, 0x1290, 0x3b, 0x1213, 0x121d, 0x1208, 0x3b, 0x1290, 0x1213, 0x1230, 0x3b, 0x1218, 0x1235, +0x12a8, 0x3b, 0x1325, 0x1245, 0x121d, 0x3b, 0x1215, 0x12f3, 0x122d, 0x3b, 0x1273, 0x1215, 0x1233, 0x3b, 0x1325, 0x122a, 0x3b, 0x1208, 0x12ab, 0x1272, +0x1275, 0x3b, 0x1218, 0x130b, 0x1262, 0x1275, 0x3b, 0x121a, 0x12eb, 0x12dd, 0x12eb, 0x3b, 0x130d, 0x1295, 0x1266, 0x1275, 0x3b, 0x1230, 0x1290, 0x3b, +0x1213, 0x121d, 0x1208, 0x3b, 0x1290, 0x1213, 0x1230, 0x3b, 0x1218, 0x1235, 0x12a8, 0x1228, 0x121d, 0x3b, 0x1325, 0x1245, 0x121d, 0x1272, 0x3b, 0x1215, +0x12f3, 0x122d, 0x3b, 0x1273, 0x1215, 0x1233, 0x1235, 0x3b, 0x53, 0x101, 0x6e, 0x3b, 0x46, 0x113, 0x70, 0x3b, 0x4d, 0x61, 0x2bb, 0x61, +0x3b, 0x2bb, 0x45, 0x70, 0x65, 0x3b, 0x4d, 0x113, 0x3b, 0x53, 0x75, 0x6e, 0x3b, 0x53, 0x69, 0x75, 0x3b, 0x2bb, 0x41, 0x6f, +0x6b, 0x3b, 0x53, 0x113, 0x70, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x3b, 0x4e, 0x14d, 0x76, 0x3b, 0x54, 0x69, 0x73, 0x3b, 0x53, +0x101, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x46, 0x113, 0x70, 0x75, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x2bb, 0x61, 0x73, +0x69, 0x3b, 0x2bb, 0x45, 0x70, 0x65, 0x6c, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x113, 0x3b, 0x53, 0x75, 0x6e, 0x65, 0x3b, 0x53, +0x69, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x2bb, 0x41, 0x6f, 0x6b, 0x6f, 0x73, 0x69, 0x3b, 0x53, 0x113, 0x70, 0x69, 0x74, 0x65, +0x6d, 0x61, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x74, 0x6f, 0x70, 0x61, 0x3b, 0x4e, 0x14d, 0x76, 0x65, 0x6d, 0x61, 0x3b, 0x54, +0x69, 0x73, 0x65, 0x6d, 0x61, 0x3b, 0x53, 0x75, 0x6e, 0x3b, 0x59, 0x61, 0x6e, 0x3b, 0x4b, 0x75, 0x6c, 0x3b, 0x44, 0x7a, +0x69, 0x3b, 0x4d, 0x75, 0x64, 0x3b, 0x4b, 0x68, 0x6f, 0x3b, 0x4d, 0x61, 0x77, 0x3b, 0x4d, 0x68, 0x61, 0x3b, 0x4e, 0x64, +0x7a, 0x3b, 0x4e, 0x68, 0x6c, 0x3b, 0x48, 0x75, 0x6b, 0x3b, 0x4e, 0x27, 0x77, 0x3b, 0x53, 0x75, 0x6e, 0x67, 0x75, 0x74, +0x69, 0x3b, 0x4e, 0x79, 0x65, 0x6e, 0x79, 0x65, 0x6e, 0x79, 0x61, 0x6e, 0x69, 0x3b, 0x4e, 0x79, 0x65, 0x6e, 0x79, 0x61, +0x6e, 0x6b, 0x75, 0x6c, 0x75, 0x3b, 0x44, 0x7a, 0x69, 0x76, 0x61, 0x6d, 0x69, 0x73, 0x6f, 0x6b, 0x6f, 0x3b, 0x4d, 0x75, +0x64, 0x79, 0x61, 0x78, 0x69, 0x68, 0x69, 0x3b, 0x4b, 0x68, 0x6f, 0x74, 0x61, 0x76, 0x75, 0x78, 0x69, 0x6b, 0x61, 0x3b, +0x4d, 0x61, 0x77, 0x75, 0x77, 0x61, 0x6e, 0x69, 0x3b, 0x4d, 0x68, 0x61, 0x77, 0x75, 0x72, 0x69, 0x3b, 0x4e, 0x64, 0x7a, +0x68, 0x61, 0x74, 0x69, 0x3b, 0x4e, 0x68, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x3b, 0x48, 0x75, 0x6b, 0x75, 0x72, +0x69, 0x3b, 0x4e, 0x27, 0x77, 0x65, 0x6e, 0x64, 0x7a, 0x61, 0x6d, 0x68, 0x61, 0x6c, 0x61, 0x3b, 0x4f, 0x63, 0x61, 0x3b, +0x15e, 0x75, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4e, 0x69, 0x73, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x48, 0x61, 0x7a, 0x3b, +0x54, 0x65, 0x6d, 0x3b, 0x41, 0x11f, 0x75, 0x3b, 0x45, 0x79, 0x6c, 0x3b, 0x45, 0x6b, 0x69, 0x3b, 0x4b, 0x61, 0x73, 0x3b, +0x41, 0x72, 0x61, 0x3b, 0x4f, 0x63, 0x61, 0x6b, 0x3b, 0x15e, 0x75, 0x62, 0x61, 0x74, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, +0x4e, 0x69, 0x73, 0x61, 0x6e, 0x3b, 0x4d, 0x61, 0x79, 0x131, 0x73, 0x3b, 0x48, 0x61, 0x7a, 0x69, 0x72, 0x61, 0x6e, 0x3b, +0x54, 0x65, 0x6d, 0x6d, 0x75, 0x7a, 0x3b, 0x41, 0x11f, 0x75, 0x73, 0x74, 0x6f, 0x73, 0x3b, 0x45, 0x79, 0x6c, 0xfc, 0x6c, +0x3b, 0x45, 0x6b, 0x69, 0x6d, 0x3b, 0x4b, 0x61, 0x73, 0x131, 0x6d, 0x3b, 0x41, 0x72, 0x61, 0x6c, 0x131, 0x6b, 0x3b, 0x441, +0x456, 0x447, 0x2e, 0x3b, 0x43b, 0x44e, 0x442, 0x2e, 0x3b, 0x431, 0x435, 0x440, 0x2e, 0x3b, 0x43a, 0x432, 0x456, 0x442, 0x2e, 0x3b, +0x442, 0x440, 0x430, 0x432, 0x2e, 0x3b, 0x447, 0x435, 0x440, 0x432, 0x2e, 0x3b, 0x43b, 0x438, 0x43f, 0x2e, 0x3b, 0x441, 0x435, 0x440, +0x43f, 0x2e, 0x3b, 0x432, 0x435, 0x440, 0x2e, 0x3b, 0x436, 0x43e, 0x432, 0x442, 0x2e, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x2e, 0x3b, +0x433, 0x440, 0x443, 0x434, 0x2e, 0x3b, 0x441, 0x456, 0x447, 0x43d, 0x44f, 0x3b, 0x43b, 0x44e, 0x442, 0x43e, 0x433, 0x43e, 0x3b, 0x431, +0x435, 0x440, 0x435, 0x437, 0x43d, 0x44f, 0x3b, 0x43a, 0x432, 0x456, 0x442, 0x43d, 0x44f, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x43d, 0x44f, +0x3b, 0x447, 0x435, 0x440, 0x432, 0x43d, 0x44f, 0x3b, 0x43b, 0x438, 0x43f, 0x43d, 0x44f, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x43d, 0x44f, +0x3b, 0x432, 0x435, 0x440, 0x435, 0x441, 0x43d, 0x44f, 0x3b, 0x436, 0x43e, 0x432, 0x442, 0x43d, 0x44f, 0x3b, 0x43b, 0x438, 0x441, 0x442, +0x43e, 0x43f, 0x430, 0x434, 0x430, 0x3b, 0x433, 0x440, 0x443, 0x434, 0x43d, 0x44f, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, +0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x20, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x626, 0x3b, +0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x626, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, +0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, +0x41c, 0x443, 0x4b3, 0x430, 0x440, 0x440, 0x430, 0x43c, 0x3b, 0x421, 0x430, 0x444, 0x430, 0x440, 0x3b, 0x420, 0x430, 0x431, 0x438, 0x443, +0x43b, 0x2d, 0x430, 0x432, 0x432, 0x430, 0x43b, 0x3b, 0x420, 0x430, 0x431, 0x438, 0x443, 0x43b, 0x2d, 0x43e, 0x445, 0x438, 0x440, 0x3b, +0x416, 0x443, 0x43c, 0x43e, 0x434, 0x438, 0x443, 0x43b, 0x2d, 0x443, 0x43b, 0x43e, 0x3b, 0x416, 0x443, 0x43c, 0x43e, 0x434, 0x438, 0x443, +0x43b, 0x2d, 0x443, 0x445, 0x440, 0x43e, 0x3b, 0x420, 0x430, 0x436, 0x430, 0x431, 0x3b, 0x428, 0x430, 0x44a, 0x431, 0x43e, 0x43d, 0x3b, +0x420, 0x430, 0x43c, 0x430, 0x437, 0x43e, 0x43d, 0x3b, 0x428, 0x430, 0x432, 0x432, 0x43e, 0x43b, 0x3b, 0x417, 0x438, 0x43b, 0x2d, 0x49b, +0x430, 0x44a, 0x434, 0x430, 0x3b, 0x417, 0x438, 0x43b, 0x2d, 0x4b3, 0x438, 0x436, 0x436, 0x430, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x31, +0x3b, 0x74, 0x68, 0x67, 0x20, 0x32, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x33, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x34, 0x3b, 0x74, +0x68, 0x67, 0x20, 0x35, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x36, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x37, 0x3b, 0x74, 0x68, 0x67, +0x20, 0x38, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x39, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x31, 0x30, 0x3b, 0x74, 0x68, 0x67, 0x20, +0x31, 0x31, 0x3b, 0x74, 0x68, 0x67, 0x20, 0x31, 0x32, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x6d, 0x1ed9, 0x74, 0x3b, +0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x68, 0x61, 0x69, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x62, 0x61, 0x3b, 0x74, +0x68, 0xe1, 0x6e, 0x67, 0x20, 0x74, 0x1b0, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x6e, 0x103, 0x6d, 0x3b, 0x74, 0x68, +0xe1, 0x6e, 0x67, 0x20, 0x73, 0xe1, 0x75, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x62, 0x1ea3, 0x79, 0x3b, 0x74, 0x68, +0xe1, 0x6e, 0x67, 0x20, 0x74, 0xe1, 0x6d, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x63, 0x68, 0xed, 0x6e, 0x3b, 0x74, +0x68, 0xe1, 0x6e, 0x67, 0x20, 0x6d, 0x1b0, 0x1edd, 0x69, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x6d, 0x1b0, 0x1edd, 0x69, +0x20, 0x6d, 0x1ed9, 0x74, 0x3b, 0x74, 0x68, 0xe1, 0x6e, 0x67, 0x20, 0x6d, 0x1b0, 0x1edd, 0x69, 0x20, 0x68, 0x61, 0x69, 0x3b, +0x49, 0x6f, 0x6e, 0x3b, 0x43, 0x68, 0x77, 0x65, 0x66, 0x3b, 0x4d, 0x61, 0x77, 0x72, 0x74, 0x68, 0x3b, 0x45, 0x62, 0x72, +0x69, 0x6c, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4d, 0x65, 0x68, 0x3b, 0x47, 0x6f, 0x72, 0x66, 0x66, 0x3b, 0x41, 0x77, +0x73, 0x74, 0x3b, 0x4d, 0x65, 0x64, 0x69, 0x3b, 0x48, 0x79, 0x64, 0x3b, 0x54, 0x61, 0x63, 0x68, 0x3b, 0x52, 0x68, 0x61, +0x67, 0x3b, 0x49, 0x6f, 0x6e, 0x61, 0x77, 0x72, 0x3b, 0x43, 0x68, 0x77, 0x65, 0x66, 0x72, 0x6f, 0x72, 0x3b, 0x4d, 0x61, +0x77, 0x72, 0x74, 0x68, 0x3b, 0x45, 0x62, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4d, 0x65, 0x68, 0x65, +0x66, 0x69, 0x6e, 0x3b, 0x47, 0x6f, 0x72, 0x66, 0x66, 0x65, 0x6e, 0x61, 0x66, 0x3b, 0x41, 0x77, 0x73, 0x74, 0x3b, 0x4d, +0x65, 0x64, 0x69, 0x3b, 0x48, 0x79, 0x64, 0x72, 0x65, 0x66, 0x3b, 0x54, 0x61, 0x63, 0x68, 0x77, 0x65, 0x64, 0x64, 0x3b, +0x52, 0x68, 0x61, 0x67, 0x66, 0x79, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x74, 0x3b, +0x45, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x61, 0x3b, +0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x79, +0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x74, 0x73, +0x68, 0x69, 0x3b, 0x45, 0x70, 0x72, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x65, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, +0x4a, 0x75, 0x6c, 0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, +0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x68, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, +0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x1e62, 0x1eb9, 0x301, 0x72, 0x1eb9, 0x301, 0x3b, 0xc8, 0x72, 0xe8, 0x6c, 0xe8, 0x3b, +0x1eb8, 0x72, 0x1eb9, 0x300, 0x6e, 0xe0, 0x3b, 0xcc, 0x67, 0x62, 0xe9, 0x3b, 0x1eb8, 0x300, 0x62, 0x69, 0x62, 0x69, 0x3b, 0xd2, +0x6b, 0xfa, 0x64, 0x75, 0x3b, 0x41, 0x67, 0x1eb9, 0x6d, 0x1ecd, 0x3b, 0xd2, 0x67, 0xfa, 0x6e, 0x3b, 0x4f, 0x77, 0x65, 0x77, +0x65, 0x3b, 0x1ecc, 0x300, 0x77, 0xe0, 0x72, 0xe0, 0x3b, 0x42, 0xe9, 0x6c, 0xfa, 0x3b, 0x1ecc, 0x300, 0x70, 0x1eb9, 0x300, 0x3b, +0x4f, 0x1e63, 0xf9, 0x20, 0x1e62, 0x1eb9, 0x301, 0x72, 0x1eb9, 0x301, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0xc8, 0x72, 0xe8, 0x6c, 0xe8, +0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0x1eb8, 0x72, 0x1eb9, 0x300, 0x6e, 0xe0, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0xcc, 0x67, 0x62, 0xe9, +0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0x1eb8, 0x300, 0x62, 0x69, 0x62, 0x69, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0xd2, 0x6b, 0xfa, 0x64, +0x75, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0x41, 0x67, 0x1eb9, 0x6d, 0x1ecd, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0xd2, 0x67, 0xfa, 0x6e, +0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0x4f, 0x77, 0x65, 0x77, 0x65, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0x1ecc, 0x300, 0x77, 0xe0, 0x72, +0xe0, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0x42, 0xe9, 0x6c, 0xfa, 0x3b, 0x4f, 0x1e63, 0xf9, 0x20, 0x1ecc, 0x300, 0x70, 0x1eb9, 0x300, +0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x73, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x79, +0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x61, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, +0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, +0x62, 0x72, 0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x73, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x69, +0x3b, 0x4d, 0x65, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, +0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x68, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x68, 0x6f, +0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, +0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x6a, 0x3b, 0x4a, +0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x76, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, +0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, +0x72, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x6a, 0x3b, 0x4a, 0x75, 0x6e, +0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, +0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, +0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4a, 0x2d, 0x67, 0x75, 0x65, 0x72, 0x3b, 0x54, 0x2d, 0x61, +0x72, 0x72, 0x65, 0x65, 0x3b, 0x4d, 0x61, 0x79, 0x72, 0x6e, 0x74, 0x3b, 0x41, 0x76, 0x72, 0x72, 0x69, 0x6c, 0x3b, 0x42, +0x6f, 0x61, 0x6c, 0x64, 0x79, 0x6e, 0x3b, 0x4d, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4a, 0x2d, 0x73, 0x6f, +0x75, 0x72, 0x65, 0x65, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x79, 0x6e, 0x3b, 0x4d, 0x2d, 0x66, 0x6f, 0x75, +0x79, 0x69, 0x72, 0x3b, 0x4a, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4d, 0x2e, 0x48, 0x6f, 0x75, 0x6e, 0x65, +0x79, 0x3b, 0x4d, 0x2e, 0x4e, 0x6f, 0x6c, 0x6c, 0x69, 0x63, 0x6b, 0x3b, 0x4a, 0x65, 0x72, 0x72, 0x65, 0x79, 0x2d, 0x67, +0x65, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x54, 0x6f, 0x73, 0x68, 0x69, 0x61, 0x67, 0x68, 0x74, 0x2d, 0x61, 0x72, 0x72, 0x65, +0x65, 0x3b, 0x4d, 0x61, 0x79, 0x72, 0x6e, 0x74, 0x3b, 0x41, 0x76, 0x65, 0x72, 0x69, 0x6c, 0x3b, 0x42, 0x6f, 0x61, 0x6c, +0x64, 0x79, 0x6e, 0x3b, 0x4d, 0x65, 0x61, 0x6e, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4a, 0x65, 0x72, 0x72, +0x65, 0x79, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x79, 0x6e, 0x3b, +0x4d, 0x65, 0x61, 0x6e, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4a, 0x65, 0x72, 0x72, 0x65, 0x79, 0x2d, 0x66, +0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x20, 0x48, 0x6f, 0x75, 0x6e, 0x65, 0x79, 0x3b, 0x4d, 0x65, 0x65, +0x20, 0x6e, 0x79, 0x20, 0x4e, 0x6f, 0x6c, 0x6c, 0x69, 0x63, 0x6b, 0x3b, 0x47, 0x65, 0x6e, 0x3b, 0x57, 0x68, 0x65, 0x3b, +0x4d, 0x65, 0x72, 0x3b, 0x45, 0x62, 0x72, 0x3b, 0x4d, 0x65, 0x3b, 0x45, 0x66, 0x6e, 0x3b, 0x47, 0x6f, 0x72, 0x3b, 0x45, +0x73, 0x74, 0x3b, 0x47, 0x77, 0x6e, 0x3b, 0x48, 0x65, 0x64, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x65, 0x76, 0x3b, 0x4d, 0x79, +0x73, 0x20, 0x47, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x57, 0x68, 0x65, 0x76, 0x72, 0x65, 0x6c, +0x3b, 0x4d, 0x79, 0x73, 0x20, 0x4d, 0x65, 0x72, 0x74, 0x68, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x45, 0x62, 0x72, 0x65, 0x6c, +0x3b, 0x4d, 0x79, 0x73, 0x20, 0x4d, 0x65, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x45, 0x66, 0x61, 0x6e, 0x3b, 0x4d, 0x79, 0x73, +0x20, 0x47, 0x6f, 0x72, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6e, 0x3b, 0x4d, 0x79, 0x65, 0x20, 0x45, 0x73, 0x74, 0x3b, 0x4d, +0x79, 0x73, 0x20, 0x47, 0x77, 0x79, 0x6e, 0x67, 0x61, 0x6c, 0x61, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x48, 0x65, 0x64, 0x72, +0x61, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x44, 0x75, 0x3b, 0x4d, 0x79, 0x73, 0x20, 0x4b, 0x65, 0x76, 0x61, 0x72, 0x64, 0x68, +0x75, 0x3b, 0x53, 0x2d, 0x186, 0x3b, 0x4b, 0x2d, 0x186, 0x3b, 0x45, 0x2d, 0x186, 0x3b, 0x45, 0x2d, 0x4f, 0x3b, 0x45, 0x2d, +0x4b, 0x3b, 0x4f, 0x2d, 0x41, 0x3b, 0x41, 0x2d, 0x4b, 0x3b, 0x44, 0x2d, 0x186, 0x3b, 0x46, 0x2d, 0x190, 0x3b, 0x186, 0x2d, +0x41, 0x3b, 0x186, 0x2d, 0x4f, 0x3b, 0x4d, 0x2d, 0x186, 0x3b, 0x53, 0x61, 0x6e, 0x64, 0x61, 0x2d, 0x186, 0x70, 0x25b, 0x70, +0x254, 0x6e, 0x3b, 0x4b, 0x77, 0x61, 0x6b, 0x77, 0x61, 0x72, 0x2d, 0x186, 0x67, 0x79, 0x65, 0x66, 0x75, 0x6f, 0x3b, 0x45, +0x62, 0x254, 0x77, 0x2d, 0x186, 0x62, 0x65, 0x6e, 0x65, 0x6d, 0x3b, 0x45, 0x62, 0x254, 0x62, 0x69, 0x72, 0x61, 0x2d, 0x4f, +0x66, 0x6f, 0x72, 0x69, 0x73, 0x75, 0x6f, 0x3b, 0x45, 0x73, 0x75, 0x73, 0x6f, 0x77, 0x20, 0x41, 0x6b, 0x65, 0x74, 0x73, +0x65, 0x61, 0x62, 0x61, 0x2d, 0x4b, 0x254, 0x74, 0x254, 0x6e, 0x69, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x62, 0x69, 0x72, 0x61, +0x64, 0x65, 0x2d, 0x41, 0x79, 0x25b, 0x77, 0x6f, 0x68, 0x6f, 0x6d, 0x75, 0x6d, 0x75, 0x3b, 0x41, 0x79, 0x25b, 0x77, 0x6f, +0x68, 0x6f, 0x2d, 0x4b, 0x69, 0x74, 0x61, 0x77, 0x6f, 0x6e, 0x73, 0x61, 0x3b, 0x44, 0x69, 0x66, 0x75, 0x75, 0x2d, 0x186, +0x73, 0x61, 0x6e, 0x64, 0x61, 0x61, 0x3b, 0x46, 0x61, 0x6e, 0x6b, 0x77, 0x61, 0x2d, 0x190, 0x62, 0x254, 0x3b, 0x186, 0x62, +0x25b, 0x73, 0x25b, 0x2d, 0x41, 0x68, 0x69, 0x6e, 0x69, 0x6d, 0x65, 0x3b, 0x186, 0x62, 0x65, 0x72, 0x25b, 0x66, 0x25b, 0x77, +0x2d, 0x4f, 0x62, 0x75, 0x62, 0x75, 0x6f, 0x3b, 0x4d, 0x75, 0x6d, 0x75, 0x2d, 0x186, 0x70, 0x25b, 0x6e, 0x69, 0x6d, 0x62, +0x61, 0x3b, 0x91c, 0x93e, 0x928, 0x947, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x943, 0x935, 0x93e, 0x930, 0x940, 0x3b, +0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x90f, 0x92a, 0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b, +0x91c, 0x941, 0x932, 0x948, 0x3b, 0x913, 0x917, 0x938, 0x94d, 0x91f, 0x3b, 0x938, 0x947, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x92c, 0x930, +0x3b, 0x913, 0x915, 0x94d, 0x91f, 0x94b, 0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x921, +0x93f, 0x938, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x41, 0x68, 0x61, 0x3b, 0x4f, 0x66, 0x6c, 0x3b, 0x4f, 0x63, 0x68, 0x3b, 0x41, +0x62, 0x65, 0x3b, 0x41, 0x67, 0x62, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x4d, 0x61, 0x6e, 0x3b, 0x47, +0x62, 0x6f, 0x3b, 0x41, 0x6e, 0x74, 0x3b, 0x41, 0x6c, 0x65, 0x3b, 0x41, 0x66, 0x75, 0x3b, 0x41, 0x68, 0x61, 0x72, 0x61, +0x62, 0x61, 0x74, 0x61, 0x3b, 0x4f, 0x66, 0x6c, 0x6f, 0x3b, 0x4f, 0x63, 0x68, 0x6f, 0x6b, 0x72, 0x69, 0x6b, 0x72, 0x69, +0x3b, 0x41, 0x62, 0x65, 0x69, 0x62, 0x65, 0x65, 0x3b, 0x41, 0x67, 0x62, 0x65, 0x69, 0x6e, 0x61, 0x61, 0x3b, 0x4f, 0x74, +0x75, 0x6b, 0x77, 0x61, 0x64, 0x61, 0x6e, 0x3b, 0x4d, 0x61, 0x61, 0x77, 0x65, 0x3b, 0x4d, 0x61, 0x6e, 0x79, 0x61, 0x77, +0x61, 0x6c, 0x65, 0x3b, 0x47, 0x62, 0x6f, 0x3b, 0x41, 0x6e, 0x74, 0x6f, 0x6e, 0x3b, 0x41, 0x6c, 0x65, 0x6d, 0x6c, 0x65, +0x3b, 0x41, 0x66, 0x75, 0x61, 0x62, 0x65, 0x65, 0x3b, 0x4a, 0x65, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x61, +0x3b, 0x45, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x75, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x1ecc, 0x67, 0x1ecd, +0x3b, 0x53, 0x65, 0x70, 0x3b, 0x1ecc, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x65, 0x6e, +0x1ee5, 0x77, 0x61, 0x72, 0x1ecb, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x1ee5, 0x77, 0x61, 0x72, 0x1ecb, 0x3b, 0x4d, 0x61, 0x61, 0x63, +0x68, 0x1ecb, 0x3b, 0x45, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x3b, 0x4a, 0x75, +0x6c, 0x61, 0x1ecb, 0x3b, 0x1ecc, 0x67, 0x1ecd, 0x1ecd, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, +0x1ecc, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, +0x62, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x69, +0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, +0x61, 0x74, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4d, 0x77, +0x65, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x69, 0x20, 0x77, 0x61, +0x20, 0x74, 0x68, 0x61, 0x6e, 0x74, 0x68, 0x61, 0x74, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, +0x75, 0x6f, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6e, 0x79, 0x61, 0x6e, 0x79, 0x61, +0x3b, 0x4d, 0x77, 0x65, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x69, 0x20, +0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, +0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x6d, 0x77, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, +0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x6c, 0x69, 0x3b, 0x70f, 0x71f, 0x722, 0xa0, 0x70f, 0x712, 0x3b, 0x72b, +0x712, 0x71b, 0x3b, 0x710, 0x715, 0x72a, 0x3b, 0x722, 0x71d, 0x723, 0x722, 0x3b, 0x710, 0x71d, 0x72a, 0x3b, 0x71a, 0x719, 0x71d, 0x72a, +0x722, 0x3b, 0x72c, 0x721, 0x718, 0x719, 0x3b, 0x710, 0x712, 0x3b, 0x710, 0x71d, 0x720, 0x718, 0x720, 0x3b, 0x70f, 0x72c, 0x72b, 0xa0, +0x70f, 0x710, 0x3b, 0x70f, 0x72c, 0x72b, 0xa0, 0x70f, 0x712, 0x3b, 0x70f, 0x71f, 0x722, 0xa0, 0x70f, 0x710, 0x3b, 0x70f, 0x71f, 0x722, +0x20, 0x70f, 0x712, 0x3b, 0x72b, 0x712, 0x71b, 0x3b, 0x710, 0x715, 0x72a, 0x3b, 0x722, 0x71d, 0x723, 0x722, 0x3b, 0x710, 0x71d, 0x72a, +0x3b, 0x71a, 0x719, 0x71d, 0x72a, 0x722, 0x3b, 0x72c, 0x721, 0x718, 0x719, 0x3b, 0x710, 0x712, 0x3b, 0x710, 0x71d, 0x720, 0x718, 0x720, +0x3b, 0x70f, 0x72c, 0x72b, 0x20, 0x70f, 0x710, 0x3b, 0x70f, 0x72c, 0x72b, 0x20, 0x70f, 0x712, 0x3b, 0x70f, 0x71f, 0x722, 0x20, 0x70f, +0x710, 0x3b, 0x120d, 0x12f0, 0x1275, 0x3b, 0x12ab, 0x1265, 0x12bd, 0x3b, 0x12ad, 0x1265, 0x120b, 0x3b, 0x134b, 0x1305, 0x12ba, 0x3b, 0x12ad, 0x1262, +0x1245, 0x3b, 0x121d, 0x2f, 0x1275, 0x3b, 0x12b0, 0x122d, 0x3b, 0x121b, 0x122d, 0x12eb, 0x3b, 0x12eb, 0x12b8, 0x1292, 0x3b, 0x1218, 0x1270, 0x1209, +0x3b, 0x121d, 0x2f, 0x121d, 0x3b, 0x1270, 0x1215, 0x1233, 0x3b, 0x120d, 0x12f0, 0x1275, 0x122a, 0x3b, 0x12ab, 0x1265, 0x12bd, 0x1265, 0x1272, 0x3b, +0x12ad, 0x1265, 0x120b, 0x3b, 0x134b, 0x1305, 0x12ba, 0x122a, 0x3b, 0x12ad, 0x1262, 0x1245, 0x122a, 0x3b, 0x121d, 0x12aa, 0x12a4, 0x120d, 0x20, 0x1275, +0x131f, 0x1292, 0x122a, 0x3b, 0x12b0, 0x122d, 0x12a9, 0x3b, 0x121b, 0x122d, 0x12eb, 0x121d, 0x20, 0x1275, 0x122a, 0x3b, 0x12eb, 0x12b8, 0x1292, 0x20, +0x1218, 0x1233, 0x1245, 0x1208, 0x122a, 0x3b, 0x1218, 0x1270, 0x1209, 0x3b, 0x121d, 0x12aa, 0x12a4, 0x120d, 0x20, 0x1218, 0x123d, 0x12c8, 0x122a, 0x3b, +0x1270, 0x1215, 0x1233, 0x1235, 0x122a, 0x3b, 0x1320, 0x1210, 0x1228, 0x3b, 0x12a8, 0x1270, 0x1270, 0x3b, 0x1218, 0x1308, 0x1260, 0x3b, 0x12a0, 0x1280, +0x12d8, 0x3b, 0x130d, 0x1295, 0x1263, 0x3b, 0x1220, 0x1295, 0x12e8, 0x3b, 0x1210, 0x1218, 0x1208, 0x3b, 0x1290, 0x1210, 0x1230, 0x3b, 0x12a8, 0x1228, +0x1218, 0x3b, 0x1320, 0x1240, 0x1218, 0x3b, 0x1280, 0x12f0, 0x1228, 0x3b, 0x1280, 0x1220, 0x1220, 0x3b, 0x1320, 0x1210, 0x1228, 0x3b, 0x12a8, 0x1270, +0x1270, 0x3b, 0x1218, 0x1308, 0x1260, 0x3b, 0x12a0, 0x1280, 0x12d8, 0x3b, 0x130d, 0x1295, 0x1263, 0x1275, 0x3b, 0x1220, 0x1295, 0x12e8, 0x3b, 0x1210, +0x1218, 0x1208, 0x3b, 0x1290, 0x1210, 0x1230, 0x3b, 0x12a8, 0x1228, 0x1218, 0x3b, 0x1320, 0x1240, 0x1218, 0x3b, 0x1280, 0x12f0, 0x1228, 0x3b, 0x1280, +0x1220, 0x1220, 0x3b, 0x57, 0x65, 0x79, 0x3b, 0x46, 0x61, 0x6e, 0x3b, 0x54, 0x61, 0x74, 0x3b, 0x4e, 0x61, 0x6e, 0x3b, 0x54, +0x75, 0x79, 0x3b, 0x54, 0x73, 0x6f, 0x3b, 0x54, 0x61, 0x66, 0x3b, 0x57, 0x61, 0x72, 0x3b, 0x4b, 0x75, 0x6e, 0x3b, 0x42, +0x61, 0x6e, 0x3b, 0x4b, 0x6f, 0x6d, 0x3b, 0x53, 0x61, 0x75, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x57, 0x65, 0x79, 0x65, 0x6e, +0x65, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x46, 0x61, 0x6e, 0x69, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x54, 0x61, 0x74, 0x61, 0x6b, +0x61, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x4e, 0x61, 0x6e, 0x67, 0x72, 0x61, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x54, 0x75, 0x79, +0x6f, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x54, 0x73, 0x6f, 0x79, 0x69, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x54, 0x61, 0x66, 0x61, +0x6b, 0x61, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x57, 0x61, 0x72, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x4b, +0x75, 0x6e, 0x6f, 0x62, 0x6f, 0x6b, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x42, 0x61, 0x6e, 0x73, 0x6f, 0x6b, 0x3b, 0x46, 0x61, +0x69, 0x20, 0x4b, 0x6f, 0x6d, 0x3b, 0x46, 0x61, 0x69, 0x20, 0x53, 0x61, 0x75, 0x6b, 0x3b, 0x44, 0x79, 0x6f, 0x6e, 0x3b, +0x42, 0x61, 0x61, 0x3b, 0x41, 0x74, 0x61, 0x74, 0x3b, 0x41, 0x6e, 0x61, 0x73, 0x3b, 0x41, 0x74, 0x79, 0x6f, 0x3b, 0x41, +0x63, 0x68, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x72, 0x3b, 0x41, 0x77, 0x75, 0x72, 0x3b, 0x53, 0x68, 0x61, 0x64, 0x3b, 0x53, +0x68, 0x61, 0x6b, 0x3b, 0x4e, 0x61, 0x62, 0x61, 0x3b, 0x4e, 0x61, 0x74, 0x61, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x44, 0x79, +0x6f, 0x6e, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x42, 0x61, 0x27, 0x61, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x41, 0x74, 0x61, 0x74, +0x3b, 0x50, 0x65, 0x6e, 0x20, 0x41, 0x6e, 0x61, 0x73, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x41, 0x74, 0x79, 0x6f, 0x6e, 0x3b, +0x50, 0x65, 0x6e, 0x20, 0x41, 0x63, 0x68, 0x69, 0x72, 0x69, 0x6d, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x41, 0x74, 0x61, 0x72, +0x69, 0x62, 0x61, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x41, 0x77, 0x75, 0x72, 0x72, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x53, 0x68, +0x61, 0x64, 0x6f, 0x6e, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x53, 0x68, 0x61, 0x6b, 0x75, 0x72, 0x3b, 0x50, 0x65, 0x6e, 0x20, +0x4b, 0x75, 0x72, 0x20, 0x4e, 0x61, 0x62, 0x61, 0x3b, 0x50, 0x65, 0x6e, 0x20, 0x4b, 0x75, 0x72, 0x20, 0x4e, 0x61, 0x74, +0x61, 0x74, 0x3b, 0x41, 0x331, 0x79, 0x72, 0x3b, 0x41, 0x331, 0x68, 0x77, 0x3b, 0x41, 0x331, 0x74, 0x61, 0x3b, 0x41, 0x331, +0x6e, 0x61, 0x3b, 0x41, 0x331, 0x70, 0x66, 0x3b, 0x41, 0x331, 0x6b, 0x69, 0x3b, 0x41, 0x331, 0x74, 0x79, 0x3b, 0x41, 0x331, +0x6e, 0x69, 0x3b, 0x41, 0x331, 0x6b, 0x75, 0x3b, 0x53, 0x77, 0x61, 0x3b, 0x53, 0x62, 0x79, 0x3b, 0x53, 0x62, 0x68, 0x3b, +0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, 0x41, 0x331, 0x79, 0x72, 0x6e, 0x69, 0x67, 0x3b, 0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, +0x41, 0x331, 0x68, 0x77, 0x61, 0x3b, 0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, 0x41, 0x331, 0x74, 0x61, 0x74, 0x3b, 0x48, 0x79, +0x77, 0x61, 0x6e, 0x20, 0x41, 0x331, 0x6e, 0x61, 0x61, 0x69, 0x3b, 0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, 0x41, 0x331, 0x70, +0x66, 0x77, 0x6f, 0x6e, 0x3b, 0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, 0x41, 0x331, 0x6b, 0x69, 0x74, 0x61, 0x74, 0x3b, 0x48, +0x79, 0x77, 0x61, 0x6e, 0x20, 0x41, 0x331, 0x74, 0x79, 0x69, 0x72, 0x69, 0x6e, 0x3b, 0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, +0x41, 0x331, 0x6e, 0x69, 0x6e, 0x61, 0x69, 0x3b, 0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, 0x41, 0x331, 0x6b, 0x75, 0x6d, 0x76, +0x69, 0x72, 0x69, 0x79, 0x69, 0x6e, 0x3b, 0x48, 0x79, 0x77, 0x61, 0x6e, 0x20, 0x53, 0x77, 0x61, 0x6b, 0x3b, 0x48, 0x79, +0x77, 0x61, 0x6e, 0x20, 0x53, 0x77, 0x61, 0x6b, 0x20, 0x42, 0x27, 0x61, 0x331, 0x79, 0x72, 0x6e, 0x69, 0x67, 0x3b, 0x48, +0x79, 0x77, 0x61, 0x6e, 0x20, 0x53, 0x77, 0x61, 0x6b, 0x20, 0x42, 0x27, 0x61, 0x331, 0x68, 0x77, 0x61, 0x3b, 0x5a, 0x65, +0x6e, 0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x76, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, +0x67, 0x3b, 0x4c, 0x75, 0x69, 0x3b, 0x41, 0x76, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4e, 0x6f, +0x76, 0x3b, 0x44, 0x69, 0x63, 0x3b, 0x5a, 0x65, 0x6e, 0xe2, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72, 0xe2, 0x72, 0x3b, 0x4d, +0x61, 0x72, 0xe7, 0x3b, 0x41, 0x76, 0x72, 0xee, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x67, 0x6e, 0x3b, 0x4c, +0x75, 0x69, 0x3b, 0x41, 0x76, 0x6f, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x74, +0x75, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44, 0x69, 0x63, 0x65, 0x6d, 0x62, +0x61, 0x72, 0x3b, 0x50, 0x68, 0x61, 0x3b, 0x4c, 0x75, 0x68, 0x3b, 0x1e70, 0x68, 0x61, 0x3b, 0x4c, 0x61, 0x6d, 0x3b, 0x53, +0x68, 0x75, 0x3b, 0x4c, 0x77, 0x69, 0x3b, 0x4c, 0x77, 0x61, 0x3b, 0x1e70, 0x68, 0x61, 0x3b, 0x4b, 0x68, 0x75, 0x3b, 0x54, +0x73, 0x68, 0x3b, 0x1e3c, 0x61, 0x72, 0x3b, 0x4e, 0x79, 0x65, 0x3b, 0x50, 0x68, 0x61, 0x6e, 0x64, 0x6f, 0x3b, 0x4c, 0x75, +0x68, 0x75, 0x68, 0x69, 0x3b, 0x1e70, 0x68, 0x61, 0x66, 0x61, 0x6d, 0x75, 0x68, 0x77, 0x65, 0x3b, 0x4c, 0x61, 0x6d, 0x62, +0x61, 0x6d, 0x61, 0x69, 0x3b, 0x53, 0x68, 0x75, 0x6e, 0x64, 0x75, 0x6e, 0x74, 0x68, 0x75, 0x6c, 0x65, 0x3b, 0x46, 0x75, +0x6c, 0x77, 0x69, 0x3b, 0x46, 0x75, 0x6c, 0x77, 0x61, 0x6e, 0x61, 0x3b, 0x1e70, 0x68, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x65, +0x3b, 0x4b, 0x68, 0x75, 0x62, 0x76, 0x75, 0x6d, 0x65, 0x64, 0x7a, 0x69, 0x3b, 0x54, 0x73, 0x68, 0x69, 0x6d, 0x65, 0x64, +0x7a, 0x69, 0x3b, 0x1e3c, 0x61, 0x72, 0x61, 0x3b, 0x4e, 0x79, 0x65, 0x6e, 0x64, 0x61, 0x76, 0x68, 0x75, 0x73, 0x69, 0x6b, +0x75, 0x3b, 0x44, 0x7a, 0x76, 0x3b, 0x44, 0x7a, 0x64, 0x3b, 0x54, 0x65, 0x64, 0x3b, 0x41, 0x66, 0x254, 0x3b, 0x44, 0x61, +0x6d, 0x3b, 0x4d, 0x61, 0x73, 0x3b, 0x53, 0x69, 0x61, 0x3b, 0x44, 0x65, 0x61, 0x3b, 0x41, 0x6e, 0x79, 0x3b, 0x4b, 0x65, +0x6c, 0x3b, 0x41, 0x64, 0x65, 0x3b, 0x44, 0x7a, 0x6d, 0x3b, 0x44, 0x7a, 0x6f, 0x76, 0x65, 0x3b, 0x44, 0x7a, 0x6f, 0x64, +0x7a, 0x65, 0x3b, 0x54, 0x65, 0x64, 0x6f, 0x78, 0x65, 0x3b, 0x41, 0x66, 0x254, 0x66, 0x69, 0x25b, 0x3b, 0x44, 0x61, 0x6d, +0x61, 0x3b, 0x4d, 0x61, 0x73, 0x61, 0x3b, 0x53, 0x69, 0x61, 0x6d, 0x6c, 0x254, 0x6d, 0x3b, 0x44, 0x65, 0x61, 0x73, 0x69, +0x61, 0x6d, 0x69, 0x6d, 0x65, 0x3b, 0x41, 0x6e, 0x79, 0x254, 0x6e, 0x79, 0x254, 0x3b, 0x4b, 0x65, 0x6c, 0x65, 0x3b, 0x41, +0x64, 0x65, 0x25b, 0x6d, 0x65, 0x6b, 0x70, 0x254, 0x78, 0x65, 0x3b, 0x44, 0x7a, 0x6f, 0x6d, 0x65, 0x3b, 0x49, 0x61, 0x6e, +0x2e, 0x3b, 0x50, 0x65, 0x70, 0x2e, 0x3b, 0x4d, 0x61, 0x6c, 0x2e, 0x3b, 0x2bb, 0x41, 0x70, 0x2e, 0x3b, 0x4d, 0x65, 0x69, +0x3b, 0x49, 0x75, 0x6e, 0x2e, 0x3b, 0x49, 0x75, 0x6c, 0x2e, 0x3b, 0x2bb, 0x41, 0x75, 0x2e, 0x3b, 0x4b, 0x65, 0x70, 0x2e, +0x3b, 0x2bb, 0x4f, 0x6b, 0x2e, 0x3b, 0x4e, 0x6f, 0x77, 0x2e, 0x3b, 0x4b, 0x65, 0x6b, 0x2e, 0x3b, 0x49, 0x61, 0x6e, 0x75, +0x61, 0x6c, 0x69, 0x3b, 0x50, 0x65, 0x70, 0x65, 0x6c, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x6b, 0x69, +0x3b, 0x2bb, 0x41, 0x70, 0x65, 0x6c, 0x69, 0x6c, 0x61, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x49, 0x75, 0x6e, 0x65, 0x3b, 0x49, +0x75, 0x6c, 0x61, 0x69, 0x3b, 0x2bb, 0x41, 0x75, 0x6b, 0x61, 0x6b, 0x65, 0x3b, 0x4b, 0x65, 0x70, 0x61, 0x6b, 0x65, 0x6d, +0x61, 0x70, 0x61, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x6b, 0x6f, 0x70, 0x61, 0x3b, 0x4e, 0x6f, 0x77, 0x65, 0x6d, 0x61, 0x70, +0x61, 0x3b, 0x4b, 0x65, 0x6b, 0x65, 0x6d, 0x61, 0x70, 0x61, 0x3b, 0x4a, 0x75, 0x77, 0x3b, 0x53, 0x77, 0x69, 0x3b, 0x54, +0x73, 0x61, 0x3b, 0x4e, 0x79, 0x61, 0x3b, 0x54, 0x73, 0x77, 0x3b, 0x41, 0x74, 0x61, 0x3b, 0x41, 0x6e, 0x61, 0x3b, 0x41, +0x72, 0x69, 0x3b, 0x41, 0x6b, 0x75, 0x3b, 0x53, 0x77, 0x61, 0x3b, 0x4d, 0x61, 0x6e, 0x3b, 0x4d, 0x61, 0x73, 0x3b, 0x5a, +0x77, 0x61, 0x74, 0x20, 0x4a, 0x75, 0x77, 0x75, 0x6e, 0x67, 0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x53, 0x77, 0x69, 0x79, +0x61, 0x6e, 0x67, 0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x54, 0x73, 0x61, 0x74, 0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x4e, +0x79, 0x61, 0x69, 0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x54, 0x73, 0x77, 0x6f, 0x6e, 0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, +0x41, 0x74, 0x61, 0x61, 0x68, 0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x41, 0x6e, 0x61, 0x74, 0x61, 0x74, 0x3b, 0x5a, 0x77, +0x61, 0x74, 0x20, 0x41, 0x72, 0x69, 0x6e, 0x61, 0x69, 0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x41, 0x6b, 0x75, 0x62, 0x75, +0x6e, 0x79, 0x75, 0x6e, 0x67, 0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x53, 0x77, 0x61, 0x67, 0x3b, 0x5a, 0x77, 0x61, 0x74, +0x20, 0x4d, 0x61, 0x6e, 0x67, 0x6a, 0x75, 0x77, 0x61, 0x6e, 0x67, 0x3b, 0x5a, 0x77, 0x61, 0x74, 0x20, 0x53, 0x77, 0x61, +0x67, 0x2d, 0x4d, 0x61, 0x2d, 0x53, 0x75, 0x79, 0x61, 0x6e, 0x67, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, +0x4d, 0x61, 0x6c, 0x3b, 0x45, 0x70, 0x75, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, +0x4f, 0x67, 0x61, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x75, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, +0x4a, 0x61, 0x6e, 0x75, 0x77, 0x61, 0x6c, 0x65, 0x3b, 0x46, 0x65, 0x62, 0x75, 0x6c, 0x75, 0x77, 0x61, 0x6c, 0x65, 0x3b, +0x4d, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x3b, 0x45, 0x70, 0x75, 0x6c, 0x6f, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, +0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x4f, 0x67, 0x61, 0x73, 0x69, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, +0x75, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x75, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, +0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b +}; + +static const ushort standalone_months_data[] = { +0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, +0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x63, 0x74, 0x3b, +0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x79, 0x3b, 0x46, 0x65, 0x62, 0x72, +0x75, 0x61, 0x72, 0x79, 0x3b, 0x4d, 0x61, 0x72, 0x63, 0x68, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, +0x3b, 0x4a, 0x75, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6c, 0x79, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, +0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x63, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, +0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, +0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x3b, 0x3b, +0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x51, 0x3b, 0x4e, 0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x43, 0x3b, +0x51, 0x3b, 0x51, 0x3b, 0x4c, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x58, 0x3b, 0x4b, 0x3b, 0x31, 0x3b, 0x32, 0x3b, 0x33, 0x3b, +0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x38, 0x3b, 0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, +0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x51, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x54, +0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x1303, 0x3b, 0x134c, 0x3b, 0x121b, 0x3b, 0x12a4, 0x3b, 0x121c, 0x3b, 0x1301, 0x3b, 0x1301, 0x3b, 0x12a6, +0x3b, 0x1234, 0x3b, 0x12a6, 0x3b, 0x1296, 0x3b, 0x12f2, 0x3b, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x648, 0x3b, 0x646, +0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x633, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x3b, 0x99c, 0x9be, 0x3b, 0x9ab, 0x9c7, 0x3b, 0x9ae, +0x9be, 0x3b, 0x98f, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x3b, 0x986, 0x3b, 0x9b8, 0x9c7, 0x3b, 0x985, +0x3b, 0x9a8, 0x3b, 0x9a1, 0x9bf, 0x3b, 0x44f, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b, 0x43c, 0x3b, 0x44e, 0x3b, 0x44e, 0x3b, +0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b, 0x434, 0x3b, 0x1007, 0x3b, 0x1016, 0x3b, 0x1019, 0x3b, 0x1027, 0x3b, 0x1019, 0x3b, +0x1007, 0x3b, 0x1007, 0x3b, 0x1029, 0x3b, 0x1005, 0x3b, 0x1021, 0x3b, 0x1014, 0x3b, 0x1012, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x442, 0x440, +0x430, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x435, 0x43d, 0x44c, +0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x441, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x43a, 0x3b, 0x43c, 0x3b, 0x447, 0x3b, +0x43b, 0x3b, 0x436, 0x3b, 0x432, 0x3b, 0x43a, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x67, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, +0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x61, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x4e00, 0x6708, 0x3b, 0x4e8c, +0x6708, 0x3b, 0x4e09, 0x6708, 0x3b, 0x56db, 0x6708, 0x3b, 0x4e94, 0x6708, 0x3b, 0x516d, 0x6708, 0x3b, 0x4e03, 0x6708, 0x3b, 0x516b, 0x6708, 0x3b, +0x4e5d, 0x6708, 0x3b, 0x5341, 0x6708, 0x3b, 0x5341, 0x4e00, 0x6708, 0x3b, 0x5341, 0x4e8c, 0x6708, 0x3b, 0x31, 0x6708, 0x3b, 0x32, 0x6708, 0x3b, +0x33, 0x6708, 0x3b, 0x34, 0x6708, 0x3b, 0x35, 0x6708, 0x3b, 0x36, 0x6708, 0x3b, 0x37, 0x6708, 0x3b, 0x38, 0x6708, 0x3b, 0x39, 0x6708, +0x3b, 0x31, 0x30, 0x6708, 0x3b, 0x31, 0x31, 0x6708, 0x3b, 0x31, 0x32, 0x6708, 0x3b, 0x73, 0x69, 0x6a, 0x65, 0x10d, 0x61, 0x6e, +0x6a, 0x3b, 0x76, 0x65, 0x6c, 0x6a, 0x61, 0x10d, 0x61, 0x3b, 0x6f, 0x17e, 0x75, 0x6a, 0x61, 0x6b, 0x3b, 0x74, 0x72, 0x61, +0x76, 0x61, 0x6e, 0x6a, 0x3b, 0x73, 0x76, 0x69, 0x62, 0x61, 0x6e, 0x6a, 0x3b, 0x6c, 0x69, 0x70, 0x61, 0x6e, 0x6a, 0x3b, +0x73, 0x72, 0x70, 0x61, 0x6e, 0x6a, 0x3b, 0x6b, 0x6f, 0x6c, 0x6f, 0x76, 0x6f, 0x7a, 0x3b, 0x72, 0x75, 0x6a, 0x61, 0x6e, +0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x3b, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x69, 0x3b, 0x70, 0x72, +0x6f, 0x73, 0x69, 0x6e, 0x61, 0x63, 0x3b, 0x73, 0x3b, 0x76, 0x3b, 0x6f, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x6c, 0x3b, 0x73, +0x3b, 0x6b, 0x3b, 0x72, 0x3b, 0x6c, 0x3b, 0x73, 0x3b, 0x70, 0x3b, 0x31, 0x2e, 0x3b, 0x32, 0x2e, 0x3b, 0x33, 0x2e, 0x3b, +0x34, 0x2e, 0x3b, 0x35, 0x2e, 0x3b, 0x36, 0x2e, 0x3b, 0x37, 0x2e, 0x3b, 0x38, 0x2e, 0x3b, 0x39, 0x2e, 0x3b, 0x31, 0x30, +0x2e, 0x3b, 0x31, 0x31, 0x2e, 0x3b, 0x31, 0x32, 0x2e, 0x3b, 0x6c, 0x65, 0x64, 0x65, 0x6e, 0x3b, 0xfa, 0x6e, 0x6f, 0x72, +0x3b, 0x62, 0x159, 0x65, 0x7a, 0x65, 0x6e, 0x3b, 0x64, 0x75, 0x62, 0x65, 0x6e, 0x3b, 0x6b, 0x76, 0x11b, 0x74, 0x65, 0x6e, +0x3b, 0x10d, 0x65, 0x72, 0x76, 0x65, 0x6e, 0x3b, 0x10d, 0x65, 0x72, 0x76, 0x65, 0x6e, 0x65, 0x63, 0x3b, 0x73, 0x72, 0x70, +0x65, 0x6e, 0x3b, 0x7a, 0xe1, 0x159, 0xed, 0x3b, 0x159, 0xed, 0x6a, 0x65, 0x6e, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, +0x61, 0x64, 0x3b, 0x70, 0x72, 0x6f, 0x73, 0x69, 0x6e, 0x65, 0x63, 0x3b, 0x6c, 0x3b, 0xfa, 0x3b, 0x62, 0x3b, 0x64, 0x3b, +0x6b, 0x3b, 0x10d, 0x3b, 0x10d, 0x3b, 0x73, 0x3b, 0x7a, 0x3b, 0x159, 0x3b, 0x6c, 0x3b, 0x70, 0x3b, 0x54, 0x3b, 0x48, 0x3b, +0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x48, 0x3b, 0x45, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, +0x58, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x58, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, +0x4e, 0x3b, 0x44, 0x3b, 0x10d8, 0x3b, 0x10d7, 0x3b, 0x10db, 0x3b, 0x10d0, 0x3b, 0x10db, 0x3b, 0x10d8, 0x3b, 0x10d8, 0x3b, 0x10d0, 0x3b, +0x10e1, 0x3b, 0x10dd, 0x3b, 0x10dc, 0x3b, 0x10d3, 0x3b, 0x3b, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4a, 0x75, 0x6c, +0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, +0x3b, 0x399, 0x3b1, 0x3bd, 0x3bf, 0x3c5, 0x3ac, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3c1, 0x3bf, 0x3c5, 0x3ac, 0x3c1, +0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39c, 0x3ac, 0x3c1, 0x3c4, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3af, 0x3bb, 0x3b9, 0x3bf, 0x3c2, +0x3b, 0x39c, 0x3ac, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bd, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bb, 0x3b9, +0x3bf, 0x3c2, 0x3b, 0x391, 0x3cd, 0x3b3, 0x3bf, 0x3c5, 0x3c3, 0x3c4, 0x3bf, 0x3c2, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3c4, 0x3ad, 0x3bc, 0x3b2, +0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3ce, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39d, 0x3bf, 0x3ad, 0x3bc, 0x3b2, +0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x399, 0x3b, 0x3a6, 0x3b, +0x39c, 0x3b, 0x391, 0x3b, 0x39c, 0x3b, 0x399, 0x3b, 0x399, 0x3b, 0x391, 0x3b, 0x3a3, 0x3b, 0x39f, 0x3b, 0x39d, 0x3b, 0x394, 0x3b, +0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, +0x4e, 0x3b, 0x44, 0x3b, 0x3b, 0x3b, 0x5de, 0x5e8, 0x5e1, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4a, +0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0xc1, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, +0x3b, 0x44, 0x3b, 0x6a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0xe1, 0x3b, 0x73, +0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x42, 0x3b, 0x4d, 0x3b, 0x49, +0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x47, 0x65, 0x6e, 0x6e, 0x61, 0x69, 0x6f, 0x3b, 0x46, +0x65, 0x62, 0x62, 0x72, 0x61, 0x69, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x65, +0x3b, 0x4d, 0x61, 0x67, 0x67, 0x69, 0x6f, 0x3b, 0x47, 0x69, 0x75, 0x67, 0x6e, 0x6f, 0x3b, 0x4c, 0x75, 0x67, 0x6c, 0x69, +0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x4c, +0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x31, 0xc6d4, 0x3b, 0x32, 0xc6d4, 0x3b, 0x33, 0xc6d4, 0x3b, +0x34, 0xc6d4, 0x3b, 0x35, 0xc6d4, 0x3b, 0x36, 0xc6d4, 0x3b, 0x37, 0xc6d4, 0x3b, 0x38, 0xc6d4, 0x3b, 0x39, 0xc6d4, 0x3b, 0x31, 0x30, +0xc6d4, 0x3b, 0x31, 0x31, 0xc6d4, 0x3b, 0x31, 0x32, 0xc6d4, 0x3b, 0x53, 0x61, 0x75, 0x73, 0x69, 0x73, 0x3b, 0x56, 0x61, 0x73, +0x61, 0x72, 0x69, 0x73, 0x3b, 0x4b, 0x6f, 0x76, 0x61, 0x73, 0x3b, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x69, 0x73, 0x3b, +0x47, 0x65, 0x67, 0x75, 0x17e, 0x117, 0x3b, 0x42, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x73, 0x3b, 0x4c, 0x69, 0x65, 0x70, +0x61, 0x3b, 0x52, 0x75, 0x67, 0x70, 0x6a, 0x16b, 0x74, 0x69, 0x73, 0x3b, 0x52, 0x75, 0x67, 0x73, 0x117, 0x6a, 0x69, 0x73, +0x3b, 0x53, 0x70, 0x61, 0x6c, 0x69, 0x73, 0x3b, 0x4c, 0x61, 0x70, 0x6b, 0x72, 0x69, 0x74, 0x69, 0x73, 0x3b, 0x47, 0x72, +0x75, 0x6f, 0x64, 0x69, 0x73, 0x3b, 0x53, 0x3b, 0x56, 0x3b, 0x4b, 0x3b, 0x42, 0x3b, 0x47, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, +0x52, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x47, 0x3b, 0x458, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b, 0x43c, 0x3b, +0x458, 0x3b, 0x458, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b, 0x434, 0x3b, 0xd1c, 0x3b, 0xd2b, 0xd46, 0x3b, 0xd2e, +0x3b, 0xd0f, 0x3b, 0xd2e, 0xd47, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd06, 0x3b, 0xd38, 0xd46, 0x3b, 0xd12, 0x3b, 0xd28, +0x3b, 0xd21, 0xd3f, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x120, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, +0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x967, 0x3b, 0x968, 0x3b, 0x969, 0x3b, 0x96a, 0x3b, 0x96b, 0x3b, 0x96c, 0x3b, +0x96d, 0x3b, 0x96e, 0x3b, 0x96f, 0x3b, 0x967, 0x966, 0x3b, 0x967, 0x967, 0x3b, 0x967, 0x968, 0x3b, 0x698, 0x627, 0x646, 0x648, 0x6cc, +0x647, 0x3b, 0x641, 0x648, 0x631, 0x6cc, 0x647, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc, 0x644, 0x3b, 0x645, +0x647, 0x3b, 0x698, 0x648, 0x626, 0x646, 0x3b, 0x698, 0x648, 0x626, 0x6cc, 0x647, 0x3b, 0x627, 0x648, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, +0x627, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x627, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, +0x627, 0x645, 0x628, 0x631, 0x3b, 0x698, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x622, 0x3b, 0x645, 0x3b, 0x698, 0x3b, 0x698, 0x3b, 0x627, +0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x62f, 0x3b, 0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x627, 0x3b, 0x645, 0x3b, 0x62c, +0x3b, 0x62c, 0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x62f, 0x3b, 0x73, 0x74, 0x79, 0x63, 0x7a, 0x65, 0x144, +0x3b, 0x6c, 0x75, 0x74, 0x79, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x65, 0x63, 0x3b, 0x6b, 0x77, 0x69, 0x65, 0x63, 0x69, 0x65, +0x144, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x63, 0x7a, 0x65, 0x72, 0x77, 0x69, 0x65, 0x63, 0x3b, 0x6c, 0x69, 0x70, 0x69, 0x65, +0x63, 0x3b, 0x73, 0x69, 0x65, 0x72, 0x70, 0x69, 0x65, 0x144, 0x3b, 0x77, 0x72, 0x7a, 0x65, 0x73, 0x69, 0x65, 0x144, 0x3b, +0x70, 0x61, 0x17a, 0x64, 0x7a, 0x69, 0x65, 0x72, 0x6e, 0x69, 0x6b, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, +0x3b, 0x67, 0x72, 0x75, 0x64, 0x7a, 0x69, 0x65, 0x144, 0x3b, 0x73, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, +0x63, 0x3b, 0x6c, 0x3b, 0x73, 0x3b, 0x77, 0x3b, 0x70, 0x3b, 0x6c, 0x3b, 0x67, 0x3b, 0xa1c, 0x3b, 0xa2b, 0x3b, 0xa2e, 0xa3e, +0x3b, 0xa05, 0x3b, 0xa2e, 0x3b, 0xa1c, 0xa42, 0x3b, 0xa1c, 0xa41, 0x3b, 0xa05, 0x3b, 0xa38, 0x3b, 0xa05, 0x3b, 0xa28, 0x3b, 0xa26, +0x3b, 0x49, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, +0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x44f, 0x43d, 0x432, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, +0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b, +0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, +0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x3b, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b, +0x44c, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e, +0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x44f, +0x431, 0x440, 0x44c, 0x3b, 0x41e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x414, +0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x3b, 0x42f, 0x3b, 0x424, 0x3b, 0x41c, 0x3b, 0x410, 0x3b, 0x41c, 0x3b, 0x418, 0x3b, 0x418, +0x3b, 0x410, 0x3b, 0x421, 0x3b, 0x41e, 0x3b, 0x41d, 0x3b, 0x414, 0x3b, 0x6a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, +0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x61, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0xda2, 0x3b, 0xdb4, 0xdd9, 0x3b, +0xdb8, 0xdcf, 0x3b, 0xd85, 0x3b, 0xdb8, 0xdd0, 0x3b, 0xda2, 0xdd6, 0x3b, 0xda2, 0xdd6, 0x3b, 0xd85, 0x3b, 0xdc3, 0xdd0, 0x3b, 0xd94, +0x3b, 0xdb1, 0xddc, 0x3b, 0xdaf, 0xdd9, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x54, +0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, +0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0xc1c, 0x3b, 0xc2b, 0xc3f, 0x3b, +0xc2e, 0x3b, 0xc0e, 0x3b, 0xc2e, 0xc46, 0x3b, 0xc1c, 0xc41, 0x3b, 0xc1c, 0xc41, 0x3b, 0xc06, 0x3b, 0xc38, 0xc46, 0x3b, 0xc05, 0x3b, +0xc28, 0x3b, 0xc21, 0xc3f, 0x3b, 0xe21, 0x2e, 0xe04, 0x2e, 0x3b, 0xe01, 0x2e, 0xe1e, 0x2e, 0x3b, 0xe21, 0xe35, 0x2e, 0xe04, 0x2e, +0x3b, 0xe40, 0xe21, 0x2e, 0xe22, 0x2e, 0x3b, 0xe1e, 0x2e, 0xe04, 0x2e, 0x3b, 0xe21, 0xe34, 0x2e, 0xe22, 0x2e, 0x3b, 0xe01, 0x2e, +0xe04, 0x2e, 0x3b, 0xe2a, 0x2e, 0xe04, 0x2e, 0x3b, 0xe01, 0x2e, 0xe22, 0x2e, 0x3b, 0xe15, 0x2e, 0xe04, 0x2e, 0x3b, 0xe1e, 0x2e, +0xe22, 0x2e, 0x3b, 0xe18, 0x2e, 0xe04, 0x2e, 0x3b, 0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, +0x53, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x4f, 0x3b, 0x15e, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, +0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x45, 0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x41, 0x3b, 0x421, 0x456, 0x447, 0x3b, +0x41b, 0x44e, 0x442, 0x3b, 0x411, 0x435, 0x440, 0x3b, 0x41a, 0x432, 0x456, 0x3b, 0x422, 0x440, 0x430, 0x3b, 0x427, 0x435, 0x440, 0x3b, +0x41b, 0x438, 0x43f, 0x3b, 0x421, 0x435, 0x440, 0x3b, 0x412, 0x435, 0x440, 0x3b, 0x416, 0x43e, 0x432, 0x3b, 0x41b, 0x438, 0x441, 0x3b, +0x413, 0x440, 0x443, 0x3b, 0x421, 0x456, 0x447, 0x435, 0x43d, 0x44c, 0x3b, 0x41b, 0x44e, 0x442, 0x438, 0x439, 0x3b, 0x411, 0x435, 0x440, +0x435, 0x437, 0x435, 0x43d, 0x44c, 0x3b, 0x41a, 0x432, 0x456, 0x442, 0x435, 0x43d, 0x44c, 0x3b, 0x422, 0x440, 0x430, 0x432, 0x435, 0x43d, +0x44c, 0x3b, 0x427, 0x435, 0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x41b, 0x438, 0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x421, 0x435, 0x440, +0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x412, 0x435, 0x440, 0x435, 0x441, 0x435, 0x43d, 0x44c, 0x3b, 0x416, 0x43e, 0x432, 0x442, 0x435, 0x43d, +0x44c, 0x3b, 0x41b, 0x438, 0x441, 0x442, 0x43e, 0x43f, 0x430, 0x434, 0x3b, 0x413, 0x440, 0x443, 0x434, 0x435, 0x43d, 0x44c, 0x3b, 0x421, +0x3b, 0x41b, 0x3b, 0x411, 0x3b, 0x41a, 0x3b, 0x422, 0x3b, 0x427, 0x3b, 0x41b, 0x3b, 0x421, 0x3b, 0x412, 0x3b, 0x416, 0x3b, 0x41b, +0x3b, 0x413, 0x3b, 0x3b, 0x43, 0x68, 0x77, 0x65, 0x3b, 0x4d, 0x61, 0x77, 0x3b, 0x45, 0x62, 0x72, 0x3b, 0x3b, 0x3b, 0x47, +0x6f, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x6f, 0x72, 0x66, 0x66, 0x65, +0x6e, 0x6e, 0x61, 0x66, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x3b, 0x43, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, +0x4d, 0x3b, 0x47, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x52, 0x3b, 0x75, 0x4a, 0x61, 0x6e, 0x75, 0x77, +0x61, 0x72, 0x69, 0x3b, 0x75, 0x46, 0x65, 0x62, 0x72, 0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x75, 0x4d, 0x61, 0x73, 0x68, +0x69, 0x3b, 0x75, 0x2d, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x69, 0x3b, 0x75, 0x4d, 0x65, 0x79, 0x69, 0x3b, 0x75, 0x4a, 0x75, +0x6e, 0x69, 0x3b, 0x75, 0x4a, 0x75, 0x6c, 0x61, 0x79, 0x69, 0x3b, 0x75, 0x41, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x75, +0x53, 0x65, 0x70, 0x74, 0x68, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x75, 0x2d, 0x4f, 0x6b, 0x74, 0x68, 0x6f, 0x62, 0x61, 0x3b, +0x75, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x75, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x120d, 0x3b, +0x12ab, 0x3b, 0x12ad, 0x3b, 0x134b, 0x3b, 0x12ad, 0x3b, 0x121d, 0x3b, 0x12b0, 0x3b, 0x121b, 0x3b, 0x12eb, 0x3b, 0x1218, 0x3b, 0x121d, 0x3b, +0x1270, 0x3b, 0x1320, 0x3b, 0x12a8, 0x3b, 0x1218, 0x3b, 0x12a0, 0x3b, 0x130d, 0x3b, 0x1220, 0x3b, 0x1210, 0x3b, 0x1290, 0x3b, 0x12a8, 0x3b, +0x1320, 0x3b, 0x1280, 0x3b, 0x1280, 0x3b, 0x5a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4c, 0x3b, +0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x44, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x44, 0x3b, +0x4d, 0x3b, 0x53, 0x3b, 0x44, 0x3b, 0x41, 0x3b, 0x4b, 0x3b, 0x41, 0x3b, 0x44, 0x3b +}; + +static const ushort days_data[] = { +0x53, 0x75, 0x6e, 0x3b, 0x4d, 0x6f, 0x6e, 0x3b, 0x54, 0x75, 0x65, 0x3b, 0x57, 0x65, 0x64, 0x3b, 0x54, 0x68, 0x75, 0x3b, +0x46, 0x72, 0x69, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x53, 0x75, 0x6e, 0x64, 0x61, 0x79, 0x3b, 0x4d, 0x6f, 0x6e, 0x64, 0x61, +0x79, 0x3b, 0x54, 0x75, 0x65, 0x73, 0x64, 0x61, 0x79, 0x3b, 0x57, 0x65, 0x64, 0x6e, 0x65, 0x73, 0x64, 0x61, 0x79, 0x3b, +0x54, 0x68, 0x75, 0x72, 0x73, 0x64, 0x61, 0x79, 0x3b, 0x46, 0x72, 0x69, 0x64, 0x61, 0x79, 0x3b, 0x53, 0x61, 0x74, 0x75, +0x72, 0x64, 0x61, 0x79, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x57, 0x3b, 0x54, 0x3b, 0x46, 0x3b, 0x53, 0x3b, 0x37, +0x3b, 0x31, 0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, +0x44, 0x69, 0x6c, 0x3b, 0x57, 0x69, 0x78, 0x3b, 0x51, 0x69, 0x62, 0x3b, 0x52, 0x6f, 0x62, 0x3b, 0x4b, 0x61, 0x6d, 0x3b, +0x4a, 0x69, 0x6d, 0x3b, 0x53, 0x61, 0x6e, 0x3b, 0x44, 0x69, 0x6c, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x57, 0x69, 0x69, 0x78, +0x61, 0x74, 0x61, 0x3b, 0x51, 0x69, 0x62, 0x78, 0x61, 0x74, 0x61, 0x3b, 0x52, 0x6f, 0x6f, 0x62, 0x69, 0x69, 0x3b, 0x4b, +0x61, 0x6d, 0x69, 0x69, 0x73, 0x61, 0x3b, 0x4a, 0x69, 0x6d, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x53, 0x61, 0x6e, 0x62, 0x61, +0x74, 0x61, 0x3b, 0x41, 0x3b, 0x45, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x41, 0x63, 0x61, +0x3b, 0x45, 0x74, 0x6c, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x41, 0x72, 0x62, 0x3b, 0x4b, 0x61, 0x6d, 0x3b, 0x47, 0x75, 0x6d, +0x3b, 0x53, 0x61, 0x62, 0x3b, 0x41, 0x63, 0x61, 0x61, 0x64, 0x61, 0x3b, 0x45, 0x74, 0x6c, 0x65, 0x65, 0x6e, 0x69, 0x3b, +0x54, 0x61, 0x6c, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x72, 0x62, 0x61, 0x71, 0x61, 0x3b, 0x4b, 0x61, 0x6d, 0x69, 0x69, +0x73, 0x69, 0x3b, 0x47, 0x75, 0x6d, 0x71, 0x61, 0x74, 0x61, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x69, 0x3b, 0x31, 0x3b, 0x32, +0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x53, 0x6f, 0x3b, 0x4d, 0x61, 0x3b, 0x44, 0x69, 0x3b, +0x57, 0x6f, 0x3b, 0x44, 0x6f, 0x3b, 0x56, 0x72, 0x3b, 0x53, 0x61, 0x3b, 0x53, 0x6f, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x4d, +0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x44, 0x69, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x57, 0x6f, 0x65, 0x6e, 0x73, +0x64, 0x61, 0x67, 0x3b, 0x44, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x56, 0x72, 0x79, 0x64, 0x61, 0x67, +0x3b, 0x53, 0x61, 0x74, 0x65, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x44, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, +0x50, 0x3b, 0x53, 0x3b, 0x44, 0x69, 0x65, 0x3b, 0x48, 0xeb, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0xeb, 0x72, 0x3b, +0x45, 0x6e, 0x6a, 0x3b, 0x50, 0x72, 0x65, 0x3b, 0x53, 0x68, 0x74, 0x3b, 0x65, 0x20, 0x64, 0x69, 0x65, 0x6c, 0x3b, 0x65, +0x20, 0x68, 0xeb, 0x6e, 0xeb, 0x3b, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x74, 0xeb, 0x3b, 0x65, 0x20, 0x6d, 0xeb, 0x72, 0x6b, +0x75, 0x72, 0xeb, 0x3b, 0x65, 0x20, 0x65, 0x6e, 0x6a, 0x74, 0x65, 0x3b, 0x65, 0x20, 0x70, 0x72, 0x65, 0x6d, 0x74, 0x65, +0x3b, 0x65, 0x20, 0x73, 0x68, 0x74, 0x75, 0x6e, 0xeb, 0x3b, 0x12a5, 0x3b, 0x1230, 0x3b, 0x121b, 0x3b, 0x1228, 0x3b, 0x1210, 0x3b, +0x12d3, 0x3b, 0x1245, 0x3b, 0x12a5, 0x1211, 0x12f5, 0x3b, 0x1230, 0x129e, 0x3b, 0x121b, 0x12ad, 0x1230, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1210, +0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1265, 0x3b, 0x1245, 0x12f3, 0x121c, 0x3b, 0x12a5, 0x1211, 0x12f5, 0x3b, 0x1230, 0x129e, 0x3b, 0x121b, 0x12ad, +0x1230, 0x129e, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1210, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1265, 0x3b, 0x1245, 0x12f3, 0x121c, 0x3b, 0x623, +0x62d, 0x62f, 0x3b, 0x627, 0x62b, 0x646, 0x64a, 0x646, 0x3b, 0x62b, 0x644, 0x627, 0x62b, 0x627, 0x621, 0x3b, 0x623, 0x631, 0x628, 0x639, +0x627, 0x621, 0x3b, 0x62e, 0x645, 0x64a, 0x633, 0x3b, 0x62c, 0x645, 0x639, 0x629, 0x3b, 0x633, 0x628, 0x62a, 0x3b, 0x62d, 0x3b, 0x646, +0x3b, 0x62b, 0x3b, 0x631, 0x3b, 0x62e, 0x3b, 0x62c, 0x3b, 0x633, 0x3b, 0x627, 0x644, 0x623, 0x62d, 0x62f, 0x3b, 0x627, 0x644, 0x627, +0x62b, 0x646, 0x64a, 0x646, 0x3b, 0x627, 0x644, 0x62b, 0x644, 0x627, 0x62b, 0x627, 0x621, 0x3b, 0x627, 0x644, 0x623, 0x631, 0x628, 0x639, +0x627, 0x621, 0x3b, 0x627, 0x644, 0x62e, 0x645, 0x64a, 0x633, 0x3b, 0x627, 0x644, 0x62c, 0x645, 0x639, 0x629, 0x3b, 0x627, 0x644, 0x633, +0x628, 0x62a, 0x3b, 0x53f, 0x56b, 0x580, 0x3b, 0x535, 0x580, 0x56f, 0x3b, 0x535, 0x580, 0x584, 0x3b, 0x549, 0x578, 0x580, 0x3b, 0x540, +0x576, 0x563, 0x3b, 0x548, 0x582, 0x580, 0x3b, 0x547, 0x561, 0x562, 0x3b, 0x53f, 0x56b, 0x580, 0x561, 0x56f, 0x56b, 0x3b, 0x535, 0x580, +0x56f, 0x578, 0x582, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x535, 0x580, 0x565, 0x584, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x549, +0x578, 0x580, 0x565, 0x584, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x540, 0x56b, 0x576, 0x563, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, +0x548, 0x582, 0x580, 0x562, 0x561, 0x569, 0x3b, 0x547, 0x561, 0x562, 0x561, 0x569, 0x3b, 0x9f0, 0x9ac, 0x9bf, 0x3b, 0x9b8, 0x9cb, 0x9ae, +0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b7, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x3b, +0x9b6, 0x9c1, 0x995, 0x9cd, 0x9f0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x3b, 0x9a6, 0x9c7, 0x993, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b8, 0x9cb, 0x9ae, +0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x9ac, 0x9be, 0x9f0, 0x3b, +0x9ac, 0x9c3, 0x9b9, 0x9b7, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9f0, 0x9ac, 0x9be, 0x9f0, +0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x42, 0x2e, 0x3b, 0x42, 0x2e, 0x45, 0x2e, 0x3b, 0xc7, 0x2e, 0x41, 0x2e, +0x3b, 0xc7, 0x2e, 0x3b, 0x43, 0x2e, 0x41, 0x2e, 0x3b, 0x43, 0x3b, 0x15e, 0x2e, 0x3b, 0x62, 0x61, 0x7a, 0x61, 0x72, 0x3b, +0x62, 0x61, 0x7a, 0x61, 0x72, 0x20, 0x65, 0x72, 0x74, 0x259, 0x73, 0x69, 0x3b, 0xe7, 0x259, 0x72, 0x15f, 0x259, 0x6e, 0x62, +0x259, 0x20, 0x61, 0x78, 0x15f, 0x61, 0x6d, 0x131, 0x3b, 0xe7, 0x259, 0x72, 0x15f, 0x259, 0x6e, 0x62, 0x259, 0x3b, 0x63, 0xfc, +0x6d, 0x259, 0x20, 0x61, 0x78, 0x15f, 0x61, 0x6d, 0x131, 0x3b, 0x63, 0xfc, 0x6d, 0x259, 0x3b, 0x15f, 0x259, 0x6e, 0x62, 0x259, +0x3b, 0x69, 0x67, 0x3b, 0x61, 0x6c, 0x3b, 0x61, 0x73, 0x3b, 0x61, 0x7a, 0x3b, 0x6f, 0x67, 0x3b, 0x6f, 0x72, 0x3b, 0x6c, +0x72, 0x3b, 0x69, 0x67, 0x61, 0x6e, 0x64, 0x65, 0x61, 0x3b, 0x61, 0x73, 0x74, 0x65, 0x6c, 0x65, 0x68, 0x65, 0x6e, 0x61, +0x3b, 0x61, 0x73, 0x74, 0x65, 0x61, 0x72, 0x74, 0x65, 0x61, 0x3b, 0x61, 0x73, 0x74, 0x65, 0x61, 0x7a, 0x6b, 0x65, 0x6e, +0x61, 0x3b, 0x6f, 0x73, 0x74, 0x65, 0x67, 0x75, 0x6e, 0x61, 0x3b, 0x6f, 0x73, 0x74, 0x69, 0x72, 0x61, 0x6c, 0x61, 0x3b, +0x6c, 0x61, 0x72, 0x75, 0x6e, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x3b, 0x9ae, 0x3b, 0x9ac, 0x9c1, 0x3b, +0x9ac, 0x9c3, 0x3b, 0x9b6, 0x9c1, 0x3b, 0x9b6, 0x3b, 0x9b0, 0x9ac, 0x9bf, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, +0x9b2, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9b0, +0x3b, 0x9b6, 0x9a8, 0x9bf, 0x3b, 0x9b0, 0x9ac, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ae, +0x999, 0x9cd, 0x997, 0x9b2, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b7, 0x9cd, +0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9b0, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac, +0x9be, 0x9b0, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x3b, 0xf58, 0xf72, 0xf62, 0xf0b, 0x3b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0x3b, 0xf55, 0xf74, 0xf62, +0xf0b, 0x3b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0x3b, 0xf49, 0xf72, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, +0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, +0xf42, 0xf5f, 0xf60, 0xf0b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, +0xf74, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf66, 0xfa4, +0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0x43d, 0x3b, 0x43f, 0x3b, +0x432, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x432, 0x442, 0x3b, 0x441, +0x440, 0x3b, 0x447, 0x442, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x44f, 0x3b, 0x43f, 0x43e, +0x43d, 0x435, 0x434, 0x435, 0x43b, 0x43d, 0x438, 0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x44f, +0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x44a, 0x440, 0x442, 0x44a, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x44a, 0x43a, 0x3b, 0x441, +0x44a, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x1010, 0x3b, 0x1010, 0x3b, 0x1021, 0x3b, 0x1017, 0x3b, 0x1000, 0x3b, 0x101e, 0x3b, 0x1005, 0x3b, +0x1014, 0x103d, 0x1031, 0x3b, 0x101c, 0x102c, 0x3b, 0x1002, 0x102b, 0x3b, 0x101f, 0x1030, 0x1038, 0x3b, 0x1010, 0x1031, 0x1038, 0x3b, 0x1000, 0x103c, +0x102c, 0x3b, 0x1014, 0x1031, 0x3b, 0x1010, 0x1014, 0x1004, 0x103a, 0x1039, 0x1002, 0x1014, 0x103d, 0x1031, 0x3b, 0x1010, 0x1014, 0x1004, 0x103a, 0x1039, +0x101c, 0x102c, 0x3b, 0x1021, 0x1004, 0x103a, 0x1039, 0x1002, 0x102b, 0x3b, 0x1017, 0x102f, 0x1012, 0x1039, 0x1013, 0x101f, 0x1030, 0x1038, 0x3b, 0x1000, +0x103c, 0x102c, 0x101e, 0x1015, 0x1010, 0x1031, 0x1038, 0x3b, 0x101e, 0x1031, 0x102c, 0x1000, 0x103c, 0x102c, 0x3b, 0x1005, 0x1014, 0x1031, 0x3b, 0x43d, +0x3b, 0x43f, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x430, +0x45e, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x446, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x3b, 0x43d, 0x44f, 0x434, 0x437, 0x435, 0x43b, +0x44f, 0x3b, 0x43f, 0x430, 0x43d, 0x44f, 0x434, 0x437, 0x435, 0x43b, 0x430, 0x43a, 0x3b, 0x430, 0x45e, 0x442, 0x43e, 0x440, 0x430, 0x43a, +0x3b, 0x441, 0x435, 0x440, 0x430, 0x434, 0x430, 0x3b, 0x447, 0x430, 0x446, 0x432, 0x435, 0x440, 0x3b, 0x43f, 0x44f, 0x442, 0x43d, 0x456, +0x446, 0x430, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x17a2, 0x17b6, 0x3b, 0x1785, 0x3b, 0x17a2, 0x3b, 0x1796, 0x17bb, 0x3b, +0x1796, 0x17d2, 0x179a, 0x3b, 0x179f, 0x17bb, 0x3b, 0x179f, 0x3b, 0x1790, 0x17d2, 0x1784, 0x17c3, 0x17a2, 0x17b6, 0x1791, 0x17b7, 0x178f, 0x17d2, 0x1799, +0x3b, 0x200b, 0x1790, 0x17d2, 0x1784, 0x17c3, 0x1785, 0x17d0, 0x1793, 0x17d2, 0x1791, 0x3b, 0x1790, 0x17d2, 0x1784, 0x17c3, 0x17a2, 0x1784, 0x17d2, 0x1782, +0x17b6, 0x179a, 0x3b, 0x1790, 0x17d2, 0x1784, 0x17c3, 0x1796, 0x17bb, 0x1792, 0x3b, 0x1790, 0x17d2, 0x1784, 0x17c3, 0x1796, 0x17d2, 0x179a, 0x17a0, 0x179f, +0x17d2, 0x1794, 0x178f, 0x17b7, 0x17cd, 0x3b, 0x1790, 0x17d2, 0x1784, 0x17c3, 0x179f, 0x17bb, 0x1780, 0x17d2, 0x179a, 0x3b, 0x1790, 0x17d2, 0x1784, 0x17c3, +0x179f, 0x17c5, 0x179a, 0x17cd, 0x3b, 0x64, 0x67, 0x3b, 0x64, 0x6c, 0x3b, 0x64, 0x74, 0x3b, 0x64, 0x63, 0x3b, 0x64, 0x6a, 0x3b, +0x64, 0x76, 0x3b, 0x64, 0x73, 0x3b, 0x67, 0x3b, 0x6c, 0x3b, 0x74, 0x3b, 0x63, 0x3b, 0x6a, 0x3b, 0x76, 0x3b, 0x73, 0x3b, +0x64, 0x67, 0x2e, 0x3b, 0x64, 0x6c, 0x2e, 0x3b, 0x64, 0x74, 0x2e, 0x3b, 0x64, 0x63, 0x2e, 0x3b, 0x64, 0x6a, 0x2e, 0x3b, +0x64, 0x76, 0x2e, 0x3b, 0x64, 0x73, 0x2e, 0x3b, 0x64, 0x69, 0x75, 0x6d, 0x65, 0x6e, 0x67, 0x65, 0x3b, 0x64, 0x69, 0x6c, +0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x64, 0x69, 0x6d, 0x65, 0x63, 0x72, 0x65, +0x73, 0x3b, 0x64, 0x69, 0x6a, 0x6f, 0x75, 0x73, 0x3b, 0x64, 0x69, 0x76, 0x65, 0x6e, 0x64, 0x72, 0x65, 0x73, 0x3b, 0x64, +0x69, 0x73, 0x73, 0x61, 0x62, 0x74, 0x65, 0x3b, 0x65e5, 0x3b, 0x4e00, 0x3b, 0x4e8c, 0x3b, 0x4e09, 0x3b, 0x56db, 0x3b, 0x4e94, 0x3b, +0x516d, 0x3b, 0x5468, 0x65e5, 0x3b, 0x5468, 0x4e00, 0x3b, 0x5468, 0x4e8c, 0x3b, 0x5468, 0x4e09, 0x3b, 0x5468, 0x56db, 0x3b, 0x5468, 0x4e94, 0x3b, +0x5468, 0x516d, 0x3b, 0x661f, 0x671f, 0x65e5, 0x3b, 0x661f, 0x671f, 0x4e00, 0x3b, 0x661f, 0x671f, 0x4e8c, 0x3b, 0x661f, 0x671f, 0x4e09, 0x3b, 0x661f, +0x671f, 0x56db, 0x3b, 0x661f, 0x671f, 0x4e94, 0x3b, 0x661f, 0x671f, 0x516d, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x75, 0x3b, 0x73, 0x3b, 0x10d, +0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x75, 0x74, 0x6f, 0x3b, 0x73, 0x72, 0x69, +0x3b, 0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x3b, 0x6e, 0x65, 0x64, 0x6a, 0x65, 0x6c, 0x6a, +0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x6b, +0x3b, 0x73, 0x72, 0x69, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65, +0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x4e, 0x3b, 0x50, 0x3b, 0xda, 0x3b, 0x53, 0x3b, 0x10c, +0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x6e, 0x65, 0x3b, 0x70, 0x6f, 0x3b, 0xfa, 0x74, 0x3b, 0x73, 0x74, 0x3b, 0x10d, 0x74, 0x3b, +0x70, 0xe1, 0x3b, 0x73, 0x6f, 0x3b, 0x6e, 0x65, 0x64, 0x11b, 0x6c, 0x65, 0x3b, 0x70, 0x6f, 0x6e, 0x64, 0x11b, 0x6c, 0xed, +0x3b, 0xfa, 0x74, 0x65, 0x72, 0xfd, 0x3b, 0x73, 0x74, 0x159, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x74, 0x76, 0x72, 0x74, 0x65, +0x6b, 0x3b, 0x70, 0xe1, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, +0x3b, 0x4f, 0x3b, 0x54, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x73, 0xf8, 0x6e, 0x3b, 0x6d, 0x61, 0x6e, 0x3b, 0x74, 0x69, 0x72, +0x3b, 0x6f, 0x6e, 0x73, 0x3b, 0x74, 0x6f, 0x72, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0xf8, 0x72, 0x3b, 0x73, 0xf8, 0x6e, +0x64, 0x61, 0x67, 0x3b, 0x6d, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x69, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, +0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, +0x3b, 0x6c, 0xf8, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x5a, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x56, 0x3b, +0x5a, 0x3b, 0x7a, 0x6f, 0x3b, 0x6d, 0x61, 0x3b, 0x64, 0x69, 0x3b, 0x77, 0x6f, 0x3b, 0x64, 0x6f, 0x3b, 0x76, 0x72, 0x3b, +0x7a, 0x61, 0x3b, 0x7a, 0x6f, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x64, 0x69, +0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x77, 0x6f, 0x65, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x64, 0x6f, 0x6e, 0x64, 0x65, +0x72, 0x64, 0x61, 0x67, 0x3b, 0x76, 0x72, 0x69, 0x6a, 0x64, 0x61, 0x67, 0x3b, 0x7a, 0x61, 0x74, 0x65, 0x72, 0x64, 0x61, +0x67, 0x3b, 0x50, 0x3b, 0x45, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x52, 0x3b, 0x4c, 0x3b, 0x70, 0xfc, 0x68, 0x61, +0x70, 0xe4, 0x65, 0x76, 0x3b, 0x65, 0x73, 0x6d, 0x61, 0x73, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x74, 0x65, 0x69, 0x73, 0x69, +0x70, 0xe4, 0x65, 0x76, 0x3b, 0x6b, 0x6f, 0x6c, 0x6d, 0x61, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x6e, 0x65, 0x6c, 0x6a, 0x61, +0x70, 0xe4, 0x65, 0x76, 0x3b, 0x72, 0x65, 0x65, 0x64, 0x65, 0x3b, 0x6c, 0x61, 0x75, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x73, +0x75, 0x6e, 0x3b, 0x6d, 0xe1, 0x6e, 0x3b, 0x74, 0xfd, 0x73, 0x3b, 0x6d, 0x69, 0x6b, 0x3b, 0x68, 0xf3, 0x73, 0x3b, 0x66, +0x72, 0xed, 0x3b, 0x6c, 0x65, 0x79, 0x3b, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0xe1, +0x6e, 0x61, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x74, 0xfd, 0x73, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0x69, 0x6b, +0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x68, 0xf3, 0x73, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66, 0x72, 0xed, 0x67, +0x67, 0x6a, 0x61, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6c, 0x65, 0x79, 0x67, 0x61, 0x72, 0x64, 0x61, 0x67, 0x75, 0x72, +0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x50, 0x3b, 0x4c, 0x3b, 0x73, 0x75, 0x3b, 0x6d, 0x61, +0x3b, 0x74, 0x69, 0x3b, 0x6b, 0x65, 0x3b, 0x74, 0x6f, 0x3b, 0x70, 0x65, 0x3b, 0x6c, 0x61, 0x3b, 0x73, 0x75, 0x6e, 0x6e, +0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, +0x74, 0x69, 0x69, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x6b, 0x65, 0x73, 0x6b, 0x69, 0x76, 0x69, 0x69, 0x6b, 0x6b, +0x6f, 0x6e, 0x61, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x70, 0x65, 0x72, 0x6a, 0x61, 0x6e, +0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x6c, 0x61, 0x75, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x44, 0x3b, 0x4c, +0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x69, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e, +0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x65, 0x72, 0x2e, 0x3b, 0x6a, 0x65, 0x75, 0x2e, 0x3b, 0x76, 0x65, 0x6e, 0x2e, +0x3b, 0x73, 0x61, 0x6d, 0x2e, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x3b, 0x6c, 0x75, 0x6e, 0x64, 0x69, +0x3b, 0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x72, 0x63, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x6a, 0x65, 0x75, 0x64, +0x69, 0x3b, 0x76, 0x65, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x73, 0x61, 0x6d, 0x65, 0x64, 0x69, 0x3b, 0x44, 0x3b, +0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x44, 0x6f, 0x6d, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, +0x4d, 0x61, 0x72, 0x3b, 0x4d, 0xe9, 0x72, 0x3b, 0x58, 0x6f, 0x76, 0x3b, 0x56, 0x65, 0x6e, 0x3b, 0x53, 0xe1, 0x62, 0x3b, +0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, +0x4d, 0xe9, 0x72, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x3b, 0x58, 0x6f, 0x76, 0x65, 0x73, 0x3b, 0x56, 0x65, 0x6e, 0x72, 0x65, +0x73, 0x3b, 0x53, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x10d9, 0x3b, 0x10dd, 0x3b, 0x10e1, 0x3b, 0x10dd, 0x3b, 0x10ee, 0x3b, 0x10de, +0x3b, 0x10e8, 0x3b, 0x10d9, 0x10d5, 0x10d8, 0x3b, 0x10dd, 0x10e0, 0x10e8, 0x3b, 0x10e1, 0x10d0, 0x10db, 0x3b, 0x10dd, 0x10d7, 0x10ee, 0x3b, 0x10ee, +0x10e3, 0x10d7, 0x3b, 0x10de, 0x10d0, 0x10e0, 0x3b, 0x10e8, 0x10d0, 0x10d1, 0x3b, 0x10d9, 0x10d5, 0x10d8, 0x10e0, 0x10d0, 0x3b, 0x10dd, 0x10e0, 0x10e8, +0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10e1, 0x10d0, 0x10db, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10dd, 0x10d7, 0x10ee, 0x10e8, +0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10ee, 0x10e3, 0x10d7, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10de, 0x10d0, 0x10e0, 0x10d0, +0x10e1, 0x10d9, 0x10d4, 0x10d5, 0x10d8, 0x3b, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x4d, +0x3b, 0x44, 0x3b, 0x46, 0x3b, 0x53, 0x3b, 0x53, 0x6f, 0x2e, 0x3b, 0x4d, 0x6f, 0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x4d, +0x69, 0x2e, 0x3b, 0x44, 0x6f, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x3b, 0x53, 0x6f, 0x6e, 0x6e, 0x74, +0x61, 0x67, 0x3b, 0x4d, 0x6f, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x44, 0x69, 0x65, 0x6e, 0x73, 0x74, 0x61, 0x67, 0x3b, 0x4d, +0x69, 0x74, 0x74, 0x77, 0x6f, 0x63, 0x68, 0x3b, 0x44, 0x6f, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x74, 0x61, 0x67, 0x3b, 0x46, +0x72, 0x65, 0x69, 0x74, 0x61, 0x67, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x74, 0x61, 0x67, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, +0x6f, 0x6e, 0x3b, 0x44, 0x69, 0x65, 0x3b, 0x4d, 0x69, 0x74, 0x3b, 0x44, 0x6f, 0x6e, 0x3b, 0x46, 0x72, 0x65, 0x3b, 0x53, +0x61, 0x6d, 0x3b, 0x39a, 0x3b, 0x394, 0x3b, 0x3a4, 0x3b, 0x3a4, 0x3b, 0x3a0, 0x3b, 0x3a0, 0x3b, 0x3a3, 0x3b, 0x39a, 0x3c5, 0x3c1, +0x3b, 0x394, 0x3b5, 0x3c5, 0x3b, 0x3a4, 0x3c1, 0x3b9, 0x3b, 0x3a4, 0x3b5, 0x3c4, 0x3b, 0x3a0, 0x3b5, 0x3bc, 0x3b, 0x3a0, 0x3b1, 0x3c1, +0x3b, 0x3a3, 0x3b1, 0x3b2, 0x3b, 0x39a, 0x3c5, 0x3c1, 0x3b9, 0x3b1, 0x3ba, 0x3ae, 0x3b, 0x394, 0x3b5, 0x3c5, 0x3c4, 0x3ad, 0x3c1, 0x3b1, +0x3b, 0x3a4, 0x3c1, 0x3af, 0x3c4, 0x3b7, 0x3b, 0x3a4, 0x3b5, 0x3c4, 0x3ac, 0x3c1, 0x3c4, 0x3b7, 0x3b, 0x3a0, 0x3ad, 0x3bc, 0x3c0, 0x3c4, +0x3b7, 0x3b, 0x3a0, 0x3b1, 0x3c1, 0x3b1, 0x3c3, 0x3ba, 0x3b5, 0x3c5, 0x3ae, 0x3b, 0x3a3, 0x3ac, 0x3b2, 0x3b2, 0x3b1, 0x3c4, 0x3bf, 0x3b, +0x73, 0x61, 0x62, 0x3b, 0x61, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x70, 0x69, 0x6e, 0x3b, 0x73, 0x69, 0x73, 0x3b, +0x74, 0x61, 0x6c, 0x3b, 0x61, 0x72, 0x66, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x61, 0x74, 0x3b, 0x61, 0x74, 0x61, 0x61, 0x73, +0x69, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x6d, 0x61, 0x72, 0x6c, 0x75, 0x6e, 0x6e, 0x67, 0x6f, 0x72, +0x6e, 0x65, 0x71, 0x3b, 0x70, 0x69, 0x6e, 0x67, 0x61, 0x73, 0x75, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, +0x73, 0x69, 0x73, 0x61, 0x6d, 0x61, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x74, 0x61, 0x6c, 0x6c, 0x69, +0x6d, 0x61, 0x6e, 0x6e, 0x67, 0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0x61, 0x72, 0x66, 0x69, 0x6e, 0x69, 0x6e, 0x6e, 0x67, +0x6f, 0x72, 0x6e, 0x65, 0x71, 0x3b, 0xab0, 0xab5, 0xabf, 0x3b, 0xab8, 0xacb, 0xaae, 0x3b, 0xaae, 0xa82, 0xa97, 0xab3, 0x3b, 0xaac, +0xac1, 0xaa7, 0x3b, 0xa97, 0xac1, 0xab0, 0xac1, 0x3b, 0xab6, 0xac1, 0xa95, 0xacd, 0xab0, 0x3b, 0xab6, 0xaa8, 0xabf, 0x3b, 0xab0, 0xab5, +0xabf, 0xab5, 0xabe, 0xab0, 0x3b, 0xab8, 0xacb, 0xaae, 0xab5, 0xabe, 0xab0, 0x3b, 0xaae, 0xa82, 0xa97, 0xab3, 0xab5, 0xabe, 0xab0, 0x3b, +0xaac, 0xac1, 0xaa7, 0xab5, 0xabe, 0xab0, 0x3b, 0xa97, 0xac1, 0xab0, 0xac1, 0xab5, 0xabe, 0xab0, 0x3b, 0xab6, 0xac1, 0xa95, 0xacd, 0xab0, +0xab5, 0xabe, 0xab0, 0x3b, 0xab6, 0xaa8, 0xabf, 0xab5, 0xabe, 0xab0, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x41, +0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x4c, 0x61, 0x68, 0x3b, 0x4c, 0x69, 0x74, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x4c, 0x61, 0x72, +0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x41, 0x73, 0x61, 0x3b, 0x4c, 0x61, 0x68, 0x61, 0x64, 0x69, 0x3b, +0x4c, 0x69, 0x74, 0x69, 0x6e, 0x69, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x4c, 0x61, 0x72, 0x61, 0x62, 0x61, +0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x6d, 0x61, 0x27, 0x61, 0x3b, 0x41, 0x73, 0x61, +0x62, 0x61, 0x72, 0x3b, 0x5d0, 0x3b, 0x5d1, 0x3b, 0x5d2, 0x3b, 0x5d3, 0x3b, 0x5d4, 0x3b, 0x5d5, 0x3b, 0x5e9, 0x3b, 0x5d9, 0x5d5, +0x5dd, 0x20, 0x5e8, 0x5d0, 0x5e9, 0x5d5, 0x5df, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, +0x5e9, 0x5dc, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e8, 0x5d1, 0x5d9, 0x5e2, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, +0x5d7, 0x5de, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5e9, 0x5d1, 0x5ea, 0x3b, 0x930, +0x3b, 0x32, 0x3b, 0x92e, 0x902, 0x3b, 0x34, 0x3b, 0x917, 0x941, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x930, 0x935, 0x93f, 0x3b, 0x938, +0x94b, 0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x3b, 0x936, 0x941, 0x915, +0x94d, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x3b, 0x930, 0x935, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935, 0x93e, 0x930, +0x3b, 0x92e, 0x902, 0x917, 0x932, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941, 0x930, 0x941, +0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x3b, +0x56, 0x3b, 0x48, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x56, 0x3b, 0x48, 0x3b, 0x4b, 0x3b, +0x53, 0x7a, 0x65, 0x3b, 0x43, 0x73, 0x3b, 0x50, 0x3b, 0x53, 0x7a, 0x6f, 0x3b, 0x76, 0x61, 0x73, 0xe1, 0x72, 0x6e, 0x61, +0x70, 0x3b, 0x68, 0xe9, 0x74, 0x66, 0x151, 0x3b, 0x6b, 0x65, 0x64, 0x64, 0x3b, 0x73, 0x7a, 0x65, 0x72, 0x64, 0x61, 0x3b, +0x63, 0x73, 0xfc, 0x74, 0xf6, 0x72, 0x74, 0xf6, 0x6b, 0x3b, 0x70, 0xe9, 0x6e, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x7a, 0x6f, +0x6d, 0x62, 0x61, 0x74, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0xfe, 0x3b, 0x6d, 0x3b, 0x66, 0x3b, 0x66, 0x3b, 0x6c, 0x3b, 0x73, +0x75, 0x6e, 0x3b, 0x6d, 0xe1, 0x6e, 0x3b, 0xfe, 0x72, 0x69, 0x3b, 0x6d, 0x69, 0xf0, 0x3b, 0x66, 0x69, 0x6d, 0x3b, 0x66, +0xf6, 0x73, 0x3b, 0x6c, 0x61, 0x75, 0x3b, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0xe1, +0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0xfe, 0x72, 0x69, 0xf0, 0x6a, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, +0x6d, 0x69, 0xf0, 0x76, 0x69, 0x6b, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66, 0x69, 0x6d, 0x6d, 0x74, 0x75, 0x64, +0x61, 0x67, 0x75, 0x72, 0x3b, 0x66, 0xf6, 0x73, 0x74, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6c, 0x61, 0x75, 0x67, +0x61, 0x72, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x4d, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x3b, +0x52, 0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6d, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4d, 0x69, 0x6e, 0x67, +0x67, 0x75, 0x3b, 0x53, 0x65, 0x6e, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73, 0x61, 0x3b, 0x52, 0x61, 0x62, 0x75, +0x3b, 0x4b, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x75, 0x3b, 0x44, +0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x44, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x44, 0x6f, 0x6d, 0x68, 0x3b, 0x4c, 0x75, +0x61, 0x6e, 0x3b, 0x4d, 0xe1, 0x69, 0x72, 0x74, 0x3b, 0x43, 0xe9, 0x61, 0x64, 0x3b, 0x44, 0xe9, 0x61, 0x72, 0x3b, 0x41, +0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x53, 0x61, 0x74, 0x68, 0x3b, 0x44, 0xe9, 0x20, 0x44, 0x6f, 0x6d, 0x68, 0x6e, 0x61, 0x69, +0x67, 0x68, 0x3b, 0x44, 0xe9, 0x20, 0x4c, 0x75, 0x61, 0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x20, 0x4d, 0xe1, 0x69, 0x72, 0x74, +0x3b, 0x44, 0xe9, 0x20, 0x43, 0xe9, 0x61, 0x64, 0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x61, 0x72, 0x64, 0x61, 0x6f, +0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x20, 0x68, 0x41, 0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x44, 0xe9, 0x20, 0x53, 0x61, 0x74, 0x68, +0x61, 0x69, 0x72, 0x6e, 0x3b, 0x44, 0x6f, 0x6d, 0x65, 0x6e, 0x69, 0x63, 0x61, 0x3b, 0x4c, 0x75, 0x6e, 0x65, 0x64, 0xec, +0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x64, 0xec, 0x3b, 0x4d, 0x65, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x64, 0xec, 0x3b, 0x47, +0x69, 0x6f, 0x76, 0x65, 0x64, 0xec, 0x3b, 0x56, 0x65, 0x6e, 0x65, 0x72, 0x64, 0xec, 0x3b, 0x53, 0x61, 0x62, 0x61, 0x74, +0x6f, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, +0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x72, 0x3b, 0x67, 0x69, 0x6f, 0x3b, 0x76, 0x65, 0x6e, 0x3b, +0x73, 0x61, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x65, 0x6e, 0x69, 0x63, 0x61, 0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x64, 0xec, 0x3b, +0x6d, 0x61, 0x72, 0x74, 0x65, 0x64, 0xec, 0x3b, 0x6d, 0x65, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x64, 0xec, 0x3b, 0x67, 0x69, +0x6f, 0x76, 0x65, 0x64, 0xec, 0x3b, 0x76, 0x65, 0x6e, 0x65, 0x72, 0x64, 0xec, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x74, 0x6f, +0x3b, 0x65e5, 0x3b, 0x6708, 0x3b, 0x706b, 0x3b, 0x6c34, 0x3b, 0x6728, 0x3b, 0x91d1, 0x3b, 0x571f, 0x3b, 0x65e5, 0x66dc, 0x65e5, 0x3b, 0x6708, +0x66dc, 0x65e5, 0x3b, 0x706b, 0x66dc, 0x65e5, 0x3b, 0x6c34, 0x66dc, 0x65e5, 0x3b, 0x6728, 0x66dc, 0x65e5, 0x3b, 0x91d1, 0x66dc, 0x65e5, 0x3b, 0x571f, +0x66dc, 0x65e5, 0x3b, 0xcb0, 0x2e, 0x3b, 0xcb8, 0xccb, 0x2e, 0x3b, 0xcae, 0xc82, 0x2e, 0x3b, 0xcac, 0xcc1, 0x2e, 0x3b, 0xc97, 0xcc1, +0x2e, 0x3b, 0xcb6, 0xcc1, 0x2e, 0x3b, 0xcb6, 0xca8, 0xcbf, 0x2e, 0x3b, 0xcb0, 0xcb5, 0xcbf, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb8, 0xccb, +0xcae, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcae, 0xc82, 0xc97, 0xcb3, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcac, 0xcc1, 0xca7, 0xcb5, 0xcbe, 0xcb0, 0x3b, +0xc97, 0xcc1, 0xcb0, 0xcc1, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb6, 0xcc1, 0xc95, 0xccd, 0xcb0, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb6, 0xca8, 0xcbf, +0xcb5, 0xcbe, 0xcb0, 0x3b, 0x436, 0x441, 0x2e, 0x3b, 0x434, 0x441, 0x2e, 0x3b, 0x441, 0x441, 0x2e, 0x3b, 0x441, 0x440, 0x2e, 0x3b, +0x431, 0x441, 0x2e, 0x3b, 0x436, 0x43c, 0x2e, 0x3b, 0x441, 0x4bb, 0x2e, 0x3b, 0x436, 0x435, 0x43a, 0x441, 0x435, 0x43d, 0x456, 0x3b, +0x434, 0x443, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x441, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x441, 0x4d9, +0x440, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x431, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x436, 0x4b1, 0x43c, 0x430, 0x3b, +0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x63, 0x79, 0x75, 0x2e, 0x3b, 0x6d, 0x62, 0x65, 0x2e, 0x3b, 0x6b, 0x61, 0x62, 0x2e, +0x3b, 0x67, 0x74, 0x75, 0x2e, 0x3b, 0x6b, 0x61, 0x6e, 0x2e, 0x3b, 0x67, 0x6e, 0x75, 0x2e, 0x3b, 0x67, 0x6e, 0x64, 0x2e, +0x3b, 0x4b, 0x75, 0x20, 0x63, 0x79, 0x75, 0x6d, 0x77, 0x65, 0x72, 0x75, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6d, 0x62, +0x65, 0x72, 0x65, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4b, 0x75, 0x77, 0x61, +0x20, 0x67, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x65, 0x3b, 0x4b, 0x75, +0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, +0x64, 0x61, 0x74, 0x75, 0x3b, 0xc77c, 0x3b, 0xc6d4, 0x3b, 0xd654, 0x3b, 0xc218, 0x3b, 0xbaa9, 0x3b, 0xae08, 0x3b, 0xd1a0, 0x3b, 0xc77c, +0xc694, 0xc77c, 0x3b, 0xc6d4, 0xc694, 0xc77c, 0x3b, 0xd654, 0xc694, 0xc77c, 0x3b, 0xc218, 0xc694, 0xc77c, 0x3b, 0xbaa9, 0xc694, 0xc77c, 0x3b, 0xae08, +0xc694, 0xc77c, 0x3b, 0xd1a0, 0xc694, 0xc77c, 0x3b, 0xead, 0xeb2, 0x2e, 0x3b, 0xe88, 0x2e, 0x3b, 0xead, 0x2e, 0x3b, 0xe9e, 0x2e, 0x3b, +0xe9e, 0xeab, 0x2e, 0x3b, 0xeaa, 0xe81, 0x2e, 0x3b, 0xeaa, 0x2e, 0x3b, 0xea7, 0xeb1, 0xe99, 0xead, 0xeb2, 0xe97, 0xeb4, 0xe94, 0x3b, +0xea7, 0xeb1, 0xe99, 0xe88, 0xeb1, 0xe99, 0x3b, 0xea7, 0xeb1, 0xe99, 0xead, 0xeb1, 0xe87, 0xe84, 0xeb2, 0xe99, 0x3b, 0xea7, 0xeb1, 0xe99, +0xe9e, 0xeb8, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xe9e, 0xeb0, 0xeab, 0xeb1, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xeaa, 0xeb8, 0xe81, 0x3b, +0xea7, 0xeb1, 0xe99, 0xec0, 0xeaa, 0xebb, 0xeb2, 0x3b, 0x3b, 0x50, 0x72, 0x3b, 0x6f, 0x74, 0x3b, 0x54, 0x72, 0x3b, 0x43, 0x65, +0x3b, 0x70, 0x6b, 0x3b, 0x53, 0x65, 0x3b, 0x53, 0x3b, 0x50, 0x3b, 0x4f, 0x3b, 0x54, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x53, +0x3b, 0x53, 0x76, 0x3b, 0x50, 0x3b, 0x4f, 0x3b, 0x54, 0x3b, 0x43, 0x3b, 0x50, 0x6b, 0x3b, 0x53, 0x3b, 0x73, 0x76, 0x113, +0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x70, 0x69, 0x72, 0x6d, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x6f, 0x74, 0x72, +0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x74, 0x72, 0x65, 0x161, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x63, 0x65, 0x74, 0x75, +0x72, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x70, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x73, +0x65, 0x73, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x65, 0x79, 0x65, 0x3b, 0x6d, 0x31, 0x3b, 0x6d, 0x32, 0x3b, 0x6d, +0x33, 0x3b, 0x6d, 0x34, 0x3b, 0x6d, 0x35, 0x3b, 0x6d, 0x70, 0x73, 0x3b, 0x65, 0x79, 0x65, 0x6e, 0x67, 0x61, 0x3b, 0x6d, +0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x79, 0x61, 0x20, 0x6c, 0x69, 0x62, 0x6f, 0x73, 0xf3, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, +0x6c, 0x254, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, +0x79, 0x61, 0x20, 0x6d, 0xed, 0x73, 0xe1, 0x74, 0x6f, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x79, 0x61, 0x20, +0x6d, 0xed, 0x6e, 0xe9, 0x69, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x74, 0xe1, +0x6e, 0x6f, 0x3b, 0x6d, 0x70, 0x254, 0x301, 0x73, 0x254, 0x3b, 0x53, 0x3b, 0x50, 0x3b, 0x41, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, +0x50, 0x3b, 0x160, 0x3b, 0x53, 0x6b, 0x3b, 0x50, 0x72, 0x3b, 0x41, 0x6e, 0x3b, 0x54, 0x72, 0x3b, 0x4b, 0x74, 0x3b, 0x50, +0x6e, 0x3b, 0x160, 0x74, 0x3b, 0x73, 0x65, 0x6b, 0x6d, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x70, 0x69, 0x72, +0x6d, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x61, 0x6e, 0x74, 0x72, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, +0x3b, 0x74, 0x72, 0x65, 0x10d, 0x69, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x6b, 0x65, 0x74, 0x76, 0x69, 0x72, +0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x70, 0x65, 0x6e, 0x6b, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, +0x73, 0x3b, 0x161, 0x65, 0x161, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x43d, 0x435, 0x434, 0x2e, 0x3b, 0x43f, +0x43e, 0x43d, 0x2e, 0x3b, 0x432, 0x442, 0x2e, 0x3b, 0x441, 0x440, 0x435, 0x2e, 0x3b, 0x447, 0x435, 0x442, 0x2e, 0x3b, 0x43f, 0x435, +0x442, 0x2e, 0x3b, 0x441, 0x430, 0x431, 0x2e, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, +0x435, 0x43b, 0x43d, 0x438, 0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, +0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x43e, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x43e, 0x43a, 0x3b, 0x441, 0x430, 0x431, 0x43e, 0x442, +0x430, 0x3b, 0x41, 0x68, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x3b, 0x4b, 0x68, +0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x41, 0x68, 0x61, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x69, 0x6e, +0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73, 0x61, 0x3b, 0x52, 0x61, 0x62, 0x75, 0x3b, 0x4b, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x3b, +0x4a, 0x75, 0x6d, 0x61, 0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x75, 0x3b, 0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15, 0xd33, +0xd3e, 0xd34, 0xd4d, 0xd1a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xd1e, 0x3b, 0xd24, 0x3b, 0xd1a, 0x3b, 0xd2c, 0x3b, 0xd35, 0x3b, +0xd35, 0x3b, 0xd36, 0x3b, 0xd1e, 0xd3e, 0x3b, 0xd24, 0xd3f, 0x3b, 0xd1a, 0xd4a, 0x3b, 0xd2c, 0xd41, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, +0x3b, 0xd35, 0xd46, 0x3b, 0xd36, 0x3b, 0xd1e, 0xd3e, 0xd2f, 0xd30, 0xd4d, 0x200d, 0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15, 0xd33, 0xd4d, +0x200d, 0x3b, 0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd28, 0xd4d, 0x200d, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0xd34, +0xd02, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0x3b, 0xd36, 0xd28, 0xd3f, 0x3b, 0x3b, 0x3b, 0xd1a, 0xd4a, 0x3b, 0x3b, 0x3b, +0x3b, 0x3b, 0x126, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x45, 0x3b, 0x126, 0x3b, 0x120, 0x3b, 0x53, 0x3b, 0x126, 0x61, 0x64, 0x3b, +0x54, 0x6e, 0x65, 0x3b, 0x54, 0x6c, 0x69, 0x3b, 0x45, 0x72, 0x62, 0x3b, 0x126, 0x61, 0x6d, 0x3b, 0x120, 0x69, 0x6d, 0x3b, +0x53, 0x69, 0x62, 0x3b, 0x49, 0x6c, 0x2d, 0x126, 0x61, 0x64, 0x64, 0x3b, 0x49, 0x74, 0x2d, 0x54, 0x6e, 0x65, 0x6a, 0x6e, +0x3b, 0x49, 0x74, 0x2d, 0x54, 0x6c, 0x69, 0x65, 0x74, 0x61, 0x3b, 0x4c, 0x2d, 0x45, 0x72, 0x62, 0x67, 0x127, 0x61, 0x3b, +0x49, 0x6c, 0x2d, 0x126, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x49, 0x6c, 0x2d, 0x120, 0x69, 0x6d, 0x67, 0x127, 0x61, 0x3b, 0x49, +0x73, 0x2d, 0x53, 0x69, 0x62, 0x74, 0x3b, 0x930, 0x935, 0x93f, 0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x3b, +0x92c, 0x941, 0x927, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x3b, 0x930, +0x935, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x935, 0x93e, 0x930, +0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, +0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x41d, 0x44f, 0x3b, 0x414, 0x430, 0x3b, 0x41c, 0x44f, +0x3b, 0x41b, 0x445, 0x3b, 0x41f, 0x4af, 0x3b, 0x411, 0x430, 0x3b, 0x411, 0x44f, 0x3b, 0x43d, 0x44f, 0x43c, 0x3b, 0x434, 0x430, 0x432, +0x430, 0x430, 0x3b, 0x43c, 0x44f, 0x433, 0x43c, 0x430, 0x440, 0x3b, 0x43b, 0x445, 0x430, 0x433, 0x432, 0x430, 0x3b, 0x43f, 0x4af, 0x440, +0x44d, 0x432, 0x3b, 0x431, 0x430, 0x430, 0x441, 0x430, 0x43d, 0x3b, 0x431, 0x44f, 0x43c, 0x431, 0x430, 0x3b, 0x967, 0x3b, 0x968, 0x3b, +0x969, 0x3b, 0x96a, 0x3b, 0x96b, 0x3b, 0x96c, 0x3b, 0x96d, 0x3b, 0x906, 0x907, 0x924, 0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x919, +0x94d, 0x917, 0x932, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x92c, 0x93f, 0x939, 0x940, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, +0x928, 0x93f, 0x3b, 0x906, 0x907, 0x924, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x92c, 0x93e, 0x930, 0x3b, 0x92e, 0x919, 0x94d, +0x917, 0x932, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x93f, 0x939, 0x940, 0x92c, 0x93e, 0x930, +0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x92c, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x73, 0xf8, 0x6e, +0x2e, 0x3b, 0x6d, 0x61, 0x6e, 0x2e, 0x3b, 0x74, 0x69, 0x72, 0x2e, 0x3b, 0x6f, 0x6e, 0x73, 0x2e, 0x3b, 0x74, 0x6f, 0x72, +0x2e, 0x3b, 0x66, 0x72, 0x65, 0x2e, 0x3b, 0x6c, 0xf8, 0x72, 0x2e, 0x3b, 0xb30, 0xb2c, 0xb3f, 0x3b, 0xb38, 0xb4b, 0xb2e, 0x3b, +0xb2e, 0xb19, 0xb4d, 0xb17, 0xb33, 0x3b, 0xb2c, 0xb41, 0xb27, 0x3b, 0xb17, 0xb41, 0xb30, 0xb41, 0x3b, 0xb36, 0xb41, 0xb15, 0xb4d, 0xb30, +0x3b, 0xb36, 0xb28, 0xb3f, 0x3b, 0xb30, 0xb2c, 0xb3f, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb38, 0xb4b, 0xb2e, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb2e, +0xb19, 0xb4d, 0xb17, 0xb33, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb2c, 0xb41, 0xb27, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb17, 0xb41, 0xb30, 0xb41, 0xb2c, +0xb3e, 0xb30, 0x3b, 0xb36, 0xb41, 0xb15, 0xb4d, 0xb30, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb36, 0xb28, 0xb3f, 0xb2c, 0xb3e, 0xb30, 0x3b, 0x6cc, +0x6a9, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x62f, 0x648, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x633, 0x647, 0x200c, 0x634, 0x646, 0x628, 0x647, +0x3b, 0x686, 0x647, 0x627, 0x631, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x67e, 0x646, 0x62c, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x62c, 0x645, +0x639, 0x647, 0x3b, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x6cc, 0x3b, 0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x62c, 0x3b, +0x634, 0x3b, 0x4e, 0x3b, 0x50, 0x3b, 0x57, 0x3b, 0x15a, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x6e, 0x69, 0x65, 0x64, +0x7a, 0x2e, 0x3b, 0x70, 0x6f, 0x6e, 0x2e, 0x3b, 0x77, 0x74, 0x2e, 0x3b, 0x15b, 0x72, 0x2e, 0x3b, 0x63, 0x7a, 0x77, 0x2e, +0x3b, 0x70, 0x74, 0x2e, 0x3b, 0x73, 0x6f, 0x62, 0x2e, 0x3b, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x69, 0x65, 0x6c, 0x61, 0x3b, +0x70, 0x6f, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x69, 0x61, 0x142, 0x65, 0x6b, 0x3b, 0x77, 0x74, 0x6f, 0x72, 0x65, 0x6b, 0x3b, +0x15b, 0x72, 0x6f, 0x64, 0x61, 0x3b, 0x63, 0x7a, 0x77, 0x61, 0x72, 0x74, 0x65, 0x6b, 0x3b, 0x70, 0x69, 0x105, 0x74, 0x65, +0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x51, 0x3b, 0x51, 0x3b, 0x53, +0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, 0x73, 0x65, 0x67, 0x3b, 0x74, 0x65, 0x72, 0x3b, 0x71, 0x75, 0x61, 0x3b, 0x71, +0x75, 0x69, 0x3b, 0x73, 0x65, 0x78, 0x3b, 0x73, 0xe1, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x73, +0x65, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x74, 0x65, 0x72, 0xe7, 0x61, 0x2d, 0x66, +0x65, 0x69, 0x72, 0x61, 0x3b, 0x71, 0x75, 0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x71, 0x75, +0x69, 0x6e, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x73, 0x65, 0x78, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, +0x72, 0x61, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0xa10, 0x3b, 0xa38, 0xa4b, 0x3b, 0xa2e, 0xa70, 0x3b, 0xa2c, 0xa41, +0xa71, 0x3b, 0xa35, 0xa40, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa71, 0x3b, 0xa38, 0xa3c, 0x3b, 0xa10, 0xa24, 0x2e, 0x3b, 0xa38, 0xa4b, 0xa2e, +0x2e, 0x3b, 0xa2e, 0xa70, 0xa17, 0xa32, 0x2e, 0x3b, 0xa2c, 0xa41, 0xa27, 0x2e, 0x3b, 0xa35, 0xa40, 0xa30, 0x2e, 0x3b, 0xa38, 0xa3c, +0xa41, 0xa15, 0xa30, 0x2e, 0x3b, 0xa38, 0xa3c, 0xa28, 0xa40, 0x2e, 0x3b, 0xa10, 0xa24, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa4b, 0xa2e, +0xa35, 0xa3e, 0xa30, 0x3b, 0xa2e, 0xa70, 0xa17, 0xa32, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa2c, 0xa41, 0xa27, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa35, +0xa40, 0xa30, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa71, 0xa15, 0xa30, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa28, 0xa40, +0xa1a, 0xa30, 0xa35, 0xa3e, 0xa30, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0xe2, 0x6d, 0x62, 0x103, 0x74, 0x103, 0x3b, +0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x61, 0x3b, 0x4d, 0x69, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x75, 0x6d, 0x69, +0x6e, 0x69, 0x63, 0x103, 0x3b, 0x6c, 0x75, 0x6e, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x21b, 0x69, 0x3b, 0x6d, 0x69, 0x65, 0x72, +0x63, 0x75, 0x72, 0x69, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x65, 0x72, 0x69, 0x3b, 0x73, 0xe2, 0x6d, 0x62, +0x103, 0x74, 0x103, 0x3b, 0x412, 0x43e, 0x441, 0x43a, 0x440, 0x435, 0x441, 0x435, 0x43d, 0x44c, 0x435, 0x3b, 0x41f, 0x43e, 0x43d, 0x435, +0x434, 0x435, 0x43b, 0x44c, 0x43d, 0x438, 0x43a, 0x3b, 0x412, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x421, 0x440, 0x435, 0x434, +0x430, 0x3b, 0x427, 0x435, 0x442, 0x432, 0x435, 0x440, 0x433, 0x3b, 0x41f, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x430, 0x3b, 0x421, 0x443, +0x431, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x412, 0x3b, 0x41f, 0x3b, 0x412, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x421, 0x3b, +0x412, 0x441, 0x3b, 0x41f, 0x43d, 0x3b, 0x412, 0x442, 0x3b, 0x421, 0x440, 0x3b, 0x427, 0x442, 0x3b, 0x41f, 0x442, 0x3b, 0x421, 0x431, +0x3b, 0x432, 0x43e, 0x441, 0x43a, 0x440, 0x435, 0x441, 0x435, 0x43d, 0x44c, 0x435, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x43b, +0x44c, 0x43d, 0x438, 0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, +0x435, 0x442, 0x432, 0x435, 0x440, 0x433, 0x3b, 0x43f, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x430, 0x3b, 0x441, 0x443, 0x431, 0x431, 0x43e, +0x442, 0x430, 0x3b, 0x43d, 0x3b, 0x43f, 0x3b, 0x443, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 0x43d, 0x435, 0x434, +0x3b, 0x43f, 0x43e, 0x43d, 0x3b, 0x443, 0x442, 0x43e, 0x3b, 0x441, 0x440, 0x435, 0x3b, 0x447, 0x435, 0x442, 0x3b, 0x43f, 0x435, 0x442, +0x3b, 0x441, 0x443, 0x431, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, +0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, +0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x43d, 0x435, 0x434, +0x3b, 0x43f, 0x43e, 0x43d, 0x3b, 0x443, 0x442, 0x43e, 0x3b, 0x441, 0x440, 0x438, 0x3b, 0x447, 0x435, 0x442, 0x3b, 0x43f, 0x435, 0x442, +0x3b, 0x441, 0x443, 0x431, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, +0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x438, 0x458, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, +0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x6e, +0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x75, 0x74, 0x6f, 0x3b, 0x73, 0x72, 0x65, 0x3b, 0x10d, 0x65, 0x74, 0x3b, 0x70, +0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x3b, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, +0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x10d, +0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, +0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x6d, 0x61, 0x3b, 0x42, 0x65, 0x64, 0x3b, 0x52, 0x61, 0x72, 0x3b, 0x4e, 0x65, 0x3b, +0x48, 0x6c, 0x61, 0x3b, 0x4d, 0x6f, 0x71, 0x3b, 0x53, 0x6f, 0x6e, 0x74, 0x61, 0x68, 0x61, 0x3b, 0x4d, 0x6d, 0x61, 0x6e, +0x74, 0x61, 0x68, 0x61, 0x3b, 0x4c, 0x61, 0x62, 0x6f, 0x62, 0x65, 0x64, 0x69, 0x3b, 0x4c, 0x61, 0x62, 0x6f, 0x72, 0x61, +0x72, 0x75, 0x3b, 0x4c, 0x61, 0x62, 0x6f, 0x6e, 0x65, 0x3b, 0x4c, 0x61, 0x62, 0x6f, 0x68, 0x6c, 0x61, 0x6e, 0x65, 0x3b, +0x4d, 0x6f, 0x71, 0x65, 0x62, 0x65, 0x6c, 0x6f, 0x3b, 0x54, 0x73, 0x68, 0x3b, 0x4d, 0x6f, 0x73, 0x3b, 0x42, 0x65, 0x64, +0x3b, 0x52, 0x61, 0x72, 0x3b, 0x4e, 0x65, 0x3b, 0x54, 0x6c, 0x61, 0x3b, 0x4d, 0x61, 0x74, 0x3b, 0x54, 0x73, 0x68, 0x69, +0x70, 0x69, 0x3b, 0x4d, 0x6f, 0x73, 0x6f, 0x70, 0x75, 0x6c, 0x6f, 0x67, 0x6f, 0x3b, 0x4c, 0x61, 0x62, 0x6f, 0x62, 0x65, +0x64, 0x69, 0x3b, 0x4c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x72, 0x6f, 0x3b, 0x4c, 0x61, 0x62, 0x6f, 0x6e, 0x65, 0x3b, 0x4c, +0x61, 0x62, 0x6f, 0x74, 0x6c, 0x68, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x61, 0x74, 0x6c, 0x68, 0x61, 0x74, 0x73, 0x6f, 0x3b, +0xd89, 0x3b, 0xdc3, 0x3b, 0xd85, 0x3b, 0xdb6, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0x3b, 0xdc3, 0xdd2, 0x3b, 0xdc3, 0xdd9, 0x3b, 0xd89, +0xdbb, 0xdd2, 0x3b, 0xdc3, 0xdb3, 0xdd4, 0x3b, 0xd85, 0xd9f, 0x3b, 0xdb6, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0xdc4, 0x3b, +0xdc3, 0xdd2, 0xd9a, 0xdd4, 0x3b, 0xdc3, 0xdd9, 0xdb1, 0x3b, 0xd89, 0xdbb, 0xdd2, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdb3, 0xdd4, 0xdaf, 0xdcf, +0x3b, 0xd85, 0xd9f, 0xdc4, 0xdbb, 0xdd4, 0xdc0, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdaf, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdca, 0x200d, +0xdbb, 0xdc4, 0xdc3, 0xdca, 0xdb4, 0xdad, 0xdd2, 0xdb1, 0xdca, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdd2, 0xd9a, 0xdd4, 0xdbb, 0xdcf, 0xdaf, 0xdcf, +0x3b, 0xdc3, 0xdd9, 0xdb1, 0xdc3, 0xdd4, 0xdbb, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x73, 0x6f, 0x3b, 0x42, +0x69, 0x6c, 0x3b, 0x54, 0x73, 0x61, 0x3b, 0x4e, 0x65, 0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x4d, 0x67, 0x63, 0x3b, 0x4c, 0x69, +0x73, 0x6f, 0x6e, 0x74, 0x66, 0x6f, 0x3b, 0x75, 0x4d, 0x73, 0x6f, 0x6d, 0x62, 0x75, 0x6c, 0x75, 0x6b, 0x6f, 0x3b, 0x4c, +0x65, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x4c, 0x65, 0x73, 0x69, 0x74, 0x73, 0x61, 0x74, 0x66, 0x75, 0x3b, 0x4c, +0x65, 0x73, 0x69, 0x6e, 0x65, 0x3b, 0x4c, 0x65, 0x73, 0x69, 0x68, 0x6c, 0x61, 0x6e, 0x75, 0x3b, 0x75, 0x4d, 0x67, 0x63, +0x69, 0x62, 0x65, 0x6c, 0x6f, 0x3b, 0x4e, 0x3b, 0x50, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x160, 0x3b, 0x50, 0x3b, 0x53, 0x3b, +0x4e, 0x65, 0x3b, 0x50, 0x6f, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x74, 0x3b, 0x160, 0x74, 0x3b, 0x50, 0x69, 0x3b, 0x53, 0x6f, +0x3b, 0x4e, 0x65, 0x64, 0x65, 0x13e, 0x61, 0x3b, 0x50, 0x6f, 0x6e, 0x64, 0x65, 0x6c, 0x6f, 0x6b, 0x3b, 0x55, 0x74, 0x6f, +0x72, 0x6f, 0x6b, 0x3b, 0x53, 0x74, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x160, 0x74, 0x76, 0x72, 0x74, 0x6f, 0x6b, 0x3b, 0x50, +0x69, 0x61, 0x74, 0x6f, 0x6b, 0x3b, 0x53, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x74, 0x3b, 0x73, +0x3b, 0x10d, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x74, 0x6f, 0x72, 0x3b, 0x73, +0x72, 0x65, 0x3b, 0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x6f, 0x62, 0x3b, 0x6e, 0x65, 0x64, 0x65, 0x6c, +0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x65, 0x6b, 0x3b, 0x74, 0x6f, 0x72, 0x65, 0x6b, 0x3b, +0x73, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x72, 0x74, 0x65, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x65, 0x6b, 0x3b, +0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b, 0x53, +0x3b, 0x41, 0x78, 0x61, 0x3b, 0x49, 0x73, 0x6e, 0x3b, 0x53, 0x61, 0x6c, 0x3b, 0x41, 0x72, 0x62, 0x3b, 0x4b, 0x68, 0x61, +0x3b, 0x4a, 0x69, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x41, 0x78, 0x61, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x69, 0x69, 0x6e, +0x3b, 0x53, 0x61, 0x6c, 0x61, 0x61, 0x73, 0x6f, 0x3b, 0x41, 0x72, 0x62, 0x61, 0x63, 0x6f, 0x3b, 0x4b, 0x68, 0x61, 0x6d, +0x69, 0x69, 0x73, 0x3b, 0x4a, 0x69, 0x6d, 0x63, 0x6f, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x69, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, +0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x69, 0xe9, 0x3b, 0x6a, 0x75, 0x65, 0x3b, 0x76, 0x69, 0x65, 0x3b, +0x73, 0xe1, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x6d, 0x61, +0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d, 0x69, 0xe9, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x6a, 0x75, 0x65, 0x76, 0x65, +0x73, 0x3b, 0x76, 0x69, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x4a, 0x70, 0x69, +0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, +0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, +0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, +0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, +0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x73, 0xf6, 0x6e, 0x3b, 0x6d, 0xe5, 0x6e, 0x3b, 0x74, 0x69, 0x73, 0x3b, 0x6f, 0x6e, 0x73, +0x3b, 0x74, 0x6f, 0x72, 0x73, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0xf6, 0x72, 0x3b, 0x73, 0xf6, 0x6e, 0x64, 0x61, 0x67, +0x3b, 0x6d, 0xe5, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x69, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73, 0x64, 0x61, +0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0xf6, 0x72, +0x64, 0x61, 0x67, 0x3b, 0x42f, 0x448, 0x431, 0x3b, 0x414, 0x448, 0x431, 0x3b, 0x421, 0x448, 0x431, 0x3b, 0x427, 0x448, 0x431, 0x3b, +0x41f, 0x448, 0x431, 0x3b, 0x4b6, 0x43c, 0x44a, 0x3b, 0x428, 0x43d, 0x431, 0x3b, 0x42f, 0x43a, 0x448, 0x430, 0x43d, 0x431, 0x435, 0x3b, +0x414, 0x443, 0x448, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0x421, 0x435, 0x448, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0x427, 0x43e, 0x440, 0x448, +0x430, 0x43d, 0x431, 0x435, 0x3b, 0x41f, 0x430, 0x43d, 0x4b7, 0x448, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0x4b6, 0x443, 0x43c, 0x44a, 0x430, +0x3b, 0x428, 0x430, 0x43d, 0x431, 0x435, 0x3b, 0xb9e, 0xbbe, 0x3b, 0xba4, 0xbbf, 0x3b, 0xb9a, 0xbc6, 0x3b, 0xbaa, 0xbc1, 0x3b, 0xbb5, +0xbbf, 0x3b, 0xbb5, 0xbc6, 0x3b, 0xb9a, 0x3b, 0xb9e, 0xbbe, 0xbaf, 0xbbf, 0xbb1, 0xbc1, 0x3b, 0xba4, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbb3, +0xbcd, 0x3b, 0xb9a, 0xbc6, 0xbb5, 0xbcd, 0xbb5, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0xbaa, 0xbc1, 0xba4, 0xba9, 0xbcd, 0x3b, 0xbb5, 0xbbf, 0xbaf, +0xbbe, 0xbb4, 0xba9, 0xbcd, 0x3b, 0xbb5, 0xbc6, 0xbb3, 0xbcd, 0xbb3, 0xbbf, 0x3b, 0xb9a, 0xba9, 0xbbf, 0x3b, 0xc06, 0x3b, 0x32, 0x3b, +0xc38, 0xc4a, 0x3b, 0xc2d, 0xc41, 0x3b, 0xc17, 0xc41, 0x3b, 0xc36, 0xc41, 0x3b, 0xc36, 0x3b, 0xc06, 0xc26, 0xc3f, 0x3b, 0xc38, 0xc4b, +0xc2e, 0x3b, 0xc2e, 0xc02, 0xc17, 0xc33, 0x3b, 0xc2c, 0xc41, 0xc27, 0x3b, 0xc17, 0xc41, 0xc30, 0xc41, 0x3b, 0xc36, 0xc41, 0xc15, 0xc4d, +0xc30, 0x3b, 0xc36, 0xc28, 0xc3f, 0x3b, 0xc06, 0xc26, 0xc3f, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc38, 0xc4b, 0xc2e, 0xc35, 0xc3e, 0xc30, +0xc02, 0x3b, 0xc2e, 0xc02, 0xc17, 0xc33, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc2c, 0xc41, 0xc27, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc17, +0xc41, 0xc30, 0xc41, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc36, 0xc41, 0xc15, 0xc4d, 0xc30, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc36, 0xc28, +0xc3f, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xe2d, 0x3b, 0xe08, 0x3b, 0xe2d, 0x3b, 0xe1e, 0x3b, 0xe1e, 0x3b, 0xe28, 0x3b, 0xe2a, 0x3b, +0xe2d, 0xe32, 0x2e, 0x3b, 0xe08, 0x2e, 0x3b, 0xe2d, 0x2e, 0x3b, 0xe1e, 0x2e, 0x3b, 0xe1e, 0xe24, 0x2e, 0x3b, 0xe28, 0x2e, 0x3b, +0xe2a, 0x2e, 0x3b, 0xe27, 0xe31, 0xe19, 0xe2d, 0xe32, 0xe17, 0xe34, 0xe15, 0xe22, 0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe08, 0xe31, 0xe19, +0xe17, 0xe23, 0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe2d, 0xe31, 0xe07, 0xe04, 0xe32, 0xe23, 0x3b, 0xe27, 0xe31, 0xe19, 0xe1e, 0xe38, 0xe18, +0x3b, 0xe27, 0xe31, 0xe19, 0xe1e, 0xe24, 0xe2b, 0xe31, 0xe2a, 0xe1a, 0xe14, 0xe35, 0x3b, 0xe27, 0xe31, 0xe19, 0xe28, 0xe38, 0xe01, 0xe23, +0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe40, 0xe2a, 0xe32, 0xe23, 0xe4c, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xe1e, 0xe24, 0x3b, 0x3b, 0x3b, +0x1230, 0x3b, 0x1230, 0x3b, 0x1220, 0x3b, 0x1228, 0x3b, 0x1283, 0x3b, 0x12d3, 0x3b, 0x1240, 0x3b, 0x1230, 0x1295, 0x1260, 0x3b, 0x1230, 0x1291, +0x12ed, 0x3b, 0x1230, 0x1209, 0x1235, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1213, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1262, 0x3b, 0x1240, 0x12f3, +0x121d, 0x3b, 0x1230, 0x1295, 0x1260, 0x1275, 0x3b, 0x1230, 0x1291, 0x12ed, 0x3b, 0x1230, 0x1209, 0x1235, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1213, +0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1262, 0x3b, 0x1240, 0x12f3, 0x121d, 0x3b, 0x1230, 0x1295, 0x1260, 0x3b, 0x1230, 0x1291, 0x12ed, 0x3b, 0x1220, +0x1209, 0x1235, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1283, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1262, 0x3b, 0x1240, 0x12f3, 0x121d, 0x3b, 0x1230, +0x1295, 0x1260, 0x1275, 0x3b, 0x1230, 0x1291, 0x12ed, 0x3b, 0x1220, 0x1209, 0x1235, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1283, 0x1219, 0x1235, 0x3b, +0x12d3, 0x122d, 0x1262, 0x3b, 0x1240, 0x12f3, 0x121d, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x50, 0x3b, 0x54, 0x3b, 0x46, 0x3b, +0x54, 0x3b, 0x53, 0x101, 0x70, 0x3b, 0x4d, 0x14d, 0x6e, 0x3b, 0x54, 0x75, 0x73, 0x3b, 0x50, 0x75, 0x6c, 0x3b, 0x54, 0x75, +0x2bb, 0x61, 0x3b, 0x46, 0x61, 0x6c, 0x3b, 0x54, 0x6f, 0x6b, 0x3b, 0x53, 0x101, 0x70, 0x61, 0x74, 0x65, 0x3b, 0x4d, 0x14d, +0x6e, 0x69, 0x74, 0x65, 0x3b, 0x54, 0x75, 0x73, 0x69, 0x74, 0x65, 0x3b, 0x50, 0x75, 0x6c, 0x65, 0x6c, 0x75, 0x6c, 0x75, +0x3b, 0x54, 0x75, 0x2bb, 0x61, 0x70, 0x75, 0x6c, 0x65, 0x6c, 0x75, 0x6c, 0x75, 0x3b, 0x46, 0x61, 0x6c, 0x61, 0x69, 0x74, +0x65, 0x3b, 0x54, 0x6f, 0x6b, 0x6f, 0x6e, 0x61, 0x6b, 0x69, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x75, 0x73, 0x3b, 0x42, +0x69, 0x72, 0x3b, 0x48, 0x61, 0x72, 0x3b, 0x4e, 0x65, 0x3b, 0x54, 0x6c, 0x68, 0x3b, 0x4d, 0x75, 0x67, 0x3b, 0x53, 0x6f, +0x6e, 0x74, 0x6f, 0x3b, 0x4d, 0x75, 0x73, 0x75, 0x6d, 0x62, 0x68, 0x75, 0x6e, 0x75, 0x6b, 0x75, 0x3b, 0x52, 0x61, 0x76, +0x75, 0x6d, 0x62, 0x69, 0x72, 0x68, 0x69, 0x3b, 0x52, 0x61, 0x76, 0x75, 0x6e, 0x68, 0x61, 0x72, 0x68, 0x75, 0x3b, 0x52, +0x61, 0x76, 0x75, 0x6d, 0x75, 0x6e, 0x65, 0x3b, 0x52, 0x61, 0x76, 0x75, 0x6e, 0x74, 0x6c, 0x68, 0x61, 0x6e, 0x75, 0x3b, +0x4d, 0x75, 0x67, 0x71, 0x69, 0x76, 0x65, 0x6c, 0x61, 0x3b, 0x50, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0xc7, 0x3b, 0x50, 0x3b, +0x43, 0x3b, 0x43, 0x3b, 0x50, 0x61, 0x7a, 0x3b, 0x50, 0x7a, 0x74, 0x3b, 0x53, 0x61, 0x6c, 0x3b, 0xc7, 0x61, 0x72, 0x3b, +0x50, 0x65, 0x72, 0x3b, 0x43, 0x75, 0x6d, 0x3b, 0x43, 0x6d, 0x74, 0x3b, 0x50, 0x61, 0x7a, 0x61, 0x72, 0x3b, 0x50, 0x61, +0x7a, 0x61, 0x72, 0x74, 0x65, 0x73, 0x69, 0x3b, 0x53, 0x61, 0x6c, 0x131, 0x3b, 0xc7, 0x61, 0x72, 0x15f, 0x61, 0x6d, 0x62, +0x61, 0x3b, 0x50, 0x65, 0x72, 0x15f, 0x65, 0x6d, 0x62, 0x65, 0x3b, 0x43, 0x75, 0x6d, 0x61, 0x3b, 0x43, 0x75, 0x6d, 0x61, +0x72, 0x74, 0x65, 0x73, 0x69, 0x3b, 0x41d, 0x3b, 0x41f, 0x3b, 0x412, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x421, 0x3b, +0x41d, 0x434, 0x3b, 0x41f, 0x43d, 0x3b, 0x412, 0x442, 0x3b, 0x421, 0x440, 0x3b, 0x427, 0x442, 0x3b, 0x41f, 0x442, 0x3b, 0x421, 0x431, +0x3b, 0x41d, 0x435, 0x434, 0x456, 0x43b, 0x44f, 0x3b, 0x41f, 0x43e, 0x43d, 0x435, 0x434, 0x456, 0x43b, 0x43e, 0x43a, 0x3b, 0x412, 0x456, +0x432, 0x442, 0x43e, 0x440, 0x43e, 0x43a, 0x3b, 0x421, 0x435, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x427, 0x435, 0x442, 0x432, 0x435, 0x440, +0x3b, 0x41f, 0x2bc, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x44f, 0x3b, 0x421, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x627, 0x62a, 0x648, +0x627, 0x631, 0x3b, 0x67e, 0x64a, 0x631, 0x3b, 0x645, 0x646, 0x6af, 0x644, 0x3b, 0x628, 0x62f, 0x647, 0x3b, 0x62c, 0x645, 0x639, 0x631, +0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641, 0x62a, 0x6c1, 0x3b, 0x627, 0x3b, 0x67e, 0x3b, 0x645, 0x3b, 0x628, +0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x6c1, 0x3b, 0x42f, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x416, 0x3b, 0x428, +0x3b, 0x42f, 0x43a, 0x448, 0x3b, 0x414, 0x443, 0x448, 0x3b, 0x421, 0x435, 0x448, 0x3b, 0x427, 0x43e, 0x440, 0x3b, 0x41f, 0x430, 0x439, +0x3b, 0x416, 0x443, 0x43c, 0x3b, 0x428, 0x430, 0x43d, 0x3b, 0x44f, 0x43a, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x434, 0x443, 0x448, +0x430, 0x43d, 0x431, 0x430, 0x3b, 0x441, 0x435, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x447, 0x43e, 0x440, 0x448, 0x430, 0x43d, 0x431, +0x430, 0x3b, 0x43f, 0x430, 0x439, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b, 0x448, 0x430, 0x43d, 0x431, +0x430, 0x3b, 0x43, 0x4e, 0x3b, 0x54, 0x68, 0x20, 0x32, 0x3b, 0x54, 0x68, 0x20, 0x33, 0x3b, 0x54, 0x68, 0x20, 0x34, 0x3b, +0x54, 0x68, 0x20, 0x35, 0x3b, 0x54, 0x68, 0x20, 0x36, 0x3b, 0x54, 0x68, 0x20, 0x37, 0x3b, 0x43, 0x68, 0x1ee7, 0x20, 0x6e, +0x68, 0x1ead, 0x74, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x68, 0x61, 0x69, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x62, 0x61, 0x3b, 0x54, +0x68, 0x1ee9, 0x20, 0x74, 0x1b0, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x6e, 0x103, 0x6d, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x73, 0xe1, +0x75, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x62, 0x1ea3, 0x79, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x77, 0x65, 0x3b, 0x3b, +0x53, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x6c, +0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x77, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x49, 0x61, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x3b, +0x53, 0x61, 0x64, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x53, 0x75, 0x6c, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x4c, 0x6c, +0x75, 0x6e, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x61, 0x77, 0x72, 0x74, 0x68, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, +0x4d, 0x65, 0x72, 0x63, 0x68, 0x65, 0x72, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x49, 0x61, 0x75, 0x3b, 0x44, 0x79, 0x64, +0x64, 0x20, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x53, 0x61, 0x64, 0x77, 0x72, 0x6e, +0x3b, 0x43, 0x61, 0x77, 0x3b, 0x4d, 0x76, 0x75, 0x3b, 0x42, 0x69, 0x6e, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x53, 0x69, 0x6e, +0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x4d, 0x67, 0x71, 0x3b, 0x43, 0x61, 0x77, 0x65, 0x3b, 0x4d, 0x76, 0x75, 0x6c, 0x6f, 0x3b, +0x4c, 0x77, 0x65, 0x73, 0x69, 0x62, 0x69, 0x6e, 0x69, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x74, 0x68, 0x61, 0x74, 0x68, +0x75, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x6e, 0x65, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x68, 0x6c, 0x61, 0x6e, 0x75, +0x3b, 0x4d, 0x67, 0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x3b, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x41, 0x6a, 0xe9, 0x3b, 0xcc, +0x73, 0x1eb9, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x72, 0xfa, 0x3b, 0xc0, 0x1e63, 0x1eb9, 0x300, 0x1e63, 0x1eb9, +0x300, 0x64, 0xe1, 0x69, 0x79, 0xe9, 0x3b, 0x1eb8, 0x74, 0xec, 0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0x1eb9, 0x301, 0x74, 0x61, 0x3b, +0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0x41, 0x6a, 0xe9, 0x3b, 0x1ecc, +0x6a, 0x1ecd, 0x301, 0x20, 0xcc, 0x73, 0x1eb9, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x72, 0xfa, 0x3b, 0x1ecc, +0x6a, 0x1ecd, 0x301, 0x20, 0xc0, 0x1e63, 0x1eb9, 0x300, 0x1e63, 0x1eb9, 0x300, 0x64, 0xe1, 0x69, 0x79, 0xe9, 0x3b, 0x1ecc, 0x6a, 0x1ecd, +0x301, 0x20, 0x1eb8, 0x74, 0xec, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0xc0, 0x62, 0xe1, 0x6d, 0x1eb9, 0x301, 0x74, 0x61, 0x3b, +0x53, 0x3b, 0x4d, 0x3b, 0x42, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x73, +0x6f, 0x3b, 0x42, 0x69, 0x6c, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x53, 0x69, 0x6e, 0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x4d, 0x67, +0x71, 0x3b, 0x53, 0x6f, 0x6e, 0x74, 0x6f, 0x3b, 0x4d, 0x73, 0x6f, 0x6d, 0x62, 0x75, 0x6c, 0x75, 0x6b, 0x6f, 0x3b, 0x4c, +0x77, 0x65, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x74, 0x68, 0x61, 0x74, 0x68, 0x75, +0x3b, 0x75, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x6e, 0x65, 0x3b, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x68, 0x6c, 0x61, 0x6e, 0x75, +0x3b, 0x4d, 0x67, 0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x3b, 0x3b, 0x6d, 0xe5, 0x2e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6c, +0x61, 0x2e, 0x3b, 0x73, 0xf8, 0x2e, 0x3b, 0x6d, 0xe5, 0x3b, 0x74, 0x79, 0x3b, 0x6f, 0x6e, 0x3b, 0x74, 0x6f, 0x3b, 0x66, +0x72, 0x3b, 0x6c, 0x61, 0x3b, 0x73, 0xf8, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x6d, 0xe5, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x74, +0x79, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x64, 0x61, 0x67, +0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0x61, 0x75, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x4e, 0x65, 0x64, 0x3b, +0x50, 0x6f, 0x6e, 0x3b, 0x55, 0x74, 0x6f, 0x3b, 0x53, 0x72, 0x69, 0x3b, 0x10c, 0x65, 0x74, 0x3b, 0x50, 0x65, 0x74, 0x3b, +0x53, 0x75, 0x62, 0x3b, 0x4e, 0x65, 0x64, 0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x50, 0x6f, 0x6e, 0x65, 0x64, 0x6a, 0x65, +0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x55, 0x74, 0x6f, 0x72, 0x61, 0x6b, 0x3b, 0x53, 0x72, 0x69, 0x6a, 0x65, 0x64, 0x61, 0x3b, +0x10c, 0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x50, 0x65, 0x74, 0x61, 0x6b, 0x3b, 0x53, 0x75, 0x62, 0x6f, 0x74, +0x61, 0x3b, 0x4a, 0x65, 0x64, 0x3b, 0x4a, 0x65, 0x6c, 0x3b, 0x4a, 0x65, 0x6d, 0x3b, 0x4a, 0x65, 0x72, 0x63, 0x3b, 0x4a, +0x65, 0x72, 0x64, 0x3b, 0x4a, 0x65, 0x68, 0x3b, 0x4a, 0x65, 0x73, 0x3b, 0x4a, 0x65, 0x64, 0x6f, 0x6f, 0x6e, 0x65, 0x65, +0x3b, 0x4a, 0x65, 0x6c, 0x68, 0x65, 0x69, 0x6e, 0x3b, 0x4a, 0x65, 0x6d, 0x61, 0x79, 0x72, 0x74, 0x3b, 0x4a, 0x65, 0x72, +0x63, 0x65, 0x61, 0x6e, 0x3b, 0x4a, 0x65, 0x72, 0x64, 0x65, 0x69, 0x6e, 0x3b, 0x4a, 0x65, 0x68, 0x65, 0x69, 0x6e, 0x65, +0x79, 0x3b, 0x4a, 0x65, 0x73, 0x61, 0x72, 0x6e, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x74, 0x68, +0x3b, 0x4d, 0x68, 0x72, 0x3b, 0x59, 0x6f, 0x77, 0x3b, 0x47, 0x77, 0x65, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x44, 0x65, 0x20, +0x53, 0x75, 0x6c, 0x3b, 0x44, 0x65, 0x20, 0x4c, 0x75, 0x6e, 0x3b, 0x44, 0x65, 0x20, 0x4d, 0x65, 0x72, 0x74, 0x68, 0x3b, +0x44, 0x65, 0x20, 0x4d, 0x65, 0x72, 0x68, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x20, 0x59, 0x6f, 0x77, 0x3b, 0x44, 0x65, 0x20, +0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x20, 0x53, 0x61, 0x64, 0x6f, 0x72, 0x6e, 0x3b, 0x4b, 0x3b, 0x44, +0x3b, 0x42, 0x3b, 0x57, 0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x4b, 0x77, 0x65, 0x3b, 0x44, 0x77, 0x6f, 0x3b, 0x42, +0x65, 0x6e, 0x3b, 0x57, 0x75, 0x6b, 0x3b, 0x59, 0x61, 0x77, 0x3b, 0x46, 0x69, 0x61, 0x3b, 0x4d, 0x65, 0x6d, 0x3b, 0x4b, +0x77, 0x65, 0x73, 0x69, 0x64, 0x61, 0x3b, 0x44, 0x77, 0x6f, 0x77, 0x64, 0x61, 0x3b, 0x42, 0x65, 0x6e, 0x61, 0x64, 0x61, +0x3b, 0x57, 0x75, 0x6b, 0x75, 0x64, 0x61, 0x3b, 0x59, 0x61, 0x77, 0x64, 0x61, 0x3b, 0x46, 0x69, 0x64, 0x61, 0x3b, 0x4d, +0x65, 0x6d, 0x65, 0x6e, 0x65, 0x64, 0x61, 0x3b, 0x906, 0x926, 0x93f, 0x924, 0x94d, 0x92f, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, +0x92e, 0x935, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, +0x941, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, +0x93e, 0x930, 0x3b, 0x48, 0x6f, 0x3b, 0x44, 0x7a, 0x75, 0x3b, 0x44, 0x7a, 0x66, 0x3b, 0x53, 0x68, 0x6f, 0x3b, 0x53, 0x6f, +0x6f, 0x3b, 0x53, 0x6f, 0x68, 0x3b, 0x48, 0x6f, 0x3b, 0x48, 0x6f, 0x67, 0x62, 0x61, 0x61, 0x3b, 0x44, 0x7a, 0x75, 0x3b, +0x44, 0x7a, 0x75, 0x66, 0x6f, 0x3b, 0x53, 0x68, 0x6f, 0x3b, 0x53, 0x6f, 0x6f, 0x3b, 0x53, 0x6f, 0x68, 0x61, 0x61, 0x3b, +0x48, 0x6f, 0x3b, 0x1ee4, 0x6b, 0x61, 0x3b, 0x4d, 0x1ecd, 0x6e, 0x3b, 0x54, 0x69, 0x75, 0x3b, 0x57, 0x65, 0x6e, 0x3b, 0x54, +0x1ecd, 0x1ecd, 0x3b, 0x46, 0x72, 0x61, 0x1ecb, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x4d, 0x62, 0x1ecd, 0x73, 0x1ecb, 0x20, 0x1ee4, 0x6b, +0x61, 0x3b, 0x4d, 0x1ecd, 0x6e, 0x64, 0x65, 0x3b, 0x54, 0x69, 0x75, 0x7a, 0x64, 0x65, 0x65, 0x3b, 0x57, 0x65, 0x6e, 0x65, +0x7a, 0x64, 0x65, 0x65, 0x3b, 0x54, 0x1ecd, 0x1ecd, 0x7a, 0x64, 0x65, 0x65, 0x3b, 0x46, 0x72, 0x61, 0x1ecb, 0x64, 0x65, 0x65, +0x3b, 0x53, 0x61, 0x74, 0x1ecd, 0x64, 0x65, 0x65, 0x3b, 0x4a, 0x70, 0x6c, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, +0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x6d, 0x3b, 0x4a, 0x6d, 0x73, 0x3b, 0x4a, 0x75, 0x6d, +0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, +0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, +0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x1230, 0x3b, 0x1230, 0x3b, +0x1230, 0x3b, 0x1208, 0x3b, 0x12a3, 0x3b, 0x12a3, 0x3b, 0x1230, 0x3b, 0x1230, 0x2f, 0x1245, 0x3b, 0x1230, 0x1291, 0x3b, 0x1230, 0x120a, 0x131d, +0x3b, 0x1208, 0x1313, 0x3b, 0x12a3, 0x121d, 0x12f5, 0x3b, 0x12a3, 0x122d, 0x1265, 0x3b, 0x1230, 0x2f, 0x123d, 0x3b, 0x1230, 0x1295, 0x1260, 0x122d, +0x20, 0x1245, 0x12f3, 0x12c5, 0x3b, 0x1230, 0x1291, 0x3b, 0x1230, 0x120a, 0x131d, 0x3b, 0x1208, 0x1313, 0x20, 0x12c8, 0x122a, 0x20, 0x1208, 0x1265, +0x12cb, 0x3b, 0x12a3, 0x121d, 0x12f5, 0x3b, 0x12a3, 0x122d, 0x1265, 0x3b, 0x1230, 0x1295, 0x1260, 0x122d, 0x20, 0x123d, 0x1313, 0x12c5, 0x3b, 0x12a5, +0x3b, 0x1230, 0x3b, 0x1220, 0x3b, 0x122b, 0x3b, 0x1210, 0x3b, 0x12d3, 0x3b, 0x1240, 0x3b, 0x12a5, 0x1281, 0x12f5, 0x3b, 0x1230, 0x1291, 0x12ed, +0x3b, 0x1220, 0x1209, 0x1235, 0x3b, 0x122b, 0x1265, 0x12d5, 0x3b, 0x1210, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1260, 0x3b, 0x1240, 0x12f3, 0x121a, +0x3b, 0x12a5, 0x1281, 0x12f5, 0x3b, 0x1230, 0x1291, 0x12ed, 0x3b, 0x1220, 0x1209, 0x1235, 0x3b, 0x122b, 0x1265, 0x12d5, 0x3b, 0x1210, 0x1219, 0x1235, +0x3b, 0x12d3, 0x122d, 0x1260, 0x3b, 0x1240, 0x12f3, 0x121a, 0x1275, 0x3b, 0x4c, 0x61, 0x68, 0x3b, 0x4b, 0x75, 0x62, 0x3b, 0x47, 0x62, +0x61, 0x3b, 0x54, 0x61, 0x6e, 0x3b, 0x59, 0x65, 0x69, 0x3b, 0x4b, 0x6f, 0x79, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x4c, 0x61, +0x68, 0x61, 0x64, 0x69, 0x3b, 0x4a, 0x65, 0x2d, 0x4b, 0x75, 0x62, 0x61, 0x63, 0x68, 0x61, 0x3b, 0x4a, 0x65, 0x2d, 0x47, +0x62, 0x61, 0x69, 0x3b, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x74, 0x69, 0x3b, 0x4a, 0x65, 0x2d, 0x59, 0x65, 0x69, 0x3b, 0x4a, +0x65, 0x2d, 0x4b, 0x6f, 0x79, 0x65, 0x3b, 0x53, 0x61, 0x74, 0x69, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x52, 0x3b, +0x48, 0x3b, 0x41, 0x3b, 0x51, 0x3b, 0x53, 0x61, 0x6d, 0x3b, 0x53, 0x61, 0x6e, 0x3b, 0x4d, 0x61, 0x6b, 0x3b, 0x52, 0x6f, +0x77, 0x3b, 0x48, 0x61, 0x6d, 0x3b, 0x41, 0x72, 0x62, 0x3b, 0x51, 0x69, 0x64, 0x3b, 0x53, 0x61, 0x6d, 0x62, 0x61, 0x74, +0x61, 0x3b, 0x53, 0x61, 0x6e, 0x79, 0x6f, 0x3b, 0x4d, 0x61, 0x61, 0x6b, 0x69, 0x73, 0x61, 0x6e, 0x79, 0x6f, 0x3b, 0x52, +0x6f, 0x6f, 0x77, 0x65, 0x3b, 0x48, 0x61, 0x6d, 0x75, 0x73, 0x65, 0x3b, 0x41, 0x72, 0x62, 0x65, 0x3b, 0x51, 0x69, 0x64, +0x61, 0x61, 0x6d, 0x65, 0x3b, 0x59, 0x6f, 0x6b, 0x3b, 0x54, 0x75, 0x6e, 0x67, 0x3b, 0x54, 0x2e, 0x20, 0x54, 0x75, 0x6e, +0x67, 0x3b, 0x54, 0x73, 0x61, 0x6e, 0x3b, 0x4e, 0x61, 0x73, 0x3b, 0x4e, 0x61, 0x74, 0x3b, 0x43, 0x68, 0x69, 0x72, 0x3b, +0x57, 0x61, 0x69, 0x20, 0x59, 0x6f, 0x6b, 0x61, 0x20, 0x42, 0x61, 0x77, 0x61, 0x69, 0x3b, 0x57, 0x61, 0x69, 0x20, 0x54, +0x75, 0x6e, 0x67, 0x61, 0x3b, 0x54, 0x6f, 0x6b, 0x69, 0x20, 0x47, 0x69, 0x74, 0x75, 0x6e, 0x67, 0x3b, 0x54, 0x73, 0x61, +0x6d, 0x20, 0x4b, 0x61, 0x73, 0x75, 0x77, 0x61, 0x3b, 0x57, 0x61, 0x69, 0x20, 0x4e, 0x61, 0x20, 0x4e, 0x61, 0x73, 0x3b, +0x57, 0x61, 0x69, 0x20, 0x4e, 0x61, 0x20, 0x54, 0x69, 0x79, 0x6f, 0x6e, 0x3b, 0x57, 0x61, 0x69, 0x20, 0x4e, 0x61, 0x20, +0x43, 0x68, 0x69, 0x72, 0x69, 0x6d, 0x3b, 0x1230, 0x3b, 0x1230, 0x3b, 0x1273, 0x3b, 0x12a3, 0x3b, 0x12a8, 0x3b, 0x1305, 0x3b, 0x1230, +0x3b, 0x1230, 0x2f, 0x12d3, 0x3b, 0x1230, 0x1296, 0x3b, 0x1273, 0x120b, 0x1238, 0x3b, 0x12a3, 0x1228, 0x122d, 0x3b, 0x12a8, 0x121a, 0x123d, 0x3b, +0x1305, 0x121d, 0x12d3, 0x3b, 0x1230, 0x2f, 0x1295, 0x3b, 0x1230, 0x1295, 0x1260, 0x1275, 0x20, 0x12d3, 0x1263, 0x12ed, 0x3b, 0x1230, 0x1296, 0x3b, +0x1273, 0x120b, 0x1238, 0x1296, 0x3b, 0x12a3, 0x1228, 0x122d, 0x1263, 0x12d3, 0x3b, 0x12a8, 0x121a, 0x123d, 0x3b, 0x1305, 0x121d, 0x12d3, 0x1275, 0x3b, +0x1230, 0x1295, 0x1260, 0x1275, 0x20, 0x1295, 0x12a2, 0x123d, 0x3b, 0x4c, 0x61, 0x64, 0x3b, 0x4c, 0x69, 0x6e, 0x3b, 0x54, 0x61, 0x6c, +0x3b, 0x4c, 0x61, 0x72, 0x3b, 0x4c, 0x61, 0x6d, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x41, 0x73, 0x61, 0x3b, 0x4c, 0x61, 0x64, +0x69, 0x3b, 0x4c, 0x69, 0x6e, 0x74, 0x61, 0x6e, 0x69, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x4c, 0x61, 0x72, +0x62, 0x61, 0x3b, 0x4c, 0x61, 0x6d, 0x69, 0x74, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x61, 0x72, +0x3b, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x69, 0x65, 0x3b, 0x6a, 0x6f, 0x69, +0x3b, 0x76, 0x69, 0x6e, 0x3b, 0x73, 0x61, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x65, 0x6e, 0x69, 0x65, 0x3b, 0x6c, 0x75, 0x6e, +0x69, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x61, 0x72, 0x73, 0x3b, 0x6d, 0x69, 0x65, 0x72, 0x63, 0x75, 0x73, 0x3b, 0x6a, +0x6f, 0x69, 0x62, 0x65, 0x3b, 0x76, 0x69, 0x6e, 0x61, 0x72, 0x73, 0x3b, 0x73, 0x61, 0x62, 0x69, 0x64, 0x65, 0x3b, 0x53, +0x77, 0x6f, 0x3b, 0x4d, 0x75, 0x73, 0x3b, 0x56, 0x68, 0x69, 0x3b, 0x52, 0x61, 0x72, 0x3b, 0x1e4a, 0x61, 0x3b, 0x1e70, 0x61, +0x6e, 0x3b, 0x4d, 0x75, 0x67, 0x3b, 0x53, 0x77, 0x6f, 0x6e, 0x64, 0x61, 0x68, 0x61, 0x3b, 0x4d, 0x75, 0x73, 0x75, 0x6d, +0x62, 0x75, 0x6c, 0x75, 0x77, 0x6f, 0x3b, 0x1e3c, 0x61, 0x76, 0x68, 0x75, 0x76, 0x68, 0x69, 0x6c, 0x69, 0x3b, 0x1e3c, 0x61, +0x76, 0x68, 0x75, 0x72, 0x61, 0x72, 0x75, 0x3b, 0x1e3c, 0x61, 0x76, 0x68, 0x75, 0x1e4b, 0x61, 0x3b, 0x1e3c, 0x61, 0x76, 0x68, +0x75, 0x1e71, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x75, 0x67, 0x69, 0x76, 0x68, 0x65, 0x6c, 0x61, 0x3b, 0x4b, 0x3b, 0x44, 0x3b, +0x42, 0x3b, 0x4b, 0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x4b, 0x254, 0x73, 0x20, 0x4b, 0x77, 0x65, 0x3b, 0x44, 0x7a, +0x6f, 0x3b, 0x42, 0x72, 0x61, 0x3b, 0x4b, 0x75, 0x256, 0x3b, 0x59, 0x61, 0x77, 0x3b, 0x46, 0x69, 0x256, 0x3b, 0x4d, 0x65, +0x6d, 0x3b, 0x4b, 0x254, 0x73, 0x69, 0x256, 0x61, 0x3b, 0x44, 0x7a, 0x6f, 0x256, 0x61, 0x3b, 0x42, 0x72, 0x61, 0x256, 0x61, +0x3b, 0x4b, 0x75, 0x256, 0x61, 0x3b, 0x59, 0x61, 0x77, 0x6f, 0x256, 0x61, 0x3b, 0x46, 0x69, 0x256, 0x61, 0x3b, 0x4d, 0x65, +0x6d, 0x6c, 0x65, 0x256, 0x61, 0x3b, 0x4c, 0x50, 0x3b, 0x50, 0x31, 0x3b, 0x50, 0x32, 0x3b, 0x50, 0x33, 0x3b, 0x50, 0x34, +0x3b, 0x50, 0x35, 0x3b, 0x50, 0x36, 0x3b, 0x4c, 0x101, 0x70, 0x75, 0x6c, 0x65, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6b, 0x61, +0x68, 0x69, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6c, 0x75, 0x61, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6b, 0x6f, 0x6c, 0x75, 0x3b, +0x50, 0x6f, 0x2bb, 0x61, 0x68, 0x101, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6c, 0x69, 0x6d, 0x61, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, +0x6f, 0x6e, 0x6f, 0x3b, 0x4c, 0x61, 0x64, 0x3b, 0x54, 0x61, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x4c, 0x61, 0x72, 0x3b, +0x4c, 0x61, 0x6d, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x41, 0x73, 0x61, 0x3b, 0x4c, 0x61, 0x64, 0x69, 0x3b, 0x54, 0x61, 0x6e, +0x69, 0x69, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x4c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x4c, 0x61, 0x6d, 0x69, +0x74, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x61, 0x74, 0x3b, 0x4d, 0x75, 0x6c, 0x3b, 0x4c, 0x65, +0x6d, 0x3b, 0x57, 0x69, 0x72, 0x3b, 0x54, 0x61, 0x74, 0x3b, 0x4e, 0x61, 0x69, 0x3b, 0x53, 0x61, 0x6e, 0x3b, 0x57, 0x65, +0x72, 0x3b, 0x4c, 0x61, 0x6d, 0x75, 0x6c, 0x75, 0x6e, 0x67, 0x75, 0x3b, 0x4c, 0x6f, 0x6c, 0x65, 0x6d, 0x62, 0x61, 0x3b, +0x4c, 0x61, 0x63, 0x68, 0x69, 0x77, 0x69, 0x72, 0x69, 0x3b, 0x4c, 0x61, 0x63, 0x68, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, +0x4c, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x61, 0x79, 0x69, 0x3b, 0x4c, 0x61, 0x63, 0x68, 0x69, 0x73, 0x61, 0x6e, 0x75, 0x3b, +0x4c, 0x6f, 0x77, 0x65, 0x72, 0x75, 0x6b, 0x61, 0x3b +}; + +static const ushort am_data[] = { +0x41, 0x4d, 0x76, 0x6d, 0x2e, 0x50, 0x44, 0x635, 0x531, 0x57c, 0x2024, 0x9aa, 0x9c2, 0x9f0, 0x9cd, 0x9ac, 0x9be, 0x9aa, 0x9c2, 0x9b0, +0x9cd, 0x9ac, 0x9be, 0x9b9, 0x9cd, 0x9a3, 0x43f, 0x440, 0x2e, 0x20, 0x43e, 0x431, 0x2e, 0x434, 0x430, 0x20, 0x43f, 0x430, 0x43b, 0x443, +0x434, 0x43d, 0x44f, 0x1796, 0x17d2, 0x179a, 0x17b9, 0x1780, 0x4e0a, 0x5348, 0x64, 0x6f, 0x70, 0x2e, 0x66, 0x2e, 0x6d, 0x2e, 0x61, 0x2e, +0x6d, 0x2e, 0x61, 0x70, 0x2e, 0x76, 0x6f, 0x72, 0x6d, 0x2e, 0x3c0, 0x2e, 0x3bc, 0x2e, 0xaaa, 0xac2, 0xab0, 0xacd, 0xab5, 0xa0, +0xaae, 0xaa7, 0xacd, 0xaaf, 0xabe, 0xab9, 0xacd, 0xaa8, 0x5dc, 0x5e4, 0x5e0, 0x5d4, 0x22, 0x5e6, 0x92a, 0x942, 0x930, 0x94d, 0x935, 0x93e, +0x939, 0x94d, 0x928, 0x64, 0x65, 0x2e, 0x6d, 0x2e, 0x5348, 0x524d, 0xcaa, 0xcc2, 0xcb0, 0xccd, 0xcb5, 0xcbe, 0xcb9, 0xccd, 0xca8, 0xc624, +0xc804, 0x70, 0x72, 0x69, 0x65, 0x161, 0x70, 0x69, 0x65, 0x74, 0x51, 0x4e, 0x92e, 0x2e, 0x92a, 0x942, 0x2e, 0x66, 0x6f, 0x72, +0x6d, 0x69, 0x64, 0x64, 0x61, 0x67, 0x63a, 0x2e, 0x645, 0x2e, 0x642, 0x628, 0x644, 0x20, 0x627, 0x632, 0x20, 0x638, 0x647, 0x631, +0x41, 0x6e, 0x74, 0x65, 0x73, 0x20, 0x64, 0x6f, 0x20, 0x6d, 0x65, 0x69, 0x6f, 0x2d, 0x64, 0x69, 0x61, 0xa38, 0xa35, 0xa47, +0xa30, 0xa47, 0x43f, 0x440, 0x435, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0xdb4, 0xdd9, 0x2e, 0xdc0, 0x2e, 0x73, 0x6e, 0x66, 0x6d, 0xb95, +0xbbe, 0xbb2, 0xbc8, 0xc2a, 0xc42, 0xc30, 0xc4d, 0xc35, 0xc3e, 0xc39, 0xc4d, 0xc28, 0xc02, 0xe01, 0xe48, 0xe2d, 0xe19, 0xe40, 0xe17, 0xe35, +0xe48, 0xe22, 0xe07, 0x1295, 0x1309, 0x1206, 0x20, 0x1230, 0x12d3, 0x1270, 0x434, 0x43f, 0x53, 0x41, 0xe0, 0xe1, 0x72, 0x1ecd, 0x300 +}; + +static const ushort pm_data[] = { +0x50, 0x4d, 0x6e, 0x6d, 0x2e, 0x4d, 0x44, 0x645, 0x535, 0x580, 0x2024, 0x985, 0x9aa, 0x985, 0x9aa, 0x9b0, 0x9be, 0x9b9, 0x9cd, 0x9a3, +0x441, 0x43b, 0x2e, 0x20, 0x43e, 0x431, 0x2e, 0x43f, 0x430, 0x441, 0x43b, 0x44f, 0x20, 0x43f, 0x430, 0x43b, 0x443, 0x434, 0x43d, 0x44f, +0x179b, 0x17d2, 0x1784, 0x17b6, 0x1785, 0x4e0b, 0x5348, 0x6f, 0x64, 0x70, 0x2e, 0x65, 0x2e, 0x6d, 0x2e, 0x70, 0x2e, 0x6d, 0x2e, 0x69, +0x70, 0x2e, 0x6e, 0x61, 0x63, 0x68, 0x6d, 0x2e, 0x3bc, 0x2e, 0x3bc, 0x2e, 0xa89, 0xaa4, 0xacd, 0xaa4, 0xab0, 0xa0, 0xaae, 0xaa7, +0xacd, 0xaaf, 0xabe, 0xab9, 0xacd, 0xaa8, 0x5d0, 0x5d7, 0x5d4, 0x22, 0x5e6, 0x905, 0x92a, 0x930, 0x93e, 0x939, 0x94d, 0x928, 0x64, 0x75, +0x2e, 0x70, 0x2e, 0x5348, 0x5f8c, 0xc85, 0xcaa, 0xcb0, 0xcbe, 0xcb9, 0xccd, 0xca8, 0xc624, 0xd6c4, 0x70, 0x6f, 0x70, 0x69, 0x65, 0x74, +0x57, 0x4e, 0x92e, 0x2e, 0x928, 0x902, 0x2e, 0x65, 0x74, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x64, 0x64, 0x61, 0x67, 0x63a, 0x2e, +0x648, 0x2e, 0x628, 0x639, 0x62f, 0x20, 0x627, 0x632, 0x20, 0x638, 0x647, 0x631, 0x44, 0x65, 0x70, 0x6f, 0x69, 0x73, 0x20, 0x64, +0x6f, 0x20, 0x6d, 0x65, 0x69, 0x6f, 0x2d, 0x64, 0x69, 0x61, 0xa38, 0xa3c, 0xa3e, 0xa2e, 0x43f, 0x43e, 0x43f, 0x43e, 0x434, 0x43d, +0x435, 0xdb4, 0x2e, 0xdc0, 0x2e, 0x67, 0x6e, 0x65, 0x6d, 0xbae, 0xbbe, 0xbb2, 0xbc8, 0xc05, 0xc2a, 0xc30, 0xc3e, 0xc39, 0xc4d, 0xc28, +0xc02, 0xe2b, 0xe25, 0xe31, 0xe07, 0xe40, 0xe17, 0xe35, 0xe48, 0xe22, 0xe07, 0x12f5, 0x1215, 0x122d, 0x20, 0x1230, 0x12d3, 0x1275, 0x43f, 0x43f, +0x43, 0x48, 0x1ecd, 0x300, 0x73, 0xe1, 0x6e +}; + +static const char language_name_list[] = +"Default\0" +"C\0" +"Abkhazian\0" +"Afan\0" +"Afar\0" +"Afrikaans\0" +"Albanian\0" +"Amharic\0" +"Arabic\0" +"Armenian\0" +"Assamese\0" +"Aymara\0" +"Azerbaijani\0" +"Bashkir\0" +"Basque\0" +"Bengali\0" +"Bhutani\0" +"Bihari\0" +"Bislama\0" +"Breton\0" +"Bulgarian\0" +"Burmese\0" +"Byelorussian\0" +"Cambodian\0" +"Catalan\0" +"Chinese\0" +"Corsican\0" +"Croatian\0" +"Czech\0" +"Danish\0" +"Dutch\0" +"English\0" +"Esperanto\0" +"Estonian\0" +"Faroese\0" +"Fiji\0" +"Finnish\0" +"French\0" +"Frisian\0" +"Gaelic\0" +"Galician\0" +"Georgian\0" +"German\0" +"Greek\0" +"Greenlandic\0" +"Guarani\0" +"Gujarati\0" +"Hausa\0" +"Hebrew\0" +"Hindi\0" +"Hungarian\0" +"Icelandic\0" +"Indonesian\0" +"Interlingua\0" +"Interlingue\0" +"Inuktitut\0" +"Inupiak\0" +"Irish\0" +"Italian\0" +"Japanese\0" +"Javanese\0" +"Kannada\0" +"Kashmiri\0" +"Kazakh\0" +"Kinyarwanda\0" +"Kirghiz\0" +"Korean\0" +"Kurdish\0" +"Kurundi\0" +"Laothian\0" +"Latin\0" +"Latvian\0" +"Lingala\0" +"Lithuanian\0" +"Macedonian\0" +"Malagasy\0" +"Malay\0" +"Malayalam\0" +"Maltese\0" +"Maori\0" +"Marathi\0" +"Moldavian\0" +"Mongolian\0" +"Nauru\0" +"Nepali\0" +"Norwegian\0" +"Occitan\0" +"Oriya\0" +"Pashto\0" +"Persian\0" +"Polish\0" +"Portuguese\0" +"Punjabi\0" +"Quechua\0" +"RhaetoRomance\0" +"Romanian\0" +"Russian\0" +"Samoan\0" +"Sangho\0" +"Sanskrit\0" +"Serbian\0" +"SerboCroatian\0" +"Sesotho\0" +"Setswana\0" +"Shona\0" +"Sindhi\0" +"Singhalese\0" +"Siswati\0" +"Slovak\0" +"Slovenian\0" +"Somali\0" +"Spanish\0" +"Sundanese\0" +"Swahili\0" +"Swedish\0" +"Tagalog\0" +"Tajik\0" +"Tamil\0" +"Tatar\0" +"Telugu\0" +"Thai\0" +"Tibetan\0" +"Tigrinya\0" +"Tonga\0" +"Tsonga\0" +"Turkish\0" +"Turkmen\0" +"Twi\0" +"Uigur\0" +"Ukrainian\0" +"Urdu\0" +"Uzbek\0" +"Vietnamese\0" +"Volapuk\0" +"Welsh\0" +"Wolof\0" +"Xhosa\0" +"Yiddish\0" +"Yoruba\0" +"Zhuang\0" +"Zulu\0" +"Nynorsk\0" +"Bosnian\0" +"Divehi\0" +"Manx\0" +"Cornish\0" +"Akan\0" +"Konkani\0" +"Ga\0" +"Igbo\0" +"Kamba\0" +"Syriac\0" +"Blin\0" +"Geez\0" +"Koro\0" +"Sidamo\0" +"Atsam\0" +"Tigre\0" +"Jju\0" +"Friulian\0" +"Venda\0" +"Ewe\0" +"Walamo\0" +"Hawaiian\0" +"Tyap\0" +"Chewa\0" +; + +static const uint language_name_index[] = { + 0, // Unused + 8, // C + 10, // Abkhazian + 20, // Afan + 25, // Afar + 30, // Afrikaans + 40, // Albanian + 49, // Amharic + 57, // Arabic + 64, // Armenian + 73, // Assamese + 82, // Aymara + 89, // Azerbaijani + 101, // Bashkir + 109, // Basque + 116, // Bengali + 124, // Bhutani + 132, // Bihari + 139, // Bislama + 147, // Breton + 154, // Bulgarian + 164, // Burmese + 172, // Byelorussian + 185, // Cambodian + 195, // Catalan + 203, // Chinese + 211, // Corsican + 220, // Croatian + 229, // Czech + 235, // Danish + 242, // Dutch + 248, // English + 256, // Esperanto + 266, // Estonian + 275, // Faroese + 283, // Fiji + 288, // Finnish + 296, // French + 303, // Frisian + 311, // Gaelic + 318, // Galician + 327, // Georgian + 336, // German + 343, // Greek + 349, // Greenlandic + 361, // Guarani + 369, // Gujarati + 378, // Hausa + 384, // Hebrew + 391, // Hindi + 397, // Hungarian + 407, // Icelandic + 417, // Indonesian + 428, // Interlingua + 440, // Interlingue + 452, // Inuktitut + 462, // Inupiak + 470, // Irish + 476, // Italian + 484, // Japanese + 493, // Javanese + 502, // Kannada + 510, // Kashmiri + 519, // Kazakh + 526, // Kinyarwanda + 538, // Kirghiz + 546, // Korean + 553, // Kurdish + 561, // Kurundi + 569, // Laothian + 578, // Latin + 584, // Latvian + 592, // Lingala + 600, // Lithuanian + 611, // Macedonian + 622, // Malagasy + 631, // Malay + 637, // Malayalam + 647, // Maltese + 655, // Maori + 661, // Marathi + 669, // Moldavian + 679, // Mongolian + 689, // Nauru + 695, // Nepali + 702, // Norwegian + 712, // Occitan + 720, // Oriya + 726, // Pashto + 733, // Persian + 741, // Polish + 748, // Portuguese + 759, // Punjabi + 767, // Quechua + 775, // RhaetoRomance + 789, // Romanian + 798, // Russian + 806, // Samoan + 813, // Sangho + 820, // Sanskrit + 829, // Serbian + 837, // SerboCroatian + 851, // Sesotho + 859, // Setswana + 868, // Shona + 874, // Sindhi + 881, // Singhalese + 892, // Siswati + 900, // Slovak + 907, // Slovenian + 917, // Somali + 924, // Spanish + 932, // Sundanese + 942, // Swahili + 950, // Swedish + 958, // Tagalog + 966, // Tajik + 972, // Tamil + 978, // Tatar + 984, // Telugu + 991, // Thai + 996, // Tibetan + 1004, // Tigrinya + 1013, // Tonga + 1019, // Tsonga + 1026, // Turkish + 1034, // Turkmen + 1042, // Twi + 1046, // Uigur + 1052, // Ukrainian + 1062, // Urdu + 1067, // Uzbek + 1073, // Vietnamese + 1084, // Volapuk + 1092, // Welsh + 1098, // Wolof + 1104, // Xhosa + 1110, // Yiddish + 1118, // Yoruba + 1125, // Zhuang + 1132, // Zulu + 1137, // Nynorsk + 1145, // Bosnian + 1153, // Divehi + 1160, // Manx + 1165, // Cornish + 1173, // Akan + 1178, // Konkani + 1186, // Ga + 1189, // Igbo + 1194, // Kamba + 1200, // Syriac + 1207, // Blin + 1212, // Geez + 1217, // Koro + 1222, // Sidamo + 1229, // Atsam + 1235, // Tigre + 1241, // Jju + 1245, // Friulian + 1254, // Venda + 1260, // Ewe + 1264, // Walamo + 1271, // Hawaiian + 1280, // Tyap + 1285, // Chewa +}; + +static const char country_name_list[] = +"Default\0" +"Afghanistan\0" +"Albania\0" +"Algeria\0" +"AmericanSamoa\0" +"Andorra\0" +"Angola\0" +"Anguilla\0" +"Antarctica\0" +"AntiguaAndBarbuda\0" +"Argentina\0" +"Armenia\0" +"Aruba\0" +"Australia\0" +"Austria\0" +"Azerbaijan\0" +"Bahamas\0" +"Bahrain\0" +"Bangladesh\0" +"Barbados\0" +"Belarus\0" +"Belgium\0" +"Belize\0" +"Benin\0" +"Bermuda\0" +"Bhutan\0" +"Bolivia\0" +"BosniaAndHerzegowina\0" +"Botswana\0" +"BouvetIsland\0" +"Brazil\0" +"BritishIndianOceanTerritory\0" +"BruneiDarussalam\0" +"Bulgaria\0" +"BurkinaFaso\0" +"Burundi\0" +"Cambodia\0" +"Cameroon\0" +"Canada\0" +"CapeVerde\0" +"CaymanIslands\0" +"CentralAfricanRepublic\0" +"Chad\0" +"Chile\0" +"China\0" +"ChristmasIsland\0" +"CocosIslands\0" +"Colombia\0" +"Comoros\0" +"DemocraticRepublicOfCongo\0" +"PeoplesRepublicOfCongo\0" +"CookIslands\0" +"CostaRica\0" +"IvoryCoast\0" +"Croatia\0" +"Cuba\0" +"Cyprus\0" +"CzechRepublic\0" +"Denmark\0" +"Djibouti\0" +"Dominica\0" +"DominicanRepublic\0" +"EastTimor\0" +"Ecuador\0" +"Egypt\0" +"ElSalvador\0" +"EquatorialGuinea\0" +"Eritrea\0" +"Estonia\0" +"Ethiopia\0" +"FalklandIslands\0" +"FaroeIslands\0" +"Fiji\0" +"Finland\0" +"France\0" +"MetropolitanFrance\0" +"FrenchGuiana\0" +"FrenchPolynesia\0" +"FrenchSouthernTerritories\0" +"Gabon\0" +"Gambia\0" +"Georgia\0" +"Germany\0" +"Ghana\0" +"Gibraltar\0" +"Greece\0" +"Greenland\0" +"Grenada\0" +"Guadeloupe\0" +"Guam\0" +"Guatemala\0" +"Guinea\0" +"GuineaBissau\0" +"Guyana\0" +"Haiti\0" +"HeardAndMcDonaldIslands\0" +"Honduras\0" +"HongKong\0" +"Hungary\0" +"Iceland\0" +"India\0" +"Indonesia\0" +"Iran\0" +"Iraq\0" +"Ireland\0" +"Israel\0" +"Italy\0" +"Jamaica\0" +"Japan\0" +"Jordan\0" +"Kazakhstan\0" +"Kenya\0" +"Kiribati\0" +"DemocraticRepublicOfKorea\0" +"RepublicOfKorea\0" +"Kuwait\0" +"Kyrgyzstan\0" +"Lao\0" +"Latvia\0" +"Lebanon\0" +"Lesotho\0" +"Liberia\0" +"LibyanArabJamahiriya\0" +"Liechtenstein\0" +"Lithuania\0" +"Luxembourg\0" +"Macau\0" +"Macedonia\0" +"Madagascar\0" +"Malawi\0" +"Malaysia\0" +"Maldives\0" +"Mali\0" +"Malta\0" +"MarshallIslands\0" +"Martinique\0" +"Mauritania\0" +"Mauritius\0" +"Mayotte\0" +"Mexico\0" +"Micronesia\0" +"Moldova\0" +"Monaco\0" +"Mongolia\0" +"Montserrat\0" +"Morocco\0" +"Mozambique\0" +"Myanmar\0" +"Namibia\0" +"Nauru\0" +"Nepal\0" +"Netherlands\0" +"NetherlandsAntilles\0" +"NewCaledonia\0" +"NewZealand\0" +"Nicaragua\0" +"Niger\0" +"Nigeria\0" +"Niue\0" +"NorfolkIsland\0" +"NorthernMarianaIslands\0" +"Norway\0" +"Oman\0" +"Pakistan\0" +"Palau\0" +"PalestinianTerritory\0" +"Panama\0" +"PapuaNewGuinea\0" +"Paraguay\0" +"Peru\0" +"Philippines\0" +"Pitcairn\0" +"Poland\0" +"Portugal\0" +"PuertoRico\0" +"Qatar\0" +"Reunion\0" +"Romania\0" +"RussianFederation\0" +"Rwanda\0" +"SaintKittsAndNevis\0" +"StLucia\0" +"StVincentAndTheGrenadines\0" +"Samoa\0" +"SanMarino\0" +"SaoTomeAndPrincipe\0" +"SaudiArabia\0" +"Senegal\0" +"Seychelles\0" +"SierraLeone\0" +"Singapore\0" +"Slovakia\0" +"Slovenia\0" +"SolomonIslands\0" +"Somalia\0" +"SouthAfrica\0" +"SouthGeorgiaAndTheSouthSandwichIslands\0" +"Spain\0" +"SriLanka\0" +"StHelena\0" +"StPierreAndMiquelon\0" +"Sudan\0" +"Suriname\0" +"SvalbardAndJanMayenIslands\0" +"Swaziland\0" +"Sweden\0" +"Switzerland\0" +"SyrianArabRepublic\0" +"Taiwan\0" +"Tajikistan\0" +"Tanzania\0" +"Thailand\0" +"Togo\0" +"Tokelau\0" +"Tonga\0" +"TrinidadAndTobago\0" +"Tunisia\0" +"Turkey\0" +"Turkmenistan\0" +"TurksAndCaicosIslands\0" +"Tuvalu\0" +"Uganda\0" +"Ukraine\0" +"UnitedArabEmirates\0" +"UnitedKingdom\0" +"UnitedStates\0" +"UnitedStatesMinorOutlyingIslands\0" +"Uruguay\0" +"Uzbekistan\0" +"Vanuatu\0" +"VaticanCityState\0" +"Venezuela\0" +"VietNam\0" +"BritishVirginIslands\0" +"USVirginIslands\0" +"WallisAndFutunaIslands\0" +"WesternSahara\0" +"Yemen\0" +"Yugoslavia\0" +"Zambia\0" +"Zimbabwe\0" +"SerbiaAndMontenegro\0" +; + +static const uint country_name_index[] = { + 0, // AnyCountry + 8, // Afghanistan + 20, // Albania + 28, // Algeria + 36, // AmericanSamoa + 50, // Andorra + 58, // Angola + 65, // Anguilla + 74, // Antarctica + 85, // AntiguaAndBarbuda + 103, // Argentina + 113, // Armenia + 121, // Aruba + 127, // Australia + 137, // Austria + 145, // Azerbaijan + 156, // Bahamas + 164, // Bahrain + 172, // Bangladesh + 183, // Barbados + 192, // Belarus + 200, // Belgium + 208, // Belize + 215, // Benin + 221, // Bermuda + 229, // Bhutan + 236, // Bolivia + 244, // BosniaAndHerzegowina + 265, // Botswana + 274, // BouvetIsland + 287, // Brazil + 294, // BritishIndianOceanTerritory + 322, // BruneiDarussalam + 339, // Bulgaria + 348, // BurkinaFaso + 360, // Burundi + 368, // Cambodia + 377, // Cameroon + 386, // Canada + 393, // CapeVerde + 403, // CaymanIslands + 417, // CentralAfricanRepublic + 440, // Chad + 445, // Chile + 451, // China + 457, // ChristmasIsland + 473, // CocosIslands + 486, // Colombia + 495, // Comoros + 503, // DemocraticRepublicOfCongo + 529, // PeoplesRepublicOfCongo + 552, // CookIslands + 564, // CostaRica + 574, // IvoryCoast + 585, // Croatia + 593, // Cuba + 598, // Cyprus + 605, // CzechRepublic + 619, // Denmark + 627, // Djibouti + 636, // Dominica + 645, // DominicanRepublic + 663, // EastTimor + 673, // Ecuador + 681, // Egypt + 687, // ElSalvador + 698, // EquatorialGuinea + 715, // Eritrea + 723, // Estonia + 731, // Ethiopia + 740, // FalklandIslands + 756, // FaroeIslands + 769, // Fiji + 774, // Finland + 782, // France + 789, // MetropolitanFrance + 808, // FrenchGuiana + 821, // FrenchPolynesia + 837, // FrenchSouthernTerritories + 863, // Gabon + 869, // Gambia + 876, // Georgia + 884, // Germany + 892, // Ghana + 898, // Gibraltar + 908, // Greece + 915, // Greenland + 925, // Grenada + 933, // Guadeloupe + 944, // Guam + 949, // Guatemala + 959, // Guinea + 966, // GuineaBissau + 979, // Guyana + 986, // Haiti + 992, // HeardAndMcDonaldIslands + 1016, // Honduras + 1025, // HongKong + 1034, // Hungary + 1042, // Iceland + 1050, // India + 1056, // Indonesia + 1066, // Iran + 1071, // Iraq + 1076, // Ireland + 1084, // Israel + 1091, // Italy + 1097, // Jamaica + 1105, // Japan + 1111, // Jordan + 1118, // Kazakhstan + 1129, // Kenya + 1135, // Kiribati + 1144, // DemocraticRepublicOfKorea + 1170, // RepublicOfKorea + 1186, // Kuwait + 1193, // Kyrgyzstan + 1204, // Lao + 1208, // Latvia + 1215, // Lebanon + 1223, // Lesotho + 1231, // Liberia + 1239, // LibyanArabJamahiriya + 1260, // Liechtenstein + 1274, // Lithuania + 1284, // Luxembourg + 1295, // Macau + 1301, // Macedonia + 1311, // Madagascar + 1322, // Malawi + 1329, // Malaysia + 1338, // Maldives + 1347, // Mali + 1352, // Malta + 1358, // MarshallIslands + 1374, // Martinique + 1385, // Mauritania + 1396, // Mauritius + 1406, // Mayotte + 1414, // Mexico + 1421, // Micronesia + 1432, // Moldova + 1440, // Monaco + 1447, // Mongolia + 1456, // Montserrat + 1467, // Morocco + 1475, // Mozambique + 1486, // Myanmar + 1494, // Namibia + 1502, // Nauru + 1508, // Nepal + 1514, // Netherlands + 1526, // NetherlandsAntilles + 1546, // NewCaledonia + 1559, // NewZealand + 1570, // Nicaragua + 1580, // Niger + 1586, // Nigeria + 1594, // Niue + 1599, // NorfolkIsland + 1613, // NorthernMarianaIslands + 1636, // Norway + 1643, // Oman + 1648, // Pakistan + 1657, // Palau + 1663, // PalestinianTerritory + 1684, // Panama + 1691, // PapuaNewGuinea + 1706, // Paraguay + 1715, // Peru + 1720, // Philippines + 1732, // Pitcairn + 1741, // Poland + 1748, // Portugal + 1757, // PuertoRico + 1768, // Qatar + 1774, // Reunion + 1782, // Romania + 1790, // RussianFederation + 1808, // Rwanda + 1815, // SaintKittsAndNevis + 1834, // StLucia + 1842, // StVincentAndTheGrenadines + 1868, // Samoa + 1874, // SanMarino + 1884, // SaoTomeAndPrincipe + 1903, // SaudiArabia + 1915, // Senegal + 1923, // Seychelles + 1934, // SierraLeone + 1946, // Singapore + 1956, // Slovakia + 1965, // Slovenia + 1974, // SolomonIslands + 1989, // Somalia + 1997, // SouthAfrica + 2009, // SouthGeorgiaAndTheSouthSandwichIslands + 2048, // Spain + 2054, // SriLanka + 2063, // StHelena + 2072, // StPierreAndMiquelon + 2092, // Sudan + 2098, // Suriname + 2107, // SvalbardAndJanMayenIslands + 2134, // Swaziland + 2144, // Sweden + 2151, // Switzerland + 2163, // SyrianArabRepublic + 2182, // Taiwan + 2189, // Tajikistan + 2200, // Tanzania + 2209, // Thailand + 2218, // Togo + 2223, // Tokelau + 2231, // Tonga + 2237, // TrinidadAndTobago + 2255, // Tunisia + 2263, // Turkey + 2270, // Turkmenistan + 2283, // TurksAndCaicosIslands + 2305, // Tuvalu + 2312, // Uganda + 2319, // Ukraine + 2327, // UnitedArabEmirates + 2346, // UnitedKingdom + 2360, // UnitedStates + 2373, // UnitedStatesMinorOutlyingIslands + 2406, // Uruguay + 2414, // Uzbekistan + 2425, // Vanuatu + 2433, // VaticanCityState + 2450, // Venezuela + 2460, // VietNam + 2468, // BritishVirginIslands + 2489, // USVirginIslands + 2505, // WallisAndFutunaIslands + 2528, // WesternSahara + 2542, // Yemen + 2548, // Yugoslavia + 2559, // Zambia + 2566, // Zimbabwe + 2575, // SerbiaAndMontenegro +}; + +static const unsigned char language_code_list[] = +" \0" // Unused +" \0" // C +"ab\0" // Abkhazian +"om\0" // Afan +"aa\0" // Afar +"af\0" // Afrikaans +"sq\0" // Albanian +"am\0" // Amharic +"ar\0" // Arabic +"hy\0" // Armenian +"as\0" // Assamese +"ay\0" // Aymara +"az\0" // Azerbaijani +"ba\0" // Bashkir +"eu\0" // Basque +"bn\0" // Bengali +"dz\0" // Bhutani +"bh\0" // Bihari +"bi\0" // Bislama +"br\0" // Breton +"bg\0" // Bulgarian +"my\0" // Burmese +"be\0" // Byelorussian +"km\0" // Cambodian +"ca\0" // Catalan +"zh\0" // Chinese +"co\0" // Corsican +"hr\0" // Croatian +"cs\0" // Czech +"da\0" // Danish +"nl\0" // Dutch +"en\0" // English +"eo\0" // Esperanto +"et\0" // Estonian +"fo\0" // Faroese +"fj\0" // Fiji +"fi\0" // Finnish +"fr\0" // French +"fy\0" // Frisian +"gd\0" // Gaelic +"gl\0" // Galician +"ka\0" // Georgian +"de\0" // German +"el\0" // Greek +"kl\0" // Greenlandic +"gn\0" // Guarani +"gu\0" // Gujarati +"ha\0" // Hausa +"he\0" // Hebrew +"hi\0" // Hindi +"hu\0" // Hungarian +"is\0" // Icelandic +"id\0" // Indonesian +"ia\0" // Interlingua +"ie\0" // Interlingue +"iu\0" // Inuktitut +"ik\0" // Inupiak +"ga\0" // Irish +"it\0" // Italian +"ja\0" // Japanese +"jv\0" // Javanese +"kn\0" // Kannada +"ks\0" // Kashmiri +"kk\0" // Kazakh +"rw\0" // Kinyarwanda +"ky\0" // Kirghiz +"ko\0" // Korean +"ku\0" // Kurdish +"rn\0" // Kurundi +"lo\0" // Laothian +"la\0" // Latin +"lv\0" // Latvian +"ln\0" // Lingala +"lt\0" // Lithuanian +"mk\0" // Macedonian +"mg\0" // Malagasy +"ms\0" // Malay +"ml\0" // Malayalam +"mt\0" // Maltese +"mi\0" // Maori +"mr\0" // Marathi +"mo\0" // Moldavian +"mn\0" // Mongolian +"na\0" // Nauru +"ne\0" // Nepali +"nb\0" // Norwegian +"oc\0" // Occitan +"or\0" // Oriya +"ps\0" // Pashto +"fa\0" // Persian +"pl\0" // Polish +"pt\0" // Portuguese +"pa\0" // Punjabi +"qu\0" // Quechua +"rm\0" // RhaetoRomance +"ro\0" // Romanian +"ru\0" // Russian +"sm\0" // Samoan +"sg\0" // Sangho +"sa\0" // Sanskrit +"sr\0" // Serbian +"sh\0" // SerboCroatian +"st\0" // Sesotho +"tn\0" // Setswana +"sn\0" // Shona +"sd\0" // Sindhi +"si\0" // Singhalese +"ss\0" // Siswati +"sk\0" // Slovak +"sl\0" // Slovenian +"so\0" // Somali +"es\0" // Spanish +"su\0" // Sundanese +"sw\0" // Swahili +"sv\0" // Swedish +"tl\0" // Tagalog +"tg\0" // Tajik +"ta\0" // Tamil +"tt\0" // Tatar +"te\0" // Telugu +"th\0" // Thai +"bo\0" // Tibetan +"ti\0" // Tigrinya +"to\0" // Tonga +"ts\0" // Tsonga +"tr\0" // Turkish +"tk\0" // Turkmen +"tw\0" // Twi +"ug\0" // Uigur +"uk\0" // Ukrainian +"ur\0" // Urdu +"uz\0" // Uzbek +"vi\0" // Vietnamese +"vo\0" // Volapuk +"cy\0" // Welsh +"wo\0" // Wolof +"xh\0" // Xhosa +"yi\0" // Yiddish +"yo\0" // Yoruba +"za\0" // Zhuang +"zu\0" // Zulu +"nn\0" // Nynorsk +"bs\0" // Bosnian +"dv\0" // Divehi +"gv\0" // Manx +"kw\0" // Cornish +"ak\0" // Akan +"kok" // Konkani +"gaa" // Ga +"ig\0" // Igbo +"kam" // Kamba +"syr" // Syriac +"byn" // Blin +"gez" // Geez +"kfo" // Koro +"sid" // Sidamo +"cch" // Atsam +"tig" // Tigre +"kaj" // Jju +"fur" // Friulian +"ve\0" // Venda +"ee\0" // Ewe +"wa\0" // Walamo +"haw" // Hawaiian +"kcg" // Tyap +"ny\0" // Chewa +; + +static const unsigned char country_code_list[] = +" " // AnyCountry +"AF" // Afghanistan +"AL" // Albania +"DZ" // Algeria +"AS" // AmericanSamoa +"AD" // Andorra +"AO" // Angola +"AI" // Anguilla +"AQ" // Antarctica +"AG" // AntiguaAndBarbuda +"AR" // Argentina +"AM" // Armenia +"AW" // Aruba +"AU" // Australia +"AT" // Austria +"AZ" // Azerbaijan +"BS" // Bahamas +"BH" // Bahrain +"BD" // Bangladesh +"BB" // Barbados +"BY" // Belarus +"BE" // Belgium +"BZ" // Belize +"BJ" // Benin +"BM" // Bermuda +"BT" // Bhutan +"BO" // Bolivia +"BA" // BosniaAndHerzegowina +"BW" // Botswana +"BV" // BouvetIsland +"BR" // Brazil +"IO" // BritishIndianOceanTerritory +"BN" // BruneiDarussalam +"BG" // Bulgaria +"BF" // BurkinaFaso +"BI" // Burundi +"KH" // Cambodia +"CM" // Cameroon +"CA" // Canada +"CV" // CapeVerde +"KY" // CaymanIslands +"CF" // CentralAfricanRepublic +"TD" // Chad +"CL" // Chile +"CN" // China +"CX" // ChristmasIsland +"CC" // CocosIslands +"CO" // Colombia +"KM" // Comoros +"CD" // DemocraticRepublicOfCongo +"CG" // PeoplesRepublicOfCongo +"CK" // CookIslands +"CR" // CostaRica +"CI" // IvoryCoast +"HR" // Croatia +"CU" // Cuba +"CY" // Cyprus +"CZ" // CzechRepublic +"DK" // Denmark +"DJ" // Djibouti +"DM" // Dominica +"DO" // DominicanRepublic +"TL" // EastTimor +"EC" // Ecuador +"EG" // Egypt +"SV" // ElSalvador +"GQ" // EquatorialGuinea +"ER" // Eritrea +"EE" // Estonia +"ET" // Ethiopia +"FK" // FalklandIslands +"FO" // FaroeIslands +"FJ" // Fiji +"FI" // Finland +"FR" // France +"FX" // MetropolitanFrance +"GF" // FrenchGuiana +"PF" // FrenchPolynesia +"TF" // FrenchSouthernTerritories +"GA" // Gabon +"GM" // Gambia +"GE" // Georgia +"DE" // Germany +"GH" // Ghana +"GI" // Gibraltar +"GR" // Greece +"GL" // Greenland +"GD" // Grenada +"GP" // Guadeloupe +"GU" // Guam +"GT" // Guatemala +"GN" // Guinea +"GW" // GuineaBissau +"GY" // Guyana +"HT" // Haiti +"HM" // HeardAndMcDonaldIslands +"HN" // Honduras +"HK" // HongKong +"HU" // Hungary +"IS" // Iceland +"IN" // India +"ID" // Indonesia +"IR" // Iran +"IQ" // Iraq +"IE" // Ireland +"IL" // Israel +"IT" // Italy +"JM" // Jamaica +"JP" // Japan +"JO" // Jordan +"KZ" // Kazakhstan +"KE" // Kenya +"KI" // Kiribati +"KP" // DemocraticRepublicOfKorea +"KR" // RepublicOfKorea +"KW" // Kuwait +"KG" // Kyrgyzstan +"LA" // Lao +"LV" // Latvia +"LB" // Lebanon +"LS" // Lesotho +"LR" // Liberia +"LY" // LibyanArabJamahiriya +"LI" // Liechtenstein +"LT" // Lithuania +"LU" // Luxembourg +"MO" // Macau +"MK" // Macedonia +"MG" // Madagascar +"MW" // Malawi +"MY" // Malaysia +"MV" // Maldives +"ML" // Mali +"MT" // Malta +"MH" // MarshallIslands +"MQ" // Martinique +"MR" // Mauritania +"MU" // Mauritius +"YT" // Mayotte +"MX" // Mexico +"FM" // Micronesia +"MD" // Moldova +"MC" // Monaco +"MN" // Mongolia +"MS" // Montserrat +"MA" // Morocco +"MZ" // Mozambique +"MM" // Myanmar +"NA" // Namibia +"NR" // Nauru +"NP" // Nepal +"NL" // Netherlands +"AN" // NetherlandsAntilles +"NC" // NewCaledonia +"NZ" // NewZealand +"NI" // Nicaragua +"NE" // Niger +"NG" // Nigeria +"NU" // Niue +"NF" // NorfolkIsland +"MP" // NorthernMarianaIslands +"NO" // Norway +"OM" // Oman +"PK" // Pakistan +"PW" // Palau +"PS" // PalestinianTerritory +"PA" // Panama +"PG" // PapuaNewGuinea +"PY" // Paraguay +"PE" // Peru +"PH" // Philippines +"PN" // Pitcairn +"PL" // Poland +"PT" // Portugal +"PR" // PuertoRico +"QA" // Qatar +"RE" // Reunion +"RO" // Romania +"RU" // RussianFederation +"RW" // Rwanda +"KN" // SaintKittsAndNevis +"LC" // StLucia +"VC" // StVincentAndTheGrenadines +"WS" // Samoa +"SM" // SanMarino +"ST" // SaoTomeAndPrincipe +"SA" // SaudiArabia +"SN" // Senegal +"SC" // Seychelles +"SL" // SierraLeone +"SG" // Singapore +"SK" // Slovakia +"SI" // Slovenia +"SB" // SolomonIslands +"SO" // Somalia +"ZA" // SouthAfrica +"GS" // SouthGeorgiaAndTheSouthSandwichIslands +"ES" // Spain +"LK" // SriLanka +"SH" // StHelena +"PM" // StPierreAndMiquelon +"SD" // Sudan +"SR" // Suriname +"SJ" // SvalbardAndJanMayenIslands +"SZ" // Swaziland +"SE" // Sweden +"CH" // Switzerland +"SY" // SyrianArabRepublic +"TW" // Taiwan +"TJ" // Tajikistan +"TZ" // Tanzania +"TH" // Thailand +"TG" // Togo +"TK" // Tokelau +"TO" // Tonga +"TT" // TrinidadAndTobago +"TN" // Tunisia +"TR" // Turkey +"TM" // Turkmenistan +"TC" // TurksAndCaicosIslands +"TV" // Tuvalu +"UG" // Uganda +"UA" // Ukraine +"AE" // UnitedArabEmirates +"GB" // UnitedKingdom +"US" // UnitedStates +"UM" // UnitedStatesMinorOutlyingIslands +"UY" // Uruguay +"UZ" // Uzbekistan +"VU" // Vanuatu +"VA" // VaticanCityState +"VE" // Venezuela +"VN" // VietNam +"VG" // BritishVirginIslands +"VI" // USVirginIslands +"WF" // WallisAndFutunaIslands +"EH" // WesternSahara +"YE" // Yemen +"YU" // Yugoslavia +"ZM" // Zambia +"ZW" // Zimbabwe +"CS" // SerbiaAndMontenegro +; + +QT_END_NAMESPACE + +#endif diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h new file mode 100644 index 0000000..9d36a83 --- /dev/null +++ b/src/corelib/tools/qlocale_p.h @@ -0,0 +1,206 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLOCALE_P_H +#define QLOCALE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include "QtCore/qstring.h" +#include "QtCore/qvarlengtharray.h" + +#include "qlocale.h" + +QT_BEGIN_NAMESPACE + +struct Q_CORE_EXPORT QLocalePrivate +{ +public: + QChar decimal() const { return QChar(m_decimal); } + QChar group() const { return QChar(m_group); } + QChar list() const { return QChar(m_list); } + QChar percent() const { return QChar(m_percent); } + QChar zero() const { return QChar(m_zero); } + QChar plus() const { return QChar(m_plus); } + QChar minus() const { return QChar(m_minus); } + QChar exponential() const { return QChar(m_exponential); } + + quint32 languageId() const { return m_language_id; } + quint32 countryId() const { return m_country_id; } + + QLocale::MeasurementSystem measurementSystem() const; + + enum DoubleForm { + DFExponent = 0, + DFDecimal, + DFSignificantDigits, + _DFMax = DFSignificantDigits + }; + + enum Flags { + NoFlags = 0, + Alternate = 0x01, + ZeroPadded = 0x02, + LeftAdjusted = 0x04, + BlankBeforePositive = 0x08, + AlwaysShowSign = 0x10, + ThousandsGroup = 0x20, + CapitalEorX = 0x40, + + ShowBase = 0x80, + UppercaseBase = 0x100, + ForcePoint = Alternate, + }; + + enum GroupSeparatorMode { + FailOnGroupSeparators, + ParseGroupSeparators + }; + + QString doubleToString(double d, + int precision = -1, + DoubleForm form = DFSignificantDigits, + int width = -1, + unsigned flags = NoFlags) const; + QString longLongToString(qint64 l, int precision = -1, + int base = 10, + int width = -1, + unsigned flags = NoFlags) const; + QString unsLongLongToString(quint64 l, int precision = -1, + int base = 10, + int width = -1, + unsigned flags = NoFlags) const; + double stringToDouble(const QString &num, bool *ok, GroupSeparatorMode group_sep_mode) const; + qint64 stringToLongLong(const QString &num, int base, bool *ok, GroupSeparatorMode group_sep_mode) const; + quint64 stringToUnsLongLong(const QString &num, int base, bool *ok, GroupSeparatorMode group_sep_mode) const; + + + static double bytearrayToDouble(const char *num, bool *ok, bool *overflow = 0); + static qint64 bytearrayToLongLong(const char *num, int base, bool *ok, bool *overflow = 0); + static quint64 bytearrayToUnsLongLong(const char *num, int base, bool *ok); + + typedef QVarLengthArray<char, 256> CharBuff; + bool numberToCLocale(const QString &num, + GroupSeparatorMode group_sep_mode, + CharBuff *result) const; + inline char digitToCLocale(const QChar &c) const; + + static void updateSystemPrivate(); + + enum NumberMode { IntegerMode, DoubleStandardMode, DoubleScientificMode }; + bool validateChars(const QString &str, NumberMode numMode, QByteArray *buff, int decDigits = -1) const; + + QString dateTimeToString(const QString &format, const QDate *date, const QTime *time, + const QLocale *q) const; + + quint32 m_language_id, m_country_id; + + quint16 m_decimal, m_group, m_list, m_percent, + m_zero, m_minus, m_plus, m_exponential; + + quint32 m_short_date_format_idx, m_short_date_format_size; + quint32 m_long_date_format_idx, m_long_date_format_size; + quint32 m_short_time_format_idx, m_short_time_format_size; + quint32 m_long_time_format_idx, m_long_time_format_size; + quint32 m_standalone_short_month_names_idx, m_standalone_short_month_names_size; + quint32 m_standalone_long_month_names_idx, m_standalone_long_month_names_size; + quint32 m_standalone_narrow_month_names_idx, m_standalone_narrow_month_names_size; + quint32 m_short_month_names_idx, m_short_month_names_size; + quint32 m_long_month_names_idx, m_long_month_names_size; + quint32 m_narrow_month_names_idx, m_narrow_month_names_size; + quint32 m_standalone_short_day_names_idx, m_standalone_short_day_names_size; + quint32 m_standalone_long_day_names_idx, m_standalone_long_day_names_size; + quint32 m_standalone_narrow_day_names_idx, m_standalone_narrow_day_names_size; + quint32 m_short_day_names_idx, m_short_day_names_size; + quint32 m_long_day_names_idx, m_long_day_names_size; + quint32 m_narrow_day_names_idx, m_narrow_day_names_size; + quint32 m_am_idx, m_am_size; + quint32 m_pm_idx, m_pm_size; +}; + +inline char QLocalePrivate::digitToCLocale(const QChar &in) const +{ + const QChar _zero = zero(); + const QChar _group = group(); + const ushort zeroUnicode = _zero.unicode(); + const ushort tenUnicode = zeroUnicode + 10; + + if (in.unicode() >= zeroUnicode && in.unicode() < tenUnicode) + return '0' + in.unicode() - zeroUnicode; + + if (in.unicode() >= '0' && in.unicode() <= '9') + return in.toLatin1(); + + if (in == plus()) + return '+'; + + if (in == minus()) + return '-'; + + if (in == decimal()) + return '.'; + + if (in == group()) + return ','; + + if (in == exponential() || in == exponential().toUpper()) + return 'e'; + + // In several languages group() is the char 0xA0, which looks like a space. + // People use a regular space instead of it and complain it doesn't work. + if (_group.unicode() == 0xA0 && in.unicode() == ' ') + return ','; + + return 0; +} + +QT_END_NAMESPACE + +#endif // QLOCALE_P_H diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp new file mode 100644 index 0000000..0699400 --- /dev/null +++ b/src/corelib/tools/qmap.cpp @@ -0,0 +1,1588 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmap.h" + +#include <stdlib.h> + +#ifdef QT_QMAP_DEBUG +# include <qstring.h> +# include <qvector.h> +#endif + +QT_BEGIN_NAMESPACE + +QMapData QMapData::shared_null = { + &shared_null, + { &shared_null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, 0, false, true +}; + +QMapData *QMapData::createData() +{ + QMapData *d = new QMapData; + Node *e = reinterpret_cast<Node *>(d); + e->backward = e; + e->forward[0] = e; + d->ref = 1; + d->topLevel = 0; + d->size = 0; + d->randomBits = 0; + d->insertInOrder = false; + d->sharable = true; + return d; +} + +void QMapData::continueFreeData(int offset) +{ + Node *e = reinterpret_cast<Node *>(this); + Node *cur = e->forward[0]; + Node *prev; + while (cur != e) { + prev = cur; + cur = cur->forward[0]; + qFree(reinterpret_cast<char *>(prev) - offset); + } + delete this; +} + +QMapData::Node *QMapData::node_create(Node *update[], int offset) +{ + int level = 0; + uint mask = (1 << Sparseness) - 1; + + while ((randomBits & mask) == mask && level < LastLevel) { + ++level; + mask <<= Sparseness; + } + + ++randomBits; + if (level == 3 && !insertInOrder) + randomBits = qrand(); + + if (level > topLevel) { + Node *e = reinterpret_cast<Node *>(this); + level = ++topLevel; + e->forward[level] = e; + update[level] = e; + } + + void *concreteNode = qMalloc(offset + sizeof(Node) + level * sizeof(Node *)); + Node *abstractNode = reinterpret_cast<Node *>(reinterpret_cast<char *>(concreteNode) + offset); + + abstractNode->backward = update[0]; + update[0]->forward[0]->backward = abstractNode; + + for (int i = level; i >= 0; i--) { + abstractNode->forward[i] = update[i]->forward[i]; + update[i]->forward[i] = abstractNode; + update[i] = abstractNode; + } + ++size; + return abstractNode; +} + +void QMapData::node_delete(Node *update[], int offset, Node *node) +{ + node->forward[0]->backward = node->backward; + + for (int i = 0; i <= topLevel; ++i) { + if (update[i]->forward[i] != node) + break; + update[i]->forward[i] = node->forward[i]; + } + --size; + qFree(reinterpret_cast<char *>(node) - offset); +} + +#ifdef QT_QMAP_DEBUG + +uint QMapData::adjust_ptr(Node *node) +{ + if (node == reinterpret_cast<Node *>(this)) { + return (uint)0xDEADBEEF; + } else { + return (uint)node; + } +} + +void QMapData::dump() +{ + qDebug("Map data (ref = %d, size = %d, randomBits = %#.8x)", ref.atomic, size, randomBits); + + QString preOutput; + QVector<QString> output(topLevel + 1); + Node *e = reinterpret_cast<Node *>(this); + + QString str; + str.sprintf(" %.8x", adjust_ptr(reinterpret_cast<Node *>(this))); + preOutput += str; + + Node *update[LastLevel + 1]; + for (int i = 0; i <= topLevel; ++i) { + str.sprintf("%d: [%.8x] -", i, adjust_ptr(forward[i])); + output[i] += str; + update[i] = forward[i]; + } + + Node *node = forward[0]; + while (node != e) { + int level = 0; + while (level < topLevel && update[level + 1] == node) + ++level; + + str.sprintf(" %.8x", adjust_ptr(node)); + preOutput += str; + + for (int i = 0; i <= level; ++i) { + str.sprintf("-> [%.8x] -", adjust_ptr(node->forward[i])); + output[i] += str; + update[i] = node->forward[i]; + } + for (int j = level + 1; j <= topLevel; ++j) + output[j] += "---------------"; + node = node->forward[0]; + } + + qDebug(preOutput.ascii()); + for (int i = 0; i <= topLevel; ++i) + qDebug(output[i].ascii()); +} +#endif + +/*! + \class QMap + \brief The QMap class is a template class that provides a skip-list-based dictionary. + + \ingroup tools + \ingroup shared + \mainclass + \reentrant + + QMap\<Key, T\> is one of Qt's generic \l{container classes}. It + stores (key, value) pairs and provides fast lookup of the + value associated with a key. + + QMap and QHash provide very similar functionality. The + differences are: + + \list + \i QHash provides faster lookups than QMap. (See \l{Algorithmic + Complexity} for details.) + \i When iterating over a QHash, the items are arbitrarily ordered. + With QMap, the items are always sorted by key. + \i The key type of a QHash must provide operator==() and a global + qHash(Key) function. The key type of a QMap must provide + operator<() specifying a total order. + \endlist + + Here's an example QMap with QString keys and \c int values: + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 0 + + To insert a (key, value) pair into the map, you can use operator[](): + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 1 + + This inserts the following three (key, value) pairs into the + QMap: ("one", 1), ("three", 3), and ("seven", 7). Another way to + insert items into the map is to use insert(): + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 2 + + To look up a value, use operator[]() or value(): + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 3 + + If there is no item with the specified key in the map, these + functions return a \l{default-constructed value}. + + If you want to check whether the map contains a certain key, use + contains(): + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 4 + + There is also a value() overload that uses its second argument as + a default value if there is no item with the specified key: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 5 + + In general, we recommend that you use contains() and value() + rather than operator[]() for looking up a key in a map. The + reason is that operator[]() silently inserts an item into the + map if no item exists with the same key (unless the map is + const). For example, the following code snippet will create 1000 + items in memory: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 6 + + To avoid this problem, replace \c map[i] with \c map.value(i) + in the code above. + + If you want to navigate through all the (key, value) pairs stored + in a QMap, you can use an iterator. QMap provides both + \l{Java-style iterators} (QMapIterator and QMutableMapIterator) + and \l{STL-style iterators} (QMap::const_iterator and + QMap::iterator). Here's how to iterate over a QMap<QString, int> + using a Java-style iterator: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 7 + + Here's the same code, but using an STL-style iterator this time: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 8 + + The items are traversed in ascending key order. + + Normally, a QMap allows only one value per key. If you call + insert() with a key that already exists in the QMap, the + previous value will be erased. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 9 + + However, you can store multiple values per key by using + insertMulti() instead of insert() (or using the convenience + subclass QMultiMap). If you want to retrieve all the values for a + single key, you can use values(const Key &key), which returns a + QList<T>: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 10 + + The items that share the same key are available from most + recently to least recently inserted. Another approach is to call + find() to get the STL-style iterator for the first item with a + key and iterate from there: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 11 + + If you only need to extract the values from a map (not the keys), + you can also use \l{foreach}: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 12 + + Items can be removed from the map in several ways. One way is to + call remove(); this will remove any item with the given key. + Another way is to use QMutableMapIterator::remove(). In addition, + you can clear the entire map using clear(). + + QMap's key and value data types must be \l{assignable data + types}. This covers most data types you are likely to encounter, + but the compiler won't let you, for example, store a QWidget as a + value; instead, store a QWidget *. In addition, QMap's key type + must provide operator<(). QMap uses it to keep its items sorted, + and assumes that two keys \c x and \c y are equal if neither \c{x + < y} nor \c{y < x} is true. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 13 + + In the example, we start by comparing the employees' names. If + they're equal, we compare their dates of birth to break the tie. + + \sa QMapIterator, QMutableMapIterator, QHash, QSet +*/ + +/*! \fn QMap::QMap() + + Constructs an empty map. + + \sa clear() +*/ + +/*! \fn QMap::QMap(const QMap<Key, T> &other) + + Constructs a copy of \a other. + + This operation occurs in \l{constant time}, because QMap is + \l{implicitly shared}. This makes returning a QMap from a + function very fast. If a shared instance is modified, it will be + copied (copy-on-write), and this takes \l{linear time}. + + \sa operator=() +*/ + +/*! \fn QMap::QMap(const std::map<Key, T> & other) + + Constructs a copy of \a other. + + This function is only available if Qt is configured with STL + compatibility enabled. + + \sa toStdMap() +*/ + +/*! \fn std::map<Key, T> QMap::toStdMap() const + + Returns an STL map equivalent to this QMap. + + This function is only available if Qt is configured with STL + compatibility enabled. +*/ + +/*! \fn QMap::~QMap() + + Destroys the map. References to the values in the map, and all + iterators over this map, become invalid. +*/ + +/*! \fn QMap<Key, T> &QMap::operator=(const QMap<Key, T> &other) + + Assigns \a other to this map and returns a reference to this map. +*/ + +/*! \fn bool QMap::operator==(const QMap<Key, T> &other) const + + Returns true if \a other is equal to this map; otherwise returns + false. + + Two maps are considered equal if they contain the same (key, + value) pairs. + + This function requires the value type to implement \c + operator==(). + + \sa operator!=() +*/ + +/*! \fn bool QMap::operator!=(const QMap<Key, T> &other) const + + Returns true if \a other is not equal to this map; otherwise + returns false. + + Two maps are considered equal if they contain the same (key, + value) pairs. + + This function requires the value type to implement \c + operator==(). + + \sa operator==() +*/ + +/*! \fn int QMap::size() const + + Returns the number of (key, value) pairs in the map. + + \sa isEmpty(), count() +*/ + +/*! + \fn bool QMap::isEmpty() const + + Returns true if the map contains no items; otherwise returns + false. + + \sa size() +*/ + +/*! \fn void QMap::detach() + + \internal + + Detaches this map from any other maps with which it may share + data. + + \sa isDetached() +*/ + +/*! \fn bool QMap::isDetached() const + + \internal + + Returns true if the map's internal data isn't shared with any + other map object; otherwise returns false. + + \sa detach() +*/ + +/*! \fn void QMap::setSharable(bool sharable) + + \internal +*/ + +/*! \fn void QMap::setInsertInOrder(bool sharable) + + \internal +*/ + +/*! \fn void QMap::clear() + + Removes all items from the map. + + \sa remove() +*/ + +/*! \fn int QMap::remove(const Key &key) + + Removes all the items that have the key \a key from the map. + Returns the number of items removed which is usually 1 but will be + 0 if the key isn't in the map, or \> 1 if insertMulti() has been + used with the \a key. + + \sa clear(), take(), QMultiMap::remove() +*/ + +/*! \fn T QMap::take(const Key &key) + + Removes the item with the key \a key from the map and returns + the value associated with it. + + If the item does not exist in the map, the function simply + returns a \l{default-constructed value}. If there are multiple + items for \a key in the map, only the most recently inserted one + is removed and returned. + + If you don't use the return value, remove() is more efficient. + + \sa remove() +*/ + +/*! \fn bool QMap::contains(const Key &key) const + + Returns true if the map contains an item with key \a key; + otherwise returns false. + + \sa count(), QMultiMap::contains() +*/ + +/*! \fn const T QMap::value(const Key &key) const + + Returns the value associated with the key \a key. + + If the map contains no item with key \a key, the function + returns a \l{default-constructed value}. If there are multiple + items for \a key in the map, the value of the most recently + inserted one is returned. + + \sa key(), values(), contains(), operator[]() +*/ + +/*! \fn const T QMap::value(const Key &key, const T &defaultValue) const + + \overload + + If the map contains no item with key \a key, the function returns + \a defaultValue. +*/ + +/*! \fn T &QMap::operator[](const Key &key) + + Returns the value associated with the key \a key as a modifiable + reference. + + If the map contains no item with key \a key, the function inserts + a \l{default-constructed value} into the map with key \a key, and + returns a reference to it. If the map contains multiple items + with key \a key, this function returns a reference to the most + recently inserted value. + + \sa insert(), value() +*/ + +/*! \fn const T QMap::operator[](const Key &key) const + + \overload + + Same as value(). +*/ + +/*! \fn QList<Key> QMap::uniqueKeys() const + \since 4.2 + + Returns a list containing all the keys in the map in ascending + order. Keys that occur multiple times in the map (because items + were inserted with insertMulti(), or unite() was used) occur only + once in the returned list. + + \sa keys(), values() +*/ + +/*! \fn QList<Key> QMap::keys() const + + Returns a list containing all the keys in the map in ascending + order. Keys that occur multiple times in the map (because items + were inserted with insertMulti(), or unite() was used) also + occur multiple times in the list. + + To obtain a list of unique keys, where each key from the map only + occurs once, use uniqueKeys(). + + The order is guaranteed to be the same as that used by values(). + + \sa uniqueKeys(), values(), key() +*/ + +/*! \fn QList<Key> QMap::keys(const T &value) const + + \overload + + Returns a list containing all the keys associated with value \a + value in ascending order. + + This function can be slow (\l{linear time}), because QMap's + internal data structure is optimized for fast lookup by key, not + by value. +*/ + +/*! \fn Key QMap::key(const T &value) const + + Returns the first key with value \a value. + + If the map contains no item with value \a value, the function + returns a \link {default-constructed value} default-constructed + key \endlink. + + This function can be slow (\l{linear time}), because QMap's + internal data structure is optimized for fast lookup by key, not + by value. + + \sa value(), keys() +*/ + +/*! + \fn Key QMap::key(const T &value, const Key &defaultKey) const + \since 4.3 + \overload + + Returns the first key with value \a value, or \a defaultKey if + the map contains no item with value \a value. + + This function can be slow (\l{linear time}), because QMap's + internal data structure is optimized for fast lookup by key, not + by value. +*/ + +/*! \fn QList<T> QMap::values() const + + Returns a list containing all the values in the map, in ascending + order of their keys. If a key is associated with multiple values, + all of its values will be in the list, and not just the most + recently inserted one. + + \sa keys(), value() +*/ + +/*! \fn QList<T> QMap::values(const Key &key) const + + \overload + + Returns a list containing all the values associated with key + \a key, from the most recently inserted to the least recently + inserted one. + + \sa count(), insertMulti() +*/ + +/*! \fn int QMap::count(const Key &key) const + + Returns the number of items associated with key \a key. + + \sa contains(), insertMulti(), QMultiMap::count() +*/ + +/*! \fn int QMap::count() const + + \overload + + Same as size(). +*/ + +/*! \fn QMap::iterator QMap::begin() + + Returns an \l{STL-style iterator} pointing to the first item in + the map. + + \sa constBegin(), end() +*/ + +/*! \fn QMap::const_iterator QMap::begin() const + + \overload +*/ + +/*! \fn QMap::const_iterator QMap::constBegin() const + + Returns a const \l{STL-style iterator} pointing to the first item + in the map. + + \sa begin(), constEnd() +*/ + +/*! \fn QMap::iterator QMap::end() + + Returns an \l{STL-style iterator} pointing to the imaginary item + after the last item in the map. + + \sa begin(), constEnd() +*/ + +/*! \fn QMap::const_iterator QMap::end() const + + \overload +*/ + +/*! \fn QMap::const_iterator QMap::constEnd() const + + Returns a const \l{STL-style iterator} pointing to the imaginary + item after the last item in the map. + + \sa constBegin(), end() +*/ + +/*! \fn QMap::iterator QMap::erase(iterator pos) + + Removes the (key, value) pair pointed to by the iterator \a pos + from the map, and returns an iterator to the next item in the + map. + + \sa remove() +*/ + +/*! \fn QMap::iterator QMap::find(const Key &key) + + Returns an iterator pointing to the item with key \a key in the + map. + + If the map contains no item with key \a key, the function + returns end(). + + If the map contains multiple items with key \a key, this + function returns an iterator that points to the most recently + inserted value. The other values are accessible by incrementing + the iterator. For example, here's some code that iterates over all + the items with the same key: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 14 + + \sa constFind(), value(), values(), lowerBound(), upperBound(), QMultiMap::find() +*/ + +/*! \fn QMap::const_iterator QMap::find(const Key &key) const + + \overload +*/ + +/*! \fn QMap::iterator QMap::constFind(const Key &key) const + \since 4.1 + + Returns an const iterator pointing to the item with key \a key in the + map. + + If the map contains no item with key \a key, the function + returns constEnd(). + + \sa find(), QMultiMap::constFind() +*/ + +/*! \fn QMap::iterator QMap::lowerBound(const Key &key) + + Returns an iterator pointing to the first item with key \a key in + the map. If the map contains no item with key \a key, the + function returns an iterator to the nearest item with a greater + key. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 15 + + If the map contains multiple items with key \a key, this + function returns an iterator that points to the most recently + inserted value. The other values are accessible by incrementing + the iterator. For example, here's some code that iterates over all + the items with the same key: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 16 + + \sa qLowerBound(), upperBound(), find() +*/ + +/*! \fn QMap::const_iterator QMap::lowerBound(const Key &key) const + + \overload +*/ + +/*! \fn QMap::iterator QMap::upperBound(const Key &key) + + Returns an iterator pointing to the item that immediately follows + the last item with key \a key in the map. If the map contains no + item with key \a key, the function returns an iterator to the + nearest item with a greater key. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 17 + + \sa qUpperBound(), lowerBound(), find() +*/ + +/*! \fn QMap::const_iterator QMap::upperBound(const Key &key) const + + \overload +*/ + +/*! \fn QMap::iterator QMap::insert(const Key &key, const T &value) + + Inserts a new item with the key \a key and a value of \a value. + + If there is already an item with the key \a key, that item's value + is replaced with \a value. + + If there are multiple items with the key \a key, the most + recently inserted item's value is replaced with \a value. + + \sa insertMulti() +*/ + +/*! \fn QMap::iterator QMap::insertMulti(const Key &key, const T &value) + + Inserts a new item with the key \a key and a value of \a value. + + If there is already an item with the same key in the map, this + function will simply create a new one. (This behavior is + different from insert(), which overwrites the value of an + existing item.) + + \sa insert(), values() +*/ + +/*! \fn QMap<Key, T> &QMap::unite(const QMap<Key, T> &other) + + Inserts all the items in the \a other map into this map. If a + key is common to both maps, the resulting map will contain the + key multiple times. + + \sa insertMulti() +*/ + +/*! \typedef QMap::Iterator + + Qt-style synonym for QMap::iterator. +*/ + +/*! \typedef QMap::ConstIterator + + Qt-style synonym for QMap::const_iterator. +*/ + +/*! \typedef QMap::difference_type + + Typedef for ptrdiff_t. Provided for STL compatibility. +*/ + +/*! \typedef QMap::key_type + + Typedef for Key. Provided for STL compatibility. +*/ + +/*! \typedef QMap::mapped_type + + Typedef for T. Provided for STL compatibility. +*/ + +/*! \typedef QMap::size_type + + Typedef for int. Provided for STL compatibility. +*/ + +/*! + \fn bool QMap::empty() const + + This function is provided for STL compatibility. It is equivalent + to isEmpty(), returning true if the map is empty; otherwise + returning false. +*/ + +/*! \class QMap::iterator + \brief The QMap::iterator class provides an STL-style non-const iterator for QMap and QMultiMap. + + QMap features both \l{STL-style iterators} and \l{Java-style + iterators}. The STL-style iterators are more low-level and more + cumbersome to use; on the other hand, they are slightly faster + and, for developers who already know STL, have the advantage of + familiarity. + + QMap\<Key, T\>::iterator allows you to iterate over a QMap (or + QMultiMap) and to modify the value (but not the key) stored under + a particular key. If you want to iterate over a const QMap, you + should use QMap::const_iterator. It is generally good practice to + use QMap::const_iterator on a non-const QMap as well, unless you + need to change the QMap through the iterator. Const iterators are + slightly faster, and can improve code readability. + + The default QMap::iterator constructor creates an uninitialized + iterator. You must initialize it using a QMap function like + QMap::begin(), QMap::end(), or QMap::find() before you can + start iterating. Here's a typical loop that prints all the (key, + value) pairs stored in a map: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 18 + + Unlike QHash, which stores its items in an arbitrary order, QMap + stores its items ordered by key. Items that share the same key + (because they were inserted using QMap::insertMulti(), or due to a + unite()) will appear consecutively, from the most recently to the + least recently inserted value. + + Let's see a few examples of things we can do with a + QMap::iterator that we cannot do with a QMap::const_iterator. + Here's an example that increments every value stored in the QMap + by 2: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 19 + + Here's an example that removes all the items whose key is a + string that starts with an underscore character: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 20 + + The call to QMap::erase() removes the item pointed to by the + iterator from the map, and returns an iterator to the next item. + Here's another way of removing an item while iterating: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 21 + + It might be tempting to write code like this: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 22 + + However, this will potentially crash in \c{++i}, because \c i is + a dangling iterator after the call to erase(). + + Multiple iterators can be used on the same map. If you add items + to the map, existing iterators will remain valid. If you remove + items from the map, iterators that point to the removed items + will become dangling iterators. + + \sa QMap::const_iterator, QMutableMapIterator +*/ + +/*! \fn QMap::iterator::operator QMapData::Node *() const + + \internal +*/ + +/*! \typedef QMap::iterator::difference_type + + \internal +*/ + +/*! \typedef QMap::iterator::iterator_category + + \internal +*/ + +/*! \typedef QMap::iterator::pointer + + \internal +*/ + +/*! \typedef QMap::iterator::reference + + \internal +*/ + +/*! \typedef QMap::iterator::value_type + + \internal +*/ + +/*! \fn QMap::iterator::iterator() + + Constructs an uninitialized iterator. + + Functions like key(), value(), and operator++() must not be + called on an uninitialized iterator. Use operator=() to assign a + value to it before using it. + + \sa QMap::begin() QMap::end() +*/ + +/*! \fn QMap::iterator::iterator(QMapData::Node *node) + + \internal +*/ + +/*! \fn const Key &QMap::iterator::key() const + + Returns the current item's key as a const reference. + + There is no direct way of changing an item's key through an + iterator, although it can be done by calling QMap::erase() + followed by QMap::insert() or QMap::insertMulti(). + + \sa value() +*/ + +/*! \fn T &QMap::iterator::value() const + + Returns a modifiable reference to the current item's value. + + You can change the value of an item by using value() on + the left side of an assignment, for example: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 23 + + \sa key(), operator*() +*/ + +/*! \fn T &QMap::iterator::operator*() const + + Returns a modifiable reference to the current item's value. + + Same as value(). + + \sa key() +*/ + +/*! \fn T *QMap::iterator::operator->() const + + Returns a pointer to the current item's value. + + \sa value() +*/ + +/*! + \fn bool QMap::iterator::operator==(const iterator &other) const + \fn bool QMap::iterator::operator==(const const_iterator &other) const + + Returns true if \a other points to the same item as this + iterator; otherwise returns false. + + \sa operator!=() +*/ + +/*! + \fn bool QMap::iterator::operator!=(const iterator &other) const + \fn bool QMap::iterator::operator!=(const const_iterator &other) const + + Returns true if \a other points to a different item than this + iterator; otherwise returns false. + + \sa operator==() +*/ + +/*! \fn QMap::iterator QMap::iterator::operator++() + + The prefix ++ operator (\c{++i}) advances the iterator to the + next item in the map and returns an iterator to the new current + item. + + Calling this function on QMap::end() leads to undefined results. + + \sa operator--() +*/ + +/*! \fn QMap::iterator QMap::iterator::operator++(int) + + \overload + + The postfix ++ operator (\c{i++}) advances the iterator to the + next item in the map and returns an iterator to the previously + current item. +*/ + +/*! \fn QMap::iterator QMap::iterator::operator--() + + The prefix -- operator (\c{--i}) makes the preceding item + current and returns an iterator pointing to the new current item. + + Calling this function on QMap::begin() leads to undefined + results. + + \sa operator++() +*/ + +/*! \fn QMap::iterator QMap::iterator::operator--(int) + + \overload + + The prefix -- operator (\c{--i}) makes the preceding item + current and returns an iterator pointing to the previously + current item. +*/ + +/*! \fn QMap::iterator QMap::iterator::operator+(int j) const + + Returns an iterator to the item at \a j positions forward from + this iterator. (If \a j is negative, the iterator goes backward.) + + This operation can be slow for large \a j values. + + \sa operator-() + +*/ + +/*! \fn QMap::iterator QMap::iterator::operator-(int j) const + + Returns an iterator to the item at \a j positions backward from + this iterator. (If \a j is negative, the iterator goes forward.) + + This operation can be slow for large \a j values. + + \sa operator+() +*/ + +/*! \fn QMap::iterator &QMap::iterator::operator+=(int j) + + Advances the iterator by \a j items. (If \a j is negative, the + iterator goes backward.) + + \sa operator-=(), operator+() +*/ + +/*! \fn QMap::iterator &QMap::iterator::operator-=(int j) + + Makes the iterator go back by \a j items. (If \a j is negative, + the iterator goes forward.) + + \sa operator+=(), operator-() +*/ + +/*! \class QMap::const_iterator + \brief The QMap::const_iterator class provides an STL-style const iterator for QMap and QMultiMap. + + QMap features both \l{STL-style iterators} and \l{Java-style + iterators}. The STL-style iterators are more low-level and more + cumbersome to use; on the other hand, they are slightly faster + and, for developers who already know STL, have the advantage of + familiarity. + + QMap\<Key, T\>::const_iterator allows you to iterate over a QMap + (or a QMultiMap). If you want to modify the QMap as you iterate + over it, you must use QMap::iterator instead. It is generally + good practice to use QMap::const_iterator on a non-const QMap as + well, unless you need to change the QMap through the iterator. + Const iterators are slightly faster, and can improve code + readability. + + The default QMap::const_iterator constructor creates an + uninitialized iterator. You must initialize it using a QMap + function like QMap::constBegin(), QMap::constEnd(), or + QMap::find() before you can start iterating. Here's a typical + loop that prints all the (key, value) pairs stored in a map: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 24 + + Unlike QHash, which stores its items in an arbitrary order, QMap + stores its items ordered by key. Items that share the same key + (because they were inserted using QMap::insertMulti()) will + appear consecutively, from the most recently to the least + recently inserted value. + + Multiple iterators can be used on the same map. If you add items + to the map, existing iterators will remain valid. If you remove + items from the map, iterators that point to the removed items + will become dangling iterators. + + \sa QMap::iterator, QMapIterator +*/ + +/*! \fn QMap::const_iterator::operator QMapData::Node *() const + + \internal +*/ + +/*! \typedef QMap::const_iterator::difference_type + + \internal +*/ + +/*! \typedef QMap::const_iterator::iterator_category + + \internal +*/ + +/*! \typedef QMap::const_iterator::pointer + + \internal +*/ + +/*! \typedef QMap::const_iterator::reference + + \internal +*/ + +/*! \typedef QMap::const_iterator::value_type + + \internal +*/ + +/*! \fn QMap::const_iterator::const_iterator() + + Constructs an uninitialized iterator. + + Functions like key(), value(), and operator++() must not be + called on an uninitialized iterator. Use operator=() to assign a + value to it before using it. + + \sa QMap::constBegin() QMap::constEnd() +*/ + +/*! \fn QMap::const_iterator::const_iterator(QMapData::Node *node) + + \internal +*/ + +/*! \fn QMap::const_iterator::const_iterator(const iterator &other) + + Constructs a copy of \a other. +*/ + +/*! \fn const Key &QMap::const_iterator::key() const + + Returns the current item's key. + + \sa value() +*/ + +/*! \fn const T &QMap::const_iterator::value() const + + Returns the current item's value. + + \sa key(), operator*() +*/ + +/*! \fn const T &QMap::const_iterator::operator*() const + + Returns the current item's value. + + Same as value(). + + \sa key() +*/ + +/*! \fn const T *QMap::const_iterator::operator->() const + + Returns a pointer to the current item's value. + + \sa value() +*/ + +/*! \fn bool QMap::const_iterator::operator==(const const_iterator &other) const + + Returns true if \a other points to the same item as this + iterator; otherwise returns false. + + \sa operator!=() +*/ + +/*! \fn bool QMap::const_iterator::operator!=(const const_iterator &other) const + + Returns true if \a other points to a different item than this + iterator; otherwise returns false. + + \sa operator==() +*/ + +/*! \fn QMap::const_iterator QMap::const_iterator::operator++() + + The prefix ++ operator (\c{++i}) advances the iterator to the + next item in the map and returns an iterator to the new current + item. + + Calling this function on QMap::end() leads to undefined results. + + \sa operator--() +*/ + +/*! \fn QMap::const_iterator QMap::const_iterator::operator++(int) + + \overload + + The postfix ++ operator (\c{i++}) advances the iterator to the + next item in the map and returns an iterator to the previously + current item. +*/ + +/*! \fn QMap::const_iterator &QMap::const_iterator::operator--() + + The prefix -- operator (\c{--i}) makes the preceding item + current and returns an iterator pointing to the new current item. + + Calling this function on QMap::begin() leads to undefined + results. + + \sa operator++() +*/ + +/*! \fn QMap::const_iterator QMap::const_iterator::operator--(int) + + \overload + + The postfix -- operator (\c{i--}) makes the preceding item + current and returns an iterator pointing to the previously + current item. +*/ + +/*! \fn QMap::const_iterator QMap::const_iterator::operator+(int j) const + + Returns an iterator to the item at \a j positions forward from + this iterator. (If \a j is negative, the iterator goes backward.) + + This operation can be slow for large \a j values. + + \sa operator-() +*/ + +/*! \fn QMap::const_iterator QMap::const_iterator::operator-(int j) const + + Returns an iterator to the item at \a j positions backward from + this iterator. (If \a j is negative, the iterator goes forward.) + + This operation can be slow for large \a j values. + + \sa operator+() +*/ + +/*! \fn QMap::const_iterator &QMap::const_iterator::operator+=(int j) + + Advances the iterator by \a j items. (If \a j is negative, the + iterator goes backward.) + + This operation can be slow for large \a j values. + + \sa operator-=(), operator+() +*/ + +/*! \fn QMap::const_iterator &QMap::const_iterator::operator-=(int j) + + Makes the iterator go back by \a j items. (If \a j is negative, + the iterator goes forward.) + + This operation can be slow for large \a j values. + + \sa operator+=(), operator-() +*/ + +/*! \fn QDataStream &operator<<(QDataStream &out, const QMap<Key, T> &map) + \relates QMap + + Writes the map \a map to stream \a out. + + This function requires the key and value types to implement \c + operator<<(). + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +/*! \fn QDataStream &operator>>(QDataStream &in, QMap<Key, T> &map) + \relates QMap + + Reads a map from stream \a in into \a map. + + This function requires the key and value types to implement \c + operator>>(). + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +/*! \class QMultiMap + \brief The QMultiMap class is a convenience QMap subclass that provides multi-valued maps. + + \ingroup tools + \ingroup shared + \mainclass + \reentrant + + QMultiMap\<Key, T\> is one of Qt's generic \l{container classes}. + It inherits QMap and extends it with a few convenience functions + that make it more suitable than QMap for storing multi-valued + maps. A multi-valued map is a map that allows multiple values + with the same key; QMap normally doesn't allow that, unless you + call QMap::insertMulti(). + + Because QMultiMap inherits QMap, all of QMap's functionality also + applies to QMultiMap. For example, you can use isEmpty() to test + whether the map is empty, and you can traverse a QMultiMap using + QMap's iterator classes (for example, QMapIterator). But in + addition, it provides an insert() function that corresponds to + QMap::insertMulti(), and a replace() function that corresponds to + QMap::insert(). It also provides convenient operator+() and + operator+=(). + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 25 + + Unlike QMap, QMultiMap provides no operator[]. Use value() or + replace() if you want to access the most recently inserted item + with a certain key. + + If you want to retrieve all the values for a single key, you can + use values(const Key &key), which returns a QList<T>: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 26 + + The items that share the same key are available from most + recently to least recently inserted. + + If you prefer the STL-style iterators, you can call find() to get + the iterator for the first item with a key and iterate from + there: + + \snippet doc/src/snippets/code/src_corelib_tools_qmap.cpp 27 + + QMultiMap's key and value data types must be \l{assignable data + types}. This covers most data types you are likely to encounter, + but the compiler won't let you, for example, store a QWidget as a + value; instead, store a QWidget *. In addition, QMultiMap's key type + must provide operator<(). See the QMap documentation for details. + + \sa QMap, QMapIterator, QMutableMapIterator, QMultiHash +*/ + +/*! \fn QMultiMap::QMultiMap() + + Constructs an empty map. +*/ + +/*! \fn QMultiMap::QMultiMap(const QMap<Key, T> &other) + + Constructs a copy of \a other (which can be a QMap or a + QMultiMap). + + \sa operator=() +*/ + +/*! \fn QMultiMap::iterator QMultiMap::replace(const Key &key, const T &value) + + Inserts a new item with the key \a key and a value of \a value. + + If there is already an item with the key \a key, that item's value + is replaced with \a value. + + If there are multiple items with the key \a key, the most + recently inserted item's value is replaced with \a value. + + \sa insert() +*/ + +/*! \fn QMultiMap::iterator QMultiMap::insert(const Key &key, const T &value) + + Inserts a new item with the key \a key and a value of \a value. + + If there is already an item with the same key in the map, this + function will simply create a new one. (This behavior is + different from replace(), which overwrites the value of an + existing item.) + + \sa replace() +*/ + +/*! \fn QMultiMap &QMultiMap::operator+=(const QMultiMap &other) + + Inserts all the items in the \a other map into this map and + returns a reference to this map. + + \sa insert(), operator+() +*/ + +/*! \fn QMultiMap QMultiMap::operator+(const QMultiMap &other) const + + Returns a map that contains all the items in this map in + addition to all the items in \a other. If a key is common to both + maps, the resulting map will contain the key multiple times. + + \sa operator+=() +*/ + +/*! + \fn bool QMultiMap::contains(const Key &key, const T &value) const + \since 4.3 + + Returns true if the map contains an item with key \a key and + value \a value; otherwise returns false. + + \sa QMap::contains() +*/ + +/*! + \fn bool QMultiMap::contains(const Key &key) const + \overload + \sa QMap::contains() +*/ + +/*! + \fn int QMultiMap::remove(const Key &key, const T &value) + \since 4.3 + + Removes all the items that have the key \a key and the value \a + value from the map. Returns the number of items removed. + + \sa QMap::remove() +*/ + +/*! + \fn int QMultiMap::remove(const Key &key) + \overload + \sa QMap::remove() +*/ + +/*! + \fn int QMultiMap::count(const Key &key, const T &value) const + \since 4.3 + + Returns the number of items with key \a key and value \a value. + + \sa QMap::count() +*/ + +/*! + \fn int QMultiMap::count(const Key &key) const + \overload + \sa QMap::count() +*/ + +/*! + \fn int QMultiMap::count() const + \overload + \sa QMap::count() +*/ + +/*! + \fn typename QMap<Key, T>::iterator QMultiMap::find(const Key &key, const T &value) + \since 4.3 + + Returns an iterator pointing to the item with key \a key and + value \a value in the map. + + If the map contains no such item, the function returns end(). + + If the map contains multiple items with key \a key, this + function returns an iterator that points to the most recently + inserted value. + + \sa QMap::find() +*/ + +/*! + \fn typename QMap<Key, T>::iterator QMultiMap::find(const Key &key) + \overload + \sa QMap::find() +*/ + +/*! + \fn typename QMap<Key, T>::const_iterator QMultiMap::find(const Key &key, const T &value) const + \since 4.3 + \overload + + Returns a const iterator pointing to the item with the given \a key and + \a value in the map. + + If the map contains no such item, the function returns end(). + + If the map contains multiple items with the specified \a key, this + function returns a const iterator that points to the most recently + inserted value. + + \sa QMap::find() +*/ + +/*! + \fn typename QMap<Key, T>::const_iterator QMultiMap::find(const Key &key) const + \since 4.3 + \overload + \sa QMap::find() +*/ + +/*! + \fn typename QMap<Key, T>::const_iterator QMultiMap::constFind(const Key &key, const T &value) const + \since 4.3 + + Returns an iterator pointing to the item with key \a key and the + value \a value in the map. + + If the map contains no such item, the function returns + constEnd(). + + \sa QMap::constFind() +*/ + +/*! + \fn typename QMap<Key, T>::const_iterator QMultiMap::constFind(const Key &key) const + \overload + \sa QMap::constFind() +*/ + +/*! + \fn T &QMap::iterator::data() const + + Use value() instead. +*/ + +/*! + \fn const T &QMap::const_iterator::data() const + + Use value() instead. +*/ + +/*! + \fn iterator QMap::remove(iterator it) + + Use erase(\a it) instead. +*/ + +/*! + \fn void QMap::erase(const Key &key) + + Use remove(\a key) instead. +*/ + +/*! + \fn iterator QMap::insert(const Key &key, const T &value, bool overwrite); + + Use the two-argument insert() overload instead. If you don't want + to overwrite, call contains() beforehand. + + \oldcode + QMap<QString, int> map; + ... + map.insert("delay", 30000, false); + \newcode + QMap<QString, int> map; + ... + if (!map.contains("delay")) + map.insert("delay", 30000); + \endcode +*/ + +/*! + \fn iterator QMap::replace(const Key &key, const T &value) + + Use remove() then insert(). +*/ + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h new file mode 100644 index 0000000..5f13e5a --- /dev/null +++ b/src/corelib/tools/qmap.h @@ -0,0 +1,1026 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMAP_H +#define QMAP_H + +#include <QtCore/qatomic.h> +#include <QtCore/qiterator.h> +#include <QtCore/qlist.h> + +#ifndef QT_NO_STL +#include <map> +#endif + +#include <new> +#undef QT_MAP_DEBUG + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +struct Q_CORE_EXPORT QMapData +{ + struct Node { + Node *backward; + Node *forward[1]; + }; + enum { LastLevel = 11, Sparseness = 3 }; + + QMapData *backward; + QMapData *forward[QMapData::LastLevel + 1]; + QBasicAtomicInt ref; + int topLevel; + int size; + uint randomBits; + uint insertInOrder : 1; + uint sharable : 1; + + static QMapData *createData(); + void continueFreeData(int offset); + Node *node_create(Node *update[], int offset); + void node_delete(Node *update[], int offset, Node *node); +#ifdef QT_QMAP_DEBUG + uint adjust_ptr(Node *node); + void dump(); +#endif + + static QMapData shared_null; +}; + + +/* + QMap uses qMapLessThanKey() to compare keys. The default + implementation uses operator<(). For pointer types, + qMapLessThanKey() casts the pointers to integers before it + compares them, because operator<() is undefined on pointers + that come from different memory blocks. (In practice, this + is only a problem when running a program such as + BoundsChecker.) +*/ + +template <class Key> inline bool qMapLessThanKey(const Key &key1, const Key &key2) +{ + return key1 < key2; +} + +#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION +template <class Ptr> inline bool qMapLessThanKey(Ptr *key1, Ptr *key2) +{ + Q_ASSERT(sizeof(quintptr) == sizeof(Ptr *)); + return quintptr(key1) < quintptr(key2); +} + +template <class Ptr> inline bool qMapLessThanKey(const Ptr *key1, const Ptr *key2) +{ + Q_ASSERT(sizeof(quintptr) == sizeof(const Ptr *)); + return quintptr(key1) < quintptr(key2); +} +#endif // QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION + +template <class Key, class T> +struct QMapNode { + Key key; + T value; + QMapData::Node *backward; + QMapData::Node *forward[1]; +}; + +template <class Key, class T> +struct QMapPayloadNode +{ + Key key; + T value; + QMapData::Node *backward; +}; + +template <class Key, class T> +class QMap +{ + typedef QMapNode<Key, T> Node; + typedef QMapPayloadNode<Key, T> PayloadNode; + + union { + QMapData *d; + QMapData::Node *e; + }; + + static inline int payload() { return sizeof(PayloadNode) - sizeof(QMapData::Node *); } + static inline Node *concrete(QMapData::Node *node) { + return reinterpret_cast<Node *>(reinterpret_cast<char *>(node) - payload()); + } + +public: + inline QMap() : d(&QMapData::shared_null) { d->ref.ref(); } + inline QMap(const QMap<Key, T> &other) : d(other.d) + { d->ref.ref(); if (!d->sharable) detach(); } + inline ~QMap() { if (!d) return; if (!d->ref.deref()) freeData(d); } + + QMap<Key, T> &operator=(const QMap<Key, T> &other); +#ifndef QT_NO_STL + explicit QMap(const typename std::map<Key, T> &other); + std::map<Key, T> toStdMap() const; +#endif + + bool operator==(const QMap<Key, T> &other) const; + inline bool operator!=(const QMap<Key, T> &other) const { return !(*this == other); } + + inline int size() const { return d->size; } + + inline bool isEmpty() const { return d->size == 0; } + + inline void detach() { if (d->ref != 1) detach_helper(); } + inline bool isDetached() const { return d->ref == 1; } + inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } + inline void setInsertInOrder(bool ordered) { d->insertInOrder = ordered; } + + void clear(); + + int remove(const Key &key); + T take(const Key &key); + + bool contains(const Key &key) const; + const Key key(const T &value) const; + const Key key(const T &value, const Key &defaultKey) const; + const T value(const Key &key) const; + const T value(const Key &key, const T &defaultValue) const; + T &operator[](const Key &key); + const T operator[](const Key &key) const; + + QList<Key> uniqueKeys() const; + QList<Key> keys() const; + QList<Key> keys(const T &value) const; + QList<T> values() const; + QList<T> values(const Key &key) const; + int count(const Key &key) const; + + class const_iterator; + + class iterator + { + friend class const_iterator; + QMapData::Node *i; + + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T *pointer; + typedef T &reference; + + // ### Qt 5: get rid of 'operator Node *' + inline operator QMapData::Node *() const { return i; } + inline iterator() : i(0) { } + inline iterator(QMapData::Node *node) : i(node) { } + + inline const Key &key() const { return concrete(i)->key; } + inline T &value() const { return concrete(i)->value; } +#ifdef QT3_SUPPORT + inline QT3_SUPPORT T &data() const { return concrete(i)->value; } +#endif + inline T &operator*() const { return concrete(i)->value; } + inline T *operator->() const { return &concrete(i)->value; } + inline bool operator==(const iterator &o) const { return i == o.i; } + inline bool operator!=(const iterator &o) const { return i != o.i; } + + inline iterator &operator++() { + i = i->forward[0]; + return *this; + } + inline iterator operator++(int) { + iterator r = *this; + i = i->forward[0]; + return r; + } + inline iterator &operator--() { + i = i->backward; + return *this; + } + inline iterator operator--(int) { + iterator r = *this; + i = i->backward; + return r; + } + inline iterator operator+(int j) const + { iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; } + inline iterator operator-(int j) const { return operator+(-j); } + inline iterator &operator+=(int j) { return *this = *this + j; } + inline iterator &operator-=(int j) { return *this = *this - j; } + + // ### Qt 5: not sure this is necessary anymore +#ifdef QT_STRICT_ITERATORS + private: +#else + public: +#endif + inline bool operator==(const const_iterator &o) const + { return i == o.i; } + inline bool operator!=(const const_iterator &o) const + { return i != o.i; } + + private: + // ### Qt 5: remove + inline operator bool() const { return false; } + }; + friend class iterator; + + class const_iterator + { + friend class iterator; + QMapData::Node *i; + + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef const T *pointer; + typedef const T &reference; + + // ### Qt 5: get rid of 'operator Node *' + inline operator QMapData::Node *() const { return i; } + inline const_iterator() : i(0) { } + inline const_iterator(QMapData::Node *node) : i(node) { } +#ifdef QT_STRICT_ITERATORS + explicit inline const_iterator(const iterator &o) +#else + inline const_iterator(const iterator &o) +#endif + { i = o.i; } + + inline const Key &key() const { return concrete(i)->key; } + inline const T &value() const { return concrete(i)->value; } +#ifdef QT3_SUPPORT + inline QT3_SUPPORT const T &data() const { return concrete(i)->value; } +#endif + inline const T &operator*() const { return concrete(i)->value; } + inline const T *operator->() const { return &concrete(i)->value; } + inline bool operator==(const const_iterator &o) const { return i == o.i; } + inline bool operator!=(const const_iterator &o) const { return i != o.i; } + + inline const_iterator &operator++() { + i = i->forward[0]; + return *this; + } + inline const_iterator operator++(int) { + const_iterator r = *this; + i = i->forward[0]; + return r; + } + inline const_iterator &operator--() { + i = i->backward; + return *this; + } + inline const_iterator operator--(int) { + const_iterator r = *this; + i = i->backward; + return r; + } + inline const_iterator operator+(int j) const + { const_iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; } + inline const_iterator operator-(int j) const { return operator+(-j); } + inline const_iterator &operator+=(int j) { return *this = *this + j; } + inline const_iterator &operator-=(int j) { return *this = *this - j; } + + // ### Qt 5: not sure this is necessary anymore +#ifdef QT_STRICT_ITERATORS + private: + inline bool operator==(const iterator &o) { return operator==(const_iterator(o)); } + inline bool operator!=(const iterator &o) { return operator!=(const_iterator(o)); } +#endif + + private: + // ### Qt 5: remove + inline operator bool() const { return false; } + }; + friend class const_iterator; + + // STL style + inline iterator begin() { detach(); return iterator(e->forward[0]); } + inline const_iterator begin() const { return const_iterator(e->forward[0]); } + inline const_iterator constBegin() const { return const_iterator(e->forward[0]); } + inline iterator end() { + detach(); + return iterator(e); + } + inline const_iterator end() const { return const_iterator(e); } + inline const_iterator constEnd() const { return const_iterator(e); } + iterator erase(iterator it); +#ifdef QT3_SUPPORT + inline QT3_SUPPORT iterator remove(iterator it) { return erase(it); } + inline QT3_SUPPORT void erase(const Key &aKey) { remove(aKey); } +#endif + + // more Qt + typedef iterator Iterator; + typedef const_iterator ConstIterator; + inline int count() const { return d->size; } + iterator find(const Key &key); + const_iterator find(const Key &key) const; + const_iterator constFind(const Key &key) const; + iterator lowerBound(const Key &key); + const_iterator lowerBound(const Key &key) const; + iterator upperBound(const Key &key); + const_iterator upperBound(const Key &key) const; + iterator insert(const Key &key, const T &value); +#ifdef QT3_SUPPORT + QT3_SUPPORT iterator insert(const Key &key, const T &value, bool overwrite); +#endif + iterator insertMulti(const Key &key, const T &value); +#ifdef QT3_SUPPORT + inline QT3_SUPPORT iterator replace(const Key &aKey, const T &aValue) { return insert(aKey, aValue); } +#endif + QMap<Key, T> &unite(const QMap<Key, T> &other); + + // STL compatibility + typedef Key key_type; + typedef T mapped_type; + typedef ptrdiff_t difference_type; + typedef int size_type; + inline bool empty() const { return isEmpty(); } + +#ifdef QT_QMAP_DEBUG + inline void dump() const { d->dump(); } +#endif + +private: + void detach_helper(); + void freeData(QMapData *d); + QMapData::Node *findNode(const Key &key) const; + QMapData::Node *mutableFindNode(QMapData::Node *update[], const Key &key) const; + QMapData::Node *node_create(QMapData *d, QMapData::Node *update[], const Key &key, + const T &value); +}; + +template <class Key, class T> +Q_INLINE_TEMPLATE QMap<Key, T> &QMap<Key, T>::operator=(const QMap<Key, T> &other) +{ + if (d != other.d) { + other.d->ref.ref(); + if (!d->ref.deref()) + freeData(d); + d = other.d; + if (!d->sharable) + detach_helper(); + } + return *this; +} + +template <class Key, class T> +Q_INLINE_TEMPLATE void QMap<Key, T>::clear() +{ + *this = QMap<Key, T>(); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QMapData::Node * +QMap<Key, T>::node_create(QMapData *adt, QMapData::Node *aupdate[], const Key &akey, const T &avalue) +{ + QMapData::Node *abstractNode = adt->node_create(aupdate, payload()); + Node *concreteNode = concrete(abstractNode); + new (&concreteNode->key) Key(akey); + new (&concreteNode->value) T(avalue); + return abstractNode; +} + +template <class Key, class T> +Q_INLINE_TEMPLATE QMapData::Node *QMap<Key, T>::findNode(const Key &akey) const +{ + QMapData::Node *cur = e; + QMapData::Node *next = e; + + for (int i = d->topLevel; i >= 0; i--) { + while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, akey)) + cur = next; + } + + if (next != e && !qMapLessThanKey<Key>(akey, concrete(next)->key)) { + return next; + } else { + return e; + } +} + +template <class Key, class T> +Q_INLINE_TEMPLATE const T QMap<Key, T>::value(const Key &akey) const +{ + QMapData::Node *node; + if (d->size == 0 || (node = findNode(akey)) == e) { + return T(); + } else { + return concrete(node)->value; + } +} + +template <class Key, class T> +Q_INLINE_TEMPLATE const T QMap<Key, T>::value(const Key &akey, const T &adefaultValue) const +{ + QMapData::Node *node; + if (d->size == 0 || (node = findNode(akey)) == e) { + return adefaultValue; + } else { + return concrete(node)->value; + } +} + +template <class Key, class T> +Q_INLINE_TEMPLATE const T QMap<Key, T>::operator[](const Key &akey) const +{ + return value(akey); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE T &QMap<Key, T>::operator[](const Key &akey) +{ + detach(); + + QMapData::Node *update[QMapData::LastLevel + 1]; + QMapData::Node *node = mutableFindNode(update, akey); + if (node == e) + node = node_create(d, update, akey, T()); + return concrete(node)->value; +} + +template <class Key, class T> +Q_INLINE_TEMPLATE int QMap<Key, T>::count(const Key &akey) const +{ + int cnt = 0; + QMapData::Node *node = findNode(akey); + if (node != e) { + do { + ++cnt; + node = node->forward[0]; + } while (node != e && !qMapLessThanKey<Key>(akey, concrete(node)->key)); + } + return cnt; +} + +template <class Key, class T> +Q_INLINE_TEMPLATE bool QMap<Key, T>::contains(const Key &akey) const +{ + return findNode(akey) != e; +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insert(const Key &akey, + const T &avalue) +{ + detach(); + + QMapData::Node *update[QMapData::LastLevel + 1]; + QMapData::Node *node = mutableFindNode(update, akey); + if (node == e) { + node = node_create(d, update, akey, avalue); + } else { + concrete(node)->value = avalue; + } + return iterator(node); +} + +#ifdef QT3_SUPPORT +template <class Key, class T> +Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insert(const Key &akey, + const T &avalue, + bool aoverwrite) +{ + detach(); + + QMapData::Node *update[QMapData::LastLevel + 1]; + QMapData::Node *node = mutableFindNode(update, akey); + if (node == e) { + node = node_create(d, update, akey, avalue); + } else { + if (aoverwrite) + concrete(node)->value = avalue; + } + return iterator(node); +} +#endif + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key &akey, + const T &avalue) +{ + detach(); + + QMapData::Node *update[QMapData::LastLevel + 1]; + mutableFindNode(update, akey); + return iterator(node_create(d, update, akey, avalue)); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator QMap<Key, T>::find(const Key &akey) const +{ + return const_iterator(findNode(akey)); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator QMap<Key, T>::constFind(const Key &akey) const +{ + return const_iterator(findNode(akey)); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::find(const Key &akey) +{ + detach(); + return iterator(findNode(akey)); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE QMap<Key, T> &QMap<Key, T>::unite(const QMap<Key, T> &other) +{ + QMap<Key, T> copy(other); + const_iterator it = copy.constEnd(); + const const_iterator b = copy.constBegin(); + while (it != b) { + --it; + insertMulti(it.key(), it.value()); + } + return *this; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::freeData(QMapData *x) +{ + if (QTypeInfo<Key>::isComplex || QTypeInfo<T>::isComplex) { + QMapData::Node *y = reinterpret_cast<QMapData::Node *>(x); + QMapData::Node *cur = y; + QMapData::Node *next = cur->forward[0]; + while (next != y) { + cur = next; + next = cur->forward[0]; +#if defined(_MSC_VER) && (_MSC_VER >= 1300) +#pragma warning(disable:4189) +#endif + Node *concreteNode = concrete(cur); + concreteNode->key.~Key(); + concreteNode->value.~T(); +#if defined(_MSC_VER) && (_MSC_VER >= 1300) +#pragma warning(default:4189) +#endif + } + } + x->continueFreeData(payload()); +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE int QMap<Key, T>::remove(const Key &akey) +{ + detach(); + + QMapData::Node *update[QMapData::LastLevel + 1]; + QMapData::Node *cur = e; + QMapData::Node *next = e; + int oldSize = d->size; + + for (int i = d->topLevel; i >= 0; i--) { + while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, akey)) + cur = next; + update[i] = cur; + } + + if (next != e && !qMapLessThanKey<Key>(akey, concrete(next)->key)) { + bool deleteNext = true; + do { + cur = next; + next = cur->forward[0]; + deleteNext = (next != e && !qMapLessThanKey<Key>(concrete(cur)->key, concrete(next)->key)); + concrete(cur)->key.~Key(); + concrete(cur)->value.~T(); + d->node_delete(update, payload(), cur); + } while (deleteNext); + } + return oldSize - d->size; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE T QMap<Key, T>::take(const Key &akey) +{ + detach(); + + QMapData::Node *update[QMapData::LastLevel + 1]; + QMapData::Node *cur = e; + QMapData::Node *next = e; + + for (int i = d->topLevel; i >= 0; i--) { + while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, akey)) + cur = next; + update[i] = cur; + } + + if (next != e && !qMapLessThanKey<Key>(akey, concrete(next)->key)) { + T t = concrete(next)->value; + concrete(next)->key.~Key(); + concrete(next)->value.~T(); + d->node_delete(update, payload(), next); + return t; + } + return T(); +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::erase(iterator it) +{ + QMapData::Node *update[QMapData::LastLevel + 1]; + QMapData::Node *cur = e; + QMapData::Node *next = e; + + if (it == iterator(e)) + return it; + + for (int i = d->topLevel; i >= 0; i--) { + while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, it.key())) + cur = next; + update[i] = cur; + } + + while (next != e) { + cur = next; + next = cur->forward[0]; + if (cur == it) { + concrete(cur)->key.~Key(); + concrete(cur)->value.~T(); + d->node_delete(update, payload(), cur); + return iterator(next); + } + + for (int i = 0; i <= d->topLevel; ++i) { + if (update[i]->forward[i] != cur) + break; + update[i] = cur; + } + } + return end(); +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE void QMap<Key, T>::detach_helper() +{ + union { QMapData *d; QMapData::Node *e; } x; + x.d = QMapData::createData(); + if (d->size) { + x.d->insertInOrder = true; + QMapData::Node *update[QMapData::LastLevel + 1]; + QMapData::Node *cur = e->forward[0]; + update[0] = x.e; + while (cur != e) { + Node *concreteNode = concrete(cur); + node_create(x.d, update, concreteNode->key, concreteNode->value); + cur = cur->forward[0]; + } + x.d->insertInOrder = false; + } + if (!d->ref.deref()) + freeData(d); + d = x.d; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE QMapData::Node *QMap<Key, T>::mutableFindNode(QMapData::Node *aupdate[], + const Key &akey) const +{ + QMapData::Node *cur = e; + QMapData::Node *next = e; + + for (int i = d->topLevel; i >= 0; i--) { + while ((next = cur->forward[i]) != e && qMapLessThanKey<Key>(concrete(next)->key, akey)) + cur = next; + aupdate[i] = cur; + } + if (next != e && !qMapLessThanKey<Key>(akey, concrete(next)->key)) { + return next; + } else { + return e; + } +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE QList<Key> QMap<Key, T>::uniqueKeys() const +{ + QList<Key> res; + const_iterator i = begin(); + if (i != end()) { + for (;;) { + const Key &aKey = i.key(); + res.append(aKey); + do { + if (++i == end()) + goto break_out_of_outer_loop; + } while (!(aKey < i.key())); // loop while (key == i.key()) + } + } +break_out_of_outer_loop: + return res; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE QList<Key> QMap<Key, T>::keys() const +{ + QList<Key> res; + const_iterator i = begin(); + while (i != end()) { + res.append(i.key()); + ++i; + } + return res; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE QList<Key> QMap<Key, T>::keys(const T &avalue) const +{ + QList<Key> res; + const_iterator i = begin(); + while (i != end()) { + if (i.value() == avalue) + res.append(i.key()); + ++i; + } + return res; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE const Key QMap<Key, T>::key(const T &avalue) const +{ + return key(avalue, Key()); +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE const Key QMap<Key, T>::key(const T &avalue, const Key &defaultKey) const +{ + const_iterator i = begin(); + while (i != end()) { + if (i.value() == avalue) + return i.key(); + ++i; + } + + return defaultKey; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE QList<T> QMap<Key, T>::values() const +{ + QList<T> res; + const_iterator i = begin(); + while (i != end()) { + res.append(i.value()); + ++i; + } + return res; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE QList<T> QMap<Key, T>::values(const Key &akey) const +{ + QList<T> res; + QMapData::Node *node = findNode(akey); + if (node != e) { + do { + res.append(concrete(node)->value); + node = node->forward[0]; + } while (node != e && !qMapLessThanKey<Key>(akey, concrete(node)->key)); + } + return res; +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator +QMap<Key, T>::lowerBound(const Key &akey) const +{ + QMapData::Node *update[QMapData::LastLevel + 1]; + mutableFindNode(update, akey); + return const_iterator(update[0]->forward[0]); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::lowerBound(const Key &akey) +{ + detach(); + return static_cast<QMapData::Node *>(const_cast<const QMap *>(this)->lowerBound(akey)); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QMap<Key, T>::const_iterator +QMap<Key, T>::upperBound(const Key &akey) const +{ + QMapData::Node *update[QMapData::LastLevel + 1]; + mutableFindNode(update, akey); + QMapData::Node *node = update[0]->forward[0]; + while (node != e && !qMapLessThanKey<Key>(akey, concrete(node)->key)) + node = node->forward[0]; + return const_iterator(node); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE typename QMap<Key, T>::iterator QMap<Key, T>::upperBound(const Key &akey) +{ + detach(); + return static_cast<QMapData::Node *>(const_cast<const QMap *>(this)->upperBound(akey)); +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE bool QMap<Key, T>::operator==(const QMap<Key, T> &other) const +{ + if (size() != other.size()) + return false; + if (d == other.d) + return true; + + const_iterator it1 = begin(); + const_iterator it2 = other.begin(); + + while (it1 != end()) { + if (!(it1.value() == it2.value()) || qMapLessThanKey(it1.key(), it2.key()) || qMapLessThanKey(it2.key(), it1.key())) + return false; + ++it2; + ++it1; + } + return true; +} + +#ifndef QT_NO_STL +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE QMap<Key, T>::QMap(const std::map<Key, T> &other) +{ + d = QMapData::createData(); + d->insertInOrder = true; + typename std::map<Key,T>::const_iterator it = other.end(); + while (it != other.begin()) { + --it; + insert((*it).first, (*it).second); + } + d->insertInOrder = false; +} + +template <class Key, class T> +Q_OUTOFLINE_TEMPLATE std::map<Key, T> QMap<Key, T>::toStdMap() const +{ + std::map<Key, T> map; + const_iterator it = end(); + while (it != begin()) { + --it; + map.insert(std::pair<Key, T>(it.key(), it.value())); + } + return map; +} + +#endif // QT_NO_STL + +template <class Key, class T> +class QMultiMap : public QMap<Key, T> +{ +public: + QMultiMap() {} + QMultiMap(const QMap<Key, T> &other) : QMap<Key, T>(other) {} + + inline typename QMap<Key, T>::iterator replace(const Key &key, const T &value) + { return QMap<Key, T>::insert(key, value); } + inline typename QMap<Key, T>::iterator insert(const Key &key, const T &value) + { return QMap<Key, T>::insertMulti(key, value); } + + inline QMultiMap &operator+=(const QMultiMap &other) + { unite(other); return *this; } + inline QMultiMap operator+(const QMultiMap &other) const + { QMultiMap result = *this; result += other; return result; } + +#ifndef Q_NO_USING_KEYWORD + using QMap<Key, T>::contains; + using QMap<Key, T>::remove; + using QMap<Key, T>::count; + using QMap<Key, T>::find; + using QMap<Key, T>::constFind; +#else + inline bool contains(const Key &key) const + { return QMap<Key, T>::contains(key); } + inline int remove(const Key &key) + { return QMap<Key, T>::remove(key); } + inline int count(const Key &key) const + { return QMap<Key, T>::count(key); } + inline int count() const + { return QMap<Key, T>::count(); } + inline typename QMap<Key, T>::iterator find(const Key &key) + { return QMap<Key, T>::find(key); } + inline typename QMap<Key, T>::const_iterator find(const Key &key) const + { return QMap<Key, T>::find(key); } + inline typename QMap<Key, T>::const_iterator constFind(const Key &key) const + { return QMap<Key, T>::constFind(key); } +#endif + + bool contains(const Key &key, const T &value) const; + + int remove(const Key &key, const T &value); + + int count(const Key &key, const T &value) const; + + typename QMap<Key, T>::iterator find(const Key &key, const T &value) { + typename QMap<Key, T>::iterator i(find(key)); + typename QMap<Key, T>::iterator end(this->end()); + while (i != end && !qMapLessThanKey<Key>(key, i.key())) { + if (i.value() == value) + return i; + ++i; + } + return end; + } + typename QMap<Key, T>::const_iterator find(const Key &key, const T &value) const { + typename QMap<Key, T>::const_iterator i(constFind(key)); + typename QMap<Key, T>::const_iterator end(QMap<Key, T>::constEnd()); + while (i != end && !qMapLessThanKey<Key>(key, i.key())) { + if (i.value() == value) + return i; + ++i; + } + return end; + } + typename QMap<Key, T>::const_iterator constFind(const Key &key, const T &value) const + { return find(key, value); } +private: + T &operator[](const Key &key); + const T operator[](const Key &key) const; +}; + +template <class Key, class T> +Q_INLINE_TEMPLATE bool QMultiMap<Key, T>::contains(const Key &key, const T &value) const +{ + return constFind(key, value) != QMap<Key, T>::constEnd(); +} + +template <class Key, class T> +Q_INLINE_TEMPLATE int QMultiMap<Key, T>::remove(const Key &key, const T &value) +{ + int n = 0; + typename QMap<Key, T>::iterator i(find(key)); + typename QMap<Key, T>::const_iterator end(QMap<Key, T>::constEnd()); + while (i != end && !qMapLessThanKey<Key>(key, i.key())) { + if (i.value() == value) { + i = erase(i); + ++n; + } else { + ++i; + } + } + return n; +} + +template <class Key, class T> +Q_INLINE_TEMPLATE int QMultiMap<Key, T>::count(const Key &key, const T &value) const +{ + int n = 0; + typename QMap<Key, T>::const_iterator i(constFind(key)); + typename QMap<Key, T>::const_iterator end(QMap<Key, T>::constEnd()); + while (i != end && !qMapLessThanKey<Key>(key, i.key())) { + if (i.value() == value) + ++n; + ++i; + } + return n; +} + +Q_DECLARE_ASSOCIATIVE_ITERATOR(Map) +Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Map) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMAP_H diff --git a/src/corelib/tools/qpair.h b/src/corelib/tools/qpair.h new file mode 100644 index 0000000..24088e4 --- /dev/null +++ b/src/corelib/tools/qpair.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPAIR_H +#define QPAIR_H + +#include <QtCore/qdatastream.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +template <class T1, class T2> +struct QPair +{ + typedef T1 first_type; + typedef T2 second_type; + + QPair() : first(T1()), second(T2()) {} + QPair(const T1 &t1, const T2 &t2) : first(t1), second(t2) {} + + QPair<T1, T2> &operator=(const QPair<T1, T2> &other) + { first = other.first; second = other.second; return *this; } + + T1 first; + T2 second; +}; + +template <class T1, class T2> +Q_INLINE_TEMPLATE bool operator==(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2) +{ return p1.first == p2.first && p1.second == p2.second; } + +template <class T1, class T2> +Q_INLINE_TEMPLATE bool operator!=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2) +{ return !(p1 == p2); } + +template <class T1, class T2> +Q_INLINE_TEMPLATE bool operator<(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2) +{ + return p1.first < p2.first || (!(p2.first < p1.first) && p1.second < p2.second); +} + +template <class T1, class T2> +Q_INLINE_TEMPLATE bool operator>(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2) +{ + return p2 < p1; +} + +template <class T1, class T2> +Q_INLINE_TEMPLATE bool operator<=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2) +{ + return !(p2 < p1); +} + +template <class T1, class T2> +Q_INLINE_TEMPLATE bool operator>=(const QPair<T1, T2> &p1, const QPair<T1, T2> &p2) +{ + return !(p1 < p2); +} + +template <class T1, class T2> +Q_OUTOFLINE_TEMPLATE QPair<T1, T2> qMakePair(const T1 &x, const T2 &y) +{ + return QPair<T1, T2>(x, y); +} + +#ifndef QT_NO_DATASTREAM +template <class T1, class T2> +inline QDataStream& operator>>(QDataStream& s, QPair<T1, T2>& p) +{ + s >> p.first >> p.second; + return s; +} + +template <class T1, class T2> +inline QDataStream& operator<<(QDataStream& s, const QPair<T1, T2>& p) +{ + s << p.first << p.second; + return s; +} +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPAIR_H diff --git a/src/corelib/tools/qpodlist_p.h b/src/corelib/tools/qpodlist_p.h new file mode 100644 index 0000000..9708f8d --- /dev/null +++ b/src/corelib/tools/qpodlist_p.h @@ -0,0 +1,263 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPODLIST_P_H +#define QPODLIST_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qcontainerfwd.h> +#include <QtCore/qglobal.h> +#include <new> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +template<class T, int Prealloc> +class QPodList +{ +public: + inline explicit QPodList(int size = 0); + + inline QPodList(const QPodList<T, Prealloc> &other) + : a(Prealloc), s(0), ptr(reinterpret_cast<T *>(array)) + { + append(other.constData(), other.size()); + } + + inline ~QPodList() { + if (ptr != reinterpret_cast<T *>(array)) + qFree(ptr); + } + inline QPodList<T, Prealloc> &operator=(const QPodList<T, Prealloc> &other) + { + if (this != &other) { + clear(); + append(other.constData(), other.size()); + } + return *this; + } + + inline int size() const { return s; } + inline int count() const { return s; } + inline bool isEmpty() const { return (s == 0); } + inline void resize(int size); + inline void clear() { resize(0); } + + inline int capacity() const { return a; } + inline void reserve(int size); + + inline T &operator[](int idx) { + Q_ASSERT(idx >= 0 && idx < s); + return ptr[idx]; + } + inline const T &operator[](int idx) const { + Q_ASSERT(idx >= 0 && idx < s); + return ptr[idx]; + } + + inline const T &at(int idx) const { + Q_ASSERT(idx >= 0 && idx < s); + return ptr[idx]; + } + + inline const T &first() const { + return at(0); + } + + inline T& append() { + const int idx = s++; + if (s == a) + realloc(s, s<<1); + return ptr[idx]; + } + inline void append(const T &t) { + append() = t; + } + + inline T& insert(int idx) { + Q_ASSERT(idx >= 0 && idx <= s); + const int sz = s++; + if (s == a) + realloc(s, s<<1); + ::memmove(ptr + idx + 1, ptr + idx, (sz - idx) * sizeof(T)); + return ptr[idx]; + } + inline void insert(int idx, const T &t) { + insert(idx) = t; + } + + inline void removeAt(int idx) { + Q_ASSERT(idx >= 0 && idx < s); + ::memmove(ptr + idx, ptr + idx + 1, (s - idx - 1) * sizeof(T)); + --s; + } + + inline void removeAll(const T &t) { + int i = 0; + for (int j = 0; j < s; ++j) { + if (ptr[j] != t) + ptr[i++] = ptr[j]; + } + s = i; + } + + inline int indexOf(const T &t, int from = 0) const { + if (from < 0) + from = qMax(from + s, 0); + if (from < s) { + const T *n = ptr + from - 1; + const T *e = ptr + s; + while (++n != e) + if (*n == t) + return n - ptr; + } + return -1; + } + + inline bool contains(const T &t) const { + return indexOf(t) >= 0; + } + + inline T takeFirst() { + Q_ASSERT(s > 0); + T tmp = ptr[0]; + removeAt(0); + return tmp; + } + + inline T *data() { return ptr; } + inline const T *data() const { return ptr; } + inline const T * constData() const { return ptr; } + +private: + void append(const T *buf, int size); + void realloc(int size, int alloc); + + int a; + int s; + T *ptr; + union { + // ### Qt 5: Use 'Prealloc * sizeof(T)' as array size + char array[sizeof(qint64) * (((Prealloc * sizeof(T)) / sizeof(qint64)) + 1)]; + qint64 q_for_alignment_1; + double q_for_alignment_2; + }; +}; + +template <class T, int Prealloc> +Q_INLINE_TEMPLATE QPodList<T, Prealloc>::QPodList(int asize) + : s(asize) { + if (s > Prealloc) { + ptr = reinterpret_cast<T *>(qMalloc(s * sizeof(T))); + a = s; + } else { + ptr = reinterpret_cast<T *>(array); + a = Prealloc; + } +} + +template <class T, int Prealloc> +Q_INLINE_TEMPLATE void QPodList<T, Prealloc>::resize(int asize) +{ realloc(asize, qMax(asize, a)); } + +template <class T, int Prealloc> +Q_INLINE_TEMPLATE void QPodList<T, Prealloc>::reserve(int asize) +{ if (asize > a) realloc(s, asize); } + +template <class T, int Prealloc> +Q_OUTOFLINE_TEMPLATE void QPodList<T, Prealloc>::append(const T *abuf, int asize) +{ + Q_ASSERT(abuf); + if (asize <= 0) + return; + + const int idx = s; + const int news = s + asize; + if (news >= a) + realloc(news, news<<1); + else + s = news; + + qMemCopy(&ptr[idx], abuf, asize * sizeof(T)); +} + +template <class T, int Prealloc> +Q_OUTOFLINE_TEMPLATE void QPodList<T, Prealloc>::realloc(int asize, int aalloc) +{ + Q_ASSERT(aalloc >= asize); + T *oldPtr = ptr; + int osize = s; + s = asize; + + if (aalloc != a) { + ptr = reinterpret_cast<T *>(qMalloc(aalloc * sizeof(T))); + if (ptr) { + a = aalloc; + qMemCopy(ptr, oldPtr, osize * sizeof(T)); + } else { + ptr = oldPtr; + s = 0; + asize = 0; + } + } + + if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr) + qFree(oldPtr); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPODLIST_P_H diff --git a/src/corelib/tools/qpoint.cpp b/src/corelib/tools/qpoint.cpp new file mode 100644 index 0000000..feea473 --- /dev/null +++ b/src/corelib/tools/qpoint.cpp @@ -0,0 +1,665 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qpoint.h" +#include "qdatastream.h" +#include "qdebug.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QPoint + \ingroup multimedia + + \brief The QPoint class defines a point in the plane using integer + precision. + + A point is specified by a x coordinate and an y coordinate which + can be accessed using the x() and y() functions. The isNull() + function returns true if both x and y are set to 0. The + coordinates can be set (or altered) using the setX() and setY() + functions, or alternatively the rx() and ry() functions which + return references to the coordinates (allowing direct + manipulation). + + Given a point \e p, the following statements are all equivalent: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 0 + + A QPoint object can also be used as a vector: Addition and + subtraction are defined as for vectors (each component is added + separately). A QPoint object can also be divided or multiplied by + an \c int or a \c qreal. + + In addition, the QPoint class provides the manhattanLength() + function which gives an inexpensive approximation of the length of + the QPoint object interpreted as a vector. Finally, QPoint objects + can be streamed as well as compared. + + \sa QPointF, QPolygon +*/ + + +/***************************************************************************** + QPoint member functions + *****************************************************************************/ + +/*! + \fn QPoint::QPoint() + + Constructs a null point, i.e. with coordinates (0, 0) + + \sa isNull() +*/ + +/*! + \fn QPoint::QPoint(int x, int y) + + Constructs a point with the given coordinates (\a x, \a y). + + \sa setX(), setY() +*/ + +/*! + \fn bool QPoint::isNull() const + + Returns true if both the x and y coordinates are set to 0, + otherwise returns false. +*/ + +/*! + \fn int QPoint::x() const + + Returns the x coordinate of this point. + + \sa setX(), rx() +*/ + +/*! + \fn int QPoint::y() const + + Returns the y coordinate of this point. + + \sa setY(), ry() +*/ + +/*! + \fn void QPoint::setX(int x) + + Sets the x coordinate of this point to the given \a x coordinate. + + \sa x() setY() +*/ + +/*! + \fn void QPoint::setY(int y) + + Sets the y coordinate of this point to the given \a y coordinate. + + \sa y() setX() +*/ + + +/*! + \fn int &QPoint::rx() + + Returns a reference to the x coordinate of this point. + + Using a reference makes it possible to directly manipulate x. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 1 + + \sa x() setX() +*/ + +/*! + \fn int &QPoint::ry() + + Returns a reference to the y coordinate of this point. + + Using a reference makes it possible to directly manipulate y. For + example: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 2 + + \sa y(), setY() +*/ + + +/*! + \fn QPoint &QPoint::operator+=(const QPoint &point) + + Adds the given \a point to this point and returns a reference to + this point. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 3 + + \sa operator-=() +*/ + +/*! + \fn QPoint &QPoint::operator-=(const QPoint &point) + + Subtracts the given \a point from this point and returns a + reference to this point. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 4 + + \sa operator+=() +*/ + +/*! + \fn QPoint &QPoint::operator*=(qreal factor) + + Multiplies this point's coordinates by the given \a factor, and + returns a reference to this point. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 5 + + Note that the result is rounded to the nearest integer as points are held as + integers. Use QPointF for floating point accuracy. + + \sa operator/=() +*/ + + +/*! + \fn bool operator==(const QPoint &p1, const QPoint &p2) + \relates QPoint + + Returns true if \a p1 and \a p2 are equal; otherwise returns + false. +*/ + +/*! + \fn bool operator!=(const QPoint &p1, const QPoint &p2) + \relates QPoint + + Returns true if \a p1 and \a p2 are not equal; otherwise returns false. +*/ + +/*! + \fn const QPoint operator+(const QPoint &p1, const QPoint &p2) + \relates QPoint + + Returns a QPoint object that is the sum of the given points, \a p1 + and \a p2; each component is added separately. + + \sa QPoint::operator+=() +*/ + +/*! + \fn const QPoint operator-(const QPoint &p1, const QPoint &p2) + \relates QPoint + + Returns a QPoint object that is formed by subtracting \a p2 from + \a p1; each component is subtracted separately. + + \sa QPoint::operator-=() +*/ + +/*! + \fn const QPoint operator*(const QPoint &point, qreal factor) + \relates QPoint + + Returns a copy of the given \a point multiplied by the given \a factor. + + Note that the result is rounded to the nearest integer as points + are held as integers. Use QPointF for floating point accuracy. + + \sa QPoint::operator*=() +*/ + +/*! + \fn const QPoint operator*(qreal factor, const QPoint &point) + \overload + \relates QPoint + + Returns a copy of the given \a point multiplied by the given \a factor. +*/ + +/*! + \fn const QPoint operator-(const QPoint &point) + \overload + \relates QPoint + + Returns a QPoint object that is formed by changing the sign of + both components of the given \a point. + + Equivalent to \c{QPoint(0,0) - point}. +*/ + +/*! + \fn QPoint &QPoint::operator/=(qreal divisor) + \overload + + Divides both x and y by the given \a divisor, and returns a reference to this + point. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 6 + + Note that the result is rounded to the nearest integer as points are held as + integers. Use QPointF for floating point accuracy. + + \sa operator*=() +*/ + +/*! + \fn const QPoint operator/(const QPoint &point, qreal divisor) + \relates QPoint + + Returns the QPoint formed by dividing both components of the given \a point + by the given \a divisor. + + Note that the result is rounded to the nearest integer as points are held as + integers. Use QPointF for floating point accuracy. + + \sa QPoint::operator/=() +*/ + +/***************************************************************************** + QPoint stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QPoint &point) + \relates QPoint + + Writes the given \a point to the given \a stream and returns a + reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator<<(QDataStream &s, const QPoint &p) +{ + if (s.version() == 1) + s << (qint16)p.x() << (qint16)p.y(); + else + s << (qint32)p.x() << (qint32)p.y(); + return s; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QPoint &point) + \relates QPoint + + Reads a point from the given \a stream into the given \a point + and returns a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator>>(QDataStream &s, QPoint &p) +{ + if (s.version() == 1) { + qint16 x, y; + s >> x; p.rx() = x; + s >> y; p.ry() = y; + } + else { + qint32 x, y; + s >> x; p.rx() = x; + s >> y; p.ry() = y; + } + return s; +} + +#endif // QT_NO_DATASTREAM +/*! + Returns the sum of the absolute values of x() and y(), + traditionally known as the "Manhattan length" of the vector from + the origin to the point. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 7 + + This is a useful, and quick to calculate, approximation to the + true length: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 8 + + The tradition of "Manhattan length" arises because such distances + apply to travelers who can only travel on a rectangular grid, like + the streets of Manhattan. +*/ +int QPoint::manhattanLength() const +{ + return qAbs(x())+qAbs(y()); +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QPoint &p) { + dbg.nospace() << "QPoint(" << p.x() << ',' << p.y() << ')'; + return dbg.space(); +} + +QDebug operator<<(QDebug d, const QPointF &p) +{ + d.nospace() << "QPointF(" << p.x() << ", " << p.y() << ")"; + return d; +} +#endif + +/*! + \class QPointF + \ingroup multimedia + + \brief The QPointF class defines a point in the plane using + floating point precision. + + A point is specified by a x coordinate and an y coordinate which + can be accessed using the x() and y() functions. The coordinates + of the point are specified using floating point numbers for + accuracy. The isNull() function returns true if both x and y are + set to 0.0. The coordinates can be set (or altered) using the setX() + and setY() functions, or alternatively the rx() and ry() functions which + return references to the coordinates (allowing direct + manipulation). + + Given a point \e p, the following statements are all equivalent: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 9 + + A QPointF object can also be used as a vector: Addition and + subtraction are defined as for vectors (each component is added + separately). A QPointF object can also be divided or multiplied by + an \c int or a \c qreal. + + In addition, the QPointF class provides a constructor converting a + QPoint object into a QPointF object, and a corresponding toPoint() + function which returns a QPoint copy of \e this point. Finally, + QPointF objects can be streamed as well as compared. + + \sa QPoint, QPolygonF +*/ + +/*! + \fn QPointF::QPointF() + + Constructs a null point, i.e. with coordinates (0.0, 0.0) + + \sa isNull() +*/ + +/*! + \fn QPointF::QPointF(const QPoint &point) + + Constructs a copy of the given \a point. + + \sa toPoint() +*/ + +/*! + \fn QPointF::QPointF(qreal x, qreal y) + + Constructs a point with the given coordinates (\a x, \a y). + + \sa setX(), setY() +*/ + +/*! + \fn bool QPointF::isNull() const + + Returns true if both the x and y coordinates are set to 0.0, + otherwise returns false. +*/ + +/*! + \fn qreal QPointF::x() const + + Returns the x-coordinate of this point. + + \sa setX(), rx() +*/ + +/*! + \fn qreal QPointF::y() const + + Returns the y-coordinate of this point. + + \sa setY(), ry() +*/ + +/*! + \fn void QPointF::setX(qreal x) + + Sets the x coordinate of this point to the given \a x coordinate. + + \sa x() setY() +*/ + +/*! + \fn void QPointF::setY(qreal y) + + Sets the y coordinate of this point to the given \a y coordinate. + + \sa y(), setX() +*/ + +/*! + \fn qreal& QPointF::rx() + + Returns a reference to the x coordinate of this point. + + Using a reference makes it possible to directly manipulate x. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 10 + + \sa x(), setX() +*/ + +/*! + \fn qreal& QPointF::ry() + + Returns a reference to the y coordinate of this point. + + Using a reference makes it possible to directly manipulate y. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 11 + + \sa y() setY() +*/ + +/*! + \fn QPointF& QPointF::operator+=(const QPointF &point) + + Adds the given \a point to this point and returns a reference to + this point. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 12 + + \sa operator-=() +*/ + +/*! + \fn QPointF& QPointF::operator-=(const QPointF &point) + + Subtracts the given \a point from this point and returns a reference + to this point. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 13 + + \sa operator+=() +*/ + +/*! + \fn QPointF& QPointF::operator*=(qreal factor) + + Multiplies this point's coordinates by the given \a factor, and + returns a reference to this point. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 14 + + \sa operator/=() +*/ + +/*! + \fn QPointF& QPointF::operator/=(qreal divisor) + + Divides both x and y by the given \a divisor, and returns a reference + to this point. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qpoint.cpp 15 + + \sa operator*=() +*/ + +/*! + \fn const QPointF operator+(const QPointF &p1, const QPointF &p2) + \relates QPointF + + Returns a QPointF object that is the sum of the given points, \a p1 + and \a p2; each component is added separately. + + \sa QPointF::operator+=() +*/ + +/*! + \fn const QPointF operator-(const QPointF &p1, const QPointF &p2) + \relates QPointF + + Returns a QPointF object that is formed by subtracting \a p2 from \a p1; + each component is subtracted separately. + + \sa QPointF::operator-=() +*/ + +/*! + \fn const QPointF operator*(const QPointF &point, qreal factor) + \relates QPointF + + Returns a copy of the given \a point, multiplied by the given \a factor. + + \sa QPointF::operator*=() +*/ + +/*! + \fn const QPointF operator*(qreal factor, const QPointF &point) + \relates QPointF + + \overload + + Returns a copy of the given \a point, multiplied by the given \a factor. +*/ + +/*! + \fn const QPointF operator-(const QPointF &point) + \relates QPointF + \overload + + Returns a QPointF object that is formed by changing the sign of + both components of the given \a point. + + Equivalent to \c {QPointF(0,0) - point}. +*/ + +/*! + \fn const QPointF operator/(const QPointF &point, qreal divisor) + \relates QPointF + + Returns the QPointF object formed by dividing both components of + the given \a point by the given \a divisor. + + \sa QPointF::operator/=() +*/ + +/*! + \fn QPoint QPointF::toPoint() const + + Rounds the coordinates of this point to the nearest integer, and + returns a QPoint object with the rounded coordinates. + + \sa QPointF() +*/ + +/*! + \fn bool operator==(const QPointF &p1, const QPointF &p2) + \relates QPointF + + Returns true if \a p1 is equal to \a p2; otherwise returns false. +*/ + +/*! + \fn bool operator!=(const QPointF &p1, const QPointF &p2); + \relates QPointF + + Returns true if \a p1 is not equal to \a p2; otherwise returns false. +*/ + +#ifndef QT_NO_DATASTREAM +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QPointF &point) + \relates QPointF + + Writes the given \a point to the given \a stream and returns a + reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator<<(QDataStream &s, const QPointF &p) +{ + s << double(p.x()) << double(p.y()); + return s; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QPointF &point) + \relates QPointF + + Reads a point from the given \a stream into the given \a point + and returns a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator>>(QDataStream &s, QPointF &p) +{ + double x, y; + s >> x; + s >> y; + p.setX(qreal(x)); + p.setY(qreal(y)); + return s; +} +#endif // QT_NO_DATASTREAM + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h new file mode 100644 index 0000000..1dab7e2 --- /dev/null +++ b/src/corelib/tools/qpoint.h @@ -0,0 +1,361 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPOINT_H +#define QPOINT_H + +#include <QtCore/qnamespace.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class Q_CORE_EXPORT QPoint +{ +public: + QPoint(); + QPoint(int xpos, int ypos); + + bool isNull() const; + + int x() const; + int y() const; + void setX(int x); + void setY(int y); + + int manhattanLength() const; + + int &rx(); + int &ry(); + + QPoint &operator+=(const QPoint &p); + QPoint &operator-=(const QPoint &p); + QPoint &operator*=(qreal c); + QPoint &operator/=(qreal c); + + friend inline bool operator==(const QPoint &, const QPoint &); + friend inline bool operator!=(const QPoint &, const QPoint &); + friend inline const QPoint operator+(const QPoint &, const QPoint &); + friend inline const QPoint operator-(const QPoint &, const QPoint &); + friend inline const QPoint operator*(const QPoint &, qreal); + friend inline const QPoint operator*(qreal, const QPoint &); + friend inline const QPoint operator-(const QPoint &); + friend inline const QPoint operator/(const QPoint &, qreal); + +private: + friend class QTransform; + // ### Qt 5; remove the ifdef and just have the same order on all platforms. +#if defined(Q_OS_MAC) + int yp; + int xp; +#else + int xp; + int yp; +#endif +}; + +Q_DECLARE_TYPEINFO(QPoint, Q_MOVABLE_TYPE); + +/***************************************************************************** + QPoint stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QPoint &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QPoint &); +#endif + +/***************************************************************************** + QPoint inline functions + *****************************************************************************/ + +inline QPoint::QPoint() +{ xp=0; yp=0; } + +inline QPoint::QPoint(int xpos, int ypos) +{ xp = xpos; yp = ypos; } + +inline bool QPoint::isNull() const +{ return xp == 0 && yp == 0; } + +inline int QPoint::x() const +{ return xp; } + +inline int QPoint::y() const +{ return yp; } + +inline void QPoint::setX(int xpos) +{ xp = xpos; } + +inline void QPoint::setY(int ypos) +{ yp = ypos; } + +inline int &QPoint::rx() +{ return xp; } + +inline int &QPoint::ry() +{ return yp; } + +inline QPoint &QPoint::operator+=(const QPoint &p) +{ xp+=p.xp; yp+=p.yp; return *this; } + +inline QPoint &QPoint::operator-=(const QPoint &p) +{ xp-=p.xp; yp-=p.yp; return *this; } + +inline QPoint &QPoint::operator*=(qreal c) +{ xp = qRound(xp*c); yp = qRound(yp*c); return *this; } + +inline bool operator==(const QPoint &p1, const QPoint &p2) +{ return p1.xp == p2.xp && p1.yp == p2.yp; } + +inline bool operator!=(const QPoint &p1, const QPoint &p2) +{ return p1.xp != p2.xp || p1.yp != p2.yp; } + +inline const QPoint operator+(const QPoint &p1, const QPoint &p2) +{ return QPoint(p1.xp+p2.xp, p1.yp+p2.yp); } + +inline const QPoint operator-(const QPoint &p1, const QPoint &p2) +{ return QPoint(p1.xp-p2.xp, p1.yp-p2.yp); } + +inline const QPoint operator*(const QPoint &p, qreal c) +{ return QPoint(qRound(p.xp*c), qRound(p.yp*c)); } + +inline const QPoint operator*(qreal c, const QPoint &p) +{ return QPoint(qRound(p.xp*c), qRound(p.yp*c)); } + +inline const QPoint operator-(const QPoint &p) +{ return QPoint(-p.xp, -p.yp); } + +inline QPoint &QPoint::operator/=(qreal c) +{ + xp = qRound(xp/c); + yp = qRound(yp/c); + return *this; +} + +inline const QPoint operator/(const QPoint &p, qreal c) +{ + return QPoint(qRound(p.xp/c), qRound(p.yp/c)); +} + +#ifndef QT_NO_DEBUG_STREAM +Q_CORE_EXPORT QDebug operator<<(QDebug, const QPoint &); +#endif + + + + + +class Q_CORE_EXPORT QPointF +{ +public: + QPointF(); + QPointF(const QPoint &p); + QPointF(qreal xpos, qreal ypos); + + bool isNull() const; + + qreal x() const; + qreal y() const; + void setX(qreal x); + void setY(qreal y); + + qreal &rx(); + qreal &ry(); + + QPointF &operator+=(const QPointF &p); + QPointF &operator-=(const QPointF &p); + QPointF &operator*=(qreal c); + QPointF &operator/=(qreal c); + + friend inline bool operator==(const QPointF &, const QPointF &); + friend inline bool operator!=(const QPointF &, const QPointF &); + friend inline const QPointF operator+(const QPointF &, const QPointF &); + friend inline const QPointF operator-(const QPointF &, const QPointF &); + friend inline const QPointF operator*(qreal, const QPointF &); + friend inline const QPointF operator*(const QPointF &, qreal); + friend inline const QPointF operator-(const QPointF &); + friend inline const QPointF operator/(const QPointF &, qreal); + + QPoint toPoint() const; + +private: + friend class QMatrix; + friend class QTransform; + + qreal xp; + qreal yp; +}; + +Q_DECLARE_TYPEINFO(QPointF, Q_MOVABLE_TYPE); + +/***************************************************************************** + QPointF stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QPointF &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QPointF &); +#endif + +/***************************************************************************** + QPointF inline functions + *****************************************************************************/ + +inline QPointF::QPointF() : xp(0), yp(0) { } + +inline QPointF::QPointF(qreal xpos, qreal ypos) : xp(xpos), yp(ypos) { } + +inline QPointF::QPointF(const QPoint &p) : xp(p.x()), yp(p.y()) { } + +inline bool QPointF::isNull() const +{ + return qIsNull(xp) && qIsNull(yp); +} + +inline qreal QPointF::x() const +{ + return xp; +} + +inline qreal QPointF::y() const +{ + return yp; +} + +inline void QPointF::setX(qreal xpos) +{ + xp = xpos; +} + +inline void QPointF::setY(qreal ypos) +{ + yp = ypos; +} + +inline qreal &QPointF::rx() +{ + return xp; +} + +inline qreal &QPointF::ry() +{ + return yp; +} + +inline QPointF &QPointF::operator+=(const QPointF &p) +{ + xp+=p.xp; + yp+=p.yp; + return *this; +} + +inline QPointF &QPointF::operator-=(const QPointF &p) +{ + xp-=p.xp; yp-=p.yp; return *this; +} + +inline QPointF &QPointF::operator*=(qreal c) +{ + xp*=c; yp*=c; return *this; +} + +inline bool operator==(const QPointF &p1, const QPointF &p2) +{ + return qFuzzyCompare(p1.xp, p2.xp) && qFuzzyCompare(p1.yp, p2.yp); +} + +inline bool operator!=(const QPointF &p1, const QPointF &p2) +{ + return !qFuzzyCompare(p1.xp, p2.xp) || !qFuzzyCompare(p1.yp, p2.yp); +} + +inline const QPointF operator+(const QPointF &p1, const QPointF &p2) +{ + return QPointF(p1.xp+p2.xp, p1.yp+p2.yp); +} + +inline const QPointF operator-(const QPointF &p1, const QPointF &p2) +{ + return QPointF(p1.xp-p2.xp, p1.yp-p2.yp); +} + +inline const QPointF operator*(const QPointF &p, qreal c) +{ + return QPointF(p.xp*c, p.yp*c); +} + +inline const QPointF operator*(qreal c, const QPointF &p) +{ + return QPointF(p.xp*c, p.yp*c); +} + +inline const QPointF operator-(const QPointF &p) +{ + return QPointF(-p.xp, -p.yp); +} + +inline QPointF &QPointF::operator/=(qreal c) +{ + xp/=c; + yp/=c; + return *this; +} + +inline const QPointF operator/(const QPointF &p, qreal c) +{ + return QPointF(p.xp/c, p.yp/c); +} + +inline QPoint QPointF::toPoint() const +{ + return QPoint(qRound(xp), qRound(yp)); +} + +#ifndef QT_NO_DEBUG_STREAM +Q_CORE_EXPORT QDebug operator<<(QDebug d, const QPointF &p); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPOINT_H diff --git a/src/corelib/tools/qqueue.cpp b/src/corelib/tools/qqueue.cpp new file mode 100644 index 0000000..de16f8c --- /dev/null +++ b/src/corelib/tools/qqueue.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QQueue + \brief The QQueue class is a generic container that provides a queue. + + \ingroup tools + \ingroup shared + \mainclass + \reentrant + + QQueue\<T\> is one of Qt's generic \l{container classes}. It + implements a queue data structure for items of a same type. + + A queue is a first in, first out (FIFO) structure. Items are + added to the tail of the queue using enqueue() and retrieved from + the head using dequeue(). The head() function provides access to + the head item without removing it. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qqueue.cpp 0 + + The example will output 1, 2, 3 in that order. + + QQueue inherits from QList. All of QList's functionality also + applies to QQueue. For example, you can use isEmpty() to test + whether the queue is empty, and you can traverse a QQueue using + QList's iterator classes (for example, QListIterator). But in + addition, QQueue provides three convenience functions that make + it easy to implement FIFO semantics: enqueue(), dequeue(), and + head(). + + QQueue's value type must be an \l{assignable data type}. This + covers most data types that are commonly used, but the compiler + won't let you, for example, store a QWidget as a value. Use + QWidget* instead. + + \sa QList, QStack +*/ + +/*! + \fn QQueue::QQueue() + + Constructs an empty queue. +*/ + +/*! + \fn QQueue::~QQueue() + + Destroys the queue. References to the values in the queue, and all + iterators over this queue, become invalid. +*/ + +/*! + \fn void QQueue::enqueue(const T& t) + + Adds value \a t to the tail of the queue. + + This is the same as QList::append(). + + \sa dequeue(), head() +*/ + +/*! + \fn T &QQueue::head() + + Returns a reference to the queue's head item. This function + assumes that the queue isn't empty. + + This is the same as QList::first(). + + \sa dequeue(), enqueue(), isEmpty() +*/ + +/*! + \fn const T &QQueue::head() const + + \overload +*/ + +/*! + \fn T QQueue::dequeue() + + Removes the head item in the queue and returns it. This function + assumes that the queue isn't empty. + + This is the same as QList::takeFirst(). + + \sa head(), enqueue(), isEmpty() +*/ diff --git a/src/corelib/tools/qqueue.h b/src/corelib/tools/qqueue.h new file mode 100644 index 0000000..8c7385e --- /dev/null +++ b/src/corelib/tools/qqueue.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUEUE_H +#define QQUEUE_H + +#include <QtCore/qlist.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +template <class T> +class QQueue : public QList<T> +{ +public: + inline QQueue() {} + inline ~QQueue() {} + inline void enqueue(const T &t) { QList<T>::append(t); } + inline T dequeue() { return QList<T>::takeFirst(); } + inline T &head() { return QList<T>::first(); } + inline const T &head() const { return QList<T>::first(); } +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QQUEUE_H diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp new file mode 100644 index 0000000..3930a0d --- /dev/null +++ b/src/corelib/tools/qrect.cpp @@ -0,0 +1,2471 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qrect.h" +#include "qdatastream.h" +#include "qdebug.h" +#include "qmath.h" + +#include <math.h> + +QT_BEGIN_NAMESPACE + +/*! + \class QRect + \ingroup multimedia + + \brief The QRect class defines a rectangle in the plane using + integer precision. + + A rectangle is normally expressed as an upper-left corner and a + size. The size (width and height) of a QRect is always equivalent + to the mathematical rectangle that forms the basis for its + rendering. + + A QRect can be constructed with a set of left, top, width and + height integers, or from a QPoint and a QSize. The following code + creates two identical rectangles. + + \snippet doc/src/snippets/code/src_corelib_tools_qrect.cpp 0 + + There is a third constructor that creates a QRect using the + top-left and bottom-right coordinates, but we recommend that you + avoid using it. The rationale is that for historical reasons the + values returned by the bottom() and right() functions deviate from + the true bottom-right corner of the rectangle. + + The QRect class provides a collection of functions that return the + various rectangle coordinates, and enable manipulation of + these. QRect also provide functions to move the rectangle relative + to the various coordinates. In addition there is a moveTo() + function that moves the rectangle, leaving its top left corner at + the given coordinates. Alternatively, the translate() function + moves the rectangle the given offset relative to the current + position, and the translated() function returns a translated copy + of this rectangle. + + The size() function returns the rectange's dimensions as a + QSize. The dimensions can also be retrieved separately using the + width() and height() functions. To manipulate the dimensions use + the setSize(), setWidth() or setHeight() functions. Alternatively, + the size can be changed by applying either of the functions + setting the rectangle coordinates, for example, setBottom() or + setRight(). + + The contains() function tells whether a given point is inside the + rectangle or not, and the intersects() function returns true if + this rectangle intersects with a given rectangle. The QRect class + also provides the intersected() function which returns the + intersection rectangle, and the united() function which returns the + rectangle that encloses the given rectangle and this: + + \table + \row + \o \inlineimage qrect-intersect.png + \o \inlineimage qrect-unite.png + \row + \o intersected() + \o united() + \endtable + + The isEmpty() function returns true if left() > right() or top() > + bottom(). Note that an empty rectangle is not valid: The isValid() + function returns true if left() <= right() \e and top() <= + bottom(). A null rectangle (isNull() == true) on the other hand, + has both width and height set to 0. + + Note that due to the way QRect and QRectF are defined, an + empty QRect is defined in essentially the same way as QRectF. + + Finally, QRect objects can be streamed as well as compared. + + \tableofcontents + + \section1 Rendering + + When using an \l {QPainter::Antialiasing}{anti-aliased} painter, + the boundary line of a QRect will be rendered symmetrically on + both sides of the mathematical rectangle's boundary line. But when + using an aliased painter (the default) other rules apply. + + Then, when rendering with a one pixel wide pen the QRect's boundary + line will be rendered to the right and below the mathematical + rectangle's boundary line. + + When rendering with a two pixels wide pen the boundary line will + be split in the middle by the mathematical rectangle. This will be + the case whenever the pen is set to an even number of pixels, + while rendering with a pen with an odd number of pixels, the spare + pixel will be rendered to the right and below the mathematical + rectangle as in the one pixel case. + + \table + \row + \o \inlineimage qrect-diagram-zero.png + \o \inlineimage qrect-diagram-one.png + \row + \o Logical representation + \o One pixel wide pen + \row + \o \inlineimage qrect-diagram-two.png + \o \inlineimage qrect-diagram-three.png + \row + \o Two pixel wide pen + \o Three pixel wide pen + \endtable + + \section1 Coordinates + + The QRect class provides a collection of functions that return the + various rectangle coordinates, and enable manipulation of + these. QRect also provide functions to move the rectangle relative + to the various coordinates. + + For example the left(), setLeft() and moveLeft() functions as an + example: left() returns the x-coordinate of the rectangle's left + edge, setLeft() sets the left edge of the rectangle to the given x + coordinate (it may change the width, but will never change the + rectangle's right edge) and moveLeft() moves the entire rectangle + horizontally, leaving the rectangle's left edge at the given x + coordinate and its size unchanged. + + \image qrect-coordinates.png + + Note that for historical reasons the values returned by the + bottom() and right() functions deviate from the true bottom-right + corner of the rectangle: The right() function returns \e { left() + + width() - 1} and the bottom() function returns \e {top() + + height() - 1}. The same is the case for the point returned by the + bottomRight() convenience function. In addition, the x and y + coordinate of the topRight() and bottomLeft() functions, + respectively, contain the same deviation from the true right and + bottom edges. + + We recommend that you use x() + width() and y() + height() to find + the true bottom-right corner, and avoid right() and + bottom(). Another solution is to use QRectF: The QRectF class + defines a rectangle in the plane using floating point accuracy for + coordinates, and the QRectF::right() and QRectF::bottom() + functions \e do return the right and bottom coordinates. + + It is also possible to add offsets to this rectangle's coordinates + using the adjust() function, as well as retrieve a new rectangle + based on adjustments of the original one using the adjusted() + function. If either of the width and height is negative, use the + normalized() function to retrieve a rectangle where the corners + are swapped. + + In addition, QRect provides the getCoords() function which extracts + the position of the rectangle's top-left and bottom-right corner, + and the getRect() function which extracts the rectangle's top-left + corner, width and height. Use the setCoords() and setRect() + function to manipulate the rectangle's coordinates and dimensions + in one go. + + \sa QRectF, QRegion +*/ + +/***************************************************************************** + QRect member functions + *****************************************************************************/ + +/*! + \fn QRect::QRect() + + Constructs a null rectangle. + + \sa isNull() +*/ + +/*! + \fn QRect::QRect(const QPoint &topLeft, const QPoint &bottomRight) + + Constructs a rectangle with the given \a topLeft and \a bottomRight corners. + + \sa setTopLeft(), setBottomRight() +*/ + + +/*! + \fn QRect::QRect(const QPoint &topLeft, const QSize &size) + + Constructs a rectangle with the given \a topLeft corner and the + given \a size. + + \sa setTopLeft(), setSize() +*/ + + +/*! + \fn QRect::QRect(int x, int y, int width, int height) + + Constructs a rectangle with (\a x, \a y) as its top-left corner + and the given \a width and \a height. + + \sa setRect() +*/ + + +/*! + \fn bool QRect::isNull() const + + Returns true if the rectangle is a null rectangle, otherwise + returns false. + + A null rectangle has both the width and the height set to 0 (i.e., + right() == left() - 1 and bottom() == top() - 1). A null rectangle + is also empty, and hence is not valid. + + \sa isEmpty(), isValid() +*/ + +/*! + \fn bool QRect::isEmpty() const + + Returns true if the rectangle is empty, otherwise returns false. + + An empty rectangle has a left() > right() or top() > bottom(). An + empty rectangle is not valid (i.e., isEmpty() == !isValid()). + + Use the normalized() function to retrieve a rectangle where the + corners are swapped. + + \sa isNull(), isValid(), normalized() +*/ + +/*! + \fn bool QRect::isValid() const + + Returns true if the rectangle is valid, otherwise returns false. + + A valid rectangle has a left() < right() and top() < + bottom(). Note that non-trivial operations like intersections are + not defined for invalid rectangles. A valid rectangle is not empty + (i.e., isValid() == !isEmpty()). + + \sa isNull(), isEmpty(), normalized() +*/ + + +/*! + Returns a normalized rectangle; i.e., a rectangle that has a + non-negative width and height. + + If width() < 0 the function swaps the left and right corners, and + it swaps the top and bottom corners if height() < 0. + + \sa isValid(), isEmpty() +*/ + +QRect QRect::normalized() const +{ + QRect r; + if (x2 < x1 - 1) { // swap bad x values + r.x1 = x2; + r.x2 = x1; + } else { + r.x1 = x1; + r.x2 = x2; + } + if (y2 < y1 - 1) { // swap bad y values + r.y1 = y2; + r.y2 = y1; + } else { + r.y1 = y1; + r.y2 = y2; + } + return r; +} + + +/*! + \fn QRect QRect::normalize() const + \compat + + Returns a normalized rectangle; i.e., a rectangle that has a + non-negative width and height. + + Use the normalized() function instead +*/ + +/*! + \fn int QRect::left() const + + Returns the x-coordinate of the rectangle's left edge. Equivalent + to x(). + + \sa setLeft(), topLeft(), bottomLeft() +*/ + +/*! + \fn int QRect::top() const + + Returns the y-coordinate of the rectangle's top edge. + Equivalent to y(). + + \sa setTop(), topLeft(), topRight() +*/ + +/*! + \fn int QRect::right() const + + Returns the x-coordinate of the rectangle's right edge. + + Note that for historical reasons this function returns left() + + width() - 1; use x() + width() to retrieve the true x-coordinate. + + \sa setRight(), topRight(), bottomRight() +*/ + +/*! + \fn int QRect::bottom() const + + Returns the y-coordinate of the rectangle's bottom edge. + + Note that for historical reasons this function returns top() + + height() - 1; use y() + height() to retrieve the true y-coordinate. + + \sa setBottom(), bottomLeft(), bottomRight() +*/ + +/*! + \fn int &QRect::rLeft() + \compat + + Returns a reference to the left coordinate of the rectangle. + + Use the left() function instead. +*/ + +/*! + \fn int &QRect::rTop() + \compat + + Returns a reference to the top coordinate of the rectangle. + + Use the top() function instead. +*/ + +/*! + \fn int &QRect::rRight() + \compat + + Returns a reference to the right coordinate of the rectangle. + + Use the right() function instead. +*/ + +/*! + \fn int &QRect::rBottom() + \compat + + Returns a reference to the bottom coordinate of the rectangle. + + Use the bottom() function instead. +*/ + +/*! + \fn int QRect::x() const + + Returns the x-coordinate of the rectangle's left edge. Equivalent to left(). + + \sa setX(), y(), topLeft() +*/ + +/*! + \fn int QRect::y() const + + Returns the y-coordinate of the rectangle's top edge. Equivalent to top(). + + \sa setY(), x(), topLeft() +*/ + +/*! + \fn void QRect::setLeft(int x) + + Sets the left edge of the rectangle to the given \a x + coordinate. May change the width, but will never change the right + edge of the rectangle. + + Equivalent to setX(). + + \sa left(), moveLeft() +*/ + +/*! + \fn void QRect::setTop(int y) + + Sets the top edge of the rectangle to the given \a y + coordinate. May change the height, but will never change the + bottom edge of the rectangle. + + Equivalent to setY(). + + \sa top(), moveTop() +*/ + +/*! + \fn void QRect::setRight(int x) + + Sets the right edge of the rectangle to the given \a x + coordinate. May change the width, but will never change the left + edge of the rectangle. + + \sa right(), moveRight() +*/ + +/*! + \fn void QRect::setBottom(int y) + + Sets the bottom edge of the rectangle to the given \a y + coordinate. May change the height, but will never change the top + edge of the rectangle. + + \sa bottom(), moveBottom(), +*/ + +/*! + \fn void QRect::setX(int x) + + Sets the left edge of the rectangle to the given \a x + coordinate. May change the width, but will never change the right + edge of the rectangle. + + Equivalent to setLeft(). + + \sa x(), setY(), setTopLeft() +*/ + +/*! + \fn void QRect::setY(int y) + + Sets the top edge of the rectangle to the given \a y + coordinate. May change the height, but will never change the + bottom edge of the rectangle. + + Equivalent to setTop(). + + \sa y(), setX(), setTopLeft() +*/ + +/*! + \fn void QRect::setTopLeft(const QPoint &position) + + Set the top-left corner of the rectangle to the given \a + position. May change the size, but will never change the + bottom-right corner of the rectangle. + + \sa topLeft(), moveTopLeft() +*/ + +/*! + \fn void QRect::setBottomRight(const QPoint &position) + + Set the bottom-right corner of the rectangle to the given \a + position. May change the size, but will never change the + top-left corner of the rectangle. + + \sa bottomRight(), moveBottomRight() +*/ + +/*! + \fn void QRect::setTopRight(const QPoint &position) + + Set the top-right corner of the rectangle to the given \a + position. May change the size, but will never change the + bottom-left corner of the rectangle. + + \sa topRight(), moveTopRight() +*/ + +/*! + \fn void QRect::setBottomLeft(const QPoint &position) + + Set the bottom-left corner of the rectangle to the given \a + position. May change the size, but will never change the + top-right corner of the rectangle. + + \sa bottomLeft(), moveBottomLeft() +*/ + +/*! + \fn QPoint QRect::topLeft() const + + Returns the position of the rectangle's top-left corner. + + \sa setTopLeft(), top(), left() +*/ + +/*! + \fn QPoint QRect::bottomRight() const + + Returns the position of the rectangle's bottom-right corner. + + Note that for historical reasons this function returns + QPoint(left() + width() -1, top() + height() - 1). + + \sa setBottomRight(), bottom(), right() +*/ + +/*! + \fn QPoint QRect::topRight() const + + Returns the position of the rectangle's top-right corner. + + Note that for historical reasons this function returns + QPoint(left() + width() -1, top()). + + \sa setTopRight(), top(), right() +*/ + +/*! + \fn QPoint QRect::bottomLeft() const + + Returns the position of the rectangle's bottom-left corner. Note + that for historical reasons this function returns QPoint(left(), + top() + height() - 1). + + \sa setBottomLeft(), bottom(), left() +*/ + +/*! + \fn QPoint QRect::center() const + + Returns the center point of the rectangle. + + \sa moveCenter() +*/ + + +/*! + \fn void QRect::getRect(int *x, int *y, int *width, int *height) const + + Extracts the position of the rectangle's top-left corner to *\a x + and *\a y, and its dimensions to *\a width and *\a height. + + \sa setRect(), getCoords() +*/ + + +/*! + \fn void QRect::getCoords(int *x1, int *y1, int *x2, int *y2) const + + Extracts the position of the rectangle's top-left corner to *\a x1 + and *\a y1, and the position of the bottom-right corner to *\a x2 + and *\a y2. + + \sa setCoords(), getRect() +*/ + +/*! + \fn void QRect::rect(int *x, int *y, int *width, int *height) const + \compat + + Extracts the position of the rectangle's top-left corner to *\a x and + *\a y, and its dimensions to *\a width and * \a height. + + Use the getRect() function instead. +*/ + + +/*! + \fn void QRect::coords(int *x1, int *y1, int *x2, int *y2) const + \compat + + Extracts the position of the rectangle's top-left corner to *\a x1 + and *\a y1, and the position of the bottom-right corner to *\a x2 + and *\a y2. + + Use the getCoords() function instead. +*/ + +/*! + \fn void QRect::moveLeft(int x) + + Moves the rectangle horizontally, leaving the rectangle's left + edge at the given \a x coordinate. The rectangle's size is + unchanged. + + \sa left(), setLeft(), moveRight() +*/ + +/*! + \fn void QRect::moveTop(int y) + + Moves the rectangle vertically, leaving the rectangle's top edge + at the given \a y coordinate. The rectangle's size is unchanged. + + \sa top(), setTop(), moveBottom() +*/ + + +/*! + \fn void QRect::moveRight(int x) + + Moves the rectangle horizontally, leaving the rectangle's right + edge at the given \a x coordinate. The rectangle's size is + unchanged. + + \sa right(), setRight(), moveLeft() +*/ + + +/*! + \fn void QRect::moveBottom(int y) + + Moves the rectangle vertically, leaving the rectangle's bottom + edge at the given \a y coordinate. The rectangle's size is + unchanged. + + \sa bottom(), setBottom(), moveTop() +*/ + + +/*! + \fn void QRect::moveTopLeft(const QPoint &position) + + Moves the rectangle, leaving the top-left corner at the given \a + position. The rectangle's size is unchanged. + + \sa setTopLeft(), moveTop(), moveLeft() +*/ + + +/*! + \fn void QRect::moveBottomRight(const QPoint &position) + + Moves the rectangle, leaving the bottom-right corner at the given + \a position. The rectangle's size is unchanged. + + \sa setBottomRight(), moveRight(), moveBottom() +*/ + + +/*! + \fn void QRect::moveTopRight(const QPoint &position) + + Moves the rectangle, leaving the top-right corner at the given \a + position. The rectangle's size is unchanged. + + \sa setTopRight(), moveTop(), moveRight() +*/ + + +/*! + \fn void QRect::moveBottomLeft(const QPoint &position) + + Moves the rectangle, leaving the bottom-left corner at the given + \a position. The rectangle's size is unchanged. + + \sa setBottomLeft(), moveBottom(), moveLeft() +*/ + + +/*! + \fn void QRect::moveCenter(const QPoint &position) + + Moves the rectangle, leaving the center point at the given \a + position. The rectangle's size is unchanged. + + \sa center() +*/ + +void QRect::moveCenter(const QPoint &p) +{ + int w = x2 - x1; + int h = y2 - y1; + x1 = p.x() - w/2; + y1 = p.y() - h/2; + x2 = x1 + w; + y2 = y1 + h; +} + +/*! + \fn void QRect::moveBy(int dx, int dy) + \compat + + Moves the rectangle \a dx along the x axis and \a dy along the y + axis, relative to the current position. + + Use the translate() function instead. +*/ + +/*! + \fn void QRect::moveBy(const QPoint &) + \compat + + Use the translate() function instead. +*/ + +/*! + \fn void QRect::moveTo(int x, int y) + + Moves the rectangle, leaving the top-left corner at the given + position (\a x, \a y). The rectangle's size is unchanged. + + \sa translate(), moveTopLeft() +*/ + +/*! + \fn void QRect::moveTo(const QPoint &position) + + Moves the rectangle, leaving the top-left corner at the given \a + position. +*/ + +/*! + \fn void QRect::translate(int dx, int dy) + + Moves the rectangle \a dx along the x axis and \a dy along the y + axis, relative to the current position. Positive values move the + rectangle to the right and down. + + \sa moveTopLeft(), moveTo(), translated() +*/ + + +/*! + \fn void QRect::translate(const QPoint &offset) + \overload + + Moves the rectangle \a{offset}.\l{QPoint::x()}{x()} along the x + axis and \a{offset}.\l{QPoint::y()}{y()} along the y axis, + relative to the current position. +*/ + + +/*! + \fn QRect QRect::translated(int dx, int dy) const + + Returns a copy of the rectangle that is translated \a dx along the + x axis and \a dy along the y axis, relative to the current + position. Positive values move the rectangle to the right and + down. + + \sa translate() + +*/ + + +/*! + \fn QRect QRect::translated(const QPoint &offset) const + + \overload + + Returns a copy of the rectangle that is translated + \a{offset}.\l{QPoint::x()}{x()} along the x axis and + \a{offset}.\l{QPoint::y()}{y()} along the y axis, relative to the + current position. +*/ + + +/*! + \fn void QRect::setRect(int x, int y, int width, int height) + + Sets the coordinates of the rectangle's top-left corner to (\a{x}, + \a{y}), and its size to the given \a width and \a height. + + \sa getRect(), setCoords() +*/ + + +/*! + \fn void QRect::setCoords(int x1, int y1, int x2, int y2) + + Sets the coordinates of the rectangle's top-left corner to (\a x1, + \a y1), and the coordinates of its bottom-right corner to (\a x2, + \a y2). + + \sa getCoords(), setRect() +*/ + + +/*! + \fn void QRect::addCoords(int dx1, int dy1, int dx2, int dy2) + \compat + + Adds \a dx1, \a dy1, \a dx2 and \a dy2 to the existing coordinates + of the rectangle respectively. + + Use the adjust() function instead. +*/ + +/*! \fn QRect QRect::adjusted(int dx1, int dy1, int dx2, int dy2) const + + Returns a new rectangle with \a dx1, \a dy1, \a dx2 and \a dy2 + added respectively to the existing coordinates of this rectangle. + + \sa adjust() +*/ + +/*! \fn void QRect::adjust(int dx1, int dy1, int dx2, int dy2) + + Adds \a dx1, \a dy1, \a dx2 and \a dy2 respectively to the + existing coordinates of the rectangle. + + \sa adjusted(), setRect() +*/ + +/*! + \fn QSize QRect::size() const + + Returns the size of the rectangle. + + \sa setSize(), width(), height() +*/ + +/*! + \fn int QRect::width() const + + Returns the width of the rectangle. + + \sa setWidth(), height(), size() +*/ + +/*! + \fn int QRect::height() const + + Returns the height of the rectangle. + + \sa setHeight(), width(), size() +*/ + +/*! + \fn void QRect::setWidth(int width) + + Sets the width of the rectangle to the given \a width. The right + edge is changed, but not the left one. + + \sa width(), setSize() +*/ + + +/*! + \fn void QRect::setHeight(int height) + + Sets the height of the rectangle to the given \a height. The bottom + edge is changed, but not the top one. + + \sa height(), setSize() +*/ + + +/*! + \fn void QRect::setSize(const QSize &size) + + Sets the size of the rectangle to the given \a size. The top-left + corner is not moved. + + \sa size(), setWidth(), setHeight() +*/ + + +/*! + \fn bool QRect::contains(const QPoint &point, bool proper) const + + Returns true if the the given \a point is inside or on the edge of + the rectangle, otherwise returns false. If \a proper is true, this + function only returns true if the given \a point is \e inside the + rectangle (i.e., not on the edge). + + \sa intersects() +*/ + +bool QRect::contains(const QPoint &p, bool proper) const +{ + int l, r; + if (x2 < x1 - 1) { + l = x2; + r = x1; + } else { + l = x1; + r = x2; + } + if (proper) { + if (p.x() <= l || p.x() >= r) + return false; + } else { + if (p.x() < l || p.x() > r) + return false; + } + int t, b; + if (y2 < y1 - 1) { + t = y2; + b = y1; + } else { + t = y1; + b = y2; + } + if (proper) { + if (p.y() <= t || p.y() >= b) + return false; + } else { + if (p.y() < t || p.y() > b) + return false; + } + return true; +} + + +/*! + \fn bool QRect::contains(int x, int y, bool proper) const + \overload + + Returns true if the point (\a x, \a y) is inside or on the edge of + the rectangle, otherwise returns false. If \a proper is true, this + function only returns true if the point is entirely inside the + rectangle(not on the edge). +*/ + +/*! + \fn bool QRect::contains(int x, int y) const + \overload + + Returns true if the point (\a x, \a y) is inside this rectangle, + otherwise returns false. +*/ + +/*! + \fn bool QRect::contains(const QRect &rectangle, bool proper) const + \overload + + Returns true if the given \a rectangle is inside this rectangle. + otherwise returns false. If \a proper is true, this function only + returns true if the \a rectangle is entirely inside this + rectangle (not on the edge). +*/ + +bool QRect::contains(const QRect &r, bool proper) const +{ + if (isNull() || r.isNull()) + return false; + + int l1 = x1; + int r1 = x1; + if (x2 - x1 + 1 < 0) + l1 = x2; + else + r1 = x2; + + int l2 = r.x1; + int r2 = r.x1; + if (r.x2 - r.x1 + 1 < 0) + l2 = r.x2; + else + r2 = r.x2; + + if (proper) { + if (l2 <= l1 || r2 >= r1) + return false; + } else { + if (l2 < l1 || r2 > r1) + return false; + } + + int t1 = y1; + int b1 = y1; + if (y2 - y1 + 1 < 0) + t1 = y2; + else + b1 = y2; + + int t2 = r.y1; + int b2 = r.y1; + if (r.y2 - r.y1 + 1 < 0) + t2 = r.y2; + else + b2 = r.y2; + + if (proper) { + if (t2 <= t1 || b2 >= b1) + return false; + } else { + if (t2 < t1 || b2 > b1) + return false; + } + + return true; +} + +/*! + \fn QRect& QRect::operator|=(const QRect &rectangle) + + Unites this rectangle with the given \a rectangle. + + \sa united(), operator|() +*/ + +/*! + \fn QRect& QRect::operator&=(const QRect &rectangle) + + Intersects this rectangle with the given \a rectangle. + + \sa intersected(), operator&() +*/ + + +/*! + \fn QRect QRect::operator|(const QRect &rectangle) const + + Returns the bounding rectangle of this rectangle and the given \a + rectangle. + + \sa operator|=(), united() +*/ + +QRect QRect::operator|(const QRect &r) const +{ + if (isNull()) + return r; + if (r.isNull()) + return *this; + + int l1 = x1; + int r1 = x1; + if (x2 - x1 + 1 < 0) + l1 = x2; + else + r1 = x2; + + int l2 = r.x1; + int r2 = r.x1; + if (r.x2 - r.x1 + 1 < 0) + l2 = r.x2; + else + r2 = r.x2; + + int t1 = y1; + int b1 = y1; + if (y2 - y1 + 1 < 0) + t1 = y2; + else + b1 = y2; + + int t2 = r.y1; + int b2 = r.y1; + if (r.y2 - r.y1 + 1 < 0) + t2 = r.y2; + else + b2 = r.y2; + + QRect tmp; + tmp.x1 = qMin(l1, l2); + tmp.x2 = qMax(r1, r2); + tmp.y1 = qMin(t1, t2); + tmp.y2 = qMax(b1, b2); + return tmp; +} + +/*! + \fn QRect QRect::unite(const QRect &rectangle) const + \obsolete + + Use united(\a rectangle) instead. +*/ + +/*! + \fn QRect QRect::united(const QRect &rectangle) const + \since 4.2 + + Returns the bounding rectangle of this rectangle and the given \a rectangle. + + \image qrect-unite.png + + \sa intersected() +*/ + + +/*! + \fn QRect QRect::operator&(const QRect &rectangle) const + + Returns the intersection of this rectangle and the given \a + rectangle. Returns an empty rectangle if there is no intersection. + + \sa operator&=(), intersected() +*/ + +QRect QRect::operator&(const QRect &r) const +{ + if (isNull() || r.isNull()) + return QRect(); + + int l1 = x1; + int r1 = x1; + if (x2 - x1 + 1 < 0) + l1 = x2; + else + r1 = x2; + + int l2 = r.x1; + int r2 = r.x1; + if (r.x2 - r.x1 + 1 < 0) + l2 = r.x2; + else + r2 = r.x2; + + if (l1 > r2 || l2 > r1) + return QRect(); + + int t1 = y1; + int b1 = y1; + if (y2 - y1 + 1 < 0) + t1 = y2; + else + b1 = y2; + + int t2 = r.y1; + int b2 = r.y1; + if (r.y2 - r.y1 + 1 < 0) + t2 = r.y2; + else + b2 = r.y2; + + if (t1 > b2 || t2 > b1) + return QRect(); + + QRect tmp; + tmp.x1 = qMax(l1, l2); + tmp.x2 = qMin(r1, r2); + tmp.y1 = qMax(t1, t2); + tmp.y2 = qMin(b1, b2); + return tmp; +} + +/*! + \fn QRect QRect::intersect(const QRect &rectangle) const + \obsolete + + Use intersected(\a rectangle) instead. +*/ + +/*! + \fn QRect QRect::intersected(const QRect &rectangle) const + \since 4.2 + + Returns the intersection of this rectangle and the given \a + rectangle. Note that \c{r.intersected(s)} is equivalent to \c{r & s}. + + \image qrect-intersect.png + + \sa intersects(), united(), operator&=() +*/ + +/*! + \fn bool QRect::intersects(const QRect &rectangle) const + + Returns true if this rectangle intersects with the given \a + rectangle (i.e., there is at least one pixel that is within both + rectangles), otherwise returns false. + + The intersection rectangle can be retrieved using the intersected() + function. + + \sa contains() +*/ + +bool QRect::intersects(const QRect &r) const +{ + if (isNull() || r.isNull()) + return false; + + int l1 = x1; + int r1 = x1; + if (x2 - x1 + 1 < 0) + l1 = x2; + else + r1 = x2; + + int l2 = r.x1; + int r2 = r.x1; + if (r.x2 - r.x1 + 1 < 0) + l2 = r.x2; + else + r2 = r.x2; + + if (l1 > r2 || l2 > r1) + return false; + + int t1 = y1; + int b1 = y1; + if (y2 - y1 + 1 < 0) + t1 = y2; + else + b1 = y2; + + int t2 = r.y1; + int b2 = r.y1; + if (r.y2 - r.y1 + 1 < 0) + t2 = r.y2; + else + b2 = r.y2; + + if (t1 > b2 || t2 > b1) + return false; + + return true; +} + +/*! + \fn bool operator==(const QRect &r1, const QRect &r2) + \relates QRect + + Returns true if the rectangles \a r1 and \a r2 are equal, + otherwise returns false. +*/ + + +/*! + \fn bool operator!=(const QRect &r1, const QRect &r2) + \relates QRect + + Returns true if the rectangles \a r1 and \a r2 are different, otherwise + returns false. +*/ + + +/***************************************************************************** + QRect stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QRect &rectangle) + \relates QRect + + Writes the given \a rectangle to the given \a stream, and returns + a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator<<(QDataStream &s, const QRect &r) +{ + if (s.version() == 1) + s << (qint16)r.left() << (qint16)r.top() + << (qint16)r.right() << (qint16)r.bottom(); + else + s << (qint32)r.left() << (qint32)r.top() + << (qint32)r.right() << (qint32)r.bottom(); + return s; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QRect &rectangle) + \relates QRect + + Reads a rectangle from the given \a stream into the given \a + rectangle, and returns a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator>>(QDataStream &s, QRect &r) +{ + if (s.version() == 1) { + qint16 x1, y1, x2, y2; + s >> x1; s >> y1; s >> x2; s >> y2; + r.setCoords(x1, y1, x2, y2); + } + else { + qint32 x1, y1, x2, y2; + s >> x1; s >> y1; s >> x2; s >> y2; + r.setCoords(x1, y1, x2, y2); + } + return s; +} + +#endif // QT_NO_DATASTREAM + + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QRect &r) { + dbg.nospace() << "QRect(" << r.x() << ',' << r.y() << ' ' + << r.width() << 'x' << r.height() << ')'; + return dbg.space(); +} +#endif + +/*! + \class QRectF + \ingroup multimedia + + \brief The QRectF class defines a rectangle in the plane using floating + point precision. + + A rectangle is normally expressed as an upper-left corner and a + size. The size (width and height) of a QRectF is always equivalent + to the mathematical rectangle that forms the basis for its + rendering. + + A QRectF can be constructed with a set of left, top, width and + height integers, or from a QPoint and a QSize. The following code + creates two identical rectangles. + + \snippet doc/src/snippets/code/src_corelib_tools_qrect.cpp 1 + + There is also a third constructor creating a QRectF from a QRect, + and a corresponding toRect() function that returns a QRect object + based on the values of this rectangle (note that the coordinates + in the returned rectangle are rounded to the nearest integer). + + The QRectF class provides a collection of functions that return + the various rectangle coordinates, and enable manipulation of + these. QRectF also provide functions to move the rectangle + relative to the various coordinates. In addition there is a + moveTo() function that moves the rectangle, leaving its top left + corner at the given coordinates. Alternatively, the translate() + function moves the rectangle the given offset relative to the + current position, and the translated() function returns a + translated copy of this rectangle. + + The size() function returns the rectange's dimensions as a + QSize. The dimensions can also be retrieved separately using the + width() and height() functions. To manipulate the dimensions use + the setSize(), setWidth() or setHeight() functions. Alternatively, + the size can be changed by applying either of the functions + setting the rectangle coordinates, for example, setBottom() or + setRight(). + + The contains() function tells whether a given point is inside the + rectangle or not, and the intersects() function returns true if + this rectangle intersects with a given rectangle (otherwise + false). The QRectF class also provides the intersected() function + which returns the intersection rectangle, and the united() function + which returns the rectangle that encloses the given rectangle and + this: + + \table + \row + \o \inlineimage qrect-intersect.png + \o \inlineimage qrect-unite.png + \row + \o intersected() + \o united() + \endtable + + The isEmpty() function returns true if the rectangle's width or + height is less than, or equal to, 0. Note that an empty rectangle + is not valid: The isValid() function returns true if both width + and height is larger than 0. A null rectangle (isNull() == true) + on the other hand, has both width and height set to 0. + + Note that due to the way QRect and QRectF are defined, an + empty QRectF is defined in essentially the same way as QRect. + + Finally, QRectF objects can be streamed as well as compared. + + \tableofcontents + + \section1 Rendering + + When using an \l {QPainter::Antialiasing}{anti-aliased} painter, + the boundary line of a QRectF will be rendered symmetrically on both + sides of the mathematical rectangle's boundary line. But when + using an aliased painter (the default) other rules apply. + + Then, when rendering with a one pixel wide pen the QRectF's boundary + line will be rendered to the right and below the mathematical + rectangle's boundary line. + + When rendering with a two pixels wide pen the boundary line will + be split in the middle by the mathematical rectangle. This will be + the case whenever the pen is set to an even number of pixels, + while rendering with a pen with an odd number of pixels, the spare + pixel will be rendered to the right and below the mathematical + rectangle as in the one pixel case. + + \table + \row + \o \inlineimage qrect-diagram-zero.png + \o \inlineimage qrectf-diagram-one.png + \row + \o Logical representation + \o One pixel wide pen + \row + \o \inlineimage qrectf-diagram-two.png + \o \inlineimage qrectf-diagram-three.png + \row + \o Two pixel wide pen + \o Three pixel wide pen + \endtable + + \section1 Coordinates + + The QRectF class provides a collection of functions that return + the various rectangle coordinates, and enable manipulation of + these. QRectF also provide functions to move the rectangle + relative to the various coordinates. + + For example: the bottom(), setBottom() and moveBottom() functions: + bottom() returns the y-coordinate of the rectangle's bottom edge, + setBottom() sets the bottom edge of the rectangle to the given y + coordinate (it may change the height, but will never change the + rectangle's top edge) and moveBottom() moves the entire rectangle + vertically, leaving the rectangle's bottom edge at the given y + coordinate and its size unchanged. + + \image qrectf-coordinates.png + + It is also possible to add offsets to this rectangle's coordinates + using the adjust() function, as well as retrieve a new rectangle + based on adjustments of the original one using the adjusted() + function. If either of the width and height is negative, use the + normalized() function to retrieve a rectangle where the corners + are swapped. + + In addition, QRectF provides the getCoords() function which extracts + the position of the rectangle's top-left and bottom-right corner, + and the getRect() function which extracts the rectangle's top-left + corner, width and height. Use the setCoords() and setRect() + function to manipulate the rectangle's coordinates and dimensions + in one go. + + \sa QRect, QRegion +*/ + +/***************************************************************************** + QRectF member functions + *****************************************************************************/ + +/*! + \fn QRectF::QRectF() + + Constructs a null rectangle. + + \sa isNull() +*/ + +/*! + \fn QRectF::QRectF(const QPointF &topLeft, const QSizeF &size) + + Constructs a rectangle with the given \a topLeft corner and the given \a size. + + \sa setTopLeft(), setSize() +*/ + +/*! + \fn QRectF::QRectF(const QPointF &topLeft, const QPointF &bottomRight) + \since 4.3 + + Constructs a rectangle with the given \a topLeft and \a bottomRight corners. + + \sa setTopLeft(), setBottomRight() +*/ + +/*! + \fn QRectF::QRectF(qreal x, qreal y, qreal width, qreal height) + + Constructs a rectangle with (\a x, \a y) as its top-left corner + and the given \a width and \a height. + + \sa setRect() +*/ + +/*! + \fn QRectF::QRectF(const QRect &rectangle) + + Constructs a QRectF rectangle from the given QRect \a rectangle. + + \sa toRect() +*/ + +/*! + \fn bool QRectF::isNull() const + + Returns true if the rectangle is a null rectangle, otherwise returns false. + + A null rectangle has both the width and the height set to 0. A + null rectangle is also empty, and hence not valid. + + \sa isEmpty(), isValid() +*/ + +/*! + \fn bool QRectF::isEmpty() const + + Returns true if the rectangle is empty, otherwise returns false. + + An empty rectangle has width() <= 0 or height() <= 0. An empty + rectangle is not valid (i.e., isEmpty() == !isValid()). + + Use the normalized() function to retrieve a rectangle where the + corners are swapped. + + \sa isNull(), isValid(), normalized() +*/ + +/*! + \fn bool QRectF::isValid() const + + Returns true if the rectangle is valid, otherwise returns false. + + A valid rectangle has a width() > 0 and height() > 0. Note that + non-trivial operations like intersections are not defined for + invalid rectangles. A valid rectangle is not empty (i.e., isValid() + == !isEmpty()). + + \sa isNull(), isEmpty(), normalized() +*/ + + +/*! + Returns a normalized rectangle; i.e., a rectangle that has a + non-negative width and height. + + If width() < 0 the function swaps the left and right corners, and + it swaps the top and bottom corners if height() < 0. + + \sa isValid(), isEmpty() +*/ + +QRectF QRectF::normalized() const +{ + QRectF r = *this; + if (r.w < 0) { + r.xp += r.w; + r.w = -r.w; + } + if (r.h < 0) { + r.yp += r.h; + r.h = -r.h; + } + return r; +} + +/*! + \fn qreal QRectF::x() const + + Returns the x-coordinate of the rectangle's left edge. Equivalent + to left(). + + + \sa setX(), y(), topLeft() +*/ + +/*! + \fn qreal QRectF::y() const + + Returns the y-coordinate of the rectangle's top edge. Equivalent + to top(). + + \sa setY(), x(), topLeft() +*/ + + +/*! + \fn void QRectF::setLeft(qreal x) + + Sets the left edge of the rectangle to the given \a x + coordinate. May change the width, but will never change the right + edge of the rectangle. + + Equivalent to setX(). + + \sa left(), moveLeft() +*/ + +/*! + \fn void QRectF::setTop(qreal y) + + Sets the top edge of the rectangle to the given \a y coordinate. May + change the height, but will never change the bottom edge of the + rectangle. + + Equivalent to setY(). + + \sa top(), moveTop() +*/ + +/*! + \fn void QRectF::setRight(qreal x) + + Sets the right edge of the rectangle to the given \a x + coordinate. May change the width, but will never change the left + edge of the rectangle. + + \sa right(), moveRight() +*/ + +/*! + \fn void QRectF::setBottom(qreal y) + + Sets the bottom edge of the rectangle to the given \a y + coordinate. May change the height, but will never change the top + edge of the rectangle. + + \sa bottom(), moveBottom() +*/ + +/*! + \fn void QRectF::setX(qreal x) + + Sets the left edge of the rectangle to the given \a x + coordinate. May change the width, but will never change the right + edge of the rectangle. + + Equivalent to setLeft(). + + \sa x(), setY(), setTopLeft() +*/ + +/*! + \fn void QRectF::setY(qreal y) + + Sets the top edge of the rectangle to the given \a y + coordinate. May change the height, but will never change the + bottom edge of the rectangle. + + Equivalent to setTop(). + + \sa y(), setX(), setTopLeft() +*/ + +/*! + \fn void QRectF::setTopLeft(const QPointF &position) + + Set the top-left corner of the rectangle to the given \a + position. May change the size, but will never change the + bottom-right corner of the rectangle. + + \sa topLeft(), moveTopLeft() +*/ + +/*! + \fn void QRectF::setBottomRight(const QPointF &position) + + Set the bottom-right corner of the rectangle to the given \a + position. May change the size, but will never change the + top-left corner of the rectangle. + + \sa bottomRight(), moveBottomRight() +*/ + +/*! + \fn void QRectF::setTopRight(const QPointF &position) + + Set the top-right corner of the rectangle to the given \a + position. May change the size, but will never change the + bottom-left corner of the rectangle. + + \sa topRight(), moveTopRight() +*/ + +/*! + \fn void QRectF::setBottomLeft(const QPointF &position) + + Set the bottom-left corner of the rectangle to the given \a + position. May change the size, but will never change the + top-right corner of the rectangle. + + \sa bottomLeft(), moveBottomLeft() +*/ + +/*! + \fn QPointF QRectF::center() const + + Returns the center point of the rectangle. + + \sa moveCenter() +*/ + + +/*! + \fn void QRectF::getRect(qreal *x, qreal *y, qreal *width, qreal *height) const + + Extracts the position of the rectangle's top-left corner to *\a x and + *\a y, and its dimensions to *\a width and *\a height. + + \sa setRect(), getCoords() +*/ + + +/*! + \fn void QRectF::getCoords(qreal *x1, qreal *y1, qreal *x2, qreal *y2) const + + Extracts the position of the rectangle's top-left corner to *\a x1 + and *\a y1, and the position of the bottom-right corner to *\a x2 and + *\a y2. + + \sa setCoords(), getRect() +*/ + +/*! + \fn void QRectF::moveLeft(qreal x) + + Moves the rectangle horizontally, leaving the rectangle's left + edge at the given \a x coordinate. The rectangle's size is + unchanged. + + \sa left(), setLeft(), moveRight() +*/ + +/*! + \fn void QRectF::moveTop(qreal y) + + Moves the rectangle vertically, leaving the rectangle's top line + at the given \a y coordinate. The rectangle's size is unchanged. + + \sa top(), setTop(), moveBottom() +*/ + + +/*! + \fn void QRectF::moveRight(qreal x) + + Moves the rectangle horizontally, leaving the rectangle's right + edge at the given \a x coordinate. The rectangle's size is + unchanged. + + \sa right(), setRight(), moveLeft() +*/ + + +/*! + \fn void QRectF::moveBottom(qreal y) + + Moves the rectangle vertically, leaving the rectangle's bottom + edge at the given \a y coordinate. The rectangle's size is + unchanged. + + \sa bottom(), setBottom(), moveTop() +*/ + + +/*! + \fn void QRectF::moveTopLeft(const QPointF &position) + + Moves the rectangle, leaving the top-left corner at the given \a + position. The rectangle's size is unchanged. + + \sa setTopLeft(), moveTop(), moveLeft() +*/ + + +/*! + \fn void QRectF::moveBottomRight(const QPointF &position) + + Moves the rectangle, leaving the bottom-right corner at the given + \a position. The rectangle's size is unchanged. + + \sa setBottomRight(), moveBottom(), moveRight() +*/ + + +/*! + \fn void QRectF::moveTopRight(const QPointF &position) + + Moves the rectangle, leaving the top-right corner at the given + \a position. The rectangle's size is unchanged. + + \sa setTopRight(), moveTop(), moveRight() +*/ + + +/*! + \fn void QRectF::moveBottomLeft(const QPointF &position) + + Moves the rectangle, leaving the bottom-left corner at the given + \a position. The rectangle's size is unchanged. + + \sa setBottomLeft(), moveBottom(), moveLeft() +*/ + + +/*! + \fn void QRectF::moveTo(qreal x, qreal y) + + Moves the rectangle, leaving the top-left corner at the given + position (\a x, \a y). The rectangle's size is unchanged. + + \sa translate(), moveTopLeft() +*/ + +/*! + \fn void QRectF::moveTo(const QPointF &position) + \overload + + Moves the rectangle, leaving the top-left corner at the given \a + position. +*/ + +/*! + \fn void QRectF::translate(qreal dx, qreal dy) + + Moves the rectangle \a dx along the x-axis and \a dy along the y-axis, + relative to the current position. Positive values move the rectangle to the + right and downwards. + + \sa moveTopLeft(), moveTo(), translated() +*/ + + +/*! + \fn void QRectF::translate(const QPointF &offset) + \overload + + Moves the rectangle \a{offset}.\l{QPointF::x()}{x()} along the x + axis and \a{offset}.\l{QPointF::y()}{y()} along the y axis, + relative to the current position. +*/ + + +/*! + \fn QRectF QRectF::translated(qreal dx, qreal dy) const + + Returns a copy of the rectangle that is translated \a dx along the + x axis and \a dy along the y axis, relative to the current + position. Positive values move the rectangle to the right and + down. + + \sa translate() +*/ + + +/*! + \fn QRectF QRectF::translated(const QPointF &offset) const + \overload + + Returns a copy of the rectangle that is translated + \a{offset}.\l{QPointF::x()}{x()} along the x axis and + \a{offset}.\l{QPointF::y()}{y()} along the y axis, relative to the + current position. +*/ + + +/*! + \fn void QRectF::setRect(qreal x, qreal y, qreal width, qreal height) + + Sets the coordinates of the rectangle's top-left corner to (\a x, + \a y), and its size to the given \a width and \a height. + + \sa getRect(), setCoords() +*/ + + +/*! + \fn void QRectF::setCoords(qreal x1, qreal y1, qreal x2, qreal y2) + + Sets the coordinates of the rectangle's top-left corner to (\a x1, + \a y1), and the coordinates of its bottom-right corner to (\a x2, + \a y2). + + \sa getCoords() setRect() +*/ + +/*! + \fn QRectF QRectF::adjusted(qreal dx1, qreal dy1, qreal dx2, qreal dy2) const + + Returns a new rectangle with \a dx1, \a dy1, \a dx2 and \a dy2 + added respectively to the existing coordinates of this rectangle. + + \sa adjust() +*/ + +/*! \fn void QRectF::adjust(qreal dx1, qreal dy1, qreal dx2, qreal dy2) + + Adds \a dx1, \a dy1, \a dx2 and \a dy2 respectively to the + existing coordinates of the rectangle. + + \sa adjusted(), setRect() +*/ +/*! + \fn QSizeF QRectF::size() const + + Returns the size of the rectangle. + + \sa setSize(), width(), height() +*/ + +/*! + \fn qreal QRectF::width() const + + Returns the width of the rectangle. + + \sa setWidth(), height(), size() +*/ + +/*! + \fn qreal QRectF::height() const + + Returns the height of the rectangle. + + \sa setHeight(), width(), size() +*/ + +/*! + \fn void QRectF::setWidth(qreal width) + + Sets the width of the rectangle to the given \a width. The right + edge is changed, but not the left one. + + \sa width(), setSize() +*/ + + +/*! + \fn void QRectF::setHeight(qreal height) + + Sets the height of the rectangle to the given \a height. The bottom + edge is changed, but not the top one. + + \sa height(), setSize() +*/ + + +/*! + \fn void QRectF::setSize(const QSizeF &size) + + Sets the size of the rectangle to the given \a size. The top-left + corner is not moved. + + \sa size(), setWidth(), setHeight() +*/ + + +/*! + \fn bool QRectF::contains(const QPointF &point) const + + Returns true if the given \a point is inside or on the edge of the + rectangle; otherwise returns false. + + \sa intersects() +*/ + +bool QRectF::contains(const QPointF &p) const +{ + qreal l = xp; + qreal r = xp; + if (w < 0) + l += w; + else + r += w; + if (l == r) // null rect + return false; + + if (p.x() < l || p.x() > r) + return false; + + qreal t = yp; + qreal b = yp; + if (h < 0) + t += h; + else + b += h; + if (t == b) // null rect + return false; + + if (p.y() < t || p.y() > b) + return false; + + return true; +} + + +/*! + \fn bool QRectF::contains(qreal x, qreal y) const + \overload + + Returns true if the point (\a x, \a y) is inside or on the edge of + the rectangle; otherwise returns false. +*/ + +/*! + \fn bool QRectF::contains(const QRectF &rectangle) const + \overload + + Returns true if the given \a rectangle is inside this rectangle; + otherwise returns false. +*/ + +bool QRectF::contains(const QRectF &r) const +{ + qreal l1 = xp; + qreal r1 = xp; + if (w < 0) + l1 += w; + else + r1 += w; + if (l1 == r1) // null rect + return false; + + qreal l2 = r.xp; + qreal r2 = r.xp; + if (r.w < 0) + l2 += r.w; + else + r2 += r.w; + if (l2 == r2) // null rect + return false; + + if (l2 < l1 || r2 > r1) + return false; + + qreal t1 = yp; + qreal b1 = yp; + if (h < 0) + t1 += h; + else + b1 += h; + if (t1 == b1) // null rect + return false; + + qreal t2 = r.yp; + qreal b2 = r.yp; + if (r.h < 0) + t2 += r.h; + else + b2 += r.h; + if (t2 == b2) // null rect + return false; + + if (t2 < t1 || b2 > b1) + return false; + + return true; +} + +/*! + \fn qreal QRectF::left() const + + Returns the x-coordinate of the rectangle's left edge. Equivalent + to x(). + + \sa setLeft(), topLeft(), bottomLeft() +*/ + +/*! + \fn qreal QRectF::top() const + + Returns the y-coordinate of the rectangle's top edge. Equivalent + to y(). + + \sa setTop(), topLeft(), topRight() +*/ + +/*! + \fn qreal QRectF::right() const + + Returns the x-coordinate of the rectangle's right edge. + + \sa setRight(), topRight(), bottomRight() +*/ + +/*! + \fn qreal QRectF::bottom() const + + Returns the y-coordinate of the rectangle's bottom edge. + + \sa setBottom(), bottomLeft(), bottomRight() +*/ + +/*! + \fn QPointF QRectF::topLeft() const + + Returns the position of the rectangle's top-left corner. + + \sa setTopLeft(), top(), left() +*/ + +/*! + \fn QPointF QRectF::bottomRight() const + + Returns the position of the rectangle's bottom-right corner. + + \sa setBottomRight(), bottom(), right() +*/ + +/*! + \fn QPointF QRectF::topRight() const + + Returns the position of the rectangle's top-right corner. + + \sa setTopRight(), top(), right() +*/ + +/*! + \fn QPointF QRectF::bottomLeft() const + + Returns the position of the rectangle's bottom-left corner. + + \sa setBottomLeft(), bottom(), left() +*/ + +/*! + \fn QRectF& QRectF::operator|=(const QRectF &rectangle) + + Unites this rectangle with the given \a rectangle. + + \sa united(), operator|() +*/ + +/*! + \fn QRectF& QRectF::operator&=(const QRectF &rectangle) + + Intersects this rectangle with the given \a rectangle. + + \sa intersected(), operator|=() +*/ + + +/*! + \fn QRectF QRectF::operator|(const QRectF &rectangle) const + + Returns the bounding rectangle of this rectangle and the given \a rectangle. + + \sa united(), operator|=() +*/ + +QRectF QRectF::operator|(const QRectF &r) const +{ + qreal l1 = xp; + qreal r1 = xp; + if (w < 0) + l1 += w; + else + r1 += w; + if (l1 == r1) // null rect + return r; + + qreal l2 = r.xp; + qreal r2 = r.xp; + if (r.w < 0) + l2 += r.w; + else + r2 += r.w; + if (l2 == r2) // null rect + return *this; + + qreal t1 = yp; + qreal b1 = yp; + if (h < 0) + t1 += h; + else + b1 += h; + if (t1 == b1) // null rect + return r; + + qreal t2 = r.yp; + qreal b2 = r.yp; + if (r.h < 0) + t2 += r.h; + else + b2 += r.h; + if (t2 == b2) // null rect + return *this; + + QRectF tmp; + tmp.xp = qMin(l1, l2); + tmp.yp = qMin(t1, t2); + tmp.w = qMax(r1, r2) - tmp.xp; + tmp.h = qMax(b1, b2) - tmp.yp; + return tmp; +} + +/*! + \fn QRectF QRectF::unite(const QRectF &rectangle) const + \obsolete + + Use united(\a rectangle) instead. +*/ + +/*! + \fn QRectF QRectF::united(const QRectF &rectangle) const + \since 4.2 + + Returns the bounding rectangle of this rectangle and the given \a + rectangle. + + \image qrect-unite.png + + \sa intersected() +*/ + + +/*! + \fn QRectF QRectF::operator &(const QRectF &rectangle) const + + Returns the intersection of this rectangle and the given \a + rectangle. Returns an empty rectangle if there is no intersection. + + \sa operator&=(), intersected() +*/ + +QRectF QRectF::operator&(const QRectF &r) const +{ + qreal l1 = xp; + qreal r1 = xp; + if (w < 0) + l1 += w; + else + r1 += w; + if (l1 == r1) // null rect + return QRectF(); + + qreal l2 = r.xp; + qreal r2 = r.xp; + if (r.w < 0) + l2 += r.w; + else + r2 += r.w; + if (l2 == r2) // null rect + return QRectF(); + + if (l1 >= r2 || l2 >= r1) + return QRectF(); + + qreal t1 = yp; + qreal b1 = yp; + if (h < 0) + t1 += h; + else + b1 += h; + if (t1 == b1) // null rect + return QRectF(); + + qreal t2 = r.yp; + qreal b2 = r.yp; + if (r.h < 0) + t2 += r.h; + else + b2 += r.h; + if (t2 == b2) // null rect + return QRectF(); + + if (t1 >= b2 || t2 >= b1) + return QRectF(); + + QRectF tmp; + tmp.xp = qMax(l1, l2); + tmp.yp = qMax(t1, t2); + tmp.w = qMin(r1, r2) - tmp.xp; + tmp.h = qMin(b1, b2) - tmp.yp; + return tmp; +} + +/*! + \fn QRectF QRectF::intersect(const QRectF &rectangle) const + \obsolete + + Use intersected(\a rectangle) instead. +*/ + +/*! + \fn QRectF QRectF::intersected(const QRectF &rectangle) const + \since 4.2 + + Returns the intersection of this rectangle and the given \a + rectangle. Note that \c {r.intersected(s)} is equivalent to \c + {r & s}. + + \image qrect-intersect.png + + \sa intersects(), united(), operator&=() +*/ + +/*! + \fn bool QRectF::intersects(const QRectF &rectangle) const + + Returns true if this rectangle intersects with the given \a + rectangle (i.e. there is a non-empty area of overlap between + them), otherwise returns false. + + The intersection rectangle can be retrieved using the intersected() + function. + + \sa contains() +*/ + +bool QRectF::intersects(const QRectF &r) const +{ + qreal l1 = xp; + qreal r1 = xp; + if (w < 0) + l1 += w; + else + r1 += w; + if (l1 == r1) // null rect + return false; + + qreal l2 = r.xp; + qreal r2 = r.xp; + if (r.w < 0) + l2 += r.w; + else + r2 += r.w; + if (l2 == r2) // null rect + return false; + + if (l1 >= r2 || l2 >= r1) + return false; + + qreal t1 = yp; + qreal b1 = yp; + if (h < 0) + t1 += h; + else + b1 += h; + if (t1 == b1) // null rect + return false; + + qreal t2 = r.yp; + qreal b2 = r.yp; + if (r.h < 0) + t2 += r.h; + else + b2 += r.h; + if (t2 == b2) // null rect + return false; + + if (t1 >= b2 || t2 >= b1) + return false; + + return true; +} + +/*! + \fn QRect QRectF::toRect() const + + Returns a QRect based on the values of this rectangle. Note that the + coordinates in the returned rectangle are rounded to the nearest integer. + + \sa QRectF(), toAlignedRect() +*/ + +/*! + \fn QRect QRectF::toAlignedRect() const + \since 4.3 + + Returns a QRect based on the values of this rectangle that is the + smallest possible integer rectangle that completely contains this + rectangle. + + \sa toRect() +*/ + +QRect QRectF::toAlignedRect() const +{ + int xmin = int(qFloor(xp)); + int xmax = int(qCeil(xp + w)); + int ymin = int(qFloor(yp)); + int ymax = int(qCeil(yp + h)); + return QRect(xmin, ymin, xmax - xmin, ymax - ymin); +} + +/*! + \fn void QRectF::moveCenter(const QPointF &position) + + Moves the rectangle, leaving the center point at the given \a + position. The rectangle's size is unchanged. + + \sa center() +*/ + +/*! + \fn bool operator==(const QRectF &r1, const QRectF &r2) + \relates QRectF + + Returns true if the rectangles \a r1 and \a r2 are equal, + otherwise returns false. +*/ + + +/*! + \fn bool operator!=(const QRectF &r1, const QRectF &r2) + \relates QRectF + + Returns true if the rectangles \a r1 and \a r2 are different, otherwise + returns false. +*/ + +/***************************************************************************** + QRectF stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QRectF &rectangle) + + \relates QRectF + + Writes the \a rectangle to the \a stream, and returns a reference to the + stream. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator<<(QDataStream &s, const QRectF &r) +{ + s << double(r.x()) << double(r.y()) << double(r.width()) << double(r.height()); + return s; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QRectF &rectangle) + + \relates QRectF + + Reads a \a rectangle from the \a stream, and returns a reference to the + stream. + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QDataStream &operator>>(QDataStream &s, QRectF &r) +{ + double x, y, w, h; + s >> x; + s >> y; + s >> w; + s >> h; + r.setRect(qreal(x), qreal(y), qreal(w), qreal(h)); + return s; +} + +#endif // QT_NO_DATASTREAM + + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QRectF &r) { + dbg.nospace() << "QRectF(" << r.x() << ',' << r.y() << ' ' + << r.width() << 'x' << r.height() << ')'; + return dbg.space(); +} +#endif + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h new file mode 100644 index 0000000..194787e --- /dev/null +++ b/src/corelib/tools/qrect.h @@ -0,0 +1,858 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QRECT_H +#define QRECT_H + +#include <QtCore/qsize.h> +#include <QtCore/qpoint.h> + +#ifdef topLeft +#error qrect.h must be included before any header file that defines topLeft +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class Q_CORE_EXPORT QRect +{ +public: + QRect() { x1 = y1 = 0; x2 = y2 = -1; } + QRect(const QPoint &topleft, const QPoint &bottomright); + QRect(const QPoint &topleft, const QSize &size); + QRect(int left, int top, int width, int height); + + bool isNull() const; + bool isEmpty() const; + bool isValid() const; + + int left() const; + int top() const; + int right() const; + int bottom() const; + QRect normalized() const; + +#ifdef QT3_SUPPORT + QT3_SUPPORT int &rLeft() { return x1; } + QT3_SUPPORT int &rTop() { return y1; } + QT3_SUPPORT int &rRight() { return x2; } + QT3_SUPPORT int &rBottom() { return y2; } + + QT3_SUPPORT QRect normalize() const { return normalized(); } +#endif + + int x() const; + int y() const; + void setLeft(int pos); + void setTop(int pos); + void setRight(int pos); + void setBottom(int pos); + void setX(int x); + void setY(int y); + + void setTopLeft(const QPoint &p); + void setBottomRight(const QPoint &p); + void setTopRight(const QPoint &p); + void setBottomLeft(const QPoint &p); + + QPoint topLeft() const; + QPoint bottomRight() const; + QPoint topRight() const; + QPoint bottomLeft() const; + QPoint center() const; + + void moveLeft(int pos); + void moveTop(int pos); + void moveRight(int pos); + void moveBottom(int pos); + void moveTopLeft(const QPoint &p); + void moveBottomRight(const QPoint &p); + void moveTopRight(const QPoint &p); + void moveBottomLeft(const QPoint &p); + void moveCenter(const QPoint &p); + + inline void translate(int dx, int dy); + inline void translate(const QPoint &p); + inline QRect translated(int dx, int dy) const; + inline QRect translated(const QPoint &p) const; + + void moveTo(int x, int t); + void moveTo(const QPoint &p); + +#ifdef QT3_SUPPORT + QT3_SUPPORT void moveBy(int dx, int dy) { translate(dx, dy); } + QT3_SUPPORT void moveBy(const QPoint &p) { translate(p); } +#endif + + void setRect(int x, int y, int w, int h); + inline void getRect(int *x, int *y, int *w, int *h) const; + + void setCoords(int x1, int y1, int x2, int y2); +#ifdef QT3_SUPPORT + QT3_SUPPORT void addCoords(int x1, int y1, int x2, int y2); +#endif + inline void getCoords(int *x1, int *y1, int *x2, int *y2) const; + + inline void adjust(int x1, int y1, int x2, int y2); + inline QRect adjusted(int x1, int y1, int x2, int y2) const; + + QSize size() const; + int width() const; + int height() const; + void setWidth(int w); + void setHeight(int h); + void setSize(const QSize &s); + + QRect operator|(const QRect &r) const; + QRect operator&(const QRect &r) const; + QRect& operator|=(const QRect &r); + QRect& operator&=(const QRect &r); + + bool contains(const QPoint &p, bool proper=false) const; + bool contains(int x, int y) const; // inline methods, _don't_ merge these + bool contains(int x, int y, bool proper) const; + bool contains(const QRect &r, bool proper = false) const; + QRect unite(const QRect &r) const; // ### Qt 5: make QT4_SUPPORT + QRect united(const QRect &other) const; + QRect intersect(const QRect &r) const; // ### Qt 5: make QT4_SUPPORT + QRect intersected(const QRect &other) const; + bool intersects(const QRect &r) const; + + friend Q_CORE_EXPORT_INLINE bool operator==(const QRect &, const QRect &); + friend Q_CORE_EXPORT_INLINE bool operator!=(const QRect &, const QRect &); + +#ifdef QT3_SUPPORT + inline QT3_SUPPORT void rect(int *x, int *y, int *w, int *h) const { getRect(x, y, w, h); } + inline QT3_SUPPORT void coords(int *ax1, int *ay1, int *ax2, int *ay2) const + { getCoords(ax1, ay1, ax2, ay2); } +#endif + +private: +#if defined(Q_WS_X11) + friend void qt_setCoords(QRect *r, int xp1, int yp1, int xp2, int yp2); +#endif + // ### Qt 5; remove the ifdef and just have the same order on all platforms. +#if defined(Q_OS_MAC) + int y1; + int x1; + int y2; + int x2; +#else + int x1; + int y1; + int x2; + int y2; +#endif + +}; +Q_DECLARE_TYPEINFO(QRect, Q_MOVABLE_TYPE); + +Q_CORE_EXPORT_INLINE bool operator==(const QRect &, const QRect &); +Q_CORE_EXPORT_INLINE bool operator!=(const QRect &, const QRect &); + + +/***************************************************************************** + QRect stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QRect &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QRect &); +#endif + +/***************************************************************************** + QRect inline member functions + *****************************************************************************/ + +inline QRect::QRect(int aleft, int atop, int awidth, int aheight) +{ + x1 = aleft; + y1 = atop; + x2 = (aleft + awidth - 1); + y2 = (atop + aheight - 1); +} + +inline QRect::QRect(const QPoint &atopLeft, const QPoint &abottomRight) +{ + x1 = atopLeft.x(); + y1 = atopLeft.y(); + x2 = abottomRight.x(); + y2 = abottomRight.y(); +} + +inline QRect::QRect(const QPoint &atopLeft, const QSize &asize) +{ + x1 = atopLeft.x(); + y1 = atopLeft.y(); + x2 = (x1+asize.width() - 1); + y2 = (y1+asize.height() - 1); +} + +inline bool QRect::isNull() const +{ return x2 == x1 - 1 && y2 == y1 - 1; } + +inline bool QRect::isEmpty() const +{ return x1 > x2 || y1 > y2; } + +inline bool QRect::isValid() const +{ return x1 <= x2 && y1 <= y2; } + +inline int QRect::left() const +{ return x1; } + +inline int QRect::top() const +{ return y1; } + +inline int QRect::right() const +{ return x2; } + +inline int QRect::bottom() const +{ return y2; } + +inline int QRect::x() const +{ return x1; } + +inline int QRect::y() const +{ return y1; } + +inline void QRect::setLeft(int pos) +{ x1 = pos; } + +inline void QRect::setTop(int pos) +{ y1 = pos; } + +inline void QRect::setRight(int pos) +{ x2 = pos; } + +inline void QRect::setBottom(int pos) +{ y2 = pos; } + +inline void QRect::setTopLeft(const QPoint &p) +{ x1 = p.x(); y1 = p.y(); } + +inline void QRect::setBottomRight(const QPoint &p) +{ x2 = p.x(); y2 = p.y(); } + +inline void QRect::setTopRight(const QPoint &p) +{ x2 = p.x(); y1 = p.y(); } + +inline void QRect::setBottomLeft(const QPoint &p) +{ x1 = p.x(); y2 = p.y(); } + +inline void QRect::setX(int ax) +{ x1 = ax; } + +inline void QRect::setY(int ay) +{ y1 = ay; } + +inline QPoint QRect::topLeft() const +{ return QPoint(x1, y1); } + +inline QPoint QRect::bottomRight() const +{ return QPoint(x2, y2); } + +inline QPoint QRect::topRight() const +{ return QPoint(x2, y1); } + +inline QPoint QRect::bottomLeft() const +{ return QPoint(x1, y2); } + +inline QPoint QRect::center() const +{ return QPoint((x1+x2)/2, (y1+y2)/2); } + +inline int QRect::width() const +{ return x2 - x1 + 1; } + +inline int QRect::height() const +{ return y2 - y1 + 1; } + +inline QSize QRect::size() const +{ return QSize(width(), height()); } + +inline void QRect::translate(int dx, int dy) +{ + x1 += dx; + y1 += dy; + x2 += dx; + y2 += dy; +} + +inline void QRect::translate(const QPoint &p) +{ + x1 += p.x(); + y1 += p.y(); + x2 += p.x(); + y2 += p.y(); +} + +inline QRect QRect::translated(int dx, int dy) const +{ return QRect(QPoint(x1 + dx, y1 + dy), QPoint(x2 + dx, y2 + dy)); } + +inline QRect QRect::translated(const QPoint &p) const +{ return QRect(QPoint(x1 + p.x(), y1 + p.y()), QPoint(x2 + p.x(), y2 + p.y())); } + +inline void QRect::moveTo(int ax, int ay) +{ + x2 += ax - x1; + y2 += ay - y1; + x1 = ax; + y1 = ay; +} + +inline void QRect::moveTo(const QPoint &p) +{ + x2 += p.x() - x1; + y2 += p.y() - y1; + x1 = p.x(); + y1 = p.y(); +} + +inline void QRect::moveLeft(int pos) +{ x2 += (pos - x1); x1 = pos; } + +inline void QRect::moveTop(int pos) +{ y2 += (pos - y1); y1 = pos; } + +inline void QRect::moveRight(int pos) +{ + x1 += (pos - x2); + x2 = pos; +} + +inline void QRect::moveBottom(int pos) +{ + y1 += (pos - y2); + y2 = pos; +} + +inline void QRect::moveTopLeft(const QPoint &p) +{ + moveLeft(p.x()); + moveTop(p.y()); +} + +inline void QRect::moveBottomRight(const QPoint &p) +{ + moveRight(p.x()); + moveBottom(p.y()); +} + +inline void QRect::moveTopRight(const QPoint &p) +{ + moveRight(p.x()); + moveTop(p.y()); +} + +inline void QRect::moveBottomLeft(const QPoint &p) +{ + moveLeft(p.x()); + moveBottom(p.y()); +} + +inline void QRect::getRect(int *ax, int *ay, int *aw, int *ah) const +{ + *ax = x1; + *ay = y1; + *aw = x2 - x1 + 1; + *ah = y2 - y1 + 1; +} + +inline void QRect::setRect(int ax, int ay, int aw, int ah) +{ + x1 = ax; + y1 = ay; + x2 = (ax + aw - 1); + y2 = (ay + ah - 1); +} + +inline void QRect::getCoords(int *xp1, int *yp1, int *xp2, int *yp2) const +{ + *xp1 = x1; + *yp1 = y1; + *xp2 = x2; + *yp2 = y2; +} + +inline void QRect::setCoords(int xp1, int yp1, int xp2, int yp2) +{ + x1 = xp1; + y1 = yp1; + x2 = xp2; + y2 = yp2; +} + +#ifdef QT3_SUPPORT +inline void QRect::addCoords(int dx1, int dy1, int dx2, int dy2) +{ + adjust(dx1, dy1, dx2, dy2); +} +#endif + +inline QRect QRect::adjusted(int xp1, int yp1, int xp2, int yp2) const +{ return QRect(QPoint(x1 + xp1, y1 + yp1), QPoint(x2 + xp2, y2 + yp2)); } + +inline void QRect::adjust(int dx1, int dy1, int dx2, int dy2) +{ + x1 += dx1; + y1 += dy1; + x2 += dx2; + y2 += dy2; +} + +inline void QRect::setWidth(int w) +{ x2 = (x1 + w - 1); } + +inline void QRect::setHeight(int h) +{ y2 = (y1 + h - 1); } + +inline void QRect::setSize(const QSize &s) +{ + x2 = (s.width() + x1 - 1); + y2 = (s.height() + y1 - 1); +} + +inline bool QRect::contains(int ax, int ay, bool aproper) const +{ + return contains(QPoint(ax, ay), aproper); +} + +inline bool QRect::contains(int ax, int ay) const +{ + return contains(QPoint(ax, ay), false); +} + +inline QRect& QRect::operator|=(const QRect &r) +{ + *this = *this | r; + return *this; +} + +inline QRect& QRect::operator&=(const QRect &r) +{ + *this = *this & r; + return *this; +} + +inline QRect QRect::intersect(const QRect &r) const +{ + return *this & r; +} + +inline QRect QRect::intersected(const QRect &other) const +{ + return intersect(other); +} + +inline QRect QRect::unite(const QRect &r) const +{ + return *this | r; +} + +inline QRect QRect::united(const QRect &r) const +{ + return unite(r); +} + +inline bool operator==(const QRect &r1, const QRect &r2) +{ + return r1.x1==r2.x1 && r1.x2==r2.x2 && r1.y1==r2.y1 && r1.y2==r2.y2; +} + +inline bool operator!=(const QRect &r1, const QRect &r2) +{ + return r1.x1!=r2.x1 || r1.x2!=r2.x2 || r1.y1!=r2.y1 || r1.y2!=r2.y2; +} + +#ifndef QT_NO_DEBUG_STREAM +Q_CORE_EXPORT QDebug operator<<(QDebug, const QRect &); +#endif + + +class Q_CORE_EXPORT QRectF +{ +public: + QRectF() { xp = yp = 0.; w = h = 0.; } + QRectF(const QPointF &topleft, const QSizeF &size); + QRectF(const QPointF &topleft, const QPointF &bottomRight); + QRectF(qreal left, qreal top, qreal width, qreal height); + QRectF(const QRect &rect); + + bool isNull() const; + bool isEmpty() const; + bool isValid() const; + QRectF normalized() const; + + inline qreal left() const { return xp; } + inline qreal top() const { return yp; } + inline qreal right() const { return xp + w; } + inline qreal bottom() const { return yp + h; } + + inline qreal x() const; + inline qreal y() const; + inline void setLeft(qreal pos); + inline void setTop(qreal pos); + inline void setRight(qreal pos); + inline void setBottom(qreal pos); + inline void setX(qreal pos) { setLeft(pos); } + inline void setY(qreal pos) { setTop(pos); } + + inline QPointF topLeft() const { return QPointF(xp, yp); } + inline QPointF bottomRight() const { return QPointF(xp+w, yp+h); } + inline QPointF topRight() const { return QPointF(xp+w, yp); } + inline QPointF bottomLeft() const { return QPointF(xp, yp+h); } + inline QPointF center() const; + + void setTopLeft(const QPointF &p); + void setBottomRight(const QPointF &p); + void setTopRight(const QPointF &p); + void setBottomLeft(const QPointF &p); + + void moveLeft(qreal pos); + void moveTop(qreal pos); + void moveRight(qreal pos); + void moveBottom(qreal pos); + void moveTopLeft(const QPointF &p); + void moveBottomRight(const QPointF &p); + void moveTopRight(const QPointF &p); + void moveBottomLeft(const QPointF &p); + void moveCenter(const QPointF &p); + + void translate(qreal dx, qreal dy); + void translate(const QPointF &p); + + QRectF translated(qreal dx, qreal dy) const; + QRectF translated(const QPointF &p) const; + + void moveTo(qreal x, qreal t); + void moveTo(const QPointF &p); + + void setRect(qreal x, qreal y, qreal w, qreal h); + void getRect(qreal *x, qreal *y, qreal *w, qreal *h) const; + + void setCoords(qreal x1, qreal y1, qreal x2, qreal y2); + void getCoords(qreal *x1, qreal *y1, qreal *x2, qreal *y2) const; + + inline void adjust(qreal x1, qreal y1, qreal x2, qreal y2); + inline QRectF adjusted(qreal x1, qreal y1, qreal x2, qreal y2) const; + + QSizeF size() const; + qreal width() const; + qreal height() const; + void setWidth(qreal w); + void setHeight(qreal h); + void setSize(const QSizeF &s); + + QRectF operator|(const QRectF &r) const; + QRectF operator&(const QRectF &r) const; + QRectF& operator|=(const QRectF &r); + QRectF& operator&=(const QRectF &r); + + bool contains(const QPointF &p) const; + bool contains(qreal x, qreal y) const; + bool contains(const QRectF &r) const; + QRectF unite(const QRectF &r) const; // ### Qt 5: make QT4_SUPPORT + QRectF united(const QRectF &other) const; + QRectF intersect(const QRectF &r) const; // ### Qt 5: make QT4_SUPPORT + QRectF intersected(const QRectF &other) const; + bool intersects(const QRectF &r) const; + + friend Q_CORE_EXPORT_INLINE bool operator==(const QRectF &, const QRectF &); + friend Q_CORE_EXPORT_INLINE bool operator!=(const QRectF &, const QRectF &); + + QRect toRect() const; + QRect toAlignedRect() const; + +private: + qreal xp; + qreal yp; + qreal w; + qreal h; +}; +Q_DECLARE_TYPEINFO(QRectF, Q_MOVABLE_TYPE); + +Q_CORE_EXPORT_INLINE bool operator==(const QRectF &, const QRectF &); +Q_CORE_EXPORT_INLINE bool operator!=(const QRectF &, const QRectF &); + + +/***************************************************************************** + QRectF stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QRectF &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QRectF &); +#endif + +/***************************************************************************** + QRectF inline member functions + *****************************************************************************/ + +inline QRectF::QRectF(qreal aleft, qreal atop, qreal awidth, qreal aheight) + : xp(aleft), yp(atop), w(awidth), h(aheight) +{ +} + +inline QRectF::QRectF(const QPointF &atopLeft, const QSizeF &asize) +{ + xp = atopLeft.x(); + yp = atopLeft.y(); + w = asize.width(); + h = asize.height(); +} + +inline QRectF::QRectF(const QPointF &atopLeft, const QPointF &abottomRight) +{ + xp = atopLeft.x(); + yp = atopLeft.y(); + w = abottomRight.x() - xp; + h = abottomRight.y() - yp; +} + +inline QRectF::QRectF(const QRect &r) + : xp(r.x()), yp(r.y()), w(r.width()), h(r.height()) +{ +} + +inline bool QRectF::isNull() const +{ return qIsNull(w) && qIsNull(h); } + +inline bool QRectF::isEmpty() const +{ return w <= 0. || h <= 0.; } + +inline bool QRectF::isValid() const +{ return w > 0. && h > 0.; } + +inline qreal QRectF::x() const +{ return xp; } + +inline qreal QRectF::y() const +{ return yp; } + +inline void QRectF::setLeft(qreal pos) { qreal diff = pos - xp; xp += diff; w -= diff; } + +inline void QRectF::setRight(qreal pos) { w = pos - xp; } + +inline void QRectF::setTop(qreal pos) { qreal diff = pos - yp; yp += diff; h -= diff; } + +inline void QRectF::setBottom(qreal pos) { h = pos - yp; } + +inline void QRectF::setTopLeft(const QPointF &p) { setLeft(p.x()); setTop(p.y()); } + +inline void QRectF::setTopRight(const QPointF &p) { setRight(p.x()); setTop(p.y()); } + +inline void QRectF::setBottomLeft(const QPointF &p) { setLeft(p.x()); setBottom(p.y()); } + +inline void QRectF::setBottomRight(const QPointF &p) { setRight(p.x()); setBottom(p.y()); } + +inline QPointF QRectF::center() const +{ return QPointF(xp + w/2, yp + h/2); } + +inline void QRectF::moveLeft(qreal pos) { xp = pos; } + +inline void QRectF::moveTop(qreal pos) { yp = pos; } + +inline void QRectF::moveRight(qreal pos) { xp = pos - w; } + +inline void QRectF::moveBottom(qreal pos) { yp = pos - h; } + +inline void QRectF::moveTopLeft(const QPointF &p) { moveLeft(p.x()); moveTop(p.y()); } + +inline void QRectF::moveTopRight(const QPointF &p) { moveRight(p.x()); moveTop(p.y()); } + +inline void QRectF::moveBottomLeft(const QPointF &p) { moveLeft(p.x()); moveBottom(p.y()); } + +inline void QRectF::moveBottomRight(const QPointF &p) { moveRight(p.x()); moveBottom(p.y()); } + +inline void QRectF::moveCenter(const QPointF &p) { xp = p.x() - w/2; yp = p.y() - h/2; } + +inline qreal QRectF::width() const +{ return w; } + +inline qreal QRectF::height() const +{ return h; } + +inline QSizeF QRectF::size() const +{ return QSizeF(w, h); } + +inline void QRectF::translate(qreal dx, qreal dy) +{ + xp += dx; + yp += dy; +} + +inline void QRectF::translate(const QPointF &p) +{ + xp += p.x(); + yp += p.y(); +} + +inline void QRectF::moveTo(qreal ax, qreal ay) +{ + xp = ax; + yp = ay; +} + +inline void QRectF::moveTo(const QPointF &p) +{ + xp = p.x(); + yp = p.y(); +} + +inline QRectF QRectF::translated(qreal dx, qreal dy) const +{ return QRectF(xp + dx, yp + dy, w, h); } + +inline QRectF QRectF::translated(const QPointF &p) const +{ return QRectF(xp + p.x(), yp + p.y(), w, h); } + +inline void QRectF::getRect(qreal *ax, qreal *ay, qreal *aaw, qreal *aah) const +{ + *ax = this->xp; + *ay = this->yp; + *aaw = this->w; + *aah = this->h; +} + +inline void QRectF::setRect(qreal ax, qreal ay, qreal aaw, qreal aah) +{ + this->xp = ax; + this->yp = ay; + this->w = aaw; + this->h = aah; +} + +inline void QRectF::getCoords(qreal *xp1, qreal *yp1, qreal *xp2, qreal *yp2) const +{ + *xp1 = xp; + *yp1 = yp; + *xp2 = xp + w; + *yp2 = yp + h; +} + +inline void QRectF::setCoords(qreal xp1, qreal yp1, qreal xp2, qreal yp2) +{ + xp = xp1; + yp = yp1; + w = xp2 - xp1; + h = yp2 - yp1; +} + +inline void QRectF::adjust(qreal xp1, qreal yp1, qreal xp2, qreal yp2) +{ xp += xp1; yp += yp1; w += xp2 - xp1; h += yp2 - yp1; } + +inline QRectF QRectF::adjusted(qreal xp1, qreal yp1, qreal xp2, qreal yp2) const +{ return QRectF(xp + xp1, yp + yp1, w + xp2 - xp1, h + yp2 - yp1); } + +inline void QRectF::setWidth(qreal aw) +{ this->w = aw; } + +inline void QRectF::setHeight(qreal ah) +{ this->h = ah; } + +inline void QRectF::setSize(const QSizeF &s) +{ + w = s.width(); + h = s.height(); +} + +inline bool QRectF::contains(qreal ax, qreal ay) const +{ + return contains(QPointF(ax, ay)); +} + +inline QRectF& QRectF::operator|=(const QRectF &r) +{ + *this = *this | r; + return *this; +} + +inline QRectF& QRectF::operator&=(const QRectF &r) +{ + *this = *this & r; + return *this; +} + +inline QRectF QRectF::intersect(const QRectF &r) const +{ + return *this & r; +} + +inline QRectF QRectF::intersected(const QRectF &r) const +{ + return intersect(r); +} + +inline QRectF QRectF::unite(const QRectF &r) const +{ + return *this | r; +} + +inline QRectF QRectF::united(const QRectF &r) const +{ + return unite(r); +} + +inline bool operator==(const QRectF &r1, const QRectF &r2) +{ + return qFuzzyCompare(r1.xp, r2.xp) && qFuzzyCompare(r1.yp, r2.yp) + && qFuzzyCompare(r1.w, r2.w) && qFuzzyCompare(r1.h, r2.h); +} + +inline bool operator!=(const QRectF &r1, const QRectF &r2) +{ + return !qFuzzyCompare(r1.xp, r2.xp) || !qFuzzyCompare(r1.yp, r2.yp) + || !qFuzzyCompare(r1.w, r2.w) || !qFuzzyCompare(r1.h, r2.h); +} + +inline QRect QRectF::toRect() const +{ + return QRect(qRound(xp), qRound(yp), qRound(w), qRound(h)); +} + +#ifndef QT_NO_DEBUG_STREAM +Q_CORE_EXPORT QDebug operator<<(QDebug, const QRectF &); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QRECT_H diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp new file mode 100644 index 0000000..e1c3921 --- /dev/null +++ b/src/corelib/tools/qregexp.cpp @@ -0,0 +1,4070 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qregexp.h" + +#include "qalgorithms.h" +#include "qbitarray.h" +#include "qcache.h" +#include "qdatastream.h" +#include "qlist.h" +#include "qmap.h" +#include "qmutex.h" +#include "qstring.h" +#include "qstringlist.h" +#include "qstringmatcher.h" +#include "qvector.h" + +#include <limits.h> + +QT_BEGIN_NAMESPACE + +int qFindString(const QChar *haystack, int haystackLen, int from, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs); + +// error strings for the regexp parser +#define RXERR_OK QT_TRANSLATE_NOOP("QRegExp", "no error occurred") +#define RXERR_DISABLED QT_TRANSLATE_NOOP("QRegExp", "disabled feature used") +#define RXERR_CHARCLASS QT_TRANSLATE_NOOP("QRegExp", "bad char class syntax") +#define RXERR_LOOKAHEAD QT_TRANSLATE_NOOP("QRegExp", "bad lookahead syntax") +#define RXERR_REPETITION QT_TRANSLATE_NOOP("QRegExp", "bad repetition syntax") +#define RXERR_OCTAL QT_TRANSLATE_NOOP("QRegExp", "invalid octal value") +#define RXERR_LEFTDELIM QT_TRANSLATE_NOOP("QRegExp", "missing left delim") +#define RXERR_END QT_TRANSLATE_NOOP("QRegExp", "unexpected end") +#define RXERR_LIMIT QT_TRANSLATE_NOOP("QRegExp", "met internal limit") + +/* + WARNING! Be sure to read qregexp.tex before modifying this file. +*/ + +/*! + \class QRegExp + \reentrant + \brief The QRegExp class provides pattern matching using regular expressions. + + \ingroup tools + \ingroup misc + \ingroup shared + \mainclass + \keyword regular expression + + A regular expression, or "regexp", is a pattern for matching + substrings in a text. This is useful in many contexts, e.g., + + \table + \row \i Validation + \i A regexp can test whether a substring meets some criteria, + e.g. is an integer or contains no whitespace. + \row \i Searching + \i A regexp provides more powerful pattern matching than + simple substring matching, e.g., match one of the words + \e{mail}, \e{letter} or \e{correspondence}, but none of the + words \e{email}, \e{mailman}, \e{mailer}, \e{letterbox}, etc. + \row \i Search and Replace + \i A regexp can replace all occurrences of a substring with a + different substring, e.g., replace all occurrences of \e{&} + with \e{\&} except where the \e{&} is already followed by + an \e{amp;}. + \row \i String Splitting + \i A regexp can be used to identify where a string should be + split apart, e.g. splitting tab-delimited strings. + \endtable + + A brief introduction to regexps is presented, a description of + Qt's regexp language, some examples, and the function + documentation itself. QRegExp is modeled on Perl's regexp + language. It fully supports Unicode. QRegExp can also be used in a + simpler, \e{wildcard mode} that is similar to the functionality + found in command shells. The syntax rules used by QRegExp can be + changed with setPatternSyntax(). In particular, the pattern syntax + can be set to QRegExp::FixedString, which means the pattern to be + matched is interpreted as a plain string, i.e., special characters + (e.g., backslash) are not escaped. + + A good text on regexps is \e {Mastering Regular Expressions} + (Third Edition) by Jeffrey E. F. Friedl, ISBN 0-596-52812-4. + + \tableofcontents + + \section1 Introduction + + Regexps are built up from expressions, quantifiers, and + assertions. The simplest expression is a character, e.g. \bold{x} + or \bold{5}. An expression can also be a set of characters + enclosed in square brackets. \bold{[ABCD]} will match an \bold{A} + or a \bold{B} or a \bold{C} or a \bold{D}. We can write this same + expression as \bold{[A-D]}, and an experession to match any + captital letter in the English alphabet is written as + \bold{[A-Z]}. + + A quantifier specifies the number of occurrences of an expression + that must be matched. \bold{x{1,1}} means match one and only one + \bold{x}. \bold{x{1,5}} means match a sequence of \bold{x} + characters that contains at least one \bold{x} but no more than + five. + + Note that in general regexps cannot be used to check for balanced + brackets or tags. For example, a regexp can be written to match an + opening html \c{<b>} and its closing \c{</b>}, if the \c{<b>} tags + are not nested, but if the \c{<b>} tags are nested, that same + regexp will match an opening \c{<b>} tag with the wrong closing + \c{</b>}. For the fragment \c{<b>bold <b>bolder</b></b>}, the + first \c{<b>} would be matched with the first \c{</b>}, which is + not correct. However, it is possible to write a regexp that will + match nested brackets or tags correctly, but only if the number of + nesting levels is fixed and known. If the number of nesting levels + is not fixed and known, it is impossible to write a regexp that + will not fail. + + Suppose we want a regexp to match integers in the range 0 to 99. + At least one digit is required, so we start with the expression + \bold{[0-9]{1,1}}, which matches a single digit exactly once. This + regexp matches integers in the range 0 to 9. To match integers up + to 99, increase the maximum number of occurrences to 2, so the + regexp becomes \bold{[0-9]{1,2}}. This regexp satisfies the + original requirement to match integers from 0 to 99, but it will + also match integers that occur in the middle of strings. If we + want the matched integer to be the whole string, we must use the + anchor assertions, \bold{^} (caret) and \bold{$} (dollar). When + \bold{^} is the first character in a regexp, it means the regexp + must match from the beginning of the string. When \bold{$} is the + last character of the regexp, it means the regexp must match to + the end of the string. The regexp becomes \bold{^[0-9]{1,2}$}. + Note that assertions, e.g. \bold{^} and \bold{$}, do not match + characters but locations in the string. + + If you have seen regexps described elsewhere, they may have looked + different from the ones shown here. This is because some sets of + characters and some quantifiers are so common that they have been + given special symbols to represent them. \bold{[0-9]} can be + replaced with the symbol \bold{\\d}. The quantifier to match + exactly one occurrence, \bold{{1,1}}, can be replaced with the + expression itself, i.e. \bold{x{1,1}} is the same as \bold{x}. So + our 0 to 99 matcher could be written as \bold{^\\d{1,2}$}. It can + also be written \bold{^\\d\\d{0,1}$}, i.e. \e{From the start of + the string, match a digit, followed immediately by 0 or 1 digits}. + In practice, it would be written as \bold{^\\d\\d?$}. The \bold{?} + is shorthand for the quantifier \bold{{0,1}}, i.e. 0 or 1 + occurrences. \bold{?} makes an expression optional. The regexp + \bold{^\\d\\d?$} means \e{From the beginning of the string, match + one digit, followed immediately by 0 or 1 more digit, followed + immediately by end of string}. + + To write a regexp that matches one of the words 'mail' \e or + 'letter' \e or 'correspondence' but does not match words that + contain these words, e.g., 'email', 'mailman', 'mailer', and + 'letterbox', start with a regexp that matches 'mail'. Expressed + fully, the regexp is \bold{m{1,1}a{1,1}i{1,1}l{1,1}}, but because + a character expression is automatically quantified by + \bold{{1,1}}, we can simplify the regexp to \bold{mail}, i.e., an + 'm' followed by an 'a' followed by an 'i' followed by an 'l'. Now + we can use the vertical bar \bold{|}, which means \bold{or}, to + include the other two words, so our regexp for matching any of the + three words becomes \bold{mail|letter|correspondence}. Match + 'mail' \bold{or} 'letter' \bold{or} 'correspondence'. While this + regexp will match one of the three words we want to match, it will + also match words we don't want to match, e.g., 'email'. To + prevent the regexp from matching unwanted words, we must tell it + to begin and end the match at word boundaries. First we enclose + our regexp in parentheses, \bold{(mail|letter|correspondence)}. + Parentheses group expressions together, and they identify a part + of the regexp that we wish to \l{capturing text}{capture}. + Enclosing the expression in parentheses allows us to use it as a + component in more complex regexps. It also allows us to examine + which of the three words was actually matched. To force the match + to begin and end on word boundaries, we enclose the regexp in + \bold{\\b} \e{word boundary} assertions: + \bold{\\b(mail|letter|correspondence)\\b}. Now the regexp means: + \e{Match a word boundary, followed by the regexp in parentheses, + followed by a word boundary}. The \bold{\\b} assertion matches a + \e position in the regexp, not a \e character. A word boundary is + any non-word character, e.g., a space, newline, or the beginning + or ending of a string. + + If we want to replace ampersand characters with the HTML entity + \bold{\&}, the regexp to match is simply \bold{\&}. But this + regexp will also match ampersands that have already been converted + to HTML entities. We want to replace only ampersands that are not + already followed by \bold{amp;}. For this, we need the negative + lookahead assertion, \bold{(?!}__\bold{)}. The regexp can then be + written as \bold{\&(?!amp;)}, i.e. \e{Match an ampersand that is} + \bold{not} \e{followed by} \bold{amp;}. + + If we want to count all the occurrences of 'Eric' and 'Eirik' in a + string, two valid solutions are \bold{\\b(Eric|Eirik)\\b} and + \bold{\\bEi?ri[ck]\\b}. The word boundary assertion '\\b' is + required to avoid matching words that contain either name, + e.g. 'Ericsson'. Note that the second regexp matches more + spellings than we want: 'Eric', 'Erik', 'Eiric' and 'Eirik'. + + Some of the examples discussed above are implemented in the + \link #code-examples code examples \endlink section. + + \target characters-and-abbreviations-for-sets-of-characters + \section1 Characters and Abbreviations for Sets of Characters + + \table + \header \i Element \i Meaning + \row \i \bold{c} + \i A character represents itself unless it has a special + regexp meaning. e.g. \bold{c} matches the character \e c. + \row \i \bold{\\c} + \i A character that follows a backslash matches the character + itself, except as specified below. e.g., To match a literal + caret at the beginning of a string, write \bold{\\^}. + \row \i \bold{\\a} + \i Matches the ASCII bell (BEL, 0x07). + \row \i \bold{\\f} + \i Matches the ASCII form feed (FF, 0x0C). + \row \i \bold{\\n} + \i Matches the ASCII line feed (LF, 0x0A, Unix newline). + \row \i \bold{\\r} + \i Matches the ASCII carriage return (CR, 0x0D). + \row \i \bold{\\t} + \i Matches the ASCII horizontal tab (HT, 0x09). + \row \i \bold{\\v} + \i Matches the ASCII vertical tab (VT, 0x0B). + \row \i \bold{\\x\e{hhhh}} + \i Matches the Unicode character corresponding to the + hexadecimal number \e{hhhh} (between 0x0000 and 0xFFFF). + \row \i \bold{\\0\e{ooo}} (i.e., \\zero \e{ooo}) + \i matches the ASCII/Latin1 character for the octal number + \e{ooo} (between 0 and 0377). + \row \i \bold{. (dot)} + \i Matches any character (including newline). + \row \i \bold{\\d} + \i Matches a digit (QChar::isDigit()). + \row \i \bold{\\D} + \i Matches a non-digit. + \row \i \bold{\\s} + \i Matches a whitespace character (QChar::isSpace()). + \row \i \bold{\\S} + \i Matches a non-whitespace character. + \row \i \bold{\\w} + \i Matches a word character (QChar::isLetterOrNumber(), QChar::isMark(), or '_'). + \row \i \bold{\\W} + \i Matches a non-word character. + \row \i \bold{\\\e{n}} + \i The \e{n}-th \l backreference, e.g. \\1, \\2, etc. + \endtable + + \bold{Note:} The C++ compiler transforms backslashes in strings. + To include a \bold{\\} in a regexp, enter it twice, i.e. \c{\\}. + To match the backslash character itself, enter it four times, i.e. + \c{\\\\}. + + \target sets-of-characters + \section1 Sets of Characters + + Square brackets mean match any character contained in the square + brackets. The character set abbreviations described above can + appear in a character set in square brackets. Except for the + character set abbreviations and the following two exceptions, + characters do not have special meanings in square brackets. + + \table + \row \i \bold{^} + + \i The caret negates the character set if it occurs as the + first character (i.e. immediately after the opening square + bracket). \bold{[abc]} matches 'a' or 'b' or 'c', but + \bold{[^abc]} matches anything \e but 'a' or 'b' or 'c'. + + \row \i \bold{-} + + \i The dash indicates a range of characters. \bold{[W-Z]} + matches 'W' or 'X' or 'Y' or 'Z'. + + \endtable + + Using the predefined character set abbreviations is more portable + than using character ranges across platforms and languages. For + example, \bold{[0-9]} matches a digit in Western alphabets but + \bold{\\d} matches a digit in \e any alphabet. + + Note: In other regexp documentation, sets of characters are often + called "character classes". + + \target quantifiers + \section1 Quantifiers + + By default, an expression is automatically quantified by + \bold{{1,1}}, i.e. it should occur exactly once. In the following + list, \bold{\e {E}} stands for expression. An expression is a + character, or an abbreviation for a set of characters, or a set of + characters in square brackets, or an expression in parentheses. + + \table + \row \i \bold{\e {E}?} + + \i Matches zero or one occurrences of \e E. This quantifier + means \e{The previous expression is optional}, because it + will match whether or not the expression is found. \bold{\e + {E}?} is the same as \bold{\e {E}{0,1}}. e.g., \bold{dents?} + matches 'dent' or 'dents'. + + \row \i \bold{\e {E}+} + + \i Matches one or more occurrences of \e E. \bold{\e {E}+} is + the same as \bold{\e {E}{1,}}. e.g., \bold{0+} matches '0', + '00', '000', etc. + + \row \i \bold{\e {E}*} + + \i Matches zero or more occurrences of \e E. It is the same + as \bold{\e {E}{0,}}. The \bold{*} quantifier is often used + in error where \bold{+} should be used. For example, if + \bold{\\s*$} is used in an expression to match strings that + end in whitespace, it will match every string because + \bold{\\s*$} means \e{Match zero or more whitespaces followed + by end of string}. The correct regexp to match strings that + have at least one trailing whitespace character is + \bold{\\s+$}. + + \row \i \bold{\e {E}{n}} + + \i Matches exactly \e n occurrences of \e E. \bold{\e {E}{n}} + is the same as repeating \e E \e n times. For example, + \bold{x{5}} is the same as \bold{xxxxx}. It is also the same + as \bold{\e {E}{n,n}}, e.g. \bold{x{5,5}}. + + \row \i \bold{\e {E}{n,}} + \i Matches at least \e n occurrences of \e E. + + \row \i \bold{\e {E}{,m}} + \i Matches at most \e m occurrences of \e E. \bold{\e {E}{,m}} + is the same as \bold{\e {E}{0,m}}. + + \row \i \bold{\e {E}{n,m}} + \i Matches at least \e n and at most \e m occurrences of \e E. + \endtable + + To apply a quantifier to more than just the preceding character, + use parentheses to group characters together in an expression. For + example, \bold{tag+} matches a 't' followed by an 'a' followed by + at least one 'g', whereas \bold{(tag)+} matches at least one + occurrence of 'tag'. + + Note: Quantifiers are normally "greedy". They always match as much + text as they can. For example, \bold{0+} matches the first zero it + finds and all the consecutive zeros after the first zero. Applied + to '20005', it matches'2\underline{000}5'. Quantifiers can be made + non-greedy, see setMinimal(). + + \target capturing parentheses + \target backreferences + \section1 Capturing Text + + Parentheses allow us to group elements together so that we can + quantify and capture them. For example if we have the expression + \bold{mail|letter|correspondence} that matches a string we know + that \e one of the words matched but not which one. Using + parentheses allows us to "capture" whatever is matched within + their bounds, so if we used \bold{(mail|letter|correspondence)} + and matched this regexp against the string "I sent you some email" + we can use the cap() or capturedTexts() functions to extract the + matched characters, in this case 'mail'. + + We can use captured text within the regexp itself. To refer to the + captured text we use \e backreferences which are indexed from 1, + the same as for cap(). For example we could search for duplicate + words in a string using \bold{\\b(\\w+)\\W+\\1\\b} which means match a + word boundary followed by one or more word characters followed by + one or more non-word characters followed by the same text as the + first parenthesized expression followed by a word boundary. + + If we want to use parentheses purely for grouping and not for + capturing we can use the non-capturing syntax, e.g. + \bold{(?:green|blue)}. Non-capturing parentheses begin '(?:' and + end ')'. In this example we match either 'green' or 'blue' but we + do not capture the match so we only know whether or not we matched + but not which color we actually found. Using non-capturing + parentheses is more efficient than using capturing parentheses + since the regexp engine has to do less book-keeping. + + Both capturing and non-capturing parentheses may be nested. + + \target greedy quantifiers + + For historical reasons, quantifiers (e.g. \bold{*}) that apply to + capturing parentheses are more "greedy" than other quantifiers. + For example, \bold{a*(a)*} will match "aaa" with cap(1) == "aaa". + This behavior is different from what other regexp engines do + (notably, Perl). To obtain a more intuitive capturing behavior, + specify QRegExp::RegExp2 to the QRegExp constructor or call + setPatternSyntax(QRegExp::RegExp2). + + \target cap_in_a_loop + + When the number of matches cannot be determined in advance, a + common idiom is to use cap() in a loop. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 0 + + \target assertions + \section1 Assertions + + Assertions make some statement about the text at the point where + they occur in the regexp but they do not match any characters. In + the following list \bold{\e {E}} stands for any expression. + + \table + \row \i \bold{^} + \i The caret signifies the beginning of the string. If you + wish to match a literal \c{^} you must escape it by + writing \c{\\^}. For example, \bold{^#include} will only + match strings which \e begin with the characters '#include'. + (When the caret is the first character of a character set it + has a special meaning, see \link #sets-of-characters Sets of + Characters \endlink.) + + \row \i \bold{$} + \i The dollar signifies the end of the string. For example + \bold{\\d\\s*$} will match strings which end with a digit + optionally followed by whitespace. If you wish to match a + literal \c{$} you must escape it by writing + \c{\\$}. + + \row \i \bold{\\b} + \i A word boundary. For example the regexp + \bold{\\bOK\\b} means match immediately after a word + boundary (e.g. start of string or whitespace) the letter 'O' + then the letter 'K' immediately before another word boundary + (e.g. end of string or whitespace). But note that the + assertion does not actually match any whitespace so if we + write \bold{(\\bOK\\b)} and we have a match it will only + contain 'OK' even if the string is "It's \underline{OK} now". + + \row \i \bold{\\B} + \i A non-word boundary. This assertion is true wherever + \bold{\\b} is false. For example if we searched for + \bold{\\Bon\\B} in "Left on" the match would fail (space + and end of string aren't non-word boundaries), but it would + match in "t\underline{on}ne". + + \row \i \bold{(?=\e E)} + \i Positive lookahead. This assertion is true if the + expression matches at this point in the regexp. For example, + \bold{const(?=\\s+char)} matches 'const' whenever it is + followed by 'char', as in 'static \underline{const} char *'. + (Compare with \bold{const\\s+char}, which matches 'static + \underline{const char} *'.) + + \row \i \bold{(?!\e E)} + \i Negative lookahead. This assertion is true if the + expression does not match at this point in the regexp. For + example, \bold{const(?!\\s+char)} matches 'const' \e except + when it is followed by 'char'. + \endtable + + \keyword QRegExp wildcard matching + \section1 Wildcard Matching + + Most command shells such as \e bash or \e cmd.exe support "file + globbing", the ability to identify a group of files by using + wildcards. The setPatternSyntax() function is used to switch + between regexp and wildcard mode. Wildcard matching is much + simpler than full regexps and has only four features: + + \table + \row \i \bold{c} + \i Any character represents itself apart from those mentioned + below. Thus \bold{c} matches the character \e c. + \row \i \bold{?} + \i Matches any single character. It is the same as + \bold{.} in full regexps. + \row \i \bold{*} + \i Matches zero or more of any characters. It is the + same as \bold{.*} in full regexps. + \row \i \bold{[...]} + \i Sets of characters can be represented in square brackets, + similar to full regexps. Within the character class, like + outside, backslash has no special meaning. + \endtable + + For example if we are in wildcard mode and have strings which + contain filenames we could identify HTML files with \bold{*.html}. + This will match zero or more characters followed by a dot followed + by 'h', 't', 'm' and 'l'. + + To test a string against a wildcard expression, use exactMatch(). + For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 1 + + \target perl-users + \section1 Notes for Perl Users + + Most of the character class abbreviations supported by Perl are + supported by QRegExp, see \link + #characters-and-abbreviations-for-sets-of-characters characters + and abbreviations for sets of characters \endlink. + + In QRegExp, apart from within character classes, \c{^} always + signifies the start of the string, so carets must always be + escaped unless used for that purpose. In Perl the meaning of caret + varies automagically depending on where it occurs so escaping it + is rarely necessary. The same applies to \c{$} which in + QRegExp always signifies the end of the string. + + QRegExp's quantifiers are the same as Perl's greedy quantifiers + (but see the \l{greedy quantifiers}{note above}). Non-greedy + matching cannot be applied to individual quantifiers, but can be + applied to all the quantifiers in the pattern. For example, to + match the Perl regexp \bold{ro+?m} requires: + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 2 + + The equivalent of Perl's \c{/i} option is + setCaseSensitivity(Qt::CaseInsensitive). + + Perl's \c{/g} option can be emulated using a \l{#cap_in_a_loop}{loop}. + + In QRegExp \bold{.} matches any character, therefore all QRegExp + regexps have the equivalent of Perl's \c{/s} option. QRegExp + does not have an equivalent to Perl's \c{/m} option, but this + can be emulated in various ways for example by splitting the input + into lines or by looping with a regexp that searches for newlines. + + Because QRegExp is string oriented, there are no \\A, \\Z, or \\z + assertions. The \\G assertion is not supported but can be emulated + in a loop. + + Perl's $& is cap(0) or capturedTexts()[0]. There are no QRegExp + equivalents for $`, $' or $+. Perl's capturing variables, $1, $2, + ... correspond to cap(1) or capturedTexts()[1], cap(2) or + capturedTexts()[2], etc. + + To substitute a pattern use QString::replace(). + + Perl's extended \c{/x} syntax is not supported, nor are + directives, e.g. (?i), or regexp comments, e.g. (?#comment). On + the other hand, C++'s rules for literal strings can be used to + achieve the same: + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 3 + + Both zero-width positive and zero-width negative lookahead + assertions (?=pattern) and (?!pattern) are supported with the same + syntax as Perl. Perl's lookbehind assertions, "independent" + subexpressions and conditional expressions are not supported. + + Non-capturing parentheses are also supported, with the same + (?:pattern) syntax. + + See QString::split() and QStringList::join() for equivalents + to Perl's split and join functions. + + Note: because C++ transforms \\'s they must be written \e twice in + code, e.g. \bold{\\b} must be written \bold{\\\\b}. + + \target code-examples + \section1 Code Examples + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 4 + + The third string matches '\underline{6}'. This is a simple validation + regexp for integers in the range 0 to 99. + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 5 + + The second string matches '\underline{This_is-OK}'. We've used the + character set abbreviation '\\S' (non-whitespace) and the anchors + to match strings which contain no whitespace. + + In the following example we match strings containing 'mail' or + 'letter' or 'correspondence' but only match whole words i.e. not + 'email' + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 6 + + The second string matches "Please write the \underline{letter}". The + word 'letter' is also captured (because of the parentheses). We + can see what text we've captured like this: + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 7 + + This will capture the text from the first set of capturing + parentheses (counting capturing left parentheses from left to + right). The parentheses are counted from 1 since cap(0) is the + whole matched regexp (equivalent to '&' in most regexp engines). + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 8 + + Here we've passed the QRegExp to QString's replace() function to + replace the matched text with new text. + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 9 + + We've used the indexIn() function to repeatedly match the regexp in + the string. Note that instead of moving forward by one character + at a time \c pos++ we could have written \c {pos += + rx.matchedLength()} to skip over the already matched string. The + count will equal 3, matching 'One \underline{Eric} another + \underline{Eirik}, and an Ericsson. How many Eiriks, \underline{Eric}?'; it + doesn't match 'Ericsson' or 'Eiriks' because they are not bounded + by non-word boundaries. + + One common use of regexps is to split lines of delimited data into + their component fields. + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 10 + + In this example our input lines have the format company name, web + address and country. Unfortunately the regexp is rather long and + not very versatile -- the code will break if we add any more + fields. A simpler and better solution is to look for the + separator, '\\t' in this case, and take the surrounding text. The + QString::split() function can take a separator string or regexp + as an argument and split a string accordingly. + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 11 + + Here field[0] is the company, field[1] the web address and so on. + + To imitate the matching of a shell we can use wildcard mode. + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 12 + + Wildcard matching can be convenient because of its simplicity, but + any wildcard regexp can be defined using full regexps, e.g. + \bold{.*\.html$}. Notice that we can't match both \c .html and \c + .htm files with a wildcard unless we use \bold{*.htm*} which will + also match 'test.html.bak'. A full regexp gives us the precision + we need, \bold{.*\\.html?$}. + + QRegExp can match case insensitively using setCaseSensitivity(), + and can use non-greedy matching, see setMinimal(). By + default QRegExp uses full regexps but this can be changed with + setWildcard(). Searching can be forward with indexIn() or backward + with lastIndexIn(). Captured text can be accessed using + capturedTexts() which returns a string list of all captured + strings, or using cap() which returns the captured string for the + given index. The pos() function takes a match index and returns + the position in the string where the match was made (or -1 if + there was no match). + + \sa QString, QStringList, QRegExpValidator, QSortFilterProxyModel, + {tools/regexp}{Regular Expression Example} +*/ + +const int NumBadChars = 64; +#define BadChar(ch) ((ch).unicode() % NumBadChars) + +const int NoOccurrence = INT_MAX; +const int EmptyCapture = INT_MAX; +const int InftyLen = INT_MAX; +const int InftyRep = 1025; +const int EOS = -1; + +static bool isWord(QChar ch) +{ + return ch.isLetterOrNumber() || ch.isMark() || ch == QLatin1Char('_'); +} + +/* + Merges two vectors of ints and puts the result into the first + one. +*/ +static void mergeInto(QVector<int> *a, const QVector<int> &b) +{ + int asize = a->size(); + int bsize = b.size(); + if (asize == 0) { + *a = b; +#ifndef QT_NO_REGEXP_OPTIM + } else if (bsize == 1 && a->at(asize - 1) < b.at(0)) { + a->resize(asize + 1); + (*a)[asize] = b.at(0); +#endif + } else if (bsize >= 1) { + int csize = asize + bsize; + QVector<int> c(csize); + int i = 0, j = 0, k = 0; + while (i < asize) { + if (j < bsize) { + if (a->at(i) == b.at(j)) { + ++i; + --csize; + } else if (a->at(i) < b.at(j)) { + c[k++] = a->at(i++); + } else { + c[k++] = b.at(j++); + } + } else { + memcpy(c.data() + k, a->constData() + i, (asize - i) * sizeof(int)); + break; + } + } + c.resize(csize); + if (j < bsize) + memcpy(c.data() + k, b.constData() + j, (bsize - j) * sizeof(int)); + *a = c; + } +} + +#ifndef QT_NO_REGEXP_WILDCARD +/* + Translates a wildcard pattern to an equivalent regular expression + pattern (e.g., *.cpp to .*\.cpp). +*/ +static QString wc2rx(const QString &wc_str) +{ + int wclen = wc_str.length(); + QString rx; + int i = 0; + const QChar *wc = wc_str.unicode(); + while (i < wclen) { + QChar c = wc[i++]; + switch (c.unicode()) { + case '*': + rx += QLatin1String(".*"); + break; + case '?': + rx += QLatin1Char('.'); + break; + case '$': + case '(': + case ')': + case '+': + case '.': + case '\\': + case '^': + case '{': + case '|': + case '}': + rx += QLatin1Char('\\'); + rx += c; + break; + case '[': + rx += c; + if (wc[i] == QLatin1Char('^')) + rx += wc[i++]; + if (i < wclen) { + if (rx[i] == QLatin1Char(']')) + rx += wc[i++]; + while (i < wclen && wc[i] != QLatin1Char(']')) { + if (wc[i] == QLatin1Char('\\')) + rx += QLatin1Char('\\'); + rx += wc[i++]; + } + } + break; + default: + rx += c; + } + } + return rx; +} +#endif + +static int caretIndex(int offset, QRegExp::CaretMode caretMode) +{ + if (caretMode == QRegExp::CaretAtZero) { + return 0; + } else if (caretMode == QRegExp::CaretAtOffset) { + return offset; + } else { // QRegExp::CaretWontMatch + return -1; + } +} + +/* + The QRegExpEngineKey struct uniquely identifies an engine. +*/ +struct QRegExpEngineKey +{ + QString pattern; + QRegExp::PatternSyntax patternSyntax; + Qt::CaseSensitivity cs; + + inline QRegExpEngineKey(const QString &pattern, QRegExp::PatternSyntax patternSyntax, + Qt::CaseSensitivity cs) + : pattern(pattern), patternSyntax(patternSyntax), cs(cs) {} + + inline void clear() { + pattern.clear(); + patternSyntax = QRegExp::RegExp; + cs = Qt::CaseSensitive; + } +}; + +bool operator==(const QRegExpEngineKey &key1, const QRegExpEngineKey &key2) +{ + return key1.pattern == key2.pattern && key1.patternSyntax == key2.patternSyntax + && key1.cs == key2.cs; +} + +class QRegExpEngine; + +//Q_DECLARE_TYPEINFO(QVector<int>, Q_MOVABLE_TYPE); + +/* + This is the engine state during matching. +*/ +struct QRegExpMatchState +{ + const QChar *in; // a pointer to the input string data + int pos; // the current position in the string + int caretPos; + int len; // the length of the input string + bool minimal; // minimal matching? + int *bigArray; // big array holding the data for the next pointers + int *inNextStack; // is state is nextStack? + int *curStack; // stack of current states + int *nextStack; // stack of next states + int *curCapBegin; // start of current states' captures + int *nextCapBegin; // start of next states' captures + int *curCapEnd; // end of current states' captures + int *nextCapEnd; // end of next states' captures + int *tempCapBegin; // start of temporary captures + int *tempCapEnd; // end of temporary captures + int *capBegin; // start of captures for a next state + int *capEnd; // end of captures for a next state + int *slideTab; // bump-along slide table for bad-character heuristic + int *captured; // what match() returned last + int slideTabSize; // size of slide table + int capturedSize; +#ifndef QT_NO_REGEXP_BACKREF + QList<QVector<int> > sleeping; // list of back-reference sleepers +#endif + int matchLen; // length of match + int oneTestMatchedLen; // length of partial match + + const QRegExpEngine *eng; + + inline QRegExpMatchState() : bigArray(0), captured(0) {} + inline ~QRegExpMatchState() { free(bigArray); } + + void drain() { free(bigArray); bigArray = 0; captured = 0; } // to save memory + void prepareForMatch(QRegExpEngine *eng); + void match(const QChar *str, int len, int pos, bool minimal, + bool oneTest, int caretIndex); + bool matchHere(); + bool testAnchor(int i, int a, const int *capBegin); +}; + +/* + The struct QRegExpAutomatonState represents one state in a modified NFA. The + input characters matched are stored in the state instead of on + the transitions, something possible for an automaton + constructed from a regular expression. +*/ +struct QRegExpAutomatonState +{ +#ifndef QT_NO_REGEXP_CAPTURE + int atom; // which atom does this state belong to? +#endif + int match; // what does it match? (see CharClassBit and BackRefBit) + QVector<int> outs; // out-transitions + QMap<int, int> reenter; // atoms reentered when transiting out + QMap<int, int> anchors; // anchors met when transiting out + + inline QRegExpAutomatonState() { } +#ifndef QT_NO_REGEXP_CAPTURE + inline QRegExpAutomatonState(int a, int m) + : atom(a), match(m) { } +#else + inline QRegExpAutomatonState(int m) + : match(m) { } +#endif +}; + +Q_DECLARE_TYPEINFO(QRegExpAutomatonState, Q_MOVABLE_TYPE); + +/* + The struct QRegExpCharClassRange represents a range of characters (e.g., + [0-9] denotes range 48 to 57). +*/ +struct QRegExpCharClassRange +{ + ushort from; // 48 + ushort len; // 10 +}; + +Q_DECLARE_TYPEINFO(QRegExpCharClassRange, Q_PRIMITIVE_TYPE); + +#ifndef QT_NO_REGEXP_CAPTURE +/* + The struct QRegExpAtom represents one node in the hierarchy of regular + expression atoms. +*/ +struct QRegExpAtom +{ + enum { NoCapture = -1, OfficialCapture = -2, UnofficialCapture = -3 }; + + int parent; // index of parent in array of atoms + int capture; // index of capture, from 1 to ncap - 1 +}; + +Q_DECLARE_TYPEINFO(QRegExpAtom, Q_PRIMITIVE_TYPE); +#endif + +struct QRegExpLookahead; + +#ifndef QT_NO_REGEXP_ANCHOR_ALT +/* + The struct QRegExpAnchorAlternation represents a pair of anchors with + OR semantics. +*/ +struct QRegExpAnchorAlternation +{ + int a; // this anchor... + int b; // ...or this one +}; + +Q_DECLARE_TYPEINFO(QRegExpAnchorAlternation, Q_PRIMITIVE_TYPE); +#endif + +#ifndef QT_NO_REGEXP_CCLASS +/* + The class QRegExpCharClass represents a set of characters, such as can + be found in regular expressions (e.g., [a-z] denotes the set + {a, b, ..., z}). +*/ +class QRegExpCharClass +{ +public: + QRegExpCharClass(); + inline QRegExpCharClass(const QRegExpCharClass &cc) { operator=(cc); } + + QRegExpCharClass &operator=(const QRegExpCharClass &cc); + + void clear(); + bool negative() const { return n; } + void setNegative(bool negative); + void addCategories(int cats); + void addRange(ushort from, ushort to); + void addSingleton(ushort ch) { addRange(ch, ch); } + + bool in(QChar ch) const; +#ifndef QT_NO_REGEXP_OPTIM + const QVector<int> &firstOccurrence() const { return occ1; } +#endif + +#if defined(QT_DEBUG) + void dump() const; +#endif + +private: + int c; // character classes + QVector<QRegExpCharClassRange> r; // character ranges + bool n; // negative? +#ifndef QT_NO_REGEXP_OPTIM + QVector<int> occ1; // first-occurrence array +#endif +}; +#else +struct QRegExpCharClass +{ + int dummy; + +#ifndef QT_NO_REGEXP_OPTIM + QRegExpCharClass() { occ1.fill(0, NumBadChars); } + + const QVector<int> &firstOccurrence() const { return occ1; } + QVector<int> occ1; +#endif +}; +#endif + +Q_DECLARE_TYPEINFO(QRegExpCharClass, Q_MOVABLE_TYPE); + +/* + The QRegExpEngine class encapsulates a modified nondeterministic + finite automaton (NFA). +*/ +class QRegExpEngine +{ +public: + QRegExpEngine(Qt::CaseSensitivity cs, bool greedyQuantifiers) + : cs(cs), greedyQuantifiers(greedyQuantifiers) { setup(); } + + QRegExpEngine(const QRegExpEngineKey &key); + ~QRegExpEngine(); + + bool isValid() const { return valid; } + const QString &errorString() const { return yyError; } + int numCaptures() const { return officialncap; } + + int createState(QChar ch); + int createState(const QRegExpCharClass &cc); +#ifndef QT_NO_REGEXP_BACKREF + int createState(int bref); +#endif + + void addCatTransitions(const QVector<int> &from, const QVector<int> &to); +#ifndef QT_NO_REGEXP_CAPTURE + void addPlusTransitions(const QVector<int> &from, const QVector<int> &to, int atom); +#endif + +#ifndef QT_NO_REGEXP_ANCHOR_ALT + int anchorAlternation(int a, int b); + int anchorConcatenation(int a, int b); +#else + int anchorAlternation(int a, int b) { return a & b; } + int anchorConcatenation(int a, int b) { return a | b; } +#endif + void addAnchors(int from, int to, int a); + +#ifndef QT_NO_REGEXP_OPTIM + void heuristicallyChooseHeuristic(); +#endif + +#if defined(QT_DEBUG) + void dump() const; +#endif + + QAtomicInt ref; + +private: + enum { CharClassBit = 0x10000, BackRefBit = 0x20000 }; + enum { InitialState = 0, FinalState = 1 }; + + void setup(); + int setupState(int match); + + /* + Let's hope that 13 lookaheads and 14 back-references are + enough. + */ + enum { MaxLookaheads = 13, MaxBackRefs = 14 }; + enum { Anchor_Dollar = 0x00000001, Anchor_Caret = 0x00000002, Anchor_Word = 0x00000004, + Anchor_NonWord = 0x00000008, Anchor_FirstLookahead = 0x00000010, + Anchor_BackRef1Empty = Anchor_FirstLookahead << MaxLookaheads, + Anchor_BackRef0Empty = Anchor_BackRef1Empty >> 1, + Anchor_Alternation = unsigned(Anchor_BackRef1Empty) << MaxBackRefs, + + Anchor_LookaheadMask = (Anchor_FirstLookahead - 1) ^ + ((Anchor_FirstLookahead << MaxLookaheads) - 1) }; +#ifndef QT_NO_REGEXP_CAPTURE + int startAtom(bool officialCapture); + void finishAtom(int atom, bool needCapture); +#endif + +#ifndef QT_NO_REGEXP_LOOKAHEAD + int addLookahead(QRegExpEngine *eng, bool negative); +#endif + +#ifndef QT_NO_REGEXP_OPTIM + bool goodStringMatch(QRegExpMatchState &matchState) const; + bool badCharMatch(QRegExpMatchState &matchState) const; +#else + bool bruteMatch(QRegExpMatchState &matchState) const; +#endif + + QVector<QRegExpAutomatonState> s; // array of states +#ifndef QT_NO_REGEXP_CAPTURE + QVector<QRegExpAtom> f; // atom hierarchy + int nf; // number of atoms + int cf; // current atom + QVector<int> captureForOfficialCapture; +#endif + int officialncap; // number of captures, seen from the outside + int ncap; // number of captures, seen from the inside +#ifndef QT_NO_REGEXP_CCLASS + QVector<QRegExpCharClass> cl; // array of character classes +#endif +#ifndef QT_NO_REGEXP_LOOKAHEAD + QVector<QRegExpLookahead *> ahead; // array of lookaheads +#endif +#ifndef QT_NO_REGEXP_ANCHOR_ALT + QVector<QRegExpAnchorAlternation> aa; // array of (a, b) pairs of anchors +#endif +#ifndef QT_NO_REGEXP_OPTIM + bool caretAnchored; // does the regexp start with ^? + bool trivial; // is the good-string all that needs to match? +#endif + bool valid; // is the regular expression valid? + Qt::CaseSensitivity cs; // case sensitive? + bool greedyQuantifiers; // RegExp2? +#ifndef QT_NO_REGEXP_BACKREF + int nbrefs; // number of back-references +#endif + +#ifndef QT_NO_REGEXP_OPTIM + bool useGoodStringHeuristic; // use goodStringMatch? otherwise badCharMatch + + int goodEarlyStart; // the index where goodStr can first occur in a match + int goodLateStart; // the index where goodStr can last occur in a match + QString goodStr; // the string that any match has to contain + + int minl; // the minimum length of a match + QVector<int> occ1; // first-occurrence array +#endif + + /* + The class Box is an abstraction for a regular expression + fragment. It can also be seen as one node in the syntax tree of + a regular expression with synthetized attributes. + + Its interface is ugly for performance reasons. + */ + class Box + { + public: + Box(QRegExpEngine *engine); + Box(const Box &b) { operator=(b); } + + Box &operator=(const Box &b); + + void clear() { operator=(Box(eng)); } + void set(QChar ch); + void set(const QRegExpCharClass &cc); +#ifndef QT_NO_REGEXP_BACKREF + void set(int bref); +#endif + + void cat(const Box &b); + void orx(const Box &b); + void plus(int atom); + void opt(); + void catAnchor(int a); +#ifndef QT_NO_REGEXP_OPTIM + void setupHeuristics(); +#endif + +#if defined(QT_DEBUG) + void dump() const; +#endif + + private: + void addAnchorsToEngine(const Box &to) const; + + QRegExpEngine *eng; // the automaton under construction + QVector<int> ls; // the left states (firstpos) + QVector<int> rs; // the right states (lastpos) + QMap<int, int> lanchors; // the left anchors + QMap<int, int> ranchors; // the right anchors + int skipanchors; // the anchors to match if the box is skipped + +#ifndef QT_NO_REGEXP_OPTIM + int earlyStart; // the index where str can first occur + int lateStart; // the index where str can last occur + QString str; // a string that has to occur in any match + QString leftStr; // a string occurring at the left of this box + QString rightStr; // a string occurring at the right of this box + int maxl; // the maximum length of this box (possibly InftyLen) +#endif + + int minl; // the minimum length of this box +#ifndef QT_NO_REGEXP_OPTIM + QVector<int> occ1; // first-occurrence array +#endif + }; + + friend class Box; + + /* + This is the lexical analyzer for regular expressions. + */ + enum { Tok_Eos, Tok_Dollar, Tok_LeftParen, Tok_MagicLeftParen, Tok_PosLookahead, + Tok_NegLookahead, Tok_RightParen, Tok_CharClass, Tok_Caret, Tok_Quantifier, Tok_Bar, + Tok_Word, Tok_NonWord, Tok_Char = 0x10000, Tok_BackRef = 0x20000 }; + int getChar(); + int getEscape(); +#ifndef QT_NO_REGEXP_INTERVAL + int getRep(int def); +#endif +#ifndef QT_NO_REGEXP_LOOKAHEAD + void skipChars(int n); +#endif + void error(const char *msg); + void startTokenizer(const QChar *rx, int len); + int getToken(); + + const QChar *yyIn; // a pointer to the input regular expression pattern + int yyPos0; // the position of yyTok in the input pattern + int yyPos; // the position of the next character to read + int yyLen; // the length of yyIn + int yyCh; // the last character read + QRegExpCharClass *yyCharClass; // attribute for Tok_CharClass tokens + int yyMinRep; // attribute for Tok_Quantifier + int yyMaxRep; // ditto + QString yyError; // syntax error or overflow during parsing? + + /* + This is the syntactic analyzer for regular expressions. + */ + int parse(const QChar *rx, int len); + void parseAtom(Box *box); + void parseFactor(Box *box); + void parseTerm(Box *box); + void parseExpression(Box *box); + + int yyTok; // the last token read + bool yyMayCapture; // set this to false to disable capturing + + friend struct QRegExpMatchState; +}; + +#ifndef QT_NO_REGEXP_LOOKAHEAD +/* + The struct QRegExpLookahead represents a lookahead a la Perl (e.g., + (?=foo) and (?!bar)). +*/ +struct QRegExpLookahead +{ + QRegExpEngine *eng; // NFA representing the embedded regular expression + bool neg; // negative lookahead? + + inline QRegExpLookahead(QRegExpEngine *eng0, bool neg0) + : eng(eng0), neg(neg0) { } + inline ~QRegExpLookahead() { delete eng; } +}; +#endif + +QRegExpEngine::QRegExpEngine(const QRegExpEngineKey &key) + : cs(key.cs), greedyQuantifiers(key.patternSyntax == QRegExp::RegExp2) +{ + setup(); + + QString rx; + + switch (key.patternSyntax) { + case QRegExp::Wildcard: +#ifndef QT_NO_REGEXP_WILDCARD + rx = wc2rx(key.pattern); +#endif + break; + case QRegExp::FixedString: + rx = QRegExp::escape(key.pattern); + break; + default: + rx = key.pattern; + } + + valid = (parse(rx.unicode(), rx.length()) == rx.length()); + if (!valid) { +#ifndef QT_NO_REGEXP_OPTIM + trivial = false; +#endif + error(RXERR_LEFTDELIM); + } +} + +QRegExpEngine::~QRegExpEngine() +{ +#ifndef QT_NO_REGEXP_LOOKAHEAD + qDeleteAll(ahead); +#endif +} + +void QRegExpMatchState::prepareForMatch(QRegExpEngine *eng) +{ + /* + We use one QVector<int> for all the big data used a lot in + matchHere() and friends. + */ + int ns = eng->s.size(); // number of states + int ncap = eng->ncap; +#ifndef QT_NO_REGEXP_OPTIM + slideTabSize = qMax(eng->minl + 1, 16); +#else + slideTabSize = 0; +#endif + int numCaptures = eng->numCaptures(); + capturedSize = 2 + 2 * numCaptures; + bigArray = (int *)realloc(bigArray, ((3 + 4 * ncap) * ns + 4 * ncap + slideTabSize + capturedSize)*sizeof(int)); + + inNextStack = bigArray; + memset(inNextStack, -1, ns * sizeof(int)); + curStack = inNextStack + ns; + nextStack = inNextStack + 2 * ns; + + curCapBegin = inNextStack + 3 * ns; + nextCapBegin = curCapBegin + ncap * ns; + curCapEnd = curCapBegin + 2 * ncap * ns; + nextCapEnd = curCapBegin + 3 * ncap * ns; + + tempCapBegin = curCapBegin + 4 * ncap * ns; + tempCapEnd = tempCapBegin + ncap; + capBegin = tempCapBegin + 2 * ncap; + capEnd = tempCapBegin + 3 * ncap; + + slideTab = tempCapBegin + 4 * ncap; + captured = slideTab + slideTabSize; + memset(captured, -1, capturedSize*sizeof(int)); + this->eng = eng; +} + +/* + Tries to match in str and returns an array of (begin, length) pairs + for captured text. If there is no match, all pairs are (-1, -1). +*/ +void QRegExpMatchState::match(const QChar *str0, int len0, int pos0, + bool minimal0, bool oneTest, int caretIndex) +{ + bool matched = false; + QChar char_null; + +#ifndef QT_NO_REGEXP_OPTIM + if (eng->trivial && !oneTest) { + pos = qFindString(str0, len0, pos0, eng->goodStr.unicode(), eng->goodStr.length(), eng->cs); + matchLen = eng->goodStr.length(); + matched = (pos != -1); + } else +#endif + { + in = str0; + if (in == 0) + in = &char_null; + pos = pos0; + caretPos = caretIndex; + len = len0; + minimal = minimal0; + matchLen = 0; + oneTestMatchedLen = 0; + + if (eng->valid && pos >= 0 && pos <= len) { +#ifndef QT_NO_REGEXP_OPTIM + if (oneTest) { + matched = matchHere(); + } else { + if (pos <= len - eng->minl) { + if (eng->caretAnchored) { + matched = matchHere(); + } else if (eng->useGoodStringHeuristic) { + matched = eng->goodStringMatch(*this); + } else { + matched = eng->badCharMatch(*this); + } + } + } +#else + matched = oneTest ? matchHere() : eng->bruteMatch(*this); +#endif + } + } + + if (matched) { + int *c = captured; + *c++ = pos; + *c++ = matchLen; + + int numCaptures = (capturedSize - 2) >> 1; +#ifndef QT_NO_REGEXP_CAPTURE + for (int i = 0; i < numCaptures; ++i) { + int j = eng->captureForOfficialCapture.at(i); + int len = capEnd[j] - capBegin[j]; + *c++ = (len > 0) ? pos + capBegin[j] : 0; + *c++ = len; + } +#endif + } else { + // we rely on 2's complement here + memset(captured, -1, capturedSize * sizeof(int)); + } +} + +/* + The three following functions add one state to the automaton and + return the number of the state. +*/ + +int QRegExpEngine::createState(QChar ch) +{ + return setupState(ch.unicode()); +} + +int QRegExpEngine::createState(const QRegExpCharClass &cc) +{ +#ifndef QT_NO_REGEXP_CCLASS + int n = cl.size(); + cl += QRegExpCharClass(cc); + return setupState(CharClassBit | n); +#else + Q_UNUSED(cc); + return setupState(CharClassBit); +#endif +} + +#ifndef QT_NO_REGEXP_BACKREF +int QRegExpEngine::createState(int bref) +{ + if (bref > nbrefs) { + nbrefs = bref; + if (nbrefs > MaxBackRefs) { + error(RXERR_LIMIT); + return 0; + } + } + return setupState(BackRefBit | bref); +} +#endif + +/* + The two following functions add a transition between all pairs of + states (i, j) where i is found in from, and j is found in to. + + Cat-transitions are distinguished from plus-transitions for + capturing. +*/ + +void QRegExpEngine::addCatTransitions(const QVector<int> &from, const QVector<int> &to) +{ + for (int i = 0; i < from.size(); i++) + mergeInto(&s[from.at(i)].outs, to); +} + +#ifndef QT_NO_REGEXP_CAPTURE +void QRegExpEngine::addPlusTransitions(const QVector<int> &from, const QVector<int> &to, int atom) +{ + for (int i = 0; i < from.size(); i++) { + QRegExpAutomatonState &st = s[from.at(i)]; + const QVector<int> oldOuts = st.outs; + mergeInto(&st.outs, to); + if (f.at(atom).capture != QRegExpAtom::NoCapture) { + for (int j = 0; j < to.size(); j++) { + // ### st.reenter.contains(to.at(j)) check looks suspicious + if (!st.reenter.contains(to.at(j)) && + qBinaryFind(oldOuts.constBegin(), oldOuts.constEnd(), to.at(j)) == oldOuts.end()) + st.reenter.insert(to.at(j), atom); + } + } + } +} +#endif + +#ifndef QT_NO_REGEXP_ANCHOR_ALT +/* + Returns an anchor that means a OR b. +*/ +int QRegExpEngine::anchorAlternation(int a, int b) +{ + if (((a & b) == a || (a & b) == b) && ((a | b) & Anchor_Alternation) == 0) + return a & b; + + int n = aa.size(); +#ifndef QT_NO_REGEXP_OPTIM + if (n > 0 && aa.at(n - 1).a == a && aa.at(n - 1).b == b) + return Anchor_Alternation | (n - 1); +#endif + + aa.resize(n + 1); + aa[n].a = a; + aa[n].b = b; + return Anchor_Alternation | n; +} + +/* + Returns an anchor that means a AND b. +*/ +int QRegExpEngine::anchorConcatenation(int a, int b) +{ + if (((a | b) & Anchor_Alternation) == 0) + return a | b; + if ((b & Anchor_Alternation) != 0) + qSwap(a, b); + + int aprime = anchorConcatenation(aa.at(a ^ Anchor_Alternation).a, b); + int bprime = anchorConcatenation(aa.at(a ^ Anchor_Alternation).b, b); + return anchorAlternation(aprime, bprime); +} +#endif + +/* + Adds anchor a on a transition caracterised by its from state and + its to state. +*/ +void QRegExpEngine::addAnchors(int from, int to, int a) +{ + QRegExpAutomatonState &st = s[from]; + if (st.anchors.contains(to)) + a = anchorAlternation(st.anchors.value(to), a); + st.anchors.insert(to, a); +} + +#ifndef QT_NO_REGEXP_OPTIM +/* + This function chooses between the good-string and the bad-character + heuristics. It computes two scores and chooses the heuristic with + the highest score. + + Here are some common-sense constraints on the scores that should be + respected if the formulas are ever modified: (1) If goodStr is + empty, the good-string heuristic scores 0. (2) If the regular + expression is trivial, the good-string heuristic should be used. + (3) If the search is case insensitive, the good-string heuristic + should be used, unless it scores 0. (Case insensitivity turns all + entries of occ1 to 0.) (4) If (goodLateStart - goodEarlyStart) is + big, the good-string heuristic should score less. +*/ +void QRegExpEngine::heuristicallyChooseHeuristic() +{ + if (minl == 0) { + useGoodStringHeuristic = false; + } else if (trivial) { + useGoodStringHeuristic = true; + } else { + /* + Magic formula: The good string has to constitute a good + proportion of the minimum-length string, and appear at a + more-or-less known index. + */ + int goodStringScore = (64 * goodStr.length() / minl) - + (goodLateStart - goodEarlyStart); + /* + Less magic formula: We pick some characters at random, and + check whether they are good or bad. + */ + int badCharScore = 0; + int step = qMax(1, NumBadChars / 32); + for (int i = 1; i < NumBadChars; i += step) { + if (occ1.at(i) == NoOccurrence) + badCharScore += minl; + else + badCharScore += occ1.at(i); + } + badCharScore /= minl; + useGoodStringHeuristic = (goodStringScore > badCharScore); + } +} +#endif + +#if defined(QT_DEBUG) +void QRegExpEngine::dump() const +{ + int i, j; + qDebug("Case %ssensitive engine", cs ? "" : "in"); + qDebug(" States"); + for (i = 0; i < s.size(); i++) { + qDebug(" %d%s", i, i == InitialState ? " (initial)" : i == FinalState ? " (final)" : ""); +#ifndef QT_NO_REGEXP_CAPTURE + if (nf > 0) + qDebug(" in atom %d", s[i].atom); +#endif + int m = s[i].match; + if ((m & CharClassBit) != 0) { + qDebug(" match character class %d", m ^ CharClassBit); +#ifndef QT_NO_REGEXP_CCLASS + cl[m ^ CharClassBit].dump(); +#else + qDebug(" negative character class"); +#endif + } else if ((m & BackRefBit) != 0) { + qDebug(" match back-reference %d", m ^ BackRefBit); + } else if (m >= 0x20 && m <= 0x7e) { + qDebug(" match 0x%.4x (%c)", m, m); + } else { + qDebug(" match 0x%.4x", m); + } + for (j = 0; j < s[i].outs.size(); j++) { + int next = s[i].outs[j]; + qDebug(" -> %d", next); + if (s[i].reenter.contains(next)) + qDebug(" [reenter %d]", s[i].reenter[next]); + if (s[i].anchors.value(next) != 0) + qDebug(" [anchors 0x%.8x]", s[i].anchors[next]); + } + } +#ifndef QT_NO_REGEXP_CAPTURE + if (nf > 0) { + qDebug(" Atom Parent Capture"); + for (i = 0; i < nf; i++) { + if (f[i].capture == QRegExpAtom::NoCapture) { + qDebug(" %6d %6d nil", i, f[i].parent); + } else { + int cap = f[i].capture; + bool official = captureForOfficialCapture.contains(cap); + qDebug(" %6d %6d %6d %s", i, f[i].parent, f[i].capture, + official ? "official" : ""); + } + } + } +#endif +#ifndef QT_NO_REGEXP_ANCHOR_ALT + for (i = 0; i < aa.size(); i++) + qDebug(" Anchor alternation 0x%.8x: 0x%.8x 0x%.9x", i, aa[i].a, aa[i].b); +#endif +} +#endif + +void QRegExpEngine::setup() +{ + ref = 1; +#ifndef QT_NO_REGEXP_CAPTURE + f.resize(32); + nf = 0; + cf = -1; +#endif + officialncap = 0; + ncap = 0; +#ifndef QT_NO_REGEXP_OPTIM + caretAnchored = true; + trivial = true; +#endif + valid = false; +#ifndef QT_NO_REGEXP_BACKREF + nbrefs = 0; +#endif +#ifndef QT_NO_REGEXP_OPTIM + useGoodStringHeuristic = true; + minl = 0; + occ1.fill(0, NumBadChars); +#endif +} + +int QRegExpEngine::setupState(int match) +{ +#ifndef QT_NO_REGEXP_CAPTURE + s += QRegExpAutomatonState(cf, match); +#else + s += QRegExpAutomatonState(match); +#endif + return s.size() - 1; +} + +#ifndef QT_NO_REGEXP_CAPTURE +/* + Functions startAtom() and finishAtom() should be called to delimit + atoms. When a state is created, it is assigned to the current atom. + The information is later used for capturing. +*/ +int QRegExpEngine::startAtom(bool officialCapture) +{ + if ((nf & (nf + 1)) == 0 && nf + 1 >= f.size()) + f.resize((nf + 1) << 1); + f[nf].parent = cf; + cf = nf++; + f[cf].capture = officialCapture ? QRegExpAtom::OfficialCapture : QRegExpAtom::NoCapture; + return cf; +} + +void QRegExpEngine::finishAtom(int atom, bool needCapture) +{ + if (greedyQuantifiers && needCapture && f[atom].capture == QRegExpAtom::NoCapture) + f[atom].capture = QRegExpAtom::UnofficialCapture; + cf = f.at(atom).parent; +} +#endif + +#ifndef QT_NO_REGEXP_LOOKAHEAD +/* + Creates a lookahead anchor. +*/ +int QRegExpEngine::addLookahead(QRegExpEngine *eng, bool negative) +{ + int n = ahead.size(); + if (n == MaxLookaheads) { + error(RXERR_LIMIT); + return 0; + } + ahead += new QRegExpLookahead(eng, negative); + return Anchor_FirstLookahead << n; +} +#endif + +#ifndef QT_NO_REGEXP_CAPTURE +/* + We want the longest leftmost captures. +*/ +static bool isBetterCapture(int ncap, const int *begin1, const int *end1, const int *begin2, + const int *end2) +{ + for (int i = 0; i < ncap; i++) { + int delta = begin2[i] - begin1[i]; // it has to start early... + if (delta == 0) + delta = end1[i] - end2[i]; // ...and end late + + if (delta != 0) + return delta > 0; + } + return false; +} +#endif + +/* + Returns true if anchor a matches at position pos + i in the input + string, otherwise false. +*/ +bool QRegExpMatchState::testAnchor(int i, int a, const int *capBegin) +{ + int j; + +#ifndef QT_NO_REGEXP_ANCHOR_ALT + if ((a & QRegExpEngine::Anchor_Alternation) != 0) + return testAnchor(i, eng->aa.at(a ^ QRegExpEngine::Anchor_Alternation).a, capBegin) + || testAnchor(i, eng->aa.at(a ^ QRegExpEngine::Anchor_Alternation).b, capBegin); +#endif + + if ((a & QRegExpEngine::Anchor_Caret) != 0) { + if (pos + i != caretPos) + return false; + } + if ((a & QRegExpEngine::Anchor_Dollar) != 0) { + if (pos + i != len) + return false; + } +#ifndef QT_NO_REGEXP_ESCAPE + if ((a & (QRegExpEngine::Anchor_Word | QRegExpEngine::Anchor_NonWord)) != 0) { + bool before = false; + bool after = false; + if (pos + i != 0) + before = isWord(in[pos + i - 1]); + if (pos + i != len) + after = isWord(in[pos + i]); + if ((a & QRegExpEngine::Anchor_Word) != 0 && (before == after)) + return false; + if ((a & QRegExpEngine::Anchor_NonWord) != 0 && (before != after)) + return false; + } +#endif +#ifndef QT_NO_REGEXP_LOOKAHEAD + if ((a & QRegExpEngine::Anchor_LookaheadMask) != 0) { + const QVector<QRegExpLookahead *> &ahead = eng->ahead; + for (j = 0; j < ahead.size(); j++) { + if ((a & (QRegExpEngine::Anchor_FirstLookahead << j)) != 0) { + QRegExpMatchState matchState; + matchState.prepareForMatch(ahead[j]->eng); + matchState.match(in + pos + i, len - pos - i, 0, + true, true, matchState.caretPos - matchState.pos - i); + if ((matchState.captured[0] == 0) == ahead[j]->neg) + return false; + } + } + } +#endif +#ifndef QT_NO_REGEXP_CAPTURE +#ifndef QT_NO_REGEXP_BACKREF + for (j = 0; j < eng->nbrefs; j++) { + if ((a & (QRegExpEngine::Anchor_BackRef1Empty << j)) != 0) { + int i = eng->captureForOfficialCapture.at(j); + if (capBegin[i] != EmptyCapture) + return false; + } + } +#endif +#endif + return true; +} + +#ifndef QT_NO_REGEXP_OPTIM +/* + The three following functions are what Jeffrey Friedl would call + transmissions (or bump-alongs). Using one or the other should make + no difference except in performance. +*/ + +bool QRegExpEngine::goodStringMatch(QRegExpMatchState &matchState) const +{ + int k = matchState.pos + goodEarlyStart; + QStringMatcher matcher(goodStr.unicode(), goodStr.length(), cs); + while ((k = matcher.indexIn(matchState.in, matchState.len, k)) != -1) { + int from = k - goodLateStart; + int to = k - goodEarlyStart; + if (from > matchState.pos) + matchState.pos = from; + + while (matchState.pos <= to) { + if (matchState.matchHere()) + return true; + ++matchState.pos; + } + ++k; + } + return false; +} + +bool QRegExpEngine::badCharMatch(QRegExpMatchState &matchState) const +{ + int slideHead = 0; + int slideNext = 0; + int i; + int lastPos = matchState.len - minl; + memset(matchState.slideTab, 0, matchState.slideTabSize * sizeof(int)); + + /* + Set up the slide table, used for the bad-character heuristic, + using the table of first occurrence of each character. + */ + for (i = 0; i < minl; i++) { + int sk = occ1[BadChar(matchState.in[matchState.pos + i])]; + if (sk == NoOccurrence) + sk = i + 1; + if (sk > 0) { + int k = i + 1 - sk; + if (k < 0) { + sk = i + 1; + k = 0; + } + if (sk > matchState.slideTab[k]) + matchState.slideTab[k] = sk; + } + } + + if (matchState.pos > lastPos) + return false; + + for (;;) { + if (++slideNext >= matchState.slideTabSize) + slideNext = 0; + if (matchState.slideTab[slideHead] > 0) { + if (matchState.slideTab[slideHead] - 1 > matchState.slideTab[slideNext]) + matchState.slideTab[slideNext] = matchState.slideTab[slideHead] - 1; + matchState.slideTab[slideHead] = 0; + } else { + if (matchState.matchHere()) + return true; + } + + if (matchState.pos == lastPos) + break; + + /* + Update the slide table. This code has much in common with + the initialization code. + */ + int sk = occ1[BadChar(matchState.in[matchState.pos + minl])]; + if (sk == NoOccurrence) { + matchState.slideTab[slideNext] = minl; + } else if (sk > 0) { + int k = slideNext + minl - sk; + if (k >= matchState.slideTabSize) + k -= matchState.slideTabSize; + if (sk > matchState.slideTab[k]) + matchState.slideTab[k] = sk; + } + slideHead = slideNext; + ++matchState.pos; + } + return false; +} +#else +bool QRegExpEngine::bruteMatch(QRegExpMatchState &matchState) const +{ + while (matchState.pos <= matchState.len) { + if (matchState.matchHere()) + return true; + ++matchState.pos; + } + return false; +} +#endif + +/* + Here's the core of the engine. It tries to do a match here and now. +*/ +bool QRegExpMatchState::matchHere() +{ + int ncur = 1, nnext = 0; + int i = 0, j, k, m; + bool stop = false; + + matchLen = -1; + oneTestMatchedLen = -1; + curStack[0] = QRegExpEngine::InitialState; + + int ncap = eng->ncap; +#ifndef QT_NO_REGEXP_CAPTURE + if (ncap > 0) { + for (j = 0; j < ncap; j++) { + curCapBegin[j] = EmptyCapture; + curCapEnd[j] = EmptyCapture; + } + } +#endif + +#ifndef QT_NO_REGEXP_BACKREF + while ((ncur > 0 || !sleeping.isEmpty()) && i <= len - pos && !stop) +#else + while (ncur > 0 && i <= len - pos && !stop) +#endif + { + int ch = (i < len - pos) ? in[pos + i].unicode() : 0; + for (j = 0; j < ncur; j++) { + int cur = curStack[j]; + const QRegExpAutomatonState &scur = eng->s.at(cur); + const QVector<int> &outs = scur.outs; + for (k = 0; k < outs.size(); k++) { + int next = outs.at(k); + const QRegExpAutomatonState &snext = eng->s.at(next); + bool inside = true; +#if !defined(QT_NO_REGEXP_BACKREF) && !defined(QT_NO_REGEXP_CAPTURE) + int needSomeSleep = 0; +#endif + + /* + First, check if the anchors are anchored properly. + */ + int a = scur.anchors.value(next); + if (a != 0 && !testAnchor(i, a, curCapBegin + j * ncap)) + inside = false; + + /* + If indeed they are, check if the input character is + correct for this transition. + */ + if (inside) { + m = snext.match; + if ((m & (QRegExpEngine::CharClassBit | QRegExpEngine::BackRefBit)) == 0) { + if (eng->cs) + inside = (m == ch); + else + inside = (QChar(m).toLower() == QChar(ch).toLower()); + } else if (next == QRegExpEngine::FinalState) { + matchLen = i; + stop = minimal; + inside = true; + } else if ((m & QRegExpEngine::CharClassBit) != 0) { +#ifndef QT_NO_REGEXP_CCLASS + const QRegExpCharClass &cc = eng->cl.at(m ^ QRegExpEngine::CharClassBit); + if (eng->cs) + inside = cc.in(ch); + else if (cc.negative()) + inside = cc.in(QChar(ch).toLower()) && + cc.in(QChar(ch).toUpper()); + else + inside = cc.in(QChar(ch).toLower()) || + cc.in(QChar(ch).toUpper()); +#endif +#if !defined(QT_NO_REGEXP_BACKREF) && !defined(QT_NO_REGEXP_CAPTURE) + } else { /* ((m & QRegExpEngine::BackRefBit) != 0) */ + int bref = m ^ QRegExpEngine::BackRefBit; + int ell = j * ncap + eng->captureForOfficialCapture.at(bref - 1); + + inside = bref <= ncap && curCapBegin[ell] != EmptyCapture; + if (inside) { + if (eng->cs) + inside = (in[pos + curCapBegin[ell]] == QChar(ch)); + else + inside = (in[pos + curCapBegin[ell]].toLower() + == QChar(ch).toLower()); + } + + if (inside) { + int delta; + if (curCapEnd[ell] == EmptyCapture) + delta = i - curCapBegin[ell]; + else + delta = curCapEnd[ell] - curCapBegin[ell]; + + inside = (delta <= len - (pos + i)); + if (inside && delta > 1) { + int n = 1; + if (eng->cs) { + while (n < delta) { + if (in[pos + curCapBegin[ell] + n] + != in[pos + i + n]) + break; + ++n; + } + } else { + while (n < delta) { + QChar a = in[pos + curCapBegin[ell] + n]; + QChar b = in[pos + i + n]; + if (a.toLower() != b.toLower()) + break; + ++n; + } + } + inside = (n == delta); + if (inside) + needSomeSleep = delta - 1; + } + } +#endif + } + } + + /* + We must now update our data structures. + */ + if (inside) { +#ifndef QT_NO_REGEXP_CAPTURE + int *capBegin, *capEnd; +#endif + /* + If the next state was not encountered yet, all + is fine. + */ + if ((m = inNextStack[next]) == -1) { + m = nnext++; + nextStack[m] = next; + inNextStack[next] = m; +#ifndef QT_NO_REGEXP_CAPTURE + capBegin = nextCapBegin + m * ncap; + capEnd = nextCapEnd + m * ncap; + + /* + Otherwise, we'll first maintain captures in + temporary arrays, and decide at the end whether + it's best to keep the previous capture zones or + the new ones. + */ + } else { + capBegin = tempCapBegin; + capEnd = tempCapEnd; +#endif + } + +#ifndef QT_NO_REGEXP_CAPTURE + /* + Updating the capture zones is much of a task. + */ + if (ncap > 0) { + memcpy(capBegin, curCapBegin + j * ncap, ncap * sizeof(int)); + memcpy(capEnd, curCapEnd + j * ncap, ncap * sizeof(int)); + int c = scur.atom, n = snext.atom; + int p = -1, q = -1; + int cap; + + /* + Lemma 1. For any x in the range [0..nf), we + have f[x].parent < x. + + Proof. By looking at startAtom(), it is + clear that cf < nf holds all the time, and + thus that f[nf].parent < nf. + */ + + /* + If we are reentering an atom, we empty all + capture zones inside it. + */ + if ((q = scur.reenter.value(next)) != 0) { + QBitArray b(eng->nf, false); + b.setBit(q, true); + for (int ell = q + 1; ell < eng->nf; ell++) { + if (b.testBit(eng->f.at(ell).parent)) { + b.setBit(ell, true); + cap = eng->f.at(ell).capture; + if (cap >= 0) { + capBegin[cap] = EmptyCapture; + capEnd[cap] = EmptyCapture; + } + } + } + p = eng->f.at(q).parent; + + /* + Otherwise, close the capture zones we are + leaving. We are leaving f[c].capture, + f[f[c].parent].capture, + f[f[f[c].parent].parent].capture, ..., + until f[x].capture, with x such that + f[x].parent is the youngest common ancestor + for c and n. + + We go up along c's and n's ancestry until + we find x. + */ + } else { + p = c; + q = n; + while (p != q) { + if (p > q) { + cap = eng->f.at(p).capture; + if (cap >= 0) { + if (capBegin[cap] == i) { + capBegin[cap] = EmptyCapture; + capEnd[cap] = EmptyCapture; + } else { + capEnd[cap] = i; + } + } + p = eng->f.at(p).parent; + } else { + q = eng->f.at(q).parent; + } + } + } + + /* + In any case, we now open the capture zones + we are entering. We work upwards from n + until we reach p (the parent of the atom we + reenter or the youngest common ancestor). + */ + while (n > p) { + cap = eng->f.at(n).capture; + if (cap >= 0) { + capBegin[cap] = i; + capEnd[cap] = EmptyCapture; + } + n = eng->f.at(n).parent; + } + /* + If the next state was already in + nextStack, we must choose carefully which + capture zones we want to keep. + */ + if (capBegin == tempCapBegin && + isBetterCapture(ncap, capBegin, capEnd, nextCapBegin + m * ncap, + nextCapEnd + m * ncap)) { + memcpy(nextCapBegin + m * ncap, capBegin, ncap * sizeof(int)); + memcpy(nextCapEnd + m * ncap, capEnd, ncap * sizeof(int)); + } + } +#ifndef QT_NO_REGEXP_BACKREF + /* + We are done with updating the capture zones. + It's now time to put the next state to sleep, + if it needs to, and to remove it from + nextStack. + */ + if (needSomeSleep > 0) { + QVector<int> zzZ(2 + 2 * ncap); + zzZ[0] = i + needSomeSleep; + zzZ[1] = next; + if (ncap > 0) { + memcpy(zzZ.data() + 2, capBegin, ncap * sizeof(int)); + memcpy(zzZ.data() + 2 + ncap, capEnd, ncap * sizeof(int)); + } + inNextStack[nextStack[--nnext]] = -1; + sleeping.append(zzZ); + } +#endif +#endif + } + } + } +#ifndef QT_NO_REGEXP_CAPTURE + /* + If we reached the final state, hurray! Copy the captured + zone. + */ + if (ncap > 0 && (m = inNextStack[QRegExpEngine::FinalState]) != -1) { + memcpy(capBegin, nextCapBegin + m * ncap, ncap * sizeof(int)); + memcpy(capEnd, nextCapEnd + m * ncap, ncap * sizeof(int)); + } +#ifndef QT_NO_REGEXP_BACKREF + /* + It's time to wake up the sleepers. + */ + j = 0; + while (j < sleeping.count()) { + if (sleeping.at(j)[0] == i) { + const QVector<int> &zzZ = sleeping.at(j); + int next = zzZ[1]; + const int *capBegin = zzZ.data() + 2; + const int *capEnd = zzZ.data() + 2 + ncap; + bool copyOver = true; + + if ((m = inNextStack[next]) == -1) { + m = nnext++; + nextStack[m] = next; + inNextStack[next] = m; + } else { + copyOver = isBetterCapture(ncap, nextCapBegin + m * ncap, nextCapEnd + m * ncap, + capBegin, capEnd); + } + if (copyOver) { + memcpy(nextCapBegin + m * ncap, capBegin, ncap * sizeof(int)); + memcpy(nextCapEnd + m * ncap, capEnd, ncap * sizeof(int)); + } + + sleeping.removeAt(j); + } else { + ++j; + } + } +#endif +#endif + for (j = 0; j < nnext; j++) + inNextStack[nextStack[j]] = -1; + + // avoid needless iteration that confuses oneTestMatchedLen + if (nnext == 1 && nextStack[0] == QRegExpEngine::FinalState +#ifndef QT_NO_REGEXP_BACKREF + && sleeping.isEmpty() +#endif + ) + stop = true; + + qSwap(curStack, nextStack); +#ifndef QT_NO_REGEXP_CAPTURE + qSwap(curCapBegin, nextCapBegin); + qSwap(curCapEnd, nextCapEnd); +#endif + ncur = nnext; + nnext = 0; + ++i; + } + +#ifndef QT_NO_REGEXP_BACKREF + /* + If minimal matching is enabled, we might have some sleepers + left. + */ + if (!sleeping.isEmpty()) + sleeping.clear(); +#endif + + oneTestMatchedLen = i - 1; + return (matchLen >= 0); +} + +#ifndef QT_NO_REGEXP_CCLASS + +QRegExpCharClass::QRegExpCharClass() + : c(0), n(false) +{ +#ifndef QT_NO_REGEXP_OPTIM + occ1.fill(NoOccurrence, NumBadChars); +#endif +} + +QRegExpCharClass &QRegExpCharClass::operator=(const QRegExpCharClass &cc) +{ + c = cc.c; + r = cc.r; + n = cc.n; +#ifndef QT_NO_REGEXP_OPTIM + occ1 = cc.occ1; +#endif + return *this; +} + +void QRegExpCharClass::clear() +{ + c = 0; + r.resize(0); + n = false; +} + +void QRegExpCharClass::setNegative(bool negative) +{ + n = negative; +#ifndef QT_NO_REGEXP_OPTIM + occ1.fill(0, NumBadChars); +#endif +} + +void QRegExpCharClass::addCategories(int cats) +{ + c |= cats; +#ifndef QT_NO_REGEXP_OPTIM + occ1.fill(0, NumBadChars); +#endif +} + +void QRegExpCharClass::addRange(ushort from, ushort to) +{ + if (from > to) + qSwap(from, to); + int m = r.size(); + r.resize(m + 1); + r[m].from = from; + r[m].len = to - from + 1; + +#ifndef QT_NO_REGEXP_OPTIM + int i; + + if (to - from < NumBadChars) { + if (from % NumBadChars <= to % NumBadChars) { + for (i = from % NumBadChars; i <= to % NumBadChars; i++) + occ1[i] = 0; + } else { + for (i = 0; i <= to % NumBadChars; i++) + occ1[i] = 0; + for (i = from % NumBadChars; i < NumBadChars; i++) + occ1[i] = 0; + } + } else { + occ1.fill(0, NumBadChars); + } +#endif +} + +bool QRegExpCharClass::in(QChar ch) const +{ +#ifndef QT_NO_REGEXP_OPTIM + if (occ1.at(BadChar(ch)) == NoOccurrence) + return n; +#endif + + if (c != 0 && (c & (1 << (int)ch.category())) != 0) + return !n; + + const int uc = ch.unicode(); + int size = r.size(); + + for (int i = 0; i < size; ++i) { + const QRegExpCharClassRange &range = r.at(i); + if (uint(uc - range.from) < uint(r.at(i).len)) + return !n; + } + return n; +} + +#if defined(QT_DEBUG) +void QRegExpCharClass::dump() const +{ + int i; + qDebug(" %stive character class", n ? "nega" : "posi"); +#ifndef QT_NO_REGEXP_CCLASS + if (c != 0) + qDebug(" categories 0x%.8x", c); +#endif + for (i = 0; i < r.size(); i++) + qDebug(" 0x%.4x through 0x%.4x", r[i].from, r[i].from + r[i].len - 1); +} +#endif +#endif + +QRegExpEngine::Box::Box(QRegExpEngine *engine) + : eng(engine), skipanchors(0) +#ifndef QT_NO_REGEXP_OPTIM + , earlyStart(0), lateStart(0), maxl(0) +#endif +{ +#ifndef QT_NO_REGEXP_OPTIM + occ1.fill(NoOccurrence, NumBadChars); +#endif + minl = 0; +} + +QRegExpEngine::Box &QRegExpEngine::Box::operator=(const Box &b) +{ + eng = b.eng; + ls = b.ls; + rs = b.rs; + lanchors = b.lanchors; + ranchors = b.ranchors; + skipanchors = b.skipanchors; +#ifndef QT_NO_REGEXP_OPTIM + earlyStart = b.earlyStart; + lateStart = b.lateStart; + str = b.str; + leftStr = b.leftStr; + rightStr = b.rightStr; + maxl = b.maxl; + occ1 = b.occ1; +#endif + minl = b.minl; + return *this; +} + +void QRegExpEngine::Box::set(QChar ch) +{ + ls.resize(1); + ls[0] = eng->createState(ch); + rs = ls; +#ifndef QT_NO_REGEXP_OPTIM + str = ch; + leftStr = ch; + rightStr = ch; + maxl = 1; + occ1[BadChar(ch)] = 0; +#endif + minl = 1; +} + +void QRegExpEngine::Box::set(const QRegExpCharClass &cc) +{ + ls.resize(1); + ls[0] = eng->createState(cc); + rs = ls; +#ifndef QT_NO_REGEXP_OPTIM + maxl = 1; + occ1 = cc.firstOccurrence(); +#endif + minl = 1; +} + +#ifndef QT_NO_REGEXP_BACKREF +void QRegExpEngine::Box::set(int bref) +{ + ls.resize(1); + ls[0] = eng->createState(bref); + rs = ls; + if (bref >= 1 && bref <= MaxBackRefs) + skipanchors = Anchor_BackRef0Empty << bref; +#ifndef QT_NO_REGEXP_OPTIM + maxl = InftyLen; +#endif + minl = 0; +} +#endif + +void QRegExpEngine::Box::cat(const Box &b) +{ + eng->addCatTransitions(rs, b.ls); + addAnchorsToEngine(b); + if (minl == 0) { + lanchors.unite(b.lanchors); + if (skipanchors != 0) { + for (int i = 0; i < b.ls.size(); i++) { + int a = eng->anchorConcatenation(lanchors.value(b.ls.at(i), 0), skipanchors); + lanchors.insert(b.ls.at(i), a); + } + } + mergeInto(&ls, b.ls); + } + if (b.minl == 0) { + ranchors.unite(b.ranchors); + if (b.skipanchors != 0) { + for (int i = 0; i < rs.size(); i++) { + int a = eng->anchorConcatenation(ranchors.value(rs.at(i), 0), b.skipanchors); + ranchors.insert(rs.at(i), a); + } + } + mergeInto(&rs, b.rs); + } else { + ranchors = b.ranchors; + rs = b.rs; + } + +#ifndef QT_NO_REGEXP_OPTIM + if (maxl != InftyLen) { + if (rightStr.length() + b.leftStr.length() > + qMax(str.length(), b.str.length())) { + earlyStart = minl - rightStr.length(); + lateStart = maxl - rightStr.length(); + str = rightStr + b.leftStr; + } else if (b.str.length() > str.length()) { + earlyStart = minl + b.earlyStart; + lateStart = maxl + b.lateStart; + str = b.str; + } + } + + if (leftStr.length() == maxl) + leftStr += b.leftStr; + + if (b.rightStr.length() == b.maxl) { + rightStr += b.rightStr; + } else { + rightStr = b.rightStr; + } + + if (maxl == InftyLen || b.maxl == InftyLen) { + maxl = InftyLen; + } else { + maxl += b.maxl; + } + + for (int i = 0; i < NumBadChars; i++) { + if (b.occ1.at(i) != NoOccurrence && minl + b.occ1.at(i) < occ1.at(i)) + occ1[i] = minl + b.occ1.at(i); + } +#endif + + minl += b.minl; + if (minl == 0) + skipanchors = eng->anchorConcatenation(skipanchors, b.skipanchors); + else + skipanchors = 0; +} + +void QRegExpEngine::Box::orx(const Box &b) +{ + mergeInto(&ls, b.ls); + lanchors.unite(b.lanchors); + mergeInto(&rs, b.rs); + ranchors.unite(b.ranchors); + + if (b.minl == 0) { + if (minl == 0) + skipanchors = eng->anchorAlternation(skipanchors, b.skipanchors); + else + skipanchors = b.skipanchors; + } + +#ifndef QT_NO_REGEXP_OPTIM + for (int i = 0; i < NumBadChars; i++) { + if (occ1.at(i) > b.occ1.at(i)) + occ1[i] = b.occ1.at(i); + } + earlyStart = 0; + lateStart = 0; + str = QString(); + leftStr = QString(); + rightStr = QString(); + if (b.maxl > maxl) + maxl = b.maxl; +#endif + if (b.minl < minl) + minl = b.minl; +} + +void QRegExpEngine::Box::plus(int atom) +{ +#ifndef QT_NO_REGEXP_CAPTURE + eng->addPlusTransitions(rs, ls, atom); +#else + Q_UNUSED(atom); + eng->addCatTransitions(rs, ls); +#endif + addAnchorsToEngine(*this); +#ifndef QT_NO_REGEXP_OPTIM + maxl = InftyLen; +#endif +} + +void QRegExpEngine::Box::opt() +{ +#ifndef QT_NO_REGEXP_OPTIM + earlyStart = 0; + lateStart = 0; + str = QString(); + leftStr = QString(); + rightStr = QString(); +#endif + skipanchors = 0; + minl = 0; +} + +void QRegExpEngine::Box::catAnchor(int a) +{ + if (a != 0) { + for (int i = 0; i < rs.size(); i++) { + a = eng->anchorConcatenation(ranchors.value(rs.at(i), 0), a); + ranchors.insert(rs.at(i), a); + } + if (minl == 0) + skipanchors = eng->anchorConcatenation(skipanchors, a); + } +} + +#ifndef QT_NO_REGEXP_OPTIM +void QRegExpEngine::Box::setupHeuristics() +{ + eng->goodEarlyStart = earlyStart; + eng->goodLateStart = lateStart; + eng->goodStr = eng->cs ? str : str.toLower(); + + eng->minl = minl; + if (eng->cs) { + /* + A regular expression such as 112|1 has occ1['2'] = 2 and minl = + 1 at this point. An entry of occ1 has to be at most minl or + infinity for the rest of the algorithm to go well. + + We waited until here before normalizing these cases (instead of + doing it in Box::orx()) because sometimes things improve by + themselves. Consider for example (112|1)34. + */ + for (int i = 0; i < NumBadChars; i++) { + if (occ1.at(i) != NoOccurrence && occ1.at(i) >= minl) + occ1[i] = minl; + } + eng->occ1 = occ1; + } else { + eng->occ1.fill(0, NumBadChars); + } + + eng->heuristicallyChooseHeuristic(); +} +#endif + +#if defined(QT_DEBUG) +void QRegExpEngine::Box::dump() const +{ + int i; + qDebug("Box of at least %d character%s", minl, minl == 1 ? "" : "s"); + qDebug(" Left states:"); + for (i = 0; i < ls.size(); i++) { + if (lanchors.value(ls[i], 0) == 0) + qDebug(" %d", ls[i]); + else + qDebug(" %d [anchors 0x%.8x]", ls[i], lanchors[ls[i]]); + } + qDebug(" Right states:"); + for (i = 0; i < rs.size(); i++) { + if (ranchors.value(rs[i], 0) == 0) + qDebug(" %d", rs[i]); + else + qDebug(" %d [anchors 0x%.8x]", rs[i], ranchors[rs[i]]); + } + qDebug(" Skip anchors: 0x%.8x", skipanchors); +} +#endif + +void QRegExpEngine::Box::addAnchorsToEngine(const Box &to) const +{ + for (int i = 0; i < to.ls.size(); i++) { + for (int j = 0; j < rs.size(); j++) { + int a = eng->anchorConcatenation(ranchors.value(rs.at(j), 0), + to.lanchors.value(to.ls.at(i), 0)); + eng->addAnchors(rs[j], to.ls[i], a); + } + } +} + +int QRegExpEngine::getChar() +{ + return (yyPos == yyLen) ? EOS : yyIn[yyPos++].unicode(); +} + +int QRegExpEngine::getEscape() +{ +#ifndef QT_NO_REGEXP_ESCAPE + const char tab[] = "afnrtv"; // no b, as \b means word boundary + const char backTab[] = "\a\f\n\r\t\v"; + ushort low; + int i; +#endif + ushort val; + int prevCh = yyCh; + + if (prevCh == EOS) { + error(RXERR_END); + return Tok_Char | '\\'; + } + yyCh = getChar(); +#ifndef QT_NO_REGEXP_ESCAPE + if ((prevCh & ~0xff) == 0) { + const char *p = strchr(tab, prevCh); + if (p != 0) + return Tok_Char | backTab[p - tab]; + } +#endif + + switch (prevCh) { +#ifndef QT_NO_REGEXP_ESCAPE + case '0': + val = 0; + for (i = 0; i < 3; i++) { + if (yyCh >= '0' && yyCh <= '7') + val = (val << 3) | (yyCh - '0'); + else + break; + yyCh = getChar(); + } + if ((val & ~0377) != 0) + error(RXERR_OCTAL); + return Tok_Char | val; +#endif +#ifndef QT_NO_REGEXP_ESCAPE + case 'B': + return Tok_NonWord; +#endif +#ifndef QT_NO_REGEXP_CCLASS + case 'D': + // see QChar::isDigit() + yyCharClass->addCategories(0x7fffffef); + return Tok_CharClass; + case 'S': + // see QChar::isSpace() + yyCharClass->addCategories(0x7ffff87f); + yyCharClass->addRange(0x0000, 0x0008); + yyCharClass->addRange(0x000e, 0x001f); + yyCharClass->addRange(0x007f, 0x009f); + return Tok_CharClass; + case 'W': + // see QChar::isLetterOrNumber() and QChar::isMark() + yyCharClass->addCategories(0x7fe07f81); + yyCharClass->addRange(0x203f, 0x2040); + yyCharClass->addSingleton(0x2040); + yyCharClass->addSingleton(0x2054); + yyCharClass->addSingleton(0x30fb); + yyCharClass->addRange(0xfe33, 0xfe34); + yyCharClass->addRange(0xfe4d, 0xfe4f); + yyCharClass->addSingleton(0xff3f); + yyCharClass->addSingleton(0xff65); + return Tok_CharClass; +#endif +#ifndef QT_NO_REGEXP_ESCAPE + case 'b': + return Tok_Word; +#endif +#ifndef QT_NO_REGEXP_CCLASS + case 'd': + // see QChar::isDigit() + yyCharClass->addCategories(0x00000010); + return Tok_CharClass; + case 's': + // see QChar::isSpace() + yyCharClass->addCategories(0x00000380); + yyCharClass->addRange(0x0009, 0x000d); + return Tok_CharClass; + case 'w': + // see QChar::isLetterOrNumber() and QChar::isMark() + yyCharClass->addCategories(0x000f807e); + yyCharClass->addSingleton(0x005f); // '_' + return Tok_CharClass; +#endif +#ifndef QT_NO_REGEXP_ESCAPE + case 'x': + val = 0; + for (i = 0; i < 4; i++) { + low = QChar(yyCh).toLower().unicode(); + if (low >= '0' && low <= '9') + val = (val << 4) | (low - '0'); + else if (low >= 'a' && low <= 'f') + val = (val << 4) | (low - 'a' + 10); + else + break; + yyCh = getChar(); + } + return Tok_Char | val; +#endif + default: + if (prevCh >= '1' && prevCh <= '9') { +#ifndef QT_NO_REGEXP_BACKREF + val = prevCh - '0'; + while (yyCh >= '0' && yyCh <= '9') { + val = (val * 10) + (yyCh - '0'); + yyCh = getChar(); + } + return Tok_BackRef | val; +#else + error(RXERR_DISABLED); +#endif + } + return Tok_Char | prevCh; + } +} + +#ifndef QT_NO_REGEXP_INTERVAL +int QRegExpEngine::getRep(int def) +{ + if (yyCh >= '0' && yyCh <= '9') { + int rep = 0; + do { + rep = 10 * rep + yyCh - '0'; + if (rep >= InftyRep) { + error(RXERR_REPETITION); + rep = def; + } + yyCh = getChar(); + } while (yyCh >= '0' && yyCh <= '9'); + return rep; + } else { + return def; + } +} +#endif + +#ifndef QT_NO_REGEXP_LOOKAHEAD +void QRegExpEngine::skipChars(int n) +{ + if (n > 0) { + yyPos += n - 1; + yyCh = getChar(); + } +} +#endif + +void QRegExpEngine::error(const char *msg) +{ + if (yyError.isEmpty()) + yyError = QLatin1String(msg); +} + +void QRegExpEngine::startTokenizer(const QChar *rx, int len) +{ + yyIn = rx; + yyPos0 = 0; + yyPos = 0; + yyLen = len; + yyCh = getChar(); + yyCharClass = new QRegExpCharClass; + yyMinRep = 0; + yyMaxRep = 0; + yyError = QString(); +} + +int QRegExpEngine::getToken() +{ +#ifndef QT_NO_REGEXP_CCLASS + ushort pendingCh = 0; + bool charPending; + bool rangePending; + int tok; +#endif + int prevCh = yyCh; + + yyPos0 = yyPos - 1; +#ifndef QT_NO_REGEXP_CCLASS + yyCharClass->clear(); +#endif + yyMinRep = 0; + yyMaxRep = 0; + yyCh = getChar(); + + switch (prevCh) { + case EOS: + yyPos0 = yyPos; + return Tok_Eos; + case '$': + return Tok_Dollar; + case '(': + if (yyCh == '?') { + prevCh = getChar(); + yyCh = getChar(); + switch (prevCh) { +#ifndef QT_NO_REGEXP_LOOKAHEAD + case '!': + return Tok_NegLookahead; + case '=': + return Tok_PosLookahead; +#endif + case ':': + return Tok_MagicLeftParen; + default: + error(RXERR_LOOKAHEAD); + return Tok_MagicLeftParen; + } + } else { + return Tok_LeftParen; + } + case ')': + return Tok_RightParen; + case '*': + yyMinRep = 0; + yyMaxRep = InftyRep; + return Tok_Quantifier; + case '+': + yyMinRep = 1; + yyMaxRep = InftyRep; + return Tok_Quantifier; + case '.': +#ifndef QT_NO_REGEXP_CCLASS + yyCharClass->setNegative(true); +#endif + return Tok_CharClass; + case '?': + yyMinRep = 0; + yyMaxRep = 1; + return Tok_Quantifier; + case '[': +#ifndef QT_NO_REGEXP_CCLASS + if (yyCh == '^') { + yyCharClass->setNegative(true); + yyCh = getChar(); + } + charPending = false; + rangePending = false; + do { + if (yyCh == '-' && charPending && !rangePending) { + rangePending = true; + yyCh = getChar(); + } else { + if (charPending && !rangePending) { + yyCharClass->addSingleton(pendingCh); + charPending = false; + } + if (yyCh == '\\') { + yyCh = getChar(); + tok = getEscape(); + if (tok == Tok_Word) + tok = '\b'; + } else { + tok = Tok_Char | yyCh; + yyCh = getChar(); + } + if (tok == Tok_CharClass) { + if (rangePending) { + yyCharClass->addSingleton('-'); + yyCharClass->addSingleton(pendingCh); + charPending = false; + rangePending = false; + } + } else if ((tok & Tok_Char) != 0) { + if (rangePending) { + yyCharClass->addRange(pendingCh, tok ^ Tok_Char); + charPending = false; + rangePending = false; + } else { + pendingCh = tok ^ Tok_Char; + charPending = true; + } + } else { + error(RXERR_CHARCLASS); + } + } + } while (yyCh != ']' && yyCh != EOS); + if (rangePending) + yyCharClass->addSingleton('-'); + if (charPending) + yyCharClass->addSingleton(pendingCh); + if (yyCh == EOS) + error(RXERR_END); + else + yyCh = getChar(); + return Tok_CharClass; +#else + error(RXERR_END); + return Tok_Char | '['; +#endif + case '\\': + return getEscape(); + case ']': + error(RXERR_LEFTDELIM); + return Tok_Char | ']'; + case '^': + return Tok_Caret; + case '{': +#ifndef QT_NO_REGEXP_INTERVAL + yyMinRep = getRep(0); + yyMaxRep = yyMinRep; + if (yyCh == ',') { + yyCh = getChar(); + yyMaxRep = getRep(InftyRep); + } + if (yyMaxRep < yyMinRep) + qSwap(yyMinRep, yyMaxRep); + if (yyCh != '}') + error(RXERR_REPETITION); + yyCh = getChar(); + return Tok_Quantifier; +#else + error(RXERR_DISABLED); + return Tok_Char | '{'; +#endif + case '|': + return Tok_Bar; + case '}': + error(RXERR_LEFTDELIM); + return Tok_Char | '}'; + default: + return Tok_Char | prevCh; + } +} + +int QRegExpEngine::parse(const QChar *pattern, int len) +{ + valid = true; + startTokenizer(pattern, len); + yyTok = getToken(); +#ifndef QT_NO_REGEXP_CAPTURE + yyMayCapture = true; +#else + yyMayCapture = false; +#endif + +#ifndef QT_NO_REGEXP_CAPTURE + int atom = startAtom(false); +#endif + QRegExpCharClass anything; + Box box(this); // create InitialState + box.set(anything); + Box rightBox(this); // create FinalState + rightBox.set(anything); + + Box middleBox(this); + parseExpression(&middleBox); +#ifndef QT_NO_REGEXP_CAPTURE + finishAtom(atom, false); +#endif +#ifndef QT_NO_REGEXP_OPTIM + middleBox.setupHeuristics(); +#endif + box.cat(middleBox); + box.cat(rightBox); + delete yyCharClass; + yyCharClass = 0; + +#ifndef QT_NO_REGEXP_CAPTURE + for (int i = 0; i < nf; ++i) { + switch (f[i].capture) { + case QRegExpAtom::NoCapture: + break; + case QRegExpAtom::OfficialCapture: + f[i].capture = ncap; + captureForOfficialCapture.append(ncap); + ++ncap; + ++officialncap; + break; + case QRegExpAtom::UnofficialCapture: + f[i].capture = greedyQuantifiers ? ncap++ : QRegExpAtom::NoCapture; + } + } + +#ifndef QT_NO_REGEXP_BACKREF +#ifndef QT_NO_REGEXP_OPTIM + if (officialncap == 0 && nbrefs == 0) { + ncap = nf = 0; + f.clear(); + } +#endif + // handle the case where there's a \5 with no corresponding capture + // (captureForOfficialCapture.size() != officialncap) + for (int i = 0; i < nbrefs - officialncap; ++i) { + captureForOfficialCapture.append(ncap); + ++ncap; + } +#endif +#endif + + if (!yyError.isEmpty()) + return -1; + +#ifndef QT_NO_REGEXP_OPTIM + const QRegExpAutomatonState &sinit = s.at(InitialState); + caretAnchored = !sinit.anchors.isEmpty(); + if (caretAnchored) { + const QMap<int, int> &anchors = sinit.anchors; + QMap<int, int>::const_iterator a; + for (a = anchors.constBegin(); a != anchors.constEnd(); ++a) { + if ( +#ifndef QT_NO_REGEXP_ANCHOR_ALT + (*a & Anchor_Alternation) != 0 || +#endif + (*a & Anchor_Caret) == 0) + { + caretAnchored = false; + break; + } + } + } +#endif + + // cleanup anchors + int numStates = s.count(); + for (int i = 0; i < numStates; ++i) { + QRegExpAutomatonState &state = s[i]; + if (!state.anchors.isEmpty()) { + QMap<int, int>::iterator a = state.anchors.begin(); + while (a != state.anchors.end()) { + if (a.value() == 0) + a = state.anchors.erase(a); + else + ++a; + } + } + } + + return yyPos0; +} + +void QRegExpEngine::parseAtom(Box *box) +{ +#ifndef QT_NO_REGEXP_LOOKAHEAD + QRegExpEngine *eng = 0; + bool neg; + int len; +#endif + + if ((yyTok & Tok_Char) != 0) { + box->set(QChar(yyTok ^ Tok_Char)); + } else { +#ifndef QT_NO_REGEXP_OPTIM + trivial = false; +#endif + switch (yyTok) { + case Tok_Dollar: + box->catAnchor(Anchor_Dollar); + break; + case Tok_Caret: + box->catAnchor(Anchor_Caret); + break; +#ifndef QT_NO_REGEXP_LOOKAHEAD + case Tok_PosLookahead: + case Tok_NegLookahead: + neg = (yyTok == Tok_NegLookahead); + eng = new QRegExpEngine(cs, greedyQuantifiers); + len = eng->parse(yyIn + yyPos - 1, yyLen - yyPos + 1); + if (len >= 0) + skipChars(len); + else + error(RXERR_LOOKAHEAD); + box->catAnchor(addLookahead(eng, neg)); + yyTok = getToken(); + if (yyTok != Tok_RightParen) + error(RXERR_LOOKAHEAD); + break; +#endif +#ifndef QT_NO_REGEXP_ESCAPE + case Tok_Word: + box->catAnchor(Anchor_Word); + break; + case Tok_NonWord: + box->catAnchor(Anchor_NonWord); + break; +#endif + case Tok_LeftParen: + case Tok_MagicLeftParen: + yyTok = getToken(); + parseExpression(box); + if (yyTok != Tok_RightParen) + error(RXERR_END); + break; + case Tok_CharClass: + box->set(*yyCharClass); + break; + case Tok_Quantifier: + error(RXERR_REPETITION); + break; + default: +#ifndef QT_NO_REGEXP_BACKREF + if ((yyTok & Tok_BackRef) != 0) + box->set(yyTok ^ Tok_BackRef); + else +#endif + error(RXERR_DISABLED); + } + } + yyTok = getToken(); +} + +void QRegExpEngine::parseFactor(Box *box) +{ +#ifndef QT_NO_REGEXP_CAPTURE + int outerAtom = greedyQuantifiers ? startAtom(false) : -1; + int innerAtom = startAtom(yyMayCapture && yyTok == Tok_LeftParen); + bool magicLeftParen = (yyTok == Tok_MagicLeftParen); +#else + const int innerAtom = -1; +#endif + +#ifndef QT_NO_REGEXP_INTERVAL +#define YYREDO() \ + yyIn = in, yyPos0 = pos0, yyPos = pos, yyLen = len, yyCh = ch, \ + *yyCharClass = charClass, yyMinRep = 0, yyMaxRep = 0, yyTok = tok + + const QChar *in = yyIn; + int pos0 = yyPos0; + int pos = yyPos; + int len = yyLen; + int ch = yyCh; + QRegExpCharClass charClass; + if (yyTok == Tok_CharClass) + charClass = *yyCharClass; + int tok = yyTok; + bool mayCapture = yyMayCapture; +#endif + + parseAtom(box); +#ifndef QT_NO_REGEXP_CAPTURE + finishAtom(innerAtom, magicLeftParen); +#endif + + bool hasQuantifier = (yyTok == Tok_Quantifier); + if (hasQuantifier) { +#ifndef QT_NO_REGEXP_OPTIM + trivial = false; +#endif + if (yyMaxRep == InftyRep) { + box->plus(innerAtom); +#ifndef QT_NO_REGEXP_INTERVAL + } else if (yyMaxRep == 0) { + box->clear(); +#endif + } + if (yyMinRep == 0) + box->opt(); + +#ifndef QT_NO_REGEXP_INTERVAL + yyMayCapture = false; + int alpha = (yyMinRep == 0) ? 0 : yyMinRep - 1; + int beta = (yyMaxRep == InftyRep) ? 0 : yyMaxRep - (alpha + 1); + + Box rightBox(this); + int i; + + for (i = 0; i < beta; i++) { + YYREDO(); + Box leftBox(this); + parseAtom(&leftBox); + leftBox.cat(rightBox); + leftBox.opt(); + rightBox = leftBox; + } + for (i = 0; i < alpha; i++) { + YYREDO(); + Box leftBox(this); + parseAtom(&leftBox); + leftBox.cat(rightBox); + rightBox = leftBox; + } + rightBox.cat(*box); + *box = rightBox; +#endif + yyTok = getToken(); +#ifndef QT_NO_REGEXP_INTERVAL + yyMayCapture = mayCapture; +#endif + } +#undef YYREDO +#ifndef QT_NO_REGEXP_CAPTURE + if (greedyQuantifiers) + finishAtom(outerAtom, hasQuantifier); +#endif +} + +void QRegExpEngine::parseTerm(Box *box) +{ +#ifndef QT_NO_REGEXP_OPTIM + if (yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar) + parseFactor(box); +#endif + while (yyTok != Tok_Eos && yyTok != Tok_RightParen && yyTok != Tok_Bar) { + Box rightBox(this); + parseFactor(&rightBox); + box->cat(rightBox); + } +} + +void QRegExpEngine::parseExpression(Box *box) +{ + parseTerm(box); + while (yyTok == Tok_Bar) { +#ifndef QT_NO_REGEXP_OPTIM + trivial = false; +#endif + Box rightBox(this); + yyTok = getToken(); + parseTerm(&rightBox); + box->orx(rightBox); + } +} + +/* + The struct QRegExpPrivate contains the private data of a regular + expression other than the automaton. It makes it possible for many + QRegExp objects to use the same QRegExpEngine object with different + QRegExpPrivate objects. +*/ +struct QRegExpPrivate +{ + QRegExpEngine *eng; + QRegExpEngineKey engineKey; + bool minimal; +#ifndef QT_NO_REGEXP_CAPTURE + QString t; // last string passed to QRegExp::indexIn() or lastIndexIn() + QStringList capturedCache; // what QRegExp::capturedTexts() returned last +#endif + QRegExpMatchState matchState; + + inline QRegExpPrivate() + : eng(0), engineKey(QString(), QRegExp::RegExp, Qt::CaseSensitive), minimal(false) { } + inline QRegExpPrivate(const QRegExpEngineKey &key) + : eng(0), engineKey(key), minimal(false) {} +}; + +#if !defined(QT_NO_REGEXP_OPTIM) +uint qHash(const QRegExpEngineKey &key) +{ + return qHash(key.pattern); +} + +typedef QCache<QRegExpEngineKey, QRegExpEngine> EngineCache; +Q_GLOBAL_STATIC(EngineCache, globalEngineCache) +Q_GLOBAL_STATIC(QMutex, mutex) +#endif // QT_NO_REGEXP_OPTIM + +static void derefEngine(QRegExpEngine *eng, const QRegExpEngineKey &key) +{ + if (!eng->ref.deref()) { +#if !defined(QT_NO_REGEXP_OPTIM) + if (globalEngineCache()) { + QMutexLocker locker(mutex()); + globalEngineCache()->insert(key, eng, 4 + key.pattern.length() / 4); + } + else + delete eng; +#else + Q_UNUSED(key); + delete eng; +#endif + } +} + +static void prepareEngine_helper(QRegExpPrivate *priv) +{ + bool initMatchState = !priv->eng; +#if !defined(QT_NO_REGEXP_OPTIM) + if (!priv->eng) { + QMutexLocker locker(mutex()); + priv->eng = globalEngineCache()->take(priv->engineKey); + if (priv->eng != 0) + priv->eng->ref.ref(); + } +#endif // QT_NO_REGEXP_OPTIM + + if (!priv->eng) + priv->eng = new QRegExpEngine(priv->engineKey); + + if (initMatchState) + priv->matchState.prepareForMatch(priv->eng); +} + +inline static void prepareEngine(QRegExpPrivate *priv) +{ + if (priv->eng) + return; + prepareEngine_helper(priv); +} + +static void prepareEngineForMatch(QRegExpPrivate *priv, const QString &str) +{ + prepareEngine(priv); + priv->matchState.prepareForMatch(priv->eng); +#ifndef QT_NO_REGEXP_CAPTURE + priv->t = str; + priv->capturedCache.clear(); +#else + Q_UNUSED(str); +#endif +} + +static void invalidateEngine(QRegExpPrivate *priv) +{ + if (priv->eng != 0) { + derefEngine(priv->eng, priv->engineKey); + priv->eng = 0; + priv->matchState.drain(); + } +} + +/*! + \enum QRegExp::CaretMode + + The CaretMode enum defines the different meanings of the caret + (\bold{^}) in a regular expression. The possible values are: + + \value CaretAtZero + The caret corresponds to index 0 in the searched string. + + \value CaretAtOffset + The caret corresponds to the start offset of the search. + + \value CaretWontMatch + The caret never matches. +*/ + +/*! + \enum QRegExp::PatternSyntax + + The syntax used to interpret the meaning of the pattern. + + \value RegExp A rich Perl-like pattern matching syntax. This is + the default. + + \value RegExp2 Like RegExp, but with \l{greedy quantifiers}. This + will be the default in Qt 5. (Introduced in Qt 4.2.) + + \value Wildcard This provides a simple pattern matching syntax + similar to that used by shells (command interpreters) for "file + globbing". See \l{Wildcard Matching}. + + \value FixedString The pattern is a fixed string. This is + equivalent to using the RegExp pattern on a string in + which all metacharacters are escaped using escape(). + + \sa setPatternSyntax() +*/ + +/*! + Constructs an empty regexp. + + \sa isValid(), errorString() +*/ +QRegExp::QRegExp() +{ + priv = new QRegExpPrivate; +} + +/*! + Constructs a regular expression object for the given \a pattern + string. The pattern must be given using wildcard notation if \a + syntax is \l Wildcard; the default is \l RegExp. The pattern is + case sensitive, unless \a cs is Qt::CaseInsensitive. Matching is + greedy (maximal), but can be changed by calling + setMinimal(). + + \sa setPattern(), setCaseSensitivity(), setPatternSyntax() +*/ +QRegExp::QRegExp(const QString &pattern, Qt::CaseSensitivity cs, PatternSyntax syntax) +{ + priv = new QRegExpPrivate(QRegExpEngineKey(pattern, syntax, cs)); +} + +/*! + Constructs a regular expression as a copy of \a rx. + + \sa operator=() +*/ +QRegExp::QRegExp(const QRegExp &rx) +{ + priv = new QRegExpPrivate; + operator=(rx); +} + +/*! + Destroys the regular expression and cleans up its internal data. +*/ +QRegExp::~QRegExp() +{ + invalidateEngine(priv); + delete priv; +} + +/*! + Copies the regular expression \a rx and returns a reference to the + copy. The case sensitivity, wildcard, and minimal matching options + are also copied. +*/ +QRegExp &QRegExp::operator=(const QRegExp &rx) +{ + prepareEngine(rx.priv); // to allow sharing + QRegExpEngine *otherEng = rx.priv->eng; + if (otherEng) + otherEng->ref.ref(); + invalidateEngine(priv); + priv->eng = otherEng; + priv->engineKey = rx.priv->engineKey; + priv->minimal = rx.priv->minimal; +#ifndef QT_NO_REGEXP_CAPTURE + priv->t = rx.priv->t; + priv->capturedCache = rx.priv->capturedCache; +#endif + if (priv->eng) + priv->matchState.prepareForMatch(priv->eng); + priv->matchState.captured = rx.priv->matchState.captured; + return *this; +} + +/*! + Returns true if this regular expression is equal to \a rx; + otherwise returns false. + + Two QRegExp objects are equal if they have the same pattern + strings and the same settings for case sensitivity, wildcard and + minimal matching. +*/ +bool QRegExp::operator==(const QRegExp &rx) const +{ + return priv->engineKey == rx.priv->engineKey && priv->minimal == rx.priv->minimal; +} + +/*! + \fn bool QRegExp::operator!=(const QRegExp &rx) const + + Returns true if this regular expression is not equal to \a rx; + otherwise returns false. + + \sa operator==() +*/ + +/*! + Returns true if the pattern string is empty; otherwise returns + false. + + If you call exactMatch() with an empty pattern on an empty string + it will return true; otherwise it returns false since it operates + over the whole string. If you call indexIn() with an empty pattern + on \e any string it will return the start offset (0 by default) + because the empty pattern matches the 'emptiness' at the start of + the string. In this case the length of the match returned by + matchedLength() will be 0. + + See QString::isEmpty(). +*/ + +bool QRegExp::isEmpty() const +{ + return priv->engineKey.pattern.isEmpty(); +} + +/*! + Returns true if the regular expression is valid; otherwise returns + false. An invalid regular expression never matches. + + The pattern \bold{[a-z} is an example of an invalid pattern, since + it lacks a closing square bracket. + + Note that the validity of a regexp may also depend on the setting + of the wildcard flag, for example \bold{*.html} is a valid + wildcard regexp but an invalid full regexp. + + \sa errorString() +*/ +bool QRegExp::isValid() const +{ + if (priv->engineKey.pattern.isEmpty()) { + return true; + } else { + prepareEngine(priv); + return priv->eng->isValid(); + } +} + +/*! + Returns the pattern string of the regular expression. The pattern + has either regular expression syntax or wildcard syntax, depending + on patternSyntax(). + + \sa patternSyntax(), caseSensitivity() +*/ +QString QRegExp::pattern() const +{ + return priv->engineKey.pattern; +} + +/*! + Sets the pattern string to \a pattern. The case sensitivity, + wildcard, and minimal matching options are not changed. + + \sa setPatternSyntax(), setCaseSensitivity() +*/ +void QRegExp::setPattern(const QString &pattern) +{ + if (priv->engineKey.pattern != pattern) { + invalidateEngine(priv); + priv->engineKey.pattern = pattern; + } +} + +/*! + Returns Qt::CaseSensitive if the regexp is matched case + sensitively; otherwise returns Qt::CaseInsensitive. + + \sa patternSyntax(), pattern(), isMinimal() +*/ +Qt::CaseSensitivity QRegExp::caseSensitivity() const +{ + return priv->engineKey.cs; +} + +/*! + Sets case sensitive matching to \a cs. + + If \a cs is Qt::CaseSensitive, \bold{\\.txt$} matches + \c{readme.txt} but not \c{README.TXT}. + + \sa setPatternSyntax(), setPattern(), setMinimal() +*/ +void QRegExp::setCaseSensitivity(Qt::CaseSensitivity cs) +{ + if ((bool)cs != (bool)priv->engineKey.cs) { + invalidateEngine(priv); + priv->engineKey.cs = cs; + } +} + +/*! + Returns the syntax used by the regular expression. The default is + QRegExp::RegExp. + + \sa pattern(), caseSensitivity() +*/ +QRegExp::PatternSyntax QRegExp::patternSyntax() const +{ + return priv->engineKey.patternSyntax; +} + +/*! + Sets the syntax mode for the regular expression. The default is + QRegExp::RegExp. + + Setting \a syntax to QRegExp::Wildcard enables simple shell-like + \l{wildcard matching}. For example, \bold{r*.txt} matches the + string \c{readme.txt} in wildcard mode, but does not match + \c{readme}. + + Setting \a syntax to QRegExp::FixedString means that the pattern + is interpreted as a plain string. Special characters (e.g., + backslash) don't need to be escaped then. + + \sa setPattern(), setCaseSensitivity(), escape() +*/ +void QRegExp::setPatternSyntax(PatternSyntax syntax) +{ + if (syntax != priv->engineKey.patternSyntax) { + invalidateEngine(priv); + priv->engineKey.patternSyntax = syntax; + } +} + +/*! + Returns true if minimal (non-greedy) matching is enabled; + otherwise returns false. + + \sa caseSensitivity(), setMinimal() +*/ +bool QRegExp::isMinimal() const +{ + return priv->minimal; +} + +/*! + Enables or disables minimal matching. If \a minimal is false, + matching is greedy (maximal) which is the default. + + For example, suppose we have the input string "We must be + <b>bold</b>, very <b>bold</b>!" and the pattern + \bold{<b>.*</b>}. With the default greedy (maximal) matching, + the match is "We must be \underline{<b>bold</b>, very + <b>bold</b>}!". But with minimal (non-greedy) matching, the + first match is: "We must be \underline{<b>bold</b>}, very + <b>bold</b>!" and the second match is "We must be <b>bold</b>, + very \underline{<b>bold</b>}!". In practice we might use the pattern + \bold{<b>[^<]*\</b>} instead, although this will still fail for + nested tags. + + \sa setCaseSensitivity() +*/ +void QRegExp::setMinimal(bool minimal) +{ + priv->minimal = minimal; +} + +// ### Qt 5: make non-const +/*! + Returns true if \a str is matched exactly by this regular + expression; otherwise returns false. You can determine how much of + the string was matched by calling matchedLength(). + + For a given regexp string R, exactMatch("R") is the equivalent of + indexIn("^R$") since exactMatch() effectively encloses the regexp + in the start of string and end of string anchors, except that it + sets matchedLength() differently. + + For example, if the regular expression is \bold{blue}, then + exactMatch() returns true only for input \c blue. For inputs \c + bluebell, \c blutak and \c lightblue, exactMatch() returns false + and matchedLength() will return 4, 3 and 0 respectively. + + Although const, this function sets matchedLength(), + capturedTexts(), and pos(). + + \sa indexIn(), lastIndexIn() +*/ +bool QRegExp::exactMatch(const QString &str) const +{ + prepareEngineForMatch(priv, str); + priv->matchState.match(str.unicode(), str.length(), 0, priv->minimal, true, 0); + if (priv->matchState.captured[1] == str.length()) { + return true; + } else { + priv->matchState.captured[0] = 0; + priv->matchState.captured[1] = priv->matchState.oneTestMatchedLen; + return false; + } +} + +// ### Qt 5: make non-const +/*! + Attempts to find a match in \a str from position \a offset (0 by + default). If \a offset is -1, the search starts at the last + character; if -2, at the next to last character; etc. + + Returns the position of the first match, or -1 if there was no + match. + + The \a caretMode parameter can be used to instruct whether \bold{^} + should match at index 0 or at \a offset. + + You might prefer to use QString::indexOf(), QString::contains(), + or even QStringList::filter(). To replace matches use + QString::replace(). + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 13 + + Although const, this function sets matchedLength(), + capturedTexts() and pos(). + + If the QRegExp is a wildcard expression (see setPatternSyntax()) + and want to test a string against the whole wildcard expression, + use exactMatch() instead of this function. + + \sa lastIndexIn(), exactMatch() +*/ + +int QRegExp::indexIn(const QString &str, int offset, CaretMode caretMode) const +{ + prepareEngineForMatch(priv, str); + if (offset < 0) + offset += str.length(); + priv->matchState.match(str.unicode(), str.length(), offset, + priv->minimal, false, caretIndex(offset, caretMode)); + return priv->matchState.captured[0]; +} + +// ### Qt 5: make non-const +/*! + Attempts to find a match backwards in \a str from position \a + offset. If \a offset is -1 (the default), the search starts at the + last character; if -2, at the next to last character; etc. + + Returns the position of the first match, or -1 if there was no + match. + + The \a caretMode parameter can be used to instruct whether \bold{^} + should match at index 0 or at \a offset. + + Although const, this function sets matchedLength(), + capturedTexts() and pos(). + + \warning Searching backwards is much slower than searching + forwards. + + \sa indexIn(), exactMatch() +*/ + +int QRegExp::lastIndexIn(const QString &str, int offset, CaretMode caretMode) const +{ + prepareEngineForMatch(priv, str); + if (offset < 0) + offset += str.length(); + if (offset < 0 || offset > str.length()) { + memset(priv->matchState.captured, -1, priv->matchState.capturedSize*sizeof(int)); + return -1; + } + + while (offset >= 0) { + priv->matchState.match(str.unicode(), str.length(), offset, + priv->minimal, true, caretIndex(offset, caretMode)); + if (priv->matchState.captured[0] == offset) + return offset; + --offset; + } + return -1; +} + +/*! + Returns the length of the last matched string, or -1 if there was + no match. + + \sa exactMatch(), indexIn(), lastIndexIn() +*/ +int QRegExp::matchedLength() const +{ + return priv->matchState.captured[1]; +} + +#ifndef QT_NO_REGEXP_CAPTURE +/*! + Returns the number of captures contained in the regular expression. + */ +int QRegExp::numCaptures() const +{ + prepareEngine(priv); + return priv->eng->numCaptures(); +} + +/*! + Returns a list of the captured text strings. + + The first string in the list is the entire matched string. Each + subsequent list element contains a string that matched a + (capturing) subexpression of the regexp. + + For example: + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 14 + + The above example also captures elements that may be present but + which we have no interest in. This problem can be solved by using + non-capturing parentheses: + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 15 + + Note that if you want to iterate over the list, you should iterate + over a copy, e.g. + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 16 + + Some regexps can match an indeterminate number of times. For + example if the input string is "Offsets: 12 14 99 231 7" and the + regexp, \c{rx}, is \bold{(\\d+)+}, we would hope to get a list of + all the numbers matched. However, after calling + \c{rx.indexIn(str)}, capturedTexts() will return the list ("12", + "12"), i.e. the entire match was "12" and the first subexpression + matched was "12". The correct approach is to use cap() in a + \l{QRegExp#cap_in_a_loop}{loop}. + + The order of elements in the string list is as follows. The first + element is the entire matching string. Each subsequent element + corresponds to the next capturing open left parentheses. Thus + capturedTexts()[1] is the text of the first capturing parentheses, + capturedTexts()[2] is the text of the second and so on + (corresponding to $1, $2, etc., in some other regexp languages). + + \sa cap(), pos() +*/ +QStringList QRegExp::capturedTexts() const +{ + if (priv->capturedCache.isEmpty()) { + prepareEngine(priv); + const int *captured = priv->matchState.captured; + int n = priv->matchState.capturedSize; + + for (int i = 0; i < n; i += 2) { + QString m; + if (captured[i + 1] == 0) + m = QLatin1String(""); // ### Qt 5: don't distinguish between null and empty + else if (captured[i] >= 0) + m = priv->t.mid(captured[i], captured[i + 1]); + priv->capturedCache.append(m); + } + priv->t.clear(); + } + return priv->capturedCache; +} + +/*! + \internal +*/ +QStringList QRegExp::capturedTexts() +{ + return const_cast<const QRegExp *>(this)->capturedTexts(); +} + +/*! + Returns the text captured by the \a nth subexpression. The entire + match has index 0 and the parenthesized subexpressions have + indexes starting from 1 (excluding non-capturing parentheses). + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 17 + + The order of elements matched by cap() is as follows. The first + element, cap(0), is the entire matching string. Each subsequent + element corresponds to the next capturing open left parentheses. + Thus cap(1) is the text of the first capturing parentheses, cap(2) + is the text of the second, and so on. + + \sa capturedTexts(), pos() +*/ +QString QRegExp::cap(int nth) const +{ + return capturedTexts().value(nth); +} + +/*! + \internal +*/ +QString QRegExp::cap(int nth) +{ + return const_cast<const QRegExp *>(this)->cap(nth); +} + +/*! + Returns the position of the \a nth captured text in the searched + string. If \a nth is 0 (the default), pos() returns the position + of the whole match. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 18 + + For zero-length matches, pos() always returns -1. (For example, if + cap(4) would return an empty string, pos(4) returns -1.) This is + a feature of the implementation. + + \sa cap(), capturedTexts() +*/ +int QRegExp::pos(int nth) const +{ + if (nth < 0 || nth >= priv->matchState.capturedSize / 2) + return -1; + else + return priv->matchState.captured[2 * nth]; +} + +/*! + \internal +*/ +int QRegExp::pos(int nth) +{ + return const_cast<const QRegExp *>(this)->pos(nth); +} + +/*! + Returns a text string that explains why a regexp pattern is + invalid the case being; otherwise returns "no error occurred". + + \sa isValid() +*/ +QString QRegExp::errorString() const +{ + if (isValid()) { + return QString::fromLatin1(RXERR_OK); + } else { + return priv->eng->errorString(); + } +} + +/*! + \internal +*/ +QString QRegExp::errorString() +{ + return const_cast<const QRegExp *>(this)->errorString(); +} +#endif + +/*! + Returns the string \a str with every regexp special character + escaped with a backslash. The special characters are $, (,), *, +, + ., ?, [, \,], ^, {, | and }. + + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 19 + + This function is useful to construct regexp patterns dynamically: + + \snippet doc/src/snippets/code/src_corelib_tools_qregexp.cpp 20 + + \sa setPatternSyntax() +*/ +QString QRegExp::escape(const QString &str) +{ + QString quoted; + const int count = str.count(); + quoted.reserve(count * 2); + const QLatin1Char backslash('\\'); + for (int i = 0; i < count; i++) { + switch (str.at(i).toLatin1()) { + case '$': + case '(': + case ')': + case '*': + case '+': + case '.': + case '?': + case '[': + case '\\': + case ']': + case '^': + case '{': + case '|': + case '}': + quoted.append(backslash); + } + quoted.append(str.at(i)); + } + return quoted; +} + +/*! + \fn bool QRegExp::caseSensitive() const + + Use \l caseSensitivity() instead. +*/ + +/*! + \fn void QRegExp::setCaseSensitive(bool sensitive) + + Use \l setCaseSensitivity() instead. +*/ + +/*! + \fn bool QRegExp::wildcard() const + + Use \l patternSyntax() instead. + + \oldcode + bool wc = rx.wildcard(); + \newcode + bool wc = (rx.patternSyntax() == QRegExp::Wildcard); + \endcode +*/ + +/*! + \fn void QRegExp::setWildcard(bool wildcard) + + Use \l setPatternSyntax() instead. + + \oldcode + rx.setWildcard(wc); + \newcode + rx.setPatternSyntax(wc ? QRegExp::Wildcard : QRegExp::RegExp); + \endcode +*/ + +/*! + \fn bool QRegExp::minimal() const + + Use \l isMinimal() instead. +*/ + +/*! + \fn int QRegExp::search(const QString &str, int from = 0, + CaretMode caretMode = CaretAtZero) const + + Use \l indexIn() instead. +*/ + +/*! + \fn int QRegExp::searchRev(const QString &str, int from = -1, \ + CaretMode caretMode = CaretAtZero) const + + Use \l lastIndexIn() instead. +*/ + +/*! + \fn QRegExp::QRegExp(const QString &pattern, bool cs, bool wildcard = false) + + Use another constructor instead. + + \oldcode + QRegExp rx("*.txt", false, true); + \newcode + QRegExp rx("*.txt", Qt::CaseInsensitive, QRegExp::Wildcard); + \endcode +*/ + +#ifndef QT_NO_DATASTREAM +/*! + \relates QRegExp + + Writes the regular expression \a regExp to stream \a out. + + \sa {Format of the QDataStream Operators} +*/ +QDataStream &operator<<(QDataStream &out, const QRegExp ®Exp) +{ + return out << regExp.pattern() << (quint8)regExp.caseSensitivity() + << (quint8)regExp.patternSyntax() + << (quint8)!!regExp.isMinimal(); +} + +/*! + \relates QRegExp + + Reads a regular expression from stream \a in into \a regExp. + + \sa {Format of the QDataStream Operators} +*/ +QDataStream &operator>>(QDataStream &in, QRegExp ®Exp) +{ + QString pattern; + quint8 cs; + quint8 patternSyntax; + quint8 isMinimal; + + in >> pattern >> cs >> patternSyntax >> isMinimal; + + QRegExp newRegExp(pattern, Qt::CaseSensitivity(cs), + QRegExp::PatternSyntax(patternSyntax)); + + newRegExp.setMinimal(isMinimal); + regExp = newRegExp; + return in; +} +#endif + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qregexp.h b/src/corelib/tools/qregexp.h new file mode 100644 index 0000000..b387e23 --- /dev/null +++ b/src/corelib/tools/qregexp.h @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QREGEXP_H +#define QREGEXP_H + +#ifndef QT_NO_REGEXP + +#include <QtCore/qstring.h> +#ifdef QT3_SUPPORT +#include <new> +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +struct QRegExpPrivate; +class QStringList; + +class Q_CORE_EXPORT QRegExp +{ +public: + enum PatternSyntax { RegExp, Wildcard, FixedString, RegExp2 }; + enum CaretMode { CaretAtZero, CaretAtOffset, CaretWontMatch }; + + QRegExp(); + explicit QRegExp(const QString &pattern, Qt::CaseSensitivity cs = Qt::CaseSensitive, + PatternSyntax syntax = RegExp); + QRegExp(const QRegExp &rx); + ~QRegExp(); + QRegExp &operator=(const QRegExp &rx); + + bool operator==(const QRegExp &rx) const; + inline bool operator!=(const QRegExp &rx) const { return !operator==(rx); } + + bool isEmpty() const; + bool isValid() const; + QString pattern() const; + void setPattern(const QString &pattern); + Qt::CaseSensitivity caseSensitivity() const; + void setCaseSensitivity(Qt::CaseSensitivity cs); +#ifdef QT3_SUPPORT + inline QT3_SUPPORT bool caseSensitive() const { return caseSensitivity() == Qt::CaseSensitive; } + inline QT3_SUPPORT void setCaseSensitive(bool sensitive) + { setCaseSensitivity(sensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); } +#endif + PatternSyntax patternSyntax() const; + void setPatternSyntax(PatternSyntax syntax); +#ifdef QT3_SUPPORT + inline QT3_SUPPORT bool wildcard() const { return patternSyntax() == Wildcard; } + inline QT3_SUPPORT void setWildcard(bool aWildcard) + { setPatternSyntax(aWildcard ? Wildcard : RegExp); } +#endif + + bool isMinimal() const; + void setMinimal(bool minimal); +#ifdef QT3_SUPPORT + inline QT3_SUPPORT bool minimal() const { return isMinimal(); } +#endif + + bool exactMatch(const QString &str) const; + + int indexIn(const QString &str, int offset = 0, CaretMode caretMode = CaretAtZero) const; + int lastIndexIn(const QString &str, int offset = -1, CaretMode caretMode = CaretAtZero) const; +#ifdef QT3_SUPPORT + inline QT3_SUPPORT int search(const QString &str, int from = 0, + CaretMode caretMode = CaretAtZero) const + { return indexIn(str, from, caretMode); } + inline QT3_SUPPORT int searchRev(const QString &str, int from = -1, + CaretMode caretMode = CaretAtZero) const + { return lastIndexIn(str, from, caretMode); } +#endif + int matchedLength() const; +#ifndef QT_NO_REGEXP_CAPTURE + int numCaptures() const; + QStringList capturedTexts() const; + QStringList capturedTexts(); + QString cap(int nth = 0) const; + QString cap(int nth = 0); + int pos(int nth = 0) const; + int pos(int nth = 0); + QString errorString() const; + QString errorString(); +#endif + + static QString escape(const QString &str); + +#ifdef QT3_SUPPORT + inline QT3_SUPPORT_CONSTRUCTOR QRegExp(const QString &aPattern, bool cs, bool aWildcard = false) + { + new (this) + QRegExp(aPattern, cs ? Qt::CaseSensitive : Qt::CaseInsensitive, + aWildcard ? Wildcard : RegExp); + } +#endif + +private: + QRegExpPrivate *priv; +}; + +Q_DECLARE_TYPEINFO(QRegExp, Q_MOVABLE_TYPE); + +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &out, const QRegExp ®Exp); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &in, QRegExp ®Exp); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QT_NO_REGEXP + +#endif // QREGEXP_H diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h new file mode 100644 index 0000000..3a0901d --- /dev/null +++ b/src/corelib/tools/qringbuffer_p.h @@ -0,0 +1,319 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QRINGBUFFER_P_H +#define QRINGBUFFER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of a number of Qt sources files. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qbytearray.h> +#include <QtCore/qlist.h> + +QT_BEGIN_NAMESPACE + +class Q_CORE_EXPORT QRingBuffer +{ +public: + inline QRingBuffer(int growth = 4096) : basicBlockSize(growth) { + buffers << QByteArray(); + clear(); + } + + inline int nextDataBlockSize() const { + return (tailBuffer == 0 ? tail : buffers.first().size()) - head; + } + + inline const char *readPointer() const { + return buffers.isEmpty() ? 0 : (buffers.first().constData() + head); + } + + inline void free(int bytes) { + bufferSize -= bytes; + if (bufferSize < 0) + bufferSize = 0; + + for (;;) { + int nextBlockSize = nextDataBlockSize(); + if (bytes < nextBlockSize) { + head += bytes; + if (head == tail && tailBuffer == 0) + head = tail = 0; + break; + } + + bytes -= nextBlockSize; + if (buffers.count() == 1) { + if (buffers.at(0).size() != basicBlockSize) + buffers[0].resize(basicBlockSize); + head = tail = 0; + tailBuffer = 0; + break; + } + + buffers.removeAt(0); + --tailBuffer; + head = 0; + } + } + + inline char *reserve(int bytes) { + bufferSize += bytes; + + // if there is already enough space, simply return. + if (tail + bytes <= buffers.at(tailBuffer).size()) { + char *writePtr = buffers[tailBuffer].data() + tail; + tail += bytes; + return writePtr; + } + + // if our buffer isn't half full yet, simply resize it. + if (tail < buffers.at(tailBuffer).size() / 2) { + buffers[tailBuffer].resize(tail + bytes); + char *writePtr = buffers[tailBuffer].data() + tail; + tail += bytes; + return writePtr; + } + + // shrink this buffer to its current size + buffers[tailBuffer].resize(tail); + + // create a new QByteArray with the right size + buffers << QByteArray(); + ++tailBuffer; + buffers[tailBuffer].resize(qMax(basicBlockSize, bytes)); + tail = bytes; + return buffers[tailBuffer].data(); + } + + inline void truncate(int pos) { + if (pos < size()) + chop(size() - pos); + } + + inline void chop(int bytes) { + bufferSize -= bytes; + if (bufferSize < 0) + bufferSize = 0; + + for (;;) { + // special case: head and tail are in the same buffer + if (tailBuffer == 0) { + tail -= bytes; + if (tail <= head) + tail = head = 0; + return; + } + + if (bytes <= tail) { + tail -= bytes; + return; + } + + bytes -= tail; + buffers.removeAt(tailBuffer); + + --tailBuffer; + tail = buffers.at(tailBuffer).size(); + } + } + + inline bool isEmpty() const { + return tailBuffer == 0 && tail == 0; + } + + inline int getChar() { + if (isEmpty()) + return -1; + char c = *readPointer(); + free(1); + return int(uchar(c)); + } + + inline void putChar(char c) { + char *ptr = reserve(1); + *ptr = c; + } + + inline void ungetChar(char c) { + --head; + if (head < 0) { + buffers.prepend(QByteArray()); + buffers[0].resize(basicBlockSize); + head = basicBlockSize - 1; + ++tailBuffer; + } + buffers[0][head] = c; + ++bufferSize; + } + + inline int size() const { + return bufferSize; + } + + inline void clear() { + if(!buffers.isEmpty()) { + QByteArray tmp = buffers[0]; + buffers.clear(); + buffers << tmp; + if (buffers.at(0).size() != basicBlockSize) + buffers[0].resize(basicBlockSize); + } + head = tail = 0; + tailBuffer = 0; + bufferSize = 0; + } + + inline int indexOf(char c) const { + int index = 0; + for (int i = 0; i < buffers.size(); ++i) { + int start = 0; + int end = buffers.at(i).size(); + + if (i == 0) + start = head; + if (i == tailBuffer) + end = tail; + const char *ptr = buffers.at(i).data() + start; + for (int j = start; j < end; ++j) { + if (*ptr++ == c) + return index; + ++index; + } + } + return -1; + } + + inline int read(char *data, int maxLength) { + int bytesToRead = qMin(size(), maxLength); + int readSoFar = 0; + while (readSoFar < bytesToRead) { + const char *ptr = readPointer(); + int bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar, nextDataBlockSize()); + if (data) + memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock); + readSoFar += bytesToReadFromThisBlock; + free(bytesToReadFromThisBlock); + } + return readSoFar; + } + + inline QByteArray read(int maxLength) { + QByteArray tmp; + tmp.resize(qMin(maxLength, size())); + read(tmp.data(), tmp.size()); + return tmp; + } + + inline QByteArray readAll() { + return read(size()); + } + + inline QByteArray peek(int maxLength) const { + int bytesToRead = qMin(size(), maxLength); + if(maxLength <= 0) + return QByteArray(); + QByteArray ret; + ret.resize(bytesToRead); + int readSoFar = 0; + for (int i = 0; readSoFar < bytesToRead && i < buffers.size(); ++i) { + int start = 0; + int end = buffers.at(i).size(); + if (i == 0) + start = head; + if (i == tailBuffer) + end = tail; + const int len = qMin(ret.size()-readSoFar, end-start); + memcpy(ret.data()+readSoFar, buffers.at(i).constData()+start, len); + readSoFar += len; + } + Q_ASSERT(readSoFar == ret.size()); + return ret; + } + + inline int skip(int length) { + return read(0, length); + } + + inline int readLine(char *data, int maxLength) { + int index = indexOf('\n'); + if (index == -1) + return read(data, maxLength); + if (maxLength <= 0) + return -1; + + int readSoFar = 0; + while (readSoFar < index + 1 && readSoFar < maxLength - 1) { + int bytesToRead = qMin((index + 1) - readSoFar, nextDataBlockSize()); + bytesToRead = qMin(bytesToRead, (maxLength - 1) - readSoFar); + memcpy(data + readSoFar, readPointer(), bytesToRead); + readSoFar += bytesToRead; + free(bytesToRead); + } + + // Terminate it. + data[readSoFar] = '\0'; + return readSoFar; + } + + inline bool canReadLine() const { + return indexOf('\n') != -1; + } + +private: + QList<QByteArray> buffers; + int head, tail; + int tailBuffer; + int basicBlockSize; + int bufferSize; +}; + +QT_END_NAMESPACE + +#endif // QRINGBUFFER_P_H diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h new file mode 100644 index 0000000..4b19adc --- /dev/null +++ b/src/corelib/tools/qset.h @@ -0,0 +1,352 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSET_H +#define QSET_H + +#include <QtCore/qhash.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +template <class T> +class QSet +{ + typedef QHash<T, QHashDummyValue> Hash; + +public: + inline QSet() {} + inline QSet(const QSet<T> &other) : q_hash(other.q_hash) {} + + inline QSet<T> &operator=(const QSet<T> &other) + { q_hash = other.q_hash; return *this; } + + inline bool operator==(const QSet<T> &other) const + { return q_hash == other.q_hash; } + inline bool operator!=(const QSet<T> &other) const + { return q_hash != other.q_hash; } + + inline int size() const { return q_hash.size(); } + + inline bool isEmpty() const { return q_hash.isEmpty(); } + + inline int capacity() const { return q_hash.capacity(); } + inline void reserve(int size); + inline void squeeze() { q_hash.squeeze(); } + + inline void detach() { q_hash.detach(); } + inline bool isDetached() const { return q_hash.isDetached(); } + inline void setSharable(bool sharable) { q_hash.setSharable(sharable); } + + inline void clear() { q_hash.clear(); } + + inline bool remove(const T &value) { return q_hash.remove(value) != 0; } + + inline bool contains(const T &value) const { return q_hash.contains(value); } + + class const_iterator; + + class iterator + { + typedef QHash<T, QHashDummyValue> Hash; + typename Hash::iterator i; + friend class const_iterator; + + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef const T *pointer; + typedef const T &reference; + + inline iterator() {} + inline iterator(typename Hash::iterator o) : i(o) {} + inline iterator(const iterator &o) : i(o.i) {} + inline iterator &operator=(const iterator &o) { i = o.i; return *this; } + inline const T &operator*() const { return i.key(); } + inline const T *operator->() const { return &i.key(); } + inline bool operator==(const iterator &o) const { return i == o.i; } + inline bool operator!=(const iterator &o) const { return i != o.i; } + inline bool operator==(const const_iterator &o) const + { return i == o.i; } + inline bool operator!=(const const_iterator &o) const + { return i != o.i; } + inline iterator &operator++() { ++i; return *this; } + inline iterator operator++(int) { iterator r = *this; ++i; return r; } + inline iterator &operator--() { --i; return *this; } + inline iterator operator--(int) { iterator r = *this; --i; return r; } + inline iterator operator+(int j) const { return i + j; } + inline iterator operator-(int j) const { return i - j; } + inline iterator &operator+=(int j) { i += j; return *this; } + inline iterator &operator-=(int j) { i -= j; return *this; } + }; + + class const_iterator + { + typedef QHash<T, QHashDummyValue> Hash; + typename Hash::const_iterator i; + friend class iterator; + + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef const T *pointer; + typedef const T &reference; + + inline const_iterator() {} + inline const_iterator(typename Hash::const_iterator o) : i(o) {} + inline const_iterator(const const_iterator &o) : i(o.i) {} + inline const_iterator(const iterator &o) + : i(o.i) {} + inline const_iterator &operator=(const const_iterator &o) { i = o.i; return *this; } + inline const T &operator*() const { return i.key(); } + inline const T *operator->() const { return &i.key(); } + inline bool operator==(const const_iterator &o) const { return i == o.i; } + inline bool operator!=(const const_iterator &o) const { return i != o.i; } + inline const_iterator &operator++() { ++i; return *this; } + inline const_iterator operator++(int) { const_iterator r = *this; ++i; return r; } + inline const_iterator &operator--() { --i; return *this; } + inline const_iterator operator--(int) { const_iterator r = *this; --i; return r; } + inline const_iterator operator+(int j) const { return i + j; } + inline const_iterator operator-(int j) const { return i - j; } + inline const_iterator &operator+=(int j) { i += j; return *this; } + inline const_iterator &operator-=(int j) { i -= j; return *this; } + }; + + // STL style + inline iterator begin() { return q_hash.begin(); } + inline const_iterator begin() const { return q_hash.begin(); } + inline const_iterator constBegin() const { return q_hash.constBegin(); } + inline iterator end() { return q_hash.end(); } + inline const_iterator end() const { return q_hash.end(); } + inline const_iterator constEnd() const { return q_hash.constEnd(); } + iterator erase(iterator i) + { return q_hash.erase(reinterpret_cast<typename Hash::iterator &>(i)); } + + // more Qt + typedef iterator Iterator; + typedef const_iterator ConstIterator; + inline int count() const { return q_hash.count(); } + inline const_iterator insert(const T &value) // ### Qt 5: should return an 'iterator' + { return static_cast<typename Hash::const_iterator>(q_hash.insert(value, + QHashDummyValue())); } + iterator find(const T &value) { return q_hash.find(value); } + const_iterator find(const T &value) const { return q_hash.find(value); } + inline const_iterator constFind(const T &value) const { return find(value); } + QSet<T> &unite(const QSet<T> &other); + QSet<T> &intersect(const QSet<T> &other); + QSet<T> &subtract(const QSet<T> &other); + + // STL compatibility + typedef T key_type; + typedef T value_type; + typedef value_type *pointer; + typedef const value_type *const_pointer; + typedef value_type &reference; + typedef const value_type &const_reference; + typedef ptrdiff_t difference_type; + typedef int size_type; + + inline bool empty() const { return isEmpty(); } + + // comfort + inline QSet<T> &operator<<(const T &value) { insert(value); return *this; } + inline QSet<T> &operator|=(const QSet<T> &other) { unite(other); return *this; } + inline QSet<T> &operator|=(const T &value) { insert(value); return *this; } + inline QSet<T> &operator&=(const QSet<T> &other) { intersect(other); return *this; } + inline QSet<T> &operator&=(const T &value) + { QSet<T> result; if (contains(value)) result.insert(value); return (*this = result); } + inline QSet<T> &operator+=(const QSet<T> &other) { unite(other); return *this; } + inline QSet<T> &operator+=(const T &value) { insert(value); return *this; } + inline QSet<T> &operator-=(const QSet<T> &other) { subtract(other); return *this; } + inline QSet<T> &operator-=(const T &value) { remove(value); return *this; } + inline QSet<T> operator|(const QSet<T> &other) const + { QSet<T> result = *this; result |= other; return result; } + inline QSet<T> operator&(const QSet<T> &other) const + { QSet<T> result = *this; result &= other; return result; } + inline QSet<T> operator+(const QSet<T> &other) const + { QSet<T> result = *this; result += other; return result; } + inline QSet<T> operator-(const QSet<T> &other) const + { QSet<T> result = *this; result -= other; return result; } +#if QT_VERSION < 0x050000 + // ### Qt 5: remove + inline QSet<T> operator|(const QSet<T> &other) + { QSet<T> result = *this; result |= other; return result; } + inline QSet<T> operator&(const QSet<T> &other) + { QSet<T> result = *this; result &= other; return result; } + inline QSet<T> operator+(const QSet<T> &other) + { QSet<T> result = *this; result += other; return result; } + inline QSet<T> operator-(const QSet<T> &other) + { QSet<T> result = *this; result -= other; return result; } +#endif + + QList<T> toList() const; + inline QList<T> values() const { return toList(); } + + static QSet<T> fromList(const QList<T> &list); + +private: + Hash q_hash; +}; + +template <class T> +Q_INLINE_TEMPLATE void QSet<T>::reserve(int asize) { q_hash.reserve(asize); } + +template <class T> +Q_INLINE_TEMPLATE QSet<T> &QSet<T>::unite(const QSet<T> &other) +{ + QSet<T> copy(other); + typename QSet<T>::const_iterator i = copy.constEnd(); + while (i != copy.constBegin()) { + --i; + insert(*i); + } + return *this; +} + +template <class T> +Q_INLINE_TEMPLATE QSet<T> &QSet<T>::intersect(const QSet<T> &other) +{ + QSet<T> copy1(*this); + QSet<T> copy2(other); + typename QSet<T>::const_iterator i = copy1.constEnd(); + while (i != copy1.constBegin()) { + --i; + if (!copy2.contains(*i)) + remove(*i); + } + return *this; +} + +template <class T> +Q_INLINE_TEMPLATE QSet<T> &QSet<T>::subtract(const QSet<T> &other) +{ + QSet<T> copy1(*this); + QSet<T> copy2(other); + typename QSet<T>::const_iterator i = copy1.constEnd(); + while (i != copy1.constBegin()) { + --i; + if (copy2.contains(*i)) + remove(*i); + } + return *this; +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE QList<T> QSet<T>::toList() const +{ + QList<T> result; + typename QSet<T>::const_iterator i = constBegin(); + while (i != constEnd()) { + result.append(*i); + ++i; + } + return result; +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE QSet<T> QList<T>::toSet() const +{ + QSet<T> result; + result.reserve(size()); + for (int i = 0; i < size(); ++i) + result.insert(at(i)); + return result; +} + +template <typename T> +QSet<T> QSet<T>::fromList(const QList<T> &list) +{ + return list.toSet(); +} + +template <typename T> +QList<T> QList<T>::fromSet(const QSet<T> &set) +{ + return set.toList(); +} + +Q_DECLARE_SEQUENTIAL_ITERATOR(Set) + +template <typename T> +class QMutableSetIterator +{ + typedef typename QSet<T>::iterator iterator; + QSet<T> *c; + iterator i, n; + inline bool item_exists() const { return n != c->constEnd(); } + +public: + inline QMutableSetIterator(QSet<T> &container) + : c(&container) + { c->setSharable(false); i = c->begin(); n = c->end(); } + inline ~QMutableSetIterator() + { c->setSharable(true); } + inline QMutableSetIterator &operator=(QSet<T> &container) + { c->setSharable(true); c = &container; c->setSharable(false); + i = c->begin(); n = c->end(); return *this; } + inline void toFront() { i = c->begin(); n = c->end(); } + inline void toBack() { i = c->end(); n = i; } + inline bool hasNext() const { return c->constEnd() != i; } + inline const T &next() { n = i++; return *n; } + inline const T &peekNext() const { return *i; } + inline bool hasPrevious() const { return c->constBegin() != i; } + inline const T &previous() { n = --i; return *n; } + inline const T &peekPrevious() const { iterator p = i; return *--p; } + inline void remove() + { if (c->constEnd() != n) { i = c->erase(n); n = c->end(); } } + inline const T &value() const { Q_ASSERT(item_exists()); return *n; } + inline bool findNext(const T &t) + { while (c->constEnd() != (n = i)) if (*i++ == t) return true; return false; } + inline bool findPrevious(const T &t) + { while (c->constBegin() != i) if (*(n = --i) == t) return true; + n = c->end(); return false; } +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSET_H diff --git a/src/corelib/tools/qshareddata.cpp b/src/corelib/tools/qshareddata.cpp new file mode 100644 index 0000000..2b879ea --- /dev/null +++ b/src/corelib/tools/qshareddata.cpp @@ -0,0 +1,550 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qshareddata.h> + +QT_BEGIN_NAMESPACE + +/*! + \class QSharedData + \brief The QSharedData class is a base class for shared data objects. + \reentrant + \ingroup misc + + QSharedData is designed to be used with QSharedDataPointer or + QExplicitlySharedDataPointer to implement custom \l{implicitly + shared} or \l {explicitly shared} classes. QSharedData provides + \l{thread-safe} reference counting. + + See QSharedDataPointer and QExplicitlySharedDataPointer for details. +*/ + +/*! \fn QSharedData::QSharedData() + Constructs a QSharedData object with a reference count of 0. +*/ + +/*! \fn QSharedData::QSharedData(const QSharedData& other) + Constructs a QSharedData object with reference count 0. + \a other is ignored. +*/ + +/*! + \class QSharedDataPointer + \brief The QSharedDataPointer class represents a pointer to an implicitly shared object. + \since 4.0 + \reentrant + \ingroup misc + \mainclass + + QSharedDataPointer\<T\> makes writing your own \l {implicitly + shared} classes easy. QSharedDataPointer implements \l {thread-safe} + reference counting, ensuring that adding QSharedDataPointers to your + \l {reentrant} classes won't make them non-reentrant. + + \l {Implicit sharing} is used by many Qt classes to combine the + speed and memory efficiency of pointers with the ease of use of + classes. See the \l{Shared Classes} page for more information. + + \target Employee example + Suppose you want to make an \c Employee class implicitly shared. The + procedure is: + + \list + + \o Define the class \c Employee to have a single data member of + type \c {QSharedDataPointer<EmployeeData>}. + + \o Define the \c EmployeeData class derived from \l QSharedData to + contain all the data members you would normally have put in the + \c Employee class. + + \endlist + + To show this in practice, we review the source code for the + implicitly shared \c Employee class. In the header file we define the + two classes \c Employee and \c EmployeeData. + + \snippet doc/src/snippets/sharedemployee/employee.h 0 + + In class \c Employee, note the single data member, a \e {d pointer} + of type \c {QSharedDataPointer<EmployeeData>}. All accesses of + employee data must go through the \e {d pointer's} \c + {operator->()}. For write accesses, \c {operator->()} will + automatically call detach(), which creates a copy of the shared data + object if the shared data object's reference count is greater than + 1. This ensures that writes to one \c Employee object don't affect + any other \c Employee objects that share the same \c EmployeeData + object. + + Class \c EmployeeData inherits QSharedData, which provides the + \e{behind the scenes} reference counter. \c EmployeeData has a default + constructor, a copy constructor, and a destructor. Normally, trivial + implementations of these are all that is needed in the \e {data} + class for an implicitly shared class. + + Implementing the two constructors for class \c Employee is also + straightforward. Both create a new instance of \c EmployeeData + and assign it to the \e{d pointer} . + + \snippet doc/src/snippets/sharedemployee/employee.h 1 + \codeline + \snippet doc/src/snippets/sharedemployee/employee.h 2 + + Note that class \c Employee also has a trivial copy constructor + defined, which is not strictly required in this case. + + \snippet doc/src/snippets/sharedemployee/employee.h 7 + + The copy constructor is not strictly required here, because class \c + EmployeeData is included in the same file as class \c Employee + (\c{employee.h}). However, including the private subclass of + QSharedData in the same file as the public class containing the + QSharedDataPointer is not typical. Normally, the idea is to hide the + private subclass of QSharedData from the user by putting it in a + separate file which would not be included in the public file. In + this case, we would normally put class \c EmployeeData in a separate + file, which would \e{not} be included in \c{employee.h}. Instead, we + would just predeclare the private subclass \c EmployeeData in \c + {employee.h} this way: + + \code + class EmployeeData; + \endcode + + If we had done it that way here, the copy constructor shown would be + required. Since the copy constructor is trivial, you might as well + just always include it. + + Behind the scenes, QSharedDataPointer automatically increments the + reference count whenever an \c Employee object is copied, assigned, + or passed as a parameter. It decrements the reference count whenever + an \c Employee object is deleted or goes out of scope. The shared + \c EmployeeData object is deleted automatically if and when the + reference count reaches 0. + + In a non-const member function of \c Employee, whenever the \e {d + pointer} is dereferenced, QSharedDataPointer automatically calls + detach() to ensure that the function operates on its own copy of the + data. + + \snippet doc/src/snippets/sharedemployee/employee.h 3 + \codeline + \snippet doc/src/snippets/sharedemployee/employee.h 4 + + Note that if detach() is called more than once in a member function + due to multiple dereferences of the \e {d pointer}, detach() will + only create a copy of the shared data the first time it is called, + if at all, because on the second and subsequent calls of detach(), + the reference count will be 1 again. + + But note that in the second \c Employee constructor, which takes an + employee ID and a name, both setId() and setName() are called, but + they don't cause \e{copy on write}, because the reference count for + the newly constructed \c EmployeeData object has just been set to 1. + + In \c Employee's \e const member functions, dereferencing the \e {d + pointer} does \e not cause detach() to be called. + + \snippet doc/src/snippets/sharedemployee/employee.h 5 + \codeline + \snippet doc/src/snippets/sharedemployee/employee.h 6 + + Notice that there is no need to implement a copy constructor or an + assignment operator for the \c Employee class, because the copy + constructor and assignment operator provided by the C++ compiler + will do the \e{member by member} shallow copy required. The only + member to copy is the \e {d pointer}, which is a QSharedDataPointer, + whose \c {operator=()} just increments the reference count of the + shared \c EmployeeData object. + + \target Implicit vs Explicit Sharing + \section1 Implicit vs Explicit Sharing + + Implicit sharing might not be right for the \c Employee class. + Consider a simple example that creates two instances of the + implicitly shared \c Employee class. + + \snippet doc/src/snippets/sharedemployee/main.cpp 0 + + After the second employee e2 is created and e1 is assigned to it, + both \c e1 and \c e2 refer to Albrecht Durer, employee 1001. Both \c + Employee objects point to the same instance of \c EmployeeData, + which has reference count 2. Then \c {e1.setName("Hans Holbein")} is + called to change the employee name, but because the reference count + is greater than 1, a \e{copy on write} is performed before the name + is changed. Now \c e1 and \c e2 point to different \c EmployeeData + objects. They have different names, but both have ID 1001, which is + probably not what you want. You can, of course, just continue with + \c {e1.setId(1002)}, if you really mean to create a second, unique + employee, but if you only want to change the employee's name + everywhere, consider using \l {QExplicitlySharedDataPointer} + {explicit sharing} in the \c Employee class instead of implicit + sharing. + + If you declare the \e {d pointer} in the \c Employee class to be + \c {QExplicitlySharedDataPointer<EmployeeData>}, then explicit + sharing is used and \e{copy on write} operations are not performed + automatically (i.e. detach() is not called in non-const + functions). In that case, after \c {e1.setName("Hans Holbein")}, the + employee's name has been changed, but both e1 and e2 still refer to + the same instance of \c EmployeeData, so there is only one employee + with ID 1001. + + In the member function documentation, \e{d pointer} always refers + to the internal pointer to the shared data object. + + \sa QSharedData, QExplicitlySharedDataPointer +*/ + +/*! \fn T& QSharedDataPointer::operator*() + Provides access to the shared data object's members. + This function calls detach(). +*/ + +/*! \fn const T& QSharedDataPointer::operator*() const + Provides const access to the shared data object's members. + This function does \e not call detach(). +*/ + +/*! \fn T* QSharedDataPointer::operator->() + Provides access to the shared data object's members. + This function calls detach(). +*/ + +/*! \fn const T* QSharedDataPointer::operator->() const + Provides const access to the shared data object's members. + This function does \e not call detach(). +*/ + +/*! \fn QSharedDataPointer::operator T*() + Returns a pointer to the shared data object. + This function calls detach(). + + \sa data(), constData() +*/ + +/*! \fn QSharedDataPointer::operator const T*() const + Returns a pointer to the shared data object. + This function does \e not call detach(). +*/ + +/*! \fn T* QSharedDataPointer::data() + Returns a pointer to the shared data object. + This function calls detach(). + + \sa constData() +*/ + +/*! \fn const T* QSharedDataPointer::data() const + Returns a pointer to the shared data object. + This function does \e not call detach(). +*/ + +/*! \fn const T* QSharedDataPointer::constData() const + Returns a const pointer to the shared data object. + This function does \e not call detach(). + + \sa data() +*/ + +/*! \fn bool QSharedDataPointer::operator==(const QSharedDataPointer<T>& other) const + Returns true if \a other and \e this have the same \e{d pointer}. + This function does \e not call detach(). +*/ + +/*! \fn bool QSharedDataPointer::operator!=(const QSharedDataPointer<T>& other) const + Returns true if \a other and \e this do \e not have the same + \e{d pointer}. This function does \e not call detach(). +*/ + +/*! \fn QSharedDataPointer::QSharedDataPointer() + Constructs a QSharedDataPointer initialized with a null \e{d pointer}. +*/ + +/*! \fn QSharedDataPointer::~QSharedDataPointer() + Decrements the reference count of the shared data object. + If the reference count becomes 0, the shared data object + is deleted. \e This is then destroyed. +*/ + +/*! \fn QSharedDataPointer::QSharedDataPointer(T* sharedData) + Constructs a QSharedDataPointer with \e{d pointer} set to + \a sharedData and increments \a{sharedData}'s reference count. +*/ + +/*! \fn QSharedDataPointer::QSharedDataPointer(const QSharedDataPointer<T>& other) + Sets the \e{d pointer} of \e this to the \e{d pointer} in + \a other and increments the reference count of the shared + data object. +*/ + +/*! \fn QSharedDataPointer<T>& QSharedDataPointer::operator=(const QSharedDataPointer<T>& other) + Sets the \e{d pointer} of \e this to the \e{d pointer} of + \a other and increments the reference count of the shared + data object. The reference count of the old shared data + object of \e this is decremented. If the reference count + of the old shared data object becomes 0, the old shared + data object is deleted. +*/ + +/*! \fn QSharedDataPointer& QSharedDataPointer::operator=(T* sharedData) + Sets the \e{d pointer} og \e this to \a sharedData and increments + \a{sharedData}'s reference count. The reference count of the old + shared data object of \e this is decremented. If the reference + count of the old shared data object becomes 0, the old shared data + object is deleted. +*/ + +/*! \fn bool QSharedDataPointer::operator!() const + Returns true if the \e{d pointer} of \e this is null. +*/ + +/*! \fn void QSharedDataPointer::detach() + If the shared data object's reference count is greater than 1, this + function creates a deep copy of the shared data object and sets the + \e{d pointer} of \e this to the copy. + + This function is called automatically by non-const member + functions of QSharedDataPointer if \e{copy on write} is + required. You don't need to call it yourself. +*/ + +/*! \fn T *QSharedDataPointer::clone() + \since 4.5 + + Creates and returns a deep copy of the current data. This function + is called by detach() when the reference count is greater than 1 in + order to create the new copy. This function uses the \e {operator + new} and calls the copy constructor of the type T. + + This function is provided so that you may support "virtual copy + constructors" for your own types. In order to so, you should declare + a template-specialization of this function for your own type, like + the example below: + + \code + template<> + EmployeeData *QSharedDataPointer<EmployeeData>::clone() + { + return d->clone(); + } + \endcode + + In the example above, the template specialization for the clone() + function calls the \e {EmployeeData::clone()} virtual function. A + class derived from EmployeeData could override that function and + return the proper polymorphic type. +*/ + +/*! + \class QExplicitlySharedDataPointer + \brief The QExplicitlySharedDataPointer class represents a pointer to an explicitly shared object. + \since 4.4 + \reentrant + \ingroup misc + \mainclass + + QExplicitlySharedDataPointer\<T\> makes writing your own explicitly + shared classes easy. QExplicitlySharedDataPointer implements + \l {thread-safe} reference counting, ensuring that adding + QExplicitlySharedDataPointers to your \l {reentrant} classes won't + make them non-reentrant. + + Except for one big difference, QExplicitlySharedDataPointer is just + like QSharedDataPointer. The big difference is that member functions + of QExplicitlySharedDataPointer \e{do not} do the automatic + \e{copy on write} operation (detach()) that non-const members of + QSharedDataPointer do before allowing the shared data object to be + modified. There is a detach() function available, but if you really + want to detach(), you have to call it yourself. This means that + QExplicitlySharedDataPointers behave like regular C++ pointers, + except that by doing reference counting and not deleting the shared + data object until the reference count is 0, they avoid the dangling + pointer problem. + + It is instructive to compare QExplicitlySharedDataPointer with + QSharedDataPointer by way of an example. Consider the \l {Employee + example} in QSharedDataPointer, modified to use explicit sharing as + explained in the discussion \l {Implicit vs Explicit Sharing}. + + Note that if you use this class but find you are calling detach() a + lot, you probably should be using QSharedDataPointer instead. + + In the member function documentation, \e{d pointer} always refers + to the internal pointer to the shared data object. + + \sa QSharedData, QSharedDataPointer +*/ + +/*! \fn T& QExplicitlySharedDataPointer::operator*() const + Provides access to the shared data object's members. +*/ + +/*! \fn T* QExplicitlySharedDataPointer::operator->() + Provides access to the shared data object's members. +*/ + +/*! \fn const T* QExplicitlySharedDataPointer::operator->() const + Provides const access to the shared data object's members. +*/ + +/*! \fn T* QExplicitlySharedDataPointer::data() const + Returns a pointer to the shared data object. +*/ + +/*! \fn const T* QExplicitlySharedDataPointer::constData() const + Returns a const pointer to the shared data object. + + \sa data() +*/ + +/*! \fn bool QExplicitlySharedDataPointer::operator==(const QExplicitlySharedDataPointer<T>& other) const + Returns true if \a other and \e this have the same \e{d pointer}. +*/ + +/*! \fn bool QExplicitlySharedDataPointer::operator==(const T* ptr) const + Returns true if the \e{d pointer} of \e this is \a ptr. + */ + +/*! \fn bool QExplicitlySharedDataPointer::operator!=(const QExplicitlySharedDataPointer<T>& other) const + Returns true if \a other and \e this do \e not have the same + \e{d pointer}. +*/ + +/*! \fn bool QExplicitlySharedDataPointer::operator!=(const T* ptr) const + Returns true if the \e{d pointer} of \e this is \e not \a ptr. + */ + +/*! \fn QExplicitlySharedDataPointer::QExplicitlySharedDataPointer() + Constructs a QExplicitlySharedDataPointer initialized with a null + \e{d pointer}. +*/ + +/*! \fn QExplicitlySharedDataPointer::~QExplicitlySharedDataPointer() + Decrements the reference count of the shared data object. + If the reference count becomes 0, the shared data object + is deleted. \e This is then destroyed. +*/ + +/*! \fn QExplicitlySharedDataPointer::QExplicitlySharedDataPointer(T* sharedData) + Constructs a QExplicitlySharedDataPointer with \e{d pointer} + set to \a sharedData and increments \a{sharedData}'s reference + count. +*/ + +/*! \fn QExplicitlySharedDataPointer::QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T>& other) + This standard copy constructor sets the \e {d pointer} of \e this to + the \e {d pointer} in \a other and increments the reference count of + the shared data object. +*/ + +/*! \fn QExplicitlySharedDataPointer::QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X>& other) + This copy constructor is different in that it allows \a other to be + a different type of explicitly shared data pointer but one that has + a compatible shared data object. It performs a static cast of the + \e{d pointer} in \a other and sets the \e {d pointer} of \e this to + the converted \e{d pointer}. It increments the reference count of + the shared data object. + */ + +/*! \fn QExplicitlySharedDataPointer<T>& QExplicitlySharedDataPointer::operator=(const QExplicitlySharedDataPointer<T>& other) + Sets the \e{d pointer} of \e this to the \e{d pointer} of + \a other and increments the reference count of the shared + data object. The reference count of the old shared data + object of \e this is decremented. If the reference count + of the old shared data object becomes 0, the old shared + data object is deleted. +*/ + +/*! \fn QExplicitlySharedDataPointer& QExplicitlySharedDataPointer::operator=(T* sharedData) + Sets the \e{d pointer} of \e this to \a sharedData and + increments \a{sharedData}'s reference count. The reference + count of the old shared data object of \e this is decremented. + If the reference count of the old shared data object becomes + 0, the old shared data object is deleted. +*/ + +/*! \fn void QExplicitlySharedDataPointer::reset() + Resets \e this to be null. i.e., this function sets the + \e{d pointer} of \e this to 0, but first it decrements + the reference count of the shared data object and deletes + the shared data object if the reference count became 0. + */ + +/*! \fn QExplicitlySharedDataPointer::operator bool () const + Returns true if the \e{d pointer} of \e this is \e not null. + */ + +/*! \fn bool QExplicitlySharedDataPointer::operator!() const + Returns true if the \e{d pointer} of \e this is null. +*/ + +/*! \fn void QExplicitlySharedDataPointer::detach() + If the shared data object's reference count is greater than 1, this + function creates a deep copy of the shared data object and sets the + \e{d pointer} of \e this to the copy. + + Because QExplicitlySharedDataPointer does not do the automatic + \e{copy on write} operations that members of QSharedDataPointer do, + detach() is \e not called automatically anywhere in the member + functions of this class. If you find that you are calling detach() + everywhere in your code, consider using QSharedDataPointer instead. +*/ + +/*! \fn T *QExplicitlySharedDataPointer::clone() + \since 4.5 + + Creates and returns a deep copy of the current data. This function + is called by detach() when the reference count is greater than 1 in + order to create the new copy. This function uses the \e {operator + new} and calls the copy constructor of the type T. + + See QSharedDataPointer::clone() for an explanation of how to use it. +*/ + +/*! + \typedef QExplicitlySharedDataPointer::Type + + This is the type of the shared data object. The \e{d pointer} + points to an object of this type. + */ + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h new file mode 100644 index 0000000..875560d --- /dev/null +++ b/src/corelib/tools/qshareddata.h @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSHAREDDATA_H +#define QSHAREDDATA_H + +#include <QtCore/qglobal.h> +#include <QtCore/qatomic.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +template <class T> class QSharedDataPointer; + +class Q_CORE_EXPORT QSharedData +{ +public: + mutable QAtomicInt ref; + + inline QSharedData() : ref(0) { } + inline QSharedData(const QSharedData &) : ref(0) { } + +private: + // using the assignment operator would lead to corruption in the ref-counting + QSharedData &operator=(const QSharedData &); +}; + +template <class T> class QSharedDataPointer +{ +public: + inline void detach() { if (d && d->ref != 1) detach_helper(); } + inline T &operator*() { detach(); return *d; } + inline const T &operator*() const { return *d; } + inline T *operator->() { detach(); return d; } + inline const T *operator->() const { return d; } + inline operator T *() { detach(); return d; } + inline operator const T *() const { return d; } + inline T *data() { detach(); return d; } + inline const T *data() const { return d; } + inline const T *constData() const { return d; } + + inline bool operator==(const QSharedDataPointer<T> &other) const { return d == other.d; } + inline bool operator!=(const QSharedDataPointer<T> &other) const { return d != other.d; } + + inline QSharedDataPointer() { d = 0; } + inline ~QSharedDataPointer() { if (d && !d->ref.deref()) delete d; } + + explicit QSharedDataPointer(T *data); + inline QSharedDataPointer(const QSharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); } + inline QSharedDataPointer<T> & operator=(const QSharedDataPointer<T> &o) { + if (o.d != d) { + if (o.d) + o.d->ref.ref(); + if (d && !d->ref.deref()) + delete d; + d = o.d; + } + return *this; + } + inline QSharedDataPointer &operator=(T *o) { + if (o != d) { + if (o) + o->ref.ref(); + if (d && !d->ref.deref()) + delete d; + d = o; + } + return *this; + } + + inline bool operator!() const { return !d; } + +protected: + T *clone(); + +private: + void detach_helper(); + + T *d; +}; + +template <class T> class QExplicitlySharedDataPointer +{ +public: + typedef T Type; + + inline T &operator*() const { return *d; } + inline T *operator->() { return d; } + inline T *operator->() const { return d; } + inline T *data() const { return d; } + inline const T *constData() const { return d; } + + inline void detach() { if (d && d->ref != 1) detach_helper(); } + + inline void reset() + { + if(d && !d->ref.deref()) + delete d; + + d = 0; + } + + inline operator bool () const { return d != 0; } + + inline bool operator==(const QExplicitlySharedDataPointer<T> &other) const { return d == other.d; } + inline bool operator!=(const QExplicitlySharedDataPointer<T> &other) const { return d != other.d; } + inline bool operator==(const T *ptr) const { return d == ptr; } + inline bool operator!=(const T *ptr) const { return d != ptr; } + + inline QExplicitlySharedDataPointer() { d = 0; } + inline ~QExplicitlySharedDataPointer() { if (d && !d->ref.deref()) delete d; } + + explicit QExplicitlySharedDataPointer(T *data); + inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<T> &o) : d(o.d) { if (d) d->ref.ref(); } + +#ifndef QT_NO_MEMBER_TEMPLATES + template<class X> + inline QExplicitlySharedDataPointer(const QExplicitlySharedDataPointer<X> &o) : d(static_cast<T *>(o.data())) + { + if(d) + d->ref.ref(); + } +#endif + + inline QExplicitlySharedDataPointer<T> & operator=(const QExplicitlySharedDataPointer<T> &o) { + if (o.d != d) { + if (o.d) + o.d->ref.ref(); + if (d && !d->ref.deref()) + delete d; + d = o.d; + } + return *this; + } + inline QExplicitlySharedDataPointer &operator=(T *o) { + if (o != d) { + if (o) + o->ref.ref(); + if (d && !d->ref.deref()) + delete d; + d = o; + } + return *this; + } + + inline bool operator!() const { return !d; } + +protected: + T *clone(); + +private: + void detach_helper(); + + T *d; +}; + +template <class T> +Q_INLINE_TEMPLATE QSharedDataPointer<T>::QSharedDataPointer(T *adata) : d(adata) +{ if (d) d->ref.ref(); } + +template <class T> +Q_INLINE_TEMPLATE T *QSharedDataPointer<T>::clone() +{ + return new T(*d); +} + +template <class T> +Q_OUTOFLINE_TEMPLATE void QSharedDataPointer<T>::detach_helper() +{ + T *x = clone(); + x->ref.ref(); + if (!d->ref.deref()) + delete d; + d = x; +} + +template <class T> +Q_INLINE_TEMPLATE T *QExplicitlySharedDataPointer<T>::clone() +{ + return new T(*d); +} + +template <class T> +Q_OUTOFLINE_TEMPLATE void QExplicitlySharedDataPointer<T>::detach_helper() +{ + T *x = clone(); + x->ref.ref(); + if (!d->ref.deref()) + delete d; + d = x; +} + +template <class T> +Q_INLINE_TEMPLATE QExplicitlySharedDataPointer<T>::QExplicitlySharedDataPointer(T *adata) : d(adata) +{ if (d) d->ref.ref(); } + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSHAREDDATA_H diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp new file mode 100644 index 0000000..d8a9923 --- /dev/null +++ b/src/corelib/tools/qsharedpointer.cpp @@ -0,0 +1,868 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsharedpointer.h" + +// to be sure we aren't causing a namespace clash: +#include "qshareddata.h" + +/*! + \class QSharedPointer + \brief The QSharedPointer class holds a strong reference to a shared pointer + \since 4.5 + + \reentrant + \ingroup misc + + The QSharedPointer is an automatic, shared pointer in C++. It + behaves exactly like a normal pointer for normal purposes, + including respect for constness. + + QSharedPointer will delete the pointer it is holding when it goes + out of scope, provided no other QSharedPointer objects are + referencing it. + + A QSharedPointer object can be created from a normal pointer, + another QSharedPointer object or by promoting a + QWeakPointer object to a strong reference. + + \section1 Thread-Safety + + QSharedPointer and QWeakPointer are thread-safe and operate + atomically on the pointer value. Different threads can also access + the same QSharedPointer or QWeakPointer object at the same time + without need for locking mechanisms. + + It should be noted that, while the pointer value can be accessed + in this manner, QSharedPointer and QWeakPointer provide no + guarantee about the object being pointed to. Thread-safety and + reentrancy rules for that object still apply. + + \section1 Other Pointer Classes + + Qt also provides two other pointer wrapper classes: QPointer and + QSharedDataPointer. They are incompatible with one another, since + each has its very different use case. + + QSharedPointer holds a shared pointer by means of an external + reference count (i.e., a reference counter placed outside the + object). Like its name indicates, the pointer value is shared + among all instances of QSharedPointer and QWeakPointer. The + contents of the object pointed to by the pointer should not + considered shared, however: there is only one object. For that + reason, QSharedPointer does not provide a way to detach or make + copies of the pointed object. + + QSharedDataPointer, on the other hand, holds a pointer to shared + data (i.e., a class derived from QSharedData). It does so by means + of an internal reference count, placed in the QSharedData base + class. This class can, therefore, detach based on the type of + access made to the data being guarded: if it's a non-const access, + it creates a copy atomically for the operation to complete. + + QExplicitlySharedDataPointer behaves like QSharedDataPointer, + except that it only detaches if + QExplicitlySharedDataPointer::detach() is explicitly called. + + Finally, QPointer holds a pointer to a QObject-derived object, but + it does so weakly. QPointer is similar, in that behaviour, to + QWeakPointer: it does not allow you to prevent the object from + being destroyed. All you can do is query whether it has been + destroyed or not. + + \sa QSharedDataPointer, QWeakPointer +*/ + +/*! + \class QWeakPointer + \brief The QWeakPointer class holds a weak reference to a shared pointer + \since 4.5 + \reentrant + \ingroup misc + + The QWeakPointer is an automatic weak reference to a + pointer in C++. It cannot be used to dereference the pointer + directly, but it can be used to verify if the pointer has been + deleted or not in another context. + + QWeakPointer objects can only be created by assignment + from a QSharedPointer. + + To access the pointer that QWeakPointer is tracking, you + must first create a QSharedPointer object and verify if the pointer + is null or not. + + \sa QSharedPointer +*/ + +/*! + \fn QSharedPointer::QSharedPointer() + + Creates a QSharedPointer that points to null (0). +*/ + +/*! + \fn QSharedPointer::~QSharedPointer() + + Destroys this QSharedPointer object. If it is the last reference to + the pointer stored, this will delete the pointer as well. +*/ + +/*! + \fn QSharedPointer::QSharedPointer(T *ptr) + + Creates a QSharedPointer that points to \a ptr. The pointer \a ptr + becomes managed by this QSharedPointer and must not be passed to + another QSharedPointer object or deleted outside this object. +*/ + +/*! + \fn QSharedPointer::QSharedPointer(T *ptr, Deleter deleter) + + Creates a QSharedPointer that points to \a ptr. The pointer \a ptr + becomes managed by this QSharedPointer and must not be passed to + another QSharedPointer object or deleted outside this object. + + The \a deleter paramter specifies the custom deleter for this + object. The custom deleter is called when the strong reference + count drops to 0 instead of the operator delete(). This is useful, + for instance, for calling deleteLater() in a QObject instead: + + \code + static void doDeleteLater(MyObject *obj) + { + obj->deleteLater(); + } + + void otherFunction() + { + QSharedPointer<MyObject> obj = + QSharedPointer<MyObject>(new MyObject, doDeleteLater); + + // continue using obj + obj.clear(); // calls obj->deleteLater(); + } + \endcode + + It is also possible to specify a member function directly, as in: + \code + QSharedPointer<MyObject> obj = + QSharedPointer<MyObject>(new MyObject, &QObject::deleteLater); + \endcode + + \sa clear() +*/ + +/*! + \fn QSharedPointer::QSharedPointer(const QSharedPointer<T> &other) + + Creates a QSharedPointer object that shares \a other's pointer. + + If \tt T is a derived type of the template parameter of this class, + QSharedPointer will perform an automatic cast. Otherwise, you will + get a compiler error. +*/ + +/*! + \fn QSharedPointer::QSharedPointer(const QWeakPointer<T> &other) + + Creates a QSharedPointer by promoting the weak reference \a other + to strong reference and sharing its pointer. + + If \tt T is a derived type of the template parameter of this + class, QSharedPointer will perform an automatic cast. Otherwise, + you will get a compiler error. +*/ + +/*! + \fn QSharedPointer &QSharedPointer::operator=(const QSharedPointer<T> &other) + + Makes this object share \a other's pointer. The current pointer + reference is discarded and, if it was the last, the pointer will + be deleted. + + If \tt T is a derived type of the template parameter of this + class, QSharedPointer will perform an automatic cast. Otherwise, + you will get a compiler error. +*/ + +/*! + \fn QSharedPointer &QSharedPointer::operator=(const QWeakPointer<T> &other) + + Promotes \a other to a strong reference and makes this object + share a reference to the pointer referenced by it. The current pointer + reference is discarded and, if it was the last, the pointer will + be deleted. + + If \tt T is a derived type of the template parameter of this + class, QSharedPointer will perform an automatic cast. Otherwise, + you will get a compiler error. +*/ + +/*! + \fn T *QSharedPointer::data() const + + Returns the value of the pointer referenced by this object. + + Note: do not delete the pointer returned by this function or pass + it to another function that could delete it, including creating + QSharedPointer or QWeakPointer objects. +*/ + +/*! + \fn T &QSharedPointer::operator *() const + + Provides access to the shared pointer's members. + + \sa isNull() +*/ + +/*! + \fn T *QSharedPointer::operator ->() const + + Provides access to the shared pointer's members. + + \sa isNull() +*/ + +/*! + \fn bool QSharedPointer::isNull() const + + Returns true if this object is holding a reference to a null + pointer. +*/ + +/*! + \fn QSharedPointer::operator bool() const + + Returns true if this object is not null. This function is suitable + for use in \tt if-constructs, like: + + \code + if (sharedptr) { ... } + \endcode + + \sa isNull() +*/ + +/*! + \fn bool QSharedPointer::operator !() const + + Returns true if this object is null. This function is suitable + for use in \tt if-constructs, like: + + \code + if (!sharedptr) { ... } + \endcode + + \sa isNull() +*/ + +/*! + \fn QSharedPointer<X> QSharedPointer::staticCast() const + + Performs a static cast from this pointer's type to \tt X and returns + a QSharedPointer that shares the reference. This function can be + used for up- and for down-casting, but is more useful for + up-casting. + + Note: the template type \c X must have the same const and volatile + qualifiers as the template of this object, or the cast will + fail. Use constCast() if you need to drop those qualifiers. + + \sa dynamicCast(), constCast(), qSharedPointerCast() +*/ + +/*! + \fn QSharedPointer<X> QSharedPointer::dynamicCast() const + + Performs a dynamic cast from this pointer's type to \tt X and + returns a QSharedPointer that shares the reference. If this + function is used to up-cast, then QSharedPointer will perform a \tt + dynamic_cast, which means that if the object being pointed by this + QSharedPointer is not of type \tt X, the returned object will be + null. + + Note: the template type \c X must have the same const and volatile + qualifiers as the template of this object, or the cast will + fail. Use constCast() if you need to drop those qualifiers. + + \sa qSharedPointerDynamicCast() +*/ + +/*! + \fn QSharedPointer<X> QSharedPointer::constCast() const + + Performs a \tt const_cast from this pointer's type to \tt X and returns + a QSharedPointer that shares the reference. This function can be + used for up- and for down-casting, but is more useful for + up-casting. + + \sa isNull(), qSharedPointerConstCast() +*/ + +/*! + \fn QWeakPointer<T> QSharedPointer::toWeakRef() const + + Returns a weak reference object that shares the pointer referenced + by this object. +*/ + +/*! + \fn void QSharedPointer::clear() + + Clears this QSharedPointer object, dropping the reference that it + may have had to the pointer. If this was the last reference, then + the pointer itself will be deleted. +*/ + +/*! + \fn QWeakPointer::QWeakPointer() + + Creates a QWeakPointer that points to nothing. +*/ + +/*! + \fn QWeakPointer::~QWeakPointer() + + Destroys this QWeakPointer object. The pointer referenced + by this object will not be deleted. +*/ + +/*! + \fn QWeakPointer::QWeakPointer(const QWeakPointer<T> &other) + + Creates a QWeakPointer that holds a weak reference to the + pointer referenced by \a other. + + If \tt T is a derived type of the template parameter of this + class, QWeakPointer will perform an automatic cast. Otherwise, + you will get a compiler error. +*/ + +/*! + \fn QWeakPointer::QWeakPointer(const QSharedPointer<T> &other) + + Creates a QWeakPointer that holds a weak reference to the + pointer referenced by \a other. + + If \tt T is a derived type of the template parameter of this + class, QWeakPointer will perform an automatic cast. Otherwise, + you will get a compiler error. +*/ + +/*! + \fn QWeakPointer &QWeakPointer::operator=(const QWeakPointer<T> &other) + + Makes this object share \a other's pointer. The current pointer + reference is discarded but is not deleted. + + If \tt T is a derived type of the template parameter of this + class, QWeakPointer will perform an automatic cast. Otherwise, + you will get a compiler error. +*/ + +/*! + \fn QWeakPointer &QWeakPointer::operator=(const QSharedPointer<T> &other) + + Makes this object share \a other's pointer. The current pointer + reference is discarded but is not deleted. + + If \tt T is a derived type of the template parameter of this + class, QWeakPointer will perform an automatic cast. Otherwise, + you will get a compiler error. +*/ + +/*! + \fn bool QWeakPointer::isNull() const + + Returns true if this object is holding a reference to a null + pointer. + + Note that, due to the nature of weak references, the pointer that + QWeakPointer references can become null at any moment, so + the value returned from this function can change from false to + true from one call to the next. +*/ + +/*! + \fn QWeakPointer::operator bool() const + + Returns true if this object is not null. This function is suitable + for use in \tt if-constructs, like: + + \code + if (weakref) { ... } + \endcode + + Note that, due to the nature of weak references, the pointer that + QWeakPointer references can become null at any moment, so + the value returned from this function can change from true to + false from one call to the next. + + \sa isNull() +*/ + +/*! + \fn bool QWeakPointer::operator !() const + + Returns true if this object is null. This function is suitable + for use in \tt if-constructs, like: + + \code + if (!weakref) { ... } + \endcode + + Note that, due to the nature of weak references, the pointer that + QWeakPointer references can become null at any moment, so + the value returned from this function can change from false to + true from one call to the next. + + \sa isNull() +*/ + +/*! + \fn QSharedPointer<T> QWeakPointer::toStrongRef() const + + Promotes this weak reference to a strong one and returns a + QSharedPointer object holding that reference. +*/ + +/*! + \fn void QWeakPointer::clear() + + Clears this QWeakPointer object, dropping the reference that it + may have had to the pointer. +*/ + +/*! + \fn bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) + \relates QSharedPointer + + Returns true if the pointer referenced by \a ptr1 is the + same pointer as that referenced by \a ptr2. + + If \a ptr2's template parameter is different from \a ptr1's, + QSharedPointer will attempt to perform an automatic \tt static_cast + to ensure that the pointers being compared are equal. If \a ptr2's + template parameter is not a base or a derived type from + \a ptr1's, you will get a compiler error. +*/ + +/*! + \fn bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) + \relates QSharedPointer + + Returns true if the pointer referenced by \a ptr1 is not the + same pointer as that referenced by \a ptr2. + + If \a ptr2's template parameter is different from \a ptr1's, + QSharedPointer will attempt to perform an automatic \tt static_cast + to ensure that the pointers being compared are equal. If \a ptr2's + template parameter is not a base or a derived type from + \a ptr1's, you will get a compiler error. +*/ + +/*! + \fn bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2) + \relates QSharedPointer + + Returns true if the pointer referenced by \a ptr1 is the + same pointer as \a ptr2. + + If \a ptr2's type is different from \a ptr1's, + QSharedPointer will attempt to perform an automatic \tt static_cast + to ensure that the pointers being compared are equal. If \a ptr2's + type is not a base or a derived type from this + \a ptr1's, you will get a compiler error. +*/ + +/*! + \fn bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2) + \relates QSharedPointer + + Returns true if the pointer referenced by \a ptr1 is not the + same pointer as \a ptr2. + + If \a ptr2's type is different from \a ptr1's, + QSharedPointer will attempt to perform an automatic \tt static_cast + to ensure that the pointers being compared are equal. If \a ptr2's + type is not a base or a derived type from this + \a ptr1's, you will get a compiler error. +*/ + +/*! + \fn bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2) + \relates QSharedPointer + + Returns true if the pointer \a ptr1 is the + same pointer as that referenced by \a ptr2. + + If \a ptr2's template parameter is different from \a ptr1's type, + QSharedPointer will attempt to perform an automatic \tt static_cast + to ensure that the pointers being compared are equal. If \a ptr2's + template parameter is not a base or a derived type from + \a ptr1's type, you will get a compiler error. +*/ + +/*! + \fn bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2) + \relates QSharedPointer + + Returns true if the pointer \a ptr1 is not the + same pointer as that referenced by \a ptr2. + + If \a ptr2's template parameter is different from \a ptr1's type, + QSharedPointer will attempt to perform an automatic \tt static_cast + to ensure that the pointers being compared are equal. If \a ptr2's + template parameter is not a base or a derived type from + \a ptr1's type, you will get a compiler error. +*/ + +/*! + \fn bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) + \relates QWeakPointer + + Returns true if the pointer referenced by \a ptr1 is the + same pointer as that referenced by \a ptr2. + + If \a ptr2's template parameter is different from \a ptr1's, + QSharedPointer will attempt to perform an automatic \tt static_cast + to ensure that the pointers being compared are equal. If \a ptr2's + template parameter is not a base or a derived type from + \a ptr1's, you will get a compiler error. +*/ + +/*! + \fn bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) + \relates QWeakPointer + + Returns true if the pointer referenced by \a ptr1 is not the + same pointer as that referenced by \a ptr2. + + If \a ptr2's template parameter is different from \a ptr1's, + QSharedPointer will attempt to perform an automatic \tt static_cast + to ensure that the pointers being compared are equal. If \a ptr2's + template parameter is not a base or a derived type from + \a ptr1's, you will get a compiler error. +*/ + +/*! + \fn bool operator==(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2) + \relates QWeakPointer + + Returns true if the pointer referenced by \a ptr1 is the + same pointer as that referenced by \a ptr2. + + If \a ptr2's template parameter is different from \a ptr1's, + QSharedPointer will attempt to perform an automatic \tt static_cast + to ensure that the pointers being compared are equal. If \a ptr2's + template parameter is not a base or a derived type from + \a ptr1's, you will get a compiler error. +*/ + +/*! + \fn bool operator!=(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2) + \relates QWeakPointer + + Returns true if the pointer referenced by \a ptr1 is not the + same pointer as that referenced by \a ptr2. + + If \a ptr2's template parameter is different from \a ptr1's, + QSharedPointer will attempt to perform an automatic \tt static_cast + to ensure that the pointers being compared are equal. If \a ptr2's + template parameter is not a base or a derived type from + \a ptr1's, you will get a compiler error. +*/ + +/*! + \fn QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &other) + \relates QSharedPointer + + Returns a shared pointer to the pointer held by \a other, cast to + type \tt X. The types \tt T and \tt X must belong to one + hierarchy for the \tt static_cast to succeed. + + Note that \tt X must have the same cv-qualifiers (\tt const and + \tt volatile) that \tt T has, or the code will fail to + compile. Use qSharedPointerConstCast to cast away the constness. + + \sa QSharedPointer::staticCast(), qSharedPointerDynamicCast(), qSharedPointerConstCast() +*/ + +/*! + \fn QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &other) + \relates QSharedPointer + \relates QWeakPointer + + Returns a shared pointer to the pointer held by \a other, cast to + type \tt X. The types \tt T and \tt X must belong to one + hierarchy for the \tt static_cast to succeed. + + The \a other object is converted first to a strong reference. If + that conversion fails (because the object it's pointing to has + already been deleted), this function returns a null + QSharedPointer. + + Note that \tt X must have the same cv-qualifiers (\tt const and + \tt volatile) that \tt T has, or the code will fail to + compile. Use qSharedPointerConstCast to cast away the constness. + + \sa QWeakPointer::toStrongRef(), qSharedPointerDynamicCast(), qSharedPointerConstCast() +*/ + +/*! + \fn QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &other) + \relates QSharedPointer + + Returns a shared pointer to the pointer held by \a other, using a + dynamic cast to type \tt X to obtain an internal pointer of the + appropriate type. If the \tt dynamic_cast fails, the object + returned will be null. + + Note that \tt X must have the same cv-qualifiers (\tt const and + \tt volatile) that \tt T has, or the code will fail to + compile. Use qSharedPointerConstCast to cast away the constness. + + \sa QSharedPointer::dynamicCast(), qSharedPointerCast(), qSharedPointerConstCast() +*/ + +/*! + \fn QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &other) + \relates QSharedPointer + \relates QWeakPointer + + Returns a shared pointer to the pointer held by \a other, using a + dynamic cast to type \tt X to obtain an internal pointer of the + appropriate type. If the \tt dynamic_cast fails, the object + returned will be null. + + The \a other object is converted first to a strong reference. If + that conversion fails (because the object it's pointing to has + already been deleted), this function also returns a null + QSharedPointer. + + Note that \tt X must have the same cv-qualifiers (\tt const and + \tt volatile) that \tt T has, or the code will fail to + compile. Use qSharedPointerConstCast to cast away the constness. + + \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerConstCast() +*/ + +/*! + \fn QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &other) + \relates QSharedPointer + + Returns a shared pointer to the pointer held by \a other, cast to + type \tt X. The types \tt T and \tt X must belong to one + hierarchy for the \tt const_cast to succeed. The \tt const and \tt + volatile differences between \tt T and \tt X are ignored. + + \sa QSharedPointer::constCast(), qSharedPointerCast(), qSharedPointerDynamicCast() +*/ + +/*! + \fn QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &other) + \relates QSharedPointer + \relates QWeakPointer + + Returns a shared pointer to the pointer held by \a other, cast to + type \tt X. The types \tt T and \tt X must belong to one + hierarchy for the \tt const_cast to succeed. The \tt const and + \tt volatile differences between \tt T and \tt X are ignored. + + The \a other object is converted first to a strong reference. If + that conversion fails (because the object it's pointing to has + already been deleted), this function returns a null + QSharedPointer. + + \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerDynamicCast() +*/ + +/*! + \fn QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &other) + \relates QWeakPointer + + Returns a weak pointer to the pointer held by \a other, cast to + type \tt X. The types \tt T and \tt X must belong to one + hierarchy for the \tt static_cast to succeed. + + Note that \tt X must have the same cv-qualifiers (\tt const and + \tt volatile) that \tt T has, or the code will fail to + compile. Use qSharedPointerConstCast to cast away the constness. +*/ + +#include <qset.h> +#include <qmutex.h> + +#if !defined(QT_NO_MEMBER_TEMPLATES) + +//# define QT_SHARED_POINTER_BACKTRACE_SUPPORT +# ifdef QT_SHARED_POINTER_BACKTRACE_SUPPORT +# if defined(__GLIBC__) && (__GLIBC__ >= 2) && !defined(__UCLIBC__) && !defined(QT_LINUXBASE) +# define BACKTRACE_SUPPORTED +# elif defined(Q_OS_MACX) +# define BACKTRACE_SUPPORTED +# endif +# endif + +# if !defined(BACKTRACE_SUPPORTED) +// Dummy implementation of the functions. +// Using QHashDummyValue also means that the QHash below is actually a QSet +typedef QT_PREPEND_NAMESPACE(QHashDummyValue) Backtrace; + +static inline Backtrace saveBacktrace() { return Backtrace(); } +static inline void printBacktrace(Backtrace) { } + +# else +# include <sys/types.h> +# include <execinfo.h> +# include <stdio.h> +# include <unistd.h> +# include <sys/wait.h> + +typedef QT_PREPEND_NAMESPACE(QByteArray) Backtrace; + +static inline Backtrace saveBacktrace() __attribute__((always_inline)); +static inline Backtrace saveBacktrace() +{ + static const int maxFrames = 32; + + Backtrace stacktrace; + stacktrace.resize(sizeof(void*) * maxFrames); + int stack_size = backtrace((void**)stacktrace.data(), maxFrames); + stacktrace.resize(sizeof(void*) * stack_size); + + return stacktrace; +} + +static void printBacktrace(Backtrace stacktrace) +{ + void *const *stack = (void *const *)stacktrace.constData(); + int stack_size = stacktrace.size() / sizeof(void*); + char **stack_symbols = backtrace_symbols(stack, stack_size); + + int filter[2]; + pid_t child = -1; + if (pipe(filter) != -1) + child = fork(); + if (child == 0) { + // child process + dup2(fileno(stderr), fileno(stdout)); + dup2(filter[0], fileno(stdin)); + close(filter[0]); + close(filter[1]); + execlp("c++filt", "c++filt", "-n", NULL); + + // execlp failed + execl("/bin/cat", "/bin/cat", NULL); + _exit(127); + } + + // parent process + close(filter[0]); + FILE *output; + if (child == -1) { + // failed forking + close(filter[1]); + output = stderr; + } else { + output = fdopen(filter[1], "w"); + } + + fprintf(stderr, "Backtrace of the first creation (most recent frame first):\n"); + for (int i = 0; i < stack_size; ++i) { + if (strlen(stack_symbols[i])) + fprintf(output, "#%-2d %s\n", i, stack_symbols[i]); + else + fprintf(output, "#%-2d %p\n", i, stack[i]); + } + + if (child != -1) { + fclose(output); + waitpid(child, 0, 0); + } +} +# endif // BACKTRACE_SUPPORTED + +namespace { + QT_USE_NAMESPACE + class KnownPointers + { + public: + QMutex mutex; + QHash<void *, Backtrace> values; + }; +} + +Q_GLOBAL_STATIC(KnownPointers, knownPointers) + +QT_BEGIN_NAMESPACE + +/*! + \internal +*/ +void QtSharedPointer::internalSafetyCheckAdd(const volatile void *ptr) +{ + QMutexLocker lock(&knownPointers()->mutex); + void *actual = const_cast<void*>(ptr); + if (knownPointers()->values.contains(actual)) { + printBacktrace(knownPointers()->values.value(actual)); + qFatal("QSharedPointerData: internal self-check failed: pointer %p was already tracked " + "by another QSharedPointerData object", actual); + } + + knownPointers()->values.insert(actual, saveBacktrace()); +} + +/*! + \internal +*/ +void QtSharedPointer::internalSafetyCheckRemove(const volatile void *ptr) +{ + QMutexLocker lock(&knownPointers()->mutex); + void *actual = const_cast<void*>(ptr); + knownPointers()->values.remove(actual); +} + +QT_END_NAMESPACE + +#endif diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h new file mode 100644 index 0000000..0a1efde --- /dev/null +++ b/src/corelib/tools/qsharedpointer.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSHAREDPOINTER_H +#define QSHAREDPOINTER_H + +#include <QtCore/qglobal.h> +#include <QtCore/qatomic.h> +#include <QtCore/qshareddata.h> + +#ifndef Q_QDOC +# if !defined(QT_NO_MEMBER_TEMPLATES) +// QSharedPointer requires member template support +# include <QtCore/qsharedpointer_impl.h> +# endif +#else + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +// These classes are here to fool qdoc into generating a better documentation + +template <class T> +class QSharedPointer +{ +public: + // basic accessor functions + T *data() const; + bool isNull() const; + operator bool() const; + bool operator!() const; + T &operator*() const; + T *operator ->() const; + + // constructors + QSharedPointer(); + explicit QSharedPointer(T *ptr); + QSharedPointer(T *ptr, Deleter d); + QSharedPointer(const QSharedPointer<T> &other); + QSharedPointer(const QWeakPointer<T> &other); + + ~QSharedPointer() { } + + QSharedPointer<T> &operator=(const QSharedPointer<T> &other); + QSharedPointer<T> &operator=(const QWeakPointer<T> &other); + + QWeakPointer<T> toWeakRef() const; + + void clear(); + + // casts: + template <class X> QSharedPointer<X> staticCast() const; + template <class X> QSharedPointer<X> dynamicCast() const; + template <class X> QSharedPointer<X> constCast() const; +}; + +template <class T> +class QWeakPointer +{ +public: + // basic accessor functions + bool isNull() const; + operator bool() const; + bool operator!() const; + + // constructors: + QWeakPointer(); + QWeakPointer(const QWeakPointer<T> &other); + QWeakPointer(const QSharedPointer<T> &other); + + ~QWeakPointer(); + + QWeakPointer<T> operator=(const QWeakPointer<T> &other); + QWeakPointer<T> operator=(const QSharedPointer<T> &other); + + void clear(); + + QSharedPointer<T> toStrongRef() const; +}; + +template<class T, class X> bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2); +template<class T, class X> bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2); +template<class T, class X> bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2); +template<class T, class X> bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2); +template<class T, class X> bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2); +template<class T, class X> bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2); +template<class T, class X> bool operator==(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2); +template<class T, class X> bool operator!=(const QWeakPointer<T> &ptr1, const QSharedPointer<X> &ptr2); +template<class T, class X> bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2); +template<class T, class X> bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2); + +template <class X, class T> QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &other); +template <class X, class T> QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &other); +template <class X, class T> QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src); +template <class X, class T> QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src); +template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src); +template <class X, class T> QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src); + +template <class X, class T> QWeakPointer<X> qWeakPointerCast(const QWeakPointer<T> &src); + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // Q_QDOC + +#endif // QSHAREDPOINTER_H diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h new file mode 100644 index 0000000..f1b35ee --- /dev/null +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -0,0 +1,585 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef Q_QDOC + +#ifndef QSHAREDPOINTER_H +#error Do not include qsharedpointer_impl.h directly +#endif +#if 0 +#pragma qt_sync_stop_processing +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +// Macro QSHAREDPOINTER_VERIFY_AUTO_CAST +// generates a compiler error if the following construct isn't valid: +// T *ptr1; +// X *ptr2 = ptr1; +// +#ifdef QT_NO_DEBUG +# define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X) qt_noop() +#else + +template<typename T> inline void qt_sharedpointer_cast_check(T *) { } +# define QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X) \ + qt_sharedpointer_cast_check<T>(static_cast<X *>(0)) +#endif + +// +// forward declarations +// +template <class T> class QWeakPointer; +template <class T> class QSharedPointer; + +template <class X, class T> +QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &ptr); +template <class X, class T> +QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &ptr); +template <class X, class T> +QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &ptr); + +namespace QtSharedPointer { + template <class T> class InternalRefCount; + template <class T> class ExternalRefCount; + + template <class X, class T> QSharedPointer<X> qStrongRefFromWeakHelper(const QWeakPointer<T> &, X*); + template <class X, class T> QSharedPointer<X> qSharedPointerCastHelper(const QSharedPointer<T> &src, X *); + template <class X, class T> QSharedPointer<X> qSharedPointerConstCastHelper(const QSharedPointer<T> &src, X *); + + // used in debug mode to verify the reuse of pointers + Q_CORE_EXPORT void internalSafetyCheckAdd(const volatile void *); + Q_CORE_EXPORT void internalSafetyCheckRemove(const volatile void *); + + template <class T, typename Klass, typename RetVal> + inline void executeDeleter(T *t, RetVal (Klass:: *memberDeleter)()) + { (t->*memberDeleter)(); } + template <class T, typename Deleter> + inline void executeDeleter(T *t, Deleter d) + { d(t); } + + // + // Depending on its template parameter, QSharedPointer derives from either + // QtSharedPointer::InternalRefCount or from QtSharedPointer::ExternalRefCount. + // Both of these classes derive from QtSharedPointer::Basic, which provides common + // operations, + // + template <class T> + class Basic + { + typedef T *Basic:: *RestrictedBool; + public: + typedef T Type; + + inline T *data() const { return value; } + inline bool isNull() const { return !data(); } + inline operator RestrictedBool() const { return isNull() ? 0 : &Basic::value; } + inline bool operator !() const { return isNull(); } + inline T &operator*() const { return *data(); } + inline T *operator->() const { return data(); } + + protected: + inline Basic() : value(0 * sizeof(T)) { } + // ~Basic(); + + inline void verifyReconstruction(const T *ptr) + { + Q_ASSERT_X(!ptr || value != ptr, "QSharedPointer", + "QSharedPointer violation: you cannot create two QSharedPointer objects " + "from the same pointer"); + + // make use of the "ptr" variable in the no-op statement below + // since this function is in a public header, we don't + // want warnings on "unused variables" to show up everywhere + ptr = 0; + } + + inline void internalConstruct(T *ptr) + { +#ifndef QT_NO_DEBUG + if (ptr) internalSafetyCheckAdd(ptr); +#endif + value = ptr; + } + inline void internalDestroy() + { +#ifndef QT_NO_DEBUG + if (value) internalSafetyCheckRemove(value); +#endif + } + +#if defined(Q_NO_TEMPLATE_FRIENDS) + public: +#else + template <class X> friend class QWeakPointer; +#endif + + Type *value; + }; + + struct ExternalRefCountData + { + QAtomicInt weakref; + QAtomicInt strongref; + + inline ExternalRefCountData() : weakref(1), strongref(1) { } + virtual inline ~ExternalRefCountData() { Q_ASSERT(!weakref); Q_ASSERT(!strongref); } + + virtual inline bool destroy() { return false; } + }; + + template <class T, typename Deleter> + struct ExternalRefCountWithSpecializedDeleter: public ExternalRefCountData + { + T *ptr; + Deleter deleter; + + inline ExternalRefCountWithSpecializedDeleter(T *p, Deleter d) + : ptr(p), deleter(d) + { } + inline bool destroy() { executeDeleter(ptr, deleter); return true; } + }; + + template <class T> + class ExternalRefCount: public Basic<T> + { + typedef ExternalRefCountData Data; + typedef void (*DeleterFunction)(T *); + protected: + inline void ref() const { d->weakref.ref(); d->strongref.ref(); } + inline bool deref() + { + if (!d->strongref.deref()) + this->internalDestroy(); + return d->weakref.deref(); + } + + inline void internalConstruct(T *ptr) + { + Basic<T>::internalConstruct(ptr); + Q_ASSERT(!d); + if (ptr) + d = new Data; + } + + template <typename Deleter> + inline void internalConstruct(T *ptr, Deleter deleter) + { + Basic<T>::internalConstruct(ptr); + Q_ASSERT(!d); + if (ptr) + d = new ExternalRefCountWithSpecializedDeleter<T, Deleter>(ptr, deleter); + } + + inline ExternalRefCount() : d(0) { } + inline ~ExternalRefCount() { if (d && !deref()) delete d; } + inline ExternalRefCount(const ExternalRefCount<T> &other) : Basic<T>(other), d(other.d) + { if (d) ref(); } + + template <class X> + inline void internalCopy(const ExternalRefCount<X> &other) + { + internalSet(other.d, other.data()); + } + + inline void internalDestroy() + { + Basic<T>::internalDestroy(); + if (!d->destroy()) + delete this->value; + } + + private: +#if defined(Q_NO_TEMPLATE_FRIENDS) + public: +#else + template <class X> friend class ExternalRefCount; + template <class X> friend class QWeakPointer; + template <class X, class Y> friend QSharedPointer<X> qSharedPointerCastHelper(const QSharedPointer<Y> &src, X *); + template <class X, class Y> friend QSharedPointer<X> qSharedPointerConstCastHelper(const QSharedPointer<Y> &src, X *); + template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::qStrongRefFromWeakHelper(const QWeakPointer<Y> &src, X *); +#endif + + inline void internalSet(Data *o, T *actual) + { + if (d == o) return; + if (o && !o->strongref) + o = 0; + if (o) { + verifyReconstruction(actual); + o->weakref.ref(); + o->strongref.ref(); + } + if (d && !deref()) + delete d; + d = o; + this->value = d && d->strongref ? actual : 0; + } + +#if defined(QT_BUILD_INTERNAL) + public: +#endif + Data *d; + + private: + template<class X> ExternalRefCount(const InternalRefCount<X> &); + }; +} // namespace QtSharedPointer + +template <class T> +class QSharedPointer: public QtSharedPointer::ExternalRefCount<T> +{ + typedef typename QtSharedPointer::ExternalRefCount<T> BaseClass; +public: + inline QSharedPointer() { } + // inline ~QSharedPointer() { } + + inline explicit QSharedPointer(T *ptr) { internalConstruct(ptr); } + + template <typename Deleter> + inline QSharedPointer(T *ptr, Deleter d) { internalConstruct(ptr, d); } + + inline QSharedPointer(const QSharedPointer<T> &other) : BaseClass(other) { } + inline QSharedPointer<T> &operator=(const QSharedPointer<T> &other) + { + internalCopy(other); + return *this; + } + + inline QSharedPointer(const QWeakPointer<T> &other) + { *this = QtSharedPointer::qStrongRefFromWeakHelper(other, static_cast<T*>(0)); } + inline QSharedPointer<T> &operator=(const QWeakPointer<T> &other) + { *this = QtSharedPointer::qStrongRefFromWeakHelper(other, static_cast<T*>(0)); return *this; } + + template <class X> + inline QSharedPointer(const QSharedPointer<X> &other) { *this = other; } + + template <class X> + inline QSharedPointer<T> &operator=(const QSharedPointer<X> &other) + { + QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid + internalCopy(other); + return *this; + } + + template <class X> + inline QSharedPointer(const QWeakPointer<X> &other) + { *this = QtSharedPointer::qStrongRefFromWeakHelper(other, static_cast<T *>(0)); } + + template <class X> + inline QSharedPointer<T> &operator=(const QWeakPointer<X> &other) + { *this = qStrongRefFromWeakHelper(other, static_cast<T *>(0)); return *this; } + + template <class X> + QSharedPointer<X> staticCast() const + { + return qSharedPointerCast<X, T>(*this); + } + + template <class X> + QSharedPointer<X> dynamicCast() const + { + return qSharedPointerDynamicCast<X, T>(*this); + } + + template <class X> + QSharedPointer<X> constCast() const + { + return qSharedPointerConstCast<X, T>(*this); + } + + inline void clear() { *this = QSharedPointer<T>(); } + + QWeakPointer<T> toWeakRef() const; +}; + +template <class T> +class QWeakPointer +{ + typedef T *QWeakPointer:: *RestrictedBool; + typedef QtSharedPointer::ExternalRefCountData Data; + +public: + inline bool isNull() const { return d == 0 || d->strongref == 0 || value == 0; } + inline operator RestrictedBool() const { return isNull() ? 0 : &QWeakPointer::value; } + inline bool operator !() const { return isNull(); } + + inline QWeakPointer() : d(0), value(0) { } + inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; } + inline QWeakPointer(const QWeakPointer<T> &o) : d(o.d), value(o.value) + { if (d) d->weakref.ref(); } + inline QWeakPointer<T> &operator=(const QWeakPointer<T> &o) + { + internalSet(o.d, o.value); + return *this; + } + + inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data()) + { if (d) d->weakref.ref();} + inline QWeakPointer<T> &operator=(const QSharedPointer<T> &o) + { + internalSet(o.d, o.value); + return *this; + } + + template <class X> + inline QWeakPointer(const QWeakPointer<X> &o) : d(0), value(0) + { *this = o; } + + template <class X> + inline QWeakPointer<T> &operator=(const QWeakPointer<X> &o) + { + // conversion between X and T could require access to the virtual table + // so force the operation to go through QSharedPointer + *this = o.toStrongRef(); + return *this; + } + + template <class X> + inline bool operator==(const QWeakPointer<X> &o) const + { return d == o.d && value == static_cast<const T *>(o.value); } + + template <class X> + inline bool operator!=(const QWeakPointer<X> &o) const + { return !(*this == o); } + + template <class X> + inline QWeakPointer(const QSharedPointer<X> &o) : d(0), value(0) + { *this = o; } + + template <class X> + inline QWeakPointer<T> &operator=(const QSharedPointer<X> &o) + { + QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalid + internalSet(o.d, o.data()); + return *this; + } + + template <class X> + inline bool operator==(const QSharedPointer<X> &o) const + { return d == o.d && value == static_cast<const T *>(o.data()); } + + template <class X> + inline bool operator!=(const QSharedPointer<X> &o) const + { return !(*this == o); } + + inline void clear() { *this = QWeakPointer<T>(); } + + inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); } + +private: + +#if defined(Q_NO_TEMPLATE_FRIENDS) +public: +#else + template <class X, class Y> friend QSharedPointer<X> QtSharedPointer::qStrongRefFromWeakHelper(const QWeakPointer<Y> &src, X *); +#endif + + inline void internalSet(Data *o, T *actual) + { + if (d == o) return; + if (o) + o->weakref.ref(); + if (d && !d->weakref.deref()) + delete d; + d = o; + value = actual; + } + + Data *d; + T *value; +}; + +template <class T, class X> +bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) +{ + return ptr1.data() == ptr2.data(); +} +template <class T, class X> +bool operator!=(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) +{ + return ptr1.data() != ptr2.data(); +} + +template <class T, class X> +bool operator==(const QSharedPointer<T> &ptr1, const X *ptr2) +{ + return ptr1.data() == ptr2; +} +template <class T, class X> +bool operator==(const T *ptr1, const QSharedPointer<X> &ptr2) +{ + return ptr1 == ptr2.data(); +} + +template <class T, class X> +bool operator!=(const QSharedPointer<T> &ptr1, const X *ptr2) +{ + return !(ptr1 == ptr2); +} +template <class T, class X> +bool operator!=(const T *ptr1, const QSharedPointer<X> &ptr2) +{ + return !(ptr2 == ptr1); +} + +template <class T, class X> +bool operator==(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) +{ + return ptr2 == ptr1; +} +template <class T, class X> +bool operator!=(const QSharedPointer<T> &ptr1, const QWeakPointer<X> &ptr2) +{ + return ptr2 != ptr1; +} + +template <class T> +Q_INLINE_TEMPLATE QWeakPointer<T> QSharedPointer<T>::toWeakRef() const +{ + return QWeakPointer<T>(*this); +} + +namespace QtSharedPointer { +// helper functions: + template <class X, class T> + Q_INLINE_TEMPLATE X *qVerifyStaticCast(T *src, X *) + { + return static_cast<X *>(src); // if you get an error in this line, the cast is invalid + } + template <class X, class T> + Q_INLINE_TEMPLATE X *qVerifyDynamicCast(T *src, X *) + { + return dynamic_cast<X *>(src); // if you get an error in this line, the cast is invalid + } + template <class X, class T> + Q_INLINE_TEMPLATE X *qVerifyConstCast(T *src, X *) + { + return const_cast<X *>(src); // if you get an error in this line, the cast is invalid + } + + template <class X, class T> + Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCastHelper(const QSharedPointer<T> &src, X *) + { + QSharedPointer<X> result; + register T *ptr = src.data(); + result.internalSet(src.d, static_cast<X *>(ptr)); + return result; + } + template <class X, class T> + Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCastHelper(const QSharedPointer<T> &src, X *) + { + QSharedPointer<X> result; + register T *ptr = src.data(); + result.internalSet(src.d, const_cast<X *>(ptr)); + return result; + } + template <class X, class T> + Q_INLINE_TEMPLATE QSharedPointer<X> qStrongRefFromWeakHelper + (const QT_PREPEND_NAMESPACE(QWeakPointer<T>) &src, X *) + { + QSharedPointer<X> result; + result.internalSet(src.d, src.value); + return result; + } +} + +// cast operators +template <class X, class T> +Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QSharedPointer<T> &src) +{ + X *x = 0; + QtSharedPointer::qVerifyStaticCast(src.data(), x); + return QtSharedPointer::qSharedPointerCastHelper(src, x); +} +template <class X, class T> +Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerCast(const QWeakPointer<T> &src) +{ + return qSharedPointerCast<X, T>(src.toStrongRef()); +} + +template <class X, class T> +Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QSharedPointer<T> &src) +{ + X *x = 0; + if (QtSharedPointer::qVerifyDynamicCast(src.data(), x)) + return QtSharedPointer::qSharedPointerCastHelper(src, x); + return QSharedPointer<X>(); +} +template <class X, class T> +Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerDynamicCast(const QWeakPointer<T> &src) +{ + return qSharedPointerDynamicCast<X, T>(src.toStrongRef()); +} + +template <class X, class T> +Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QSharedPointer<T> &src) +{ + X *x = 0; + if (QtSharedPointer::qVerifyConstCast(src.data(), x)) + return QtSharedPointer::qSharedPointerConstCastHelper(src, x); + return QSharedPointer<X>(); +} +template <class X, class T> +Q_INLINE_TEMPLATE QSharedPointer<X> qSharedPointerConstCast(const QWeakPointer<T> &src) +{ + X *x = 0; + if (QtSharedPointer::qVerifyConstCast(src.data(), x)) + return QtSharedPointer::qSharedPointerCastHelper(src, x); + return QSharedPointer<X>(); +} + +template <class X, class T> +Q_INLINE_TEMPLATE +QWeakPointer<X> qWeakPointerCast(const QSharedPointer<T> &src) +{ + return qSharedPointerCast<X, T>(src).toWeakRef(); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/corelib/tools/qsize.cpp b/src/corelib/tools/qsize.cpp new file mode 100644 index 0000000..76a5484 --- /dev/null +++ b/src/corelib/tools/qsize.cpp @@ -0,0 +1,824 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsize.h" +#include "qdatastream.h" +#include "qdebug.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QSize + \ingroup multimedia + + \brief The QSize class defines the size of a two-dimensional + object using integer point precision. + + A size is specified by a width() and a height(). It can be set in + the constructor and changed using the setWidth(), setHeight(), or + scale() functions, or using arithmetic operators. A size can also + be manipulated directly by retrieving references to the width and + height using the rwidth() and rheight() functions. Finally, the + width and height can be swapped using the transpose() function. + + The isValid() function determines if a size is valid (a valid size + has both width and height greater than zero). The isEmpty() + function returns true if either of the width and height is less + than, or equal to, zero, while the isNull() function returns true + only if both the width and the height is zero. + + Use the expandedTo() function to retrieve a size which holds the + maximum height and width of \e this size and a given + size. Similarly, the boundedTo() function returns a size which + holds the minimum height and width of \e this size and a given + size. + + QSize objects can be streamed as well as compared. + + \sa QSizeF, QPoint, QRect +*/ + + +/***************************************************************************** + QSize member functions + *****************************************************************************/ + +/*! + \fn QSize::QSize() + + Constructs a size with an invalid width and height (i.e., isValid() + returns false). + + \sa isValid() +*/ + +/*! + \fn QSize::QSize(int width, int height) + + Constructs a size with the given \a width and \a height. + + \sa setWidth(), setHeight() +*/ + +/*! + \fn bool QSize::isNull() const + + Returns true if both the width and height is 0; otherwise returns + false. + + \sa isValid(), isEmpty() +*/ + +/*! + \fn bool QSize::isEmpty() const + + Returns true if either of the width and height is less than or + equal to 0; otherwise returns false. + + \sa isNull(), isValid() +*/ + +/*! + \fn bool QSize::isValid() const + + Returns true if both the width and height is equal to or greater + than 0; otherwise returns false. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn int QSize::width() const + + Returns the width. + + \sa height(), setWidth() +*/ + +/*! + \fn int QSize::height() const + + Returns the height. + + \sa width(), setHeight() +*/ + +/*! + \fn void QSize::setWidth(int width) + + Sets the width to the given \a width. + + \sa rwidth(), width(), setHeight() +*/ + +/*! + \fn void QSize::setHeight(int height) + + Sets the height to the given \a height. + + \sa rheight(), height(), setWidth() +*/ + +/*! + Swaps the width and height values. + + \sa setWidth(), setHeight() +*/ + +void QSize::transpose() +{ + int tmp = wd; + wd = ht; + ht = tmp; +} + +/*! + \fn void QSize::scale(int width, int height, Qt::AspectRatioMode mode) + + Scales the size to a rectangle with the given \a width and \a + height, according to the specified \a mode: + + \list + \i If \a mode is Qt::IgnoreAspectRatio, the size is set to (\a width, \a height). + \i If \a mode is Qt::KeepAspectRatio, the current size is scaled to a rectangle + as large as possible inside (\a width, \a height), preserving the aspect ratio. + \i If \a mode is Qt::KeepAspectRatioByExpanding, the current size is scaled to a rectangle + as small as possible outside (\a width, \a height), preserving the aspect ratio. + \endlist + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 0 + + \sa setWidth(), setHeight() +*/ + +/*! + \fn void QSize::scale(const QSize &size, Qt::AspectRatioMode mode) + \overload + + Scales the size to a rectangle with the given \a size, according to + the specified \a mode. +*/ +void QSize::scale(const QSize &s, Qt::AspectRatioMode mode) +{ + if (mode == Qt::IgnoreAspectRatio || wd == 0 || ht == 0) { + wd = s.wd; + ht = s.ht; + } else { + bool useHeight; + qint64 rw = qint64(s.ht) * qint64(wd) / qint64(ht); + + if (mode == Qt::KeepAspectRatio) { + useHeight = (rw <= s.wd); + } else { // mode == Qt::KeepAspectRatioByExpanding + useHeight = (rw >= s.wd); + } + + if (useHeight) { + wd = rw; + ht = s.ht; + } else { + ht = qint32(qint64(s.wd) * qint64(ht) / qint64(wd)); + wd = s.wd; + } + } +} + +/*! + \fn int &QSize::rwidth() + + Returns a reference to the width. + + Using a reference makes it possible to manipulate the width + directly. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 1 + + \sa rheight(), setWidth() +*/ + +/*! + \fn int &QSize::rheight() + + Returns a reference to the height. + + Using a reference makes it possible to manipulate the height + directly. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 2 + + \sa rwidth(), setHeight() +*/ + +/*! + \fn QSize &QSize::operator+=(const QSize &size) + + Adds the given \a size to \e this size, and returns a reference to + this size. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 3 +*/ + +/*! + \fn QSize &QSize::operator-=(const QSize &size) + + Subtracts the given \a size from \e this size, and returns a + reference to this size. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 4 +*/ + +/*! + \fn QSize &QSize::operator*=(qreal factor) + \overload + + Multiplies both the width and height by the given \a factor, and + returns a reference to the size. + + Note that the result is rounded to the nearest integer. + + \sa scale() +*/ + +/*! + \fn bool operator==(const QSize &s1, const QSize &s2) + \relates QSize + + Returns true if \a s1 and \a s2 are equal; otherwise returns false. +*/ + +/*! + \fn bool operator!=(const QSize &s1, const QSize &s2) + \relates QSize + + Returns true if \a s1 and \a s2 are different; otherwise returns false. +*/ + +/*! + \fn const QSize operator+(const QSize &s1, const QSize &s2) + \relates QSize + + Returns the sum of \a s1 and \a s2; each component is added separately. +*/ + +/*! + \fn const QSize operator-(const QSize &s1, const QSize &s2) + \relates QSize + + Returns \a s2 subtracted from \a s1; each component is subtracted + separately. +*/ + +/*! + \fn const QSize operator*(const QSize &size, qreal factor) + \relates QSize + + Multiplies the given \a size by the given \a factor, and returns + the result rounded to the nearest integer. + + \sa QSize::scale() +*/ + +/*! + \fn const QSize operator*(qreal factor, const QSize &size) + \overload + \relates QSize + + Multiplies the given \a size by the given \a factor, and returns + the result rounded to the nearest integer. +*/ + +/*! + \fn QSize &QSize::operator/=(qreal divisor) + \overload + + Divides both the width and height by the given \a divisor, and + returns a reference to the size. + + Note that the result is rounded to the nearest integer. + + \sa QSize::scale() +*/ + +/*! + \fn const QSize operator/(const QSize &size, qreal divisor) + \relates QSize + \overload + + Divides the given \a size by the given \a divisor, and returns the + result rounded to the nearest integer. + + \sa QSize::scale() +*/ + +/*! + \fn QSize QSize::expandedTo(const QSize & otherSize) const + + Returns a size holding the maximum width and height of this size + and the given \a otherSize. + + \sa boundedTo(), scale() +*/ + +/*! + \fn QSize QSize::boundedTo(const QSize & otherSize) const + + Returns a size holding the minimum width and height of this size + and the given \a otherSize. + + \sa expandedTo(), scale() +*/ + + + +/***************************************************************************** + QSize stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QSize &size) + \relates QSize + + Writes the given \a size to the given \a stream, and returns a + reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator<<(QDataStream &s, const QSize &sz) +{ + if (s.version() == 1) + s << (qint16)sz.width() << (qint16)sz.height(); + else + s << (qint32)sz.width() << (qint32)sz.height(); + return s; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QSize &size) + \relates QSize + + Reads a size from the given \a stream into the given \a size, and + returns a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator>>(QDataStream &s, QSize &sz) +{ + if (s.version() == 1) { + qint16 w, h; + s >> w; sz.rwidth() = w; + s >> h; sz.rheight() = h; + } + else { + qint32 w, h; + s >> w; sz.rwidth() = w; + s >> h; sz.rheight() = h; + } + return s; +} +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QSize &s) { + dbg.nospace() << "QSize(" << s.width() << ", " << s.height() << ')'; + return dbg.space(); +} +#endif + + + +/*! + \class QSizeF + \brief The QSizeF class defines the size of a two-dimensional object + using floating point precision. + + \ingroup multimedia + + A size is specified by a width() and a height(). It can be set in + the constructor and changed using the setWidth(), setHeight(), or + scale() functions, or using arithmetic operators. A size can also + be manipulated directly by retrieving references to the width and + height using the rwidth() and rheight() functions. Finally, the + width and height can be swapped using the transpose() function. + + The isValid() function determines if a size is valid. A valid size + has both width and height greater than or equal to zero. The + isEmpty() function returns true if either of the width and height + is \e less than (or equal to) zero, while the isNull() function + returns true only if both the width and the height is zero. + + Use the expandedTo() function to retrieve a size which holds the + maximum height and width of this size and a given + size. Similarly, the boundedTo() function returns a size which + holds the minimum height and width of this size and a given size. + + The QSizeF class also provides the toSize() function returning a + QSize copy of this size, constructed by rounding the width and + height to the nearest integers. + + QSizeF objects can be streamed as well as compared. + + \sa QSize, QPointF, QRectF +*/ + + +/***************************************************************************** + QSizeF member functions + *****************************************************************************/ + +/*! + \fn QSizeF::QSizeF() + + Constructs an invalid size. + + \sa isValid() +*/ + +/*! + \fn QSizeF::QSizeF(const QSize &size) + + Constructs a size with floating point accuracy from the given \a + size. + + \sa toSize() +*/ + +/*! + \fn QSizeF::QSizeF(qreal width, qreal height) + + Constructs a size with the given \a width and \a height. +*/ + +/*! + \fn bool QSizeF::isNull() const + + Returns true if both the width and height is 0; otherwise returns + false. + + \sa isValid(), isEmpty() +*/ + +/*! + \fn bool QSizeF::isEmpty() const + + Returns true if either of the width and height is less than or + equal to 0; otherwise returns false. + + \sa isNull(), isValid() +*/ + +/*! + \fn bool QSizeF::isValid() const + + Returns true if both the width and height is equal to or greater + than 0; otherwise returns false. + + \sa isNull(), isEmpty() +*/ + +/*! + \fn int QSizeF::width() const + + Returns the width. + + \sa height(), setWidth() +*/ + +/*! + \fn int QSizeF::height() const + + Returns the height. + + \sa width(), setHeight() +*/ + +/*! + \fn void QSizeF::setWidth(qreal width) + + Sets the width to the given \a width. + + \sa width(), rwidth(), setHeight() +*/ + +/*! + \fn void QSizeF::setHeight(qreal height) + + Sets the height to the given \a height. + + \sa height(), rheight(), setWidth() +*/ + +/*! + \fn QSize QSizeF::toSize() const + + Returns an integer based copy of this size. + + Note that the coordinates in the returned size will be rounded to + the nearest integer. + + \sa QSizeF() +*/ + +/*! + Swaps the width and height values. + + \sa setWidth(), setHeight() +*/ + +void QSizeF::transpose() +{ + qreal tmp = wd; + wd = ht; + ht = tmp; +} + +/*! + \fn void QSizeF::scale(qreal width, qreal height, Qt::AspectRatioMode mode) + + Scales the size to a rectangle with the given \a width and \a + height, according to the specified \a mode. + + \list + \i If \a mode is Qt::IgnoreAspectRatio, the size is set to (\a width, \a height). + \i If \a mode is Qt::KeepAspectRatio, the current size is scaled to a rectangle + as large as possible inside (\a width, \a height), preserving the aspect ratio. + \i If \a mode is Qt::KeepAspectRatioByExpanding, the current size is scaled to a rectangle + as small as possible outside (\a width, \a height), preserving the aspect ratio. + \endlist + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 5 + + \sa setWidth(), setHeight() +*/ + +/*! + \fn void QSizeF::scale(const QSizeF &size, Qt::AspectRatioMode mode) + \overload + + Scales the size to a rectangle with the given \a size, according to + the specified \a mode. +*/ +void QSizeF::scale(const QSizeF &s, Qt::AspectRatioMode mode) +{ + if (mode == Qt::IgnoreAspectRatio || qIsNull(wd) || qIsNull(ht)) { + wd = s.wd; + ht = s.ht; + } else { + bool useHeight; + qreal rw = s.ht * wd / ht; + + if (mode == Qt::KeepAspectRatio) { + useHeight = (rw <= s.wd); + } else { // mode == Qt::KeepAspectRatioByExpanding + useHeight = (rw >= s.wd); + } + + if (useHeight) { + wd = rw; + ht = s.ht; + } else { + ht = s.wd * ht / wd; + wd = s.wd; + } + } +} + +/*! + \fn int &QSizeF::rwidth() + + Returns a reference to the width. + + Using a reference makes it possible to manipulate the width + directly. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 6 + + \sa rheight(), setWidth() +*/ + +/*! + \fn int &QSizeF::rheight() + + Returns a reference to the height. + + Using a reference makes it possible to manipulate the height + directly. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 7 + + \sa rwidth(), setHeight() +*/ + +/*! + \fn QSizeF &QSizeF::operator+=(const QSizeF &size) + + Adds the given \a size to this size and returns a reference to + this size. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 8 +*/ + +/*! + \fn QSizeF &QSizeF::operator-=(const QSizeF &size) + + Subtracts the given \a size from this size and returns a reference + to this size. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qsize.cpp 9 +*/ + +/*! + \fn QSizeF &QSizeF::operator*=(qreal factor) + \overload + + Multiplies both the width and height by the given \a factor and + returns a reference to the size. + + \sa scale() +*/ + +/*! + \fn bool operator==(const QSizeF &s1, const QSizeF &s2) + \relates QSizeF + + Returns true if \a s1 and \a s2 are equal; otherwise returns + false. +*/ + +/*! + \fn bool operator!=(const QSizeF &s1, const QSizeF &s2) + \relates QSizeF + + Returns true if \a s1 and \a s2 are different; otherwise returns false. +*/ + +/*! + \fn const QSizeF operator+(const QSizeF &s1, const QSizeF &s2) + \relates QSizeF + + Returns the sum of \a s1 and \a s2; each component is added separately. +*/ + +/*! + \fn const QSizeF operator-(const QSizeF &s1, const QSizeF &s2) + \relates QSizeF + + Returns \a s2 subtracted from \a s1; each component is subtracted + separately. +*/ + +/*! + \fn const QSizeF operator*(const QSizeF &size, qreal factor) + + \overload + \relates QSizeF + + Multiplies the given \a size by the given \a factor and returns + the result. + + \sa QSizeF::scale() +*/ + +/*! + \fn const QSizeF operator*(qreal factor, const QSizeF &size) + + \overload + \relates QSizeF + + Multiplies the given \a size by the given \a factor and returns + the result. +*/ + +/*! + \fn QSizeF &QSizeF::operator/=(qreal divisor) + + \overload + + Divides both the width and height by the given \a divisor and + returns a reference to the size. + + \sa scale() +*/ + +/*! + \fn const QSizeF operator/(const QSizeF &size, qreal divisor) + + \relates QSizeF + \overload + + Divides the given \a size by the given \a divisor and returns the + result. + + \sa QSizeF::scale() +*/ + +/*! + \fn QSizeF QSizeF::expandedTo(const QSizeF & otherSize) const + + Returns a size holding the maximum width and height of this size + and the given \a otherSize. + + \sa boundedTo(), scale() +*/ + +/*! + \fn QSizeF QSizeF::boundedTo(const QSizeF & otherSize) const + + Returns a size holding the minimum width and height of this size + and the given \a otherSize. + + \sa expandedTo(), scale() +*/ + + + +/***************************************************************************** + QSizeF stream functions + *****************************************************************************/ +#ifndef QT_NO_DATASTREAM +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QSizeF &size) + \relates QSizeF + + Writes the the given \a size to the given \a stream and returns a + reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator<<(QDataStream &s, const QSizeF &sz) +{ + s << double(sz.width()) << double(sz.height()); + return s; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QSizeF &size) + \relates QSizeF + + Reads a size from the given \a stream into the given \a size and + returns a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator>>(QDataStream &s, QSizeF &sz) +{ + double w, h; + s >> w; + s >> h; + sz.setWidth(qreal(w)); + sz.setHeight(qreal(h)); + return s; +} +#endif // QT_NO_DATASTREAM + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QSizeF &s) { + dbg.nospace() << "QSizeF(" << s.width() << ", " << s.height() << ')'; + return dbg.space(); +} +#endif + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qsize.h b/src/corelib/tools/qsize.h new file mode 100644 index 0000000..57c55ca --- /dev/null +++ b/src/corelib/tools/qsize.h @@ -0,0 +1,364 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSIZE_H +#define QSIZE_H + +#include <QtCore/qnamespace.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class Q_CORE_EXPORT QSize +{ +public: + QSize(); + QSize(int w, int h); + + bool isNull() const; + bool isEmpty() const; + bool isValid() const; + + int width() const; + int height() const; + void setWidth(int w); + void setHeight(int h); + void transpose(); + + void scale(int w, int h, Qt::AspectRatioMode mode); + void scale(const QSize &s, Qt::AspectRatioMode mode); + + QSize expandedTo(const QSize &) const; + QSize boundedTo(const QSize &) const; + + int &rwidth(); + int &rheight(); + + QSize &operator+=(const QSize &); + QSize &operator-=(const QSize &); + QSize &operator*=(qreal c); + QSize &operator/=(qreal c); + + friend inline bool operator==(const QSize &, const QSize &); + friend inline bool operator!=(const QSize &, const QSize &); + friend inline const QSize operator+(const QSize &, const QSize &); + friend inline const QSize operator-(const QSize &, const QSize &); + friend inline const QSize operator*(const QSize &, qreal); + friend inline const QSize operator*(qreal, const QSize &); + friend inline const QSize operator/(const QSize &, qreal); + +private: + int wd; + int ht; +}; +Q_DECLARE_TYPEINFO(QSize, Q_MOVABLE_TYPE); + +/***************************************************************************** + QSize stream functions + *****************************************************************************/ + +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QSize &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QSize &); + + +/***************************************************************************** + QSize inline functions + *****************************************************************************/ + +inline QSize::QSize() +{ wd = ht = -1; } + +inline QSize::QSize(int w, int h) +{ wd = w; ht = h; } + +inline bool QSize::isNull() const +{ return wd==0 && ht==0; } + +inline bool QSize::isEmpty() const +{ return wd<1 || ht<1; } + +inline bool QSize::isValid() const +{ return wd>=0 && ht>=0; } + +inline int QSize::width() const +{ return wd; } + +inline int QSize::height() const +{ return ht; } + +inline void QSize::setWidth(int w) +{ wd = w; } + +inline void QSize::setHeight(int h) +{ ht = h; } + +inline void QSize::scale(int w, int h, Qt::AspectRatioMode mode) +{ scale(QSize(w, h), mode); } + +inline int &QSize::rwidth() +{ return wd; } + +inline int &QSize::rheight() +{ return ht; } + +inline QSize &QSize::operator+=(const QSize &s) +{ wd+=s.wd; ht+=s.ht; return *this; } + +inline QSize &QSize::operator-=(const QSize &s) +{ wd-=s.wd; ht-=s.ht; return *this; } + +inline QSize &QSize::operator*=(qreal c) +{ wd = qRound(wd*c); ht = qRound(ht*c); return *this; } + +inline bool operator==(const QSize &s1, const QSize &s2) +{ return s1.wd == s2.wd && s1.ht == s2.ht; } + +inline bool operator!=(const QSize &s1, const QSize &s2) +{ return s1.wd != s2.wd || s1.ht != s2.ht; } + +inline const QSize operator+(const QSize & s1, const QSize & s2) +{ return QSize(s1.wd+s2.wd, s1.ht+s2.ht); } + +inline const QSize operator-(const QSize &s1, const QSize &s2) +{ return QSize(s1.wd-s2.wd, s1.ht-s2.ht); } + +inline const QSize operator*(const QSize &s, qreal c) +{ return QSize(qRound(s.wd*c), qRound(s.ht*c)); } + +inline const QSize operator*(qreal c, const QSize &s) +{ return QSize(qRound(s.wd*c), qRound(s.ht*c)); } + +inline QSize &QSize::operator/=(qreal c) +{ + Q_ASSERT(!qFuzzyCompare(c + 1, 1)); + wd = qRound(wd/c); ht = qRound(ht/c); + return *this; +} + +inline const QSize operator/(const QSize &s, qreal c) +{ + Q_ASSERT(!qFuzzyCompare(c + 1, 1)); + return QSize(qRound(s.wd/c), qRound(s.ht/c)); +} + +inline QSize QSize::expandedTo(const QSize & otherSize) const +{ + return QSize(qMax(wd,otherSize.wd), qMax(ht,otherSize.ht)); +} + +inline QSize QSize::boundedTo(const QSize & otherSize) const +{ + return QSize(qMin(wd,otherSize.wd), qMin(ht,otherSize.ht)); +} + +#ifndef QT_NO_DEBUG_STREAM +Q_CORE_EXPORT QDebug operator<<(QDebug, const QSize &); +#endif + + +class Q_CORE_EXPORT QSizeF +{ +public: + QSizeF(); + QSizeF(const QSize &sz); + QSizeF(qreal w, qreal h); + + bool isNull() const; + bool isEmpty() const; + bool isValid() const; + + qreal width() const; + qreal height() const; + void setWidth(qreal w); + void setHeight(qreal h); + void transpose(); + + void scale(qreal w, qreal h, Qt::AspectRatioMode mode); + void scale(const QSizeF &s, Qt::AspectRatioMode mode); + + QSizeF expandedTo(const QSizeF &) const; + QSizeF boundedTo(const QSizeF &) const; + + qreal &rwidth(); + qreal &rheight(); + + QSizeF &operator+=(const QSizeF &); + QSizeF &operator-=(const QSizeF &); + QSizeF &operator*=(qreal c); + QSizeF &operator/=(qreal c); + + friend inline bool operator==(const QSizeF &, const QSizeF &); + friend inline bool operator!=(const QSizeF &, const QSizeF &); + friend inline const QSizeF operator+(const QSizeF &, const QSizeF &); + friend inline const QSizeF operator-(const QSizeF &, const QSizeF &); + friend inline const QSizeF operator*(const QSizeF &, qreal); + friend inline const QSizeF operator*(qreal, const QSizeF &); + friend inline const QSizeF operator/(const QSizeF &, qreal); + + inline QSize toSize() const; + +private: + qreal wd; + qreal ht; +}; +Q_DECLARE_TYPEINFO(QSizeF, Q_MOVABLE_TYPE); + + +/***************************************************************************** + QSizeF stream functions + *****************************************************************************/ + +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QSizeF &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QSizeF &); + + +/***************************************************************************** + QSizeF inline functions + *****************************************************************************/ + +inline QSizeF::QSizeF() +{ wd = ht = -1.; } + +inline QSizeF::QSizeF(const QSize &sz) + : wd(sz.width()), ht(sz.height()) +{ +} + +inline QSizeF::QSizeF(qreal w, qreal h) +{ wd = w; ht = h; } + +inline bool QSizeF::isNull() const +{ return qIsNull(wd) && qIsNull(ht); } + +inline bool QSizeF::isEmpty() const +{ return wd <= 0. || ht <= 0.; } + +inline bool QSizeF::isValid() const +{ return wd >= 0. && ht >= 0.; } + +inline qreal QSizeF::width() const +{ return wd; } + +inline qreal QSizeF::height() const +{ return ht; } + +inline void QSizeF::setWidth(qreal w) +{ wd = w; } + +inline void QSizeF::setHeight(qreal h) +{ ht = h; } + +inline void QSizeF::scale(qreal w, qreal h, Qt::AspectRatioMode mode) +{ scale(QSizeF(w, h), mode); } + +inline qreal &QSizeF::rwidth() +{ return wd; } + +inline qreal &QSizeF::rheight() +{ return ht; } + +inline QSizeF &QSizeF::operator+=(const QSizeF &s) +{ wd += s.wd; ht += s.ht; return *this; } + +inline QSizeF &QSizeF::operator-=(const QSizeF &s) +{ wd -= s.wd; ht -= s.ht; return *this; } + +inline QSizeF &QSizeF::operator*=(qreal c) +{ wd *= c; ht *= c; return *this; } + +inline bool operator==(const QSizeF &s1, const QSizeF &s2) +{ return qFuzzyCompare(s1.wd, s2.wd) && qFuzzyCompare(s1.ht, s2.ht); } + +inline bool operator!=(const QSizeF &s1, const QSizeF &s2) +{ return !qFuzzyCompare(s1.wd, s2.wd) || !qFuzzyCompare(s1.ht, s2.ht); } + +inline const QSizeF operator+(const QSizeF & s1, const QSizeF & s2) +{ return QSizeF(s1.wd+s2.wd, s1.ht+s2.ht); } + +inline const QSizeF operator-(const QSizeF &s1, const QSizeF &s2) +{ return QSizeF(s1.wd-s2.wd, s1.ht-s2.ht); } + +inline const QSizeF operator*(const QSizeF &s, qreal c) +{ return QSizeF(s.wd*c, s.ht*c); } + +inline const QSizeF operator*(qreal c, const QSizeF &s) +{ return QSizeF(s.wd*c, s.ht*c); } + +inline QSizeF &QSizeF::operator/=(qreal c) +{ + Q_ASSERT(!qFuzzyCompare(c + 1, 1)); + wd = wd/c; ht = ht/c; + return *this; +} + +inline const QSizeF operator/(const QSizeF &s, qreal c) +{ + Q_ASSERT(!qFuzzyCompare(c + 1, 1)); + return QSizeF(s.wd/c, s.ht/c); +} + +inline QSizeF QSizeF::expandedTo(const QSizeF & otherSize) const +{ + return QSizeF(qMax(wd,otherSize.wd), qMax(ht,otherSize.ht)); +} + +inline QSizeF QSizeF::boundedTo(const QSizeF & otherSize) const +{ + return QSizeF(qMin(wd,otherSize.wd), qMin(ht,otherSize.ht)); +} + +inline QSize QSizeF::toSize() const +{ + return QSize(qRound(wd), qRound(ht)); +} + +#ifndef QT_NO_DEBUG_STREAM +Q_CORE_EXPORT QDebug operator<<(QDebug, const QSizeF &); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSIZE_H diff --git a/src/corelib/tools/qstack.cpp b/src/corelib/tools/qstack.cpp new file mode 100644 index 0000000..9fdaf0d --- /dev/null +++ b/src/corelib/tools/qstack.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QStack + \brief The QStack class is a template class that provides a stack. + + \ingroup tools + \ingroup shared + \mainclass + \reentrant + + QStack\<T\> is one of Qt's generic \l{container classes}. It implements + a stack data structure for items of a same type. + + A stack is a last in, first out (LIFO) structure. Items are added + to the top of the stack using push() and retrieved from the top + using pop(). The top() function provides access to the topmost + item without removing it. + + Example: + + \snippet doc/src/snippets/qstack/main.cpp 0 + + The example will output 3, 2, 1 in that order. + + QStack inherits from QVector. All of QVector's functionality also + applies to QStack. For example, you can use isEmpty() to test + whether the stack is empty, and you can traverse a QStack using + QVector's iterator classes (for example, QVectorIterator). But in + addition, QStack provides three convenience functions that make + it easy to implement LIFO semantics: push(), pop(), and top(). + + QStack's value type must be an \l{assignable data type}. This + covers most data types that are commonly used, but the compiler + won't let you, for example, store a QWidget as a value; instead, + store a QWidget *. + + \sa QVector, QQueue +*/ + +/*! + \fn QStack::QStack() + + Constructs an empty stack. +*/ + +/*! + \fn QStack::~QStack() + + Destroys the stack. References to the values in the stack, and all + iterators over this stack, become invalid. +*/ + +/*! + \fn void QStack::push(const T& t) + + Adds element \a t to the top of the stack. + + This is the same as QVector::append(). + + \sa pop(), top() +*/ + +/*! + \fn T& QStack::top() + + Returns a reference to the stack's top item. This function + assumes that the stack isn't empty. + + This is the same as QVector::last(). + + \sa pop(), push(), isEmpty() +*/ + +/*! + \fn const T& QStack::top() const + + \overload + + \sa pop(), push() +*/ + +/*! + \fn T QStack::pop() + + Removes the top item from the stack and returns it. This function + assumes that the stack isn't empty. + + \sa top(), push(), isEmpty() +*/ diff --git a/src/corelib/tools/qstack.h b/src/corelib/tools/qstack.h new file mode 100644 index 0000000..f55b53d --- /dev/null +++ b/src/corelib/tools/qstack.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTACK_H +#define QSTACK_H + +#include <QtCore/qvector.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +template<class T> +class QStack : public QVector<T> +{ +public: + inline QStack() {} + inline ~QStack() {} + inline void push(const T &t) { QVector<T>::append(t); } + T pop(); + T &top(); + const T &top() const; +}; + +template<class T> +inline T QStack<T>::pop() +{ Q_ASSERT(!this->isEmpty()); T t = this->data()[this->size() -1]; + this->resize(this->size()-1); return t; } + +template<class T> +inline T &QStack<T>::top() +{ Q_ASSERT(!this->isEmpty()); this->detach(); return this->data()[this->size()-1]; } + +template<class T> +inline const T &QStack<T>::top() const +{ Q_ASSERT(!this->isEmpty()); return this->data()[this->size()-1]; } + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSTACK_H diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp new file mode 100644 index 0000000..1b29adc --- /dev/null +++ b/src/corelib/tools/qstring.cpp @@ -0,0 +1,8083 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstringlist.h" +#include "qregexp.h" +#include "qunicodetables_p.h" +#ifndef QT_NO_TEXTCODEC +#include <qtextcodec.h> +#endif +#include <qdatastream.h> +#include <qlist.h> +#include "qlocale.h" +#include "qlocale_p.h" +#include "qstringmatcher.h" +#include "qvarlengtharray.h" +#include "qtools_p.h" +#include "qhash.h" +#include "qdebug.h" + +#ifdef Q_OS_MAC +#include <private/qcore_mac_p.h> +#endif + +#include <private/qfunctions_p.h> + +#if defined(Q_OS_WINCE) +#include <windows.h> +#include <winnls.h> +#endif + +#include <limits.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> + +#ifdef truncate +#undef truncate +#endif + +#include "qchar.cpp" +#include "qstringmatcher.cpp" + +#ifndef LLONG_MAX +#define LLONG_MAX qint64_C(9223372036854775807) +#endif +#ifndef LLONG_MIN +#define LLONG_MIN (-LLONG_MAX - qint64_C(1)) +#endif +#ifndef ULLONG_MAX +#define ULLONG_MAX quint64_C(18446744073709551615) +#endif + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_TEXTCODEC +QTextCodec *QString::codecForCStrings; +#endif + +#ifdef QT3_SUPPORT +static QHash<void *, QByteArray> *asciiCache = 0; +#endif + +// internal +int qFindString(const QChar *haystack, int haystackLen, int from, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs); +int qFindStringBoyerMoore(const QChar *haystack, int haystackLen, int from, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs); + + +// Unicode case-insensitive comparison +static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const ushort *be) +{ + if (a == b) + return 0; + if (a == 0) + return 1; + if (b == 0) + return -1; + + const ushort *e = ae; + if (be - b < ae - a) + e = a + (be - b); + + uint alast = 0; + uint blast = 0; + while (a != e) { +// qDebug() << hex << alast << blast; +// qDebug() << hex << "*a=" << *a << "alast=" << alast << "folded=" << foldCase (*a, alast); +// qDebug() << hex << "*b=" << *b << "blast=" << blast << "folded=" << foldCase (*b, blast); + int diff = foldCase(*a, alast) - foldCase(*b, blast); + if ((diff)) + return diff; + ++a; + ++b; + } + if (a == ae) { + if (b == be) + return 0; + return -1; + } + return 1; +} + +// Case-insensitive comparison between a Unicode string and a QLatin1String +static int ucstricmp(const ushort *a, const ushort *ae, const uchar *b) +{ + if (a == 0) { + if (b == 0) + return 0; + return 1; + } + if (b == 0) + return -1; + + while (a != ae && *b) { + int diff = foldCase(*a) - foldCase(*b); + if ((diff)) + return diff; + ++a; + ++b; + } + if (a == ae) { + if (!*b) + return 0; + return -1; + } + return 1; +} + +// Unicode case-insensitive comparison +static int ucstrcmp(const QChar *a, int alen, const QChar *b, int blen) +{ + if (a == b) + return 0; + int l = qMin(alen, blen); + while (l-- && *a == *b) + a++,b++; + if (l == -1) + return (alen-blen); + return a->unicode() - b->unicode(); +} + +// Unicode case-sensitive compare two same-sized strings +static int ucstrncmp(const QChar *a, const QChar *b, int l) +{ + while (l-- && *a == *b) + a++,b++; + if (l==-1) + return 0; + return a->unicode() - b->unicode(); +} + +// Unicode case-insensitive compare two same-sized strings +static int ucstrnicmp(const ushort *a, const ushort *b, int l) +{ + return ucstricmp(a, a + l, b, b + l); +} + + +/*! + \internal + + Returns the index position of the first occurrence of the + character \a ch in the string given by \a str and \a len, + searching forward from index + position \a from. Returns -1 if \a ch could not be found. +*/ +static int findChar(const QChar *str, int len, QChar ch, int from, + Qt::CaseSensitivity cs) +{ + const ushort *s = (const ushort *)str; + ushort c = ch.unicode(); + if (from < 0) + from = qMax(from + len, 0); + if (from < len) { + const ushort *n = s + from - 1; + const ushort *e = s + len; + if (cs == Qt::CaseSensitive) { + while (++n != e) + if (*n == c) + return n - s; + } else { + c = foldCase(c); + while (++n != e) + if (foldCase(*n) == c) + return n - s; + } + } + return -1; +} + +#define REHASH(a) \ + if (sl_minus_1 < (int)sizeof(int) * CHAR_BIT) \ + hashHaystack -= (a) << sl_minus_1; \ + hashHaystack <<= 1 + +inline bool qIsUpper(char ch) +{ + return ch >= 'A' && ch <= 'Z'; +} + +inline bool qIsDigit(char ch) +{ + return ch >= '0' && ch <= '9'; +} + +inline char qToLower(char ch) +{ + if (ch >= 'A' && ch <= 'Z') + return ch - 'A' + 'a'; + else + return ch; +} + +#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 +const QString::Null QString::null; +#else +const QString::Null QString::null = { }; +#endif + +/*! + \macro QT_NO_CAST_FROM_ASCII + \relates QString + + Disables automatic conversions from 8-bit strings (char *) to unicode QStrings + + \sa QT_NO_CAST_TO_ASCII, QT_NO_CAST_FROM_BYTEARRAY +*/ + +/*! + \macro QT_NO_CAST_TO_ASCII + \relates QString + + disables automatic conversion from QString to ASCII 8-bit strings (char *) + + \sa QT_NO_CAST_FROM_ASCII, QT_NO_CAST_FROM_BYTEARRAY +*/ + +/*! + \macro QT_ASCII_CAST_WARNINGS + \internal + \relates QString + + This macro can be defined to force a warning whenever a function is + called that automatically converts between unicode and 8-bit encodings. + + Note: This only works for compilers that support warnings for + deprecated API. + + \sa QT_NO_CAST_TO_ASCII, QT_NO_CAST_FROM_ASCII +*/ + +/*! + \class QCharRef + \reentrant + \brief The QCharRef class is a helper class for QString. + + \internal + + \ingroup text + + When you get an object of type QCharRef, if you can assign to it, + the assignment will apply to the character in the string from + which you got the reference. That is its whole purpose in life. + The QCharRef becomes invalid once modifications are made to the + string: if you want to keep the character, copy it into a QChar. + + Most of the QChar member functions also exist in QCharRef. + However, they are not explicitly documented here. + + \sa QString::operator[]() QString::at() QChar +*/ + +/*! + \class QString + \reentrant + + \brief The QString class provides a Unicode character string. + + \ingroup tools + \ingroup shared + \ingroup text + \mainclass + + QString stores a string of 16-bit \l{QChar}s, where each QChar + corresponds one Unicode 4.0 character. (Unicode characters + with code values above 65535 are stored using surrogate pairs, + i.e., two consecutive \l{QChar}s.) + + \l{Unicode} is an international standard that supports most of + the writing systems in use today. It is a superset of ASCII and + Latin-1 (ISO 8859-1), and all the ASCII/Latin-1 characters are + available at the same code positions. + + Behind the scenes, QString uses \l{implicit sharing} + (copy-on-write) to reduce memory usage and to avoid the needless + copying of data. This also helps reduce the inherent overhead of + storing 16-bit characters instead of 8-bit characters. + + In addition to QString, Qt also provides the QByteArray class to + store raw bytes and traditional 8-bit '\\0'-terminated strings. + For most purposes, QString is the class you want to use. It is + used throughout the Qt API, and the Unicode support ensures that + your applications will be easy to translate if you want to expand + your application's market at some point. The two main cases where + QByteArray is appropriate are when you need to store raw binary + data, and when memory conservation is critical (e.g., with + \l{Qt for Embedded Linux}). + + \tableofcontents + + \section1 Initializing a String + + One way to initialize a QString is simply to pass a \c{const char + *} to its constructor. For example, the following code creates a + QString of size 5 containing the data "Hello": + + \snippet doc/src/snippets/qstring/main.cpp 0 + + QString converts the \c{const char *} data into Unicode using the + fromAscii() function. By default, fromAscii() treats character + above 128 as Latin-1 characters, but this can be changed by + calling QTextCodec::setCodecForCStrings(). + + In all of the QString functions that take \c{const char *} + parameters, the \c{const char *} is interpreted as a classic + C-style '\\0'-terminated string. It is legal for the \c{const char + *} parameter to be 0. + + You can also provide string data as an array of \l{QChar}s: + + \snippet doc/src/snippets/qstring/main.cpp 1 + + QString makes a deep copy of the QChar data, so you can modify it + later without experiencing side effects. (If for performance + reasons you don't want to take a deep copy of the character data, + use QString::fromRawData() instead.) + + Another approach is to set the size of the string using resize() + and to initialize the data character per character. QString uses + 0-based indexes, just like C++ arrays. To access the character at + a particular index position, you can use \l operator[](). On + non-const strings, \l operator[]() returns a reference to a + character that can be used on the left side of an assignment. For + example: + + \snippet doc/src/snippets/qstring/main.cpp 2 + + For read-only access, an alternative syntax is to use the at() + function: + + \snippet doc/src/snippets/qstring/main.cpp 3 + + The at() function can be faster than \l operator[](), because it + never causes a \l{deep copy} to occur. Alternatively, use the + left(), right(), or mid() functions to extract several characters + at a time. + + A QString can embed '\\0' characters (QChar::Null). The size() + function always returns the size of the whole string, including + embedded '\\0' characters. + + After a call to the resize() function, newly allocated characters + have undefined values. To set all the characters in the string to + a particular value, use the fill() function. + + QString provides dozens of overloads designed to simplify string + usage. For example, if you want to compare a QString with a string + literal, you can write code like this and it will work as expected: + + \snippet doc/src/snippets/qstring/main.cpp 4 + + You can also pass string literals to functions that take QStrings + as arguments, invoking the QString(const char *) + constructor. Similarly, you can pass a QString to a function that + takes a \c{const char *} argument using the \l qPrintable() macro + which returns the given QString as a \c{const char *}. This is + equivalent to calling <QString>.toLocal8Bit().constData(). + + \section1 Manipulating String Data + + QString provides the following basic functions for modifying the + character data: append(), prepend(), insert(), replace(), and + remove(). For example: + + \snippet doc/src/snippets/qstring/main.cpp 5 + + If you are building a QString gradually and know in advance + approximately how many characters the QString will contain, you + can call reserve(), asking QString to preallocate a certain amount + of memory. You can also call capacity() to find out how much + memory QString actually allocated. + + The replace() and remove() functions' first two arguments are the + position from which to start erasing and the number of characters + that should be erased. If you want to replace all occurrences of + a particular substring with another, use one of the two-parameter + replace() overloads. + + A frequent requirement is to remove whitespace characters from a + string ('\\n', '\\t', ' ', etc.). If you want to remove whitespace + from both ends of a QString, use the trimmed() function. If you + want to remove whitespace from both ends and replace multiple + consecutive whitespaces with a single space character within the + string, use simplified(). + + If you want to find all occurrences of a particular character or + substring in a QString, use the indexOf() or lastIndexOf() + functions. The former searches forward starting from a given index + position, the latter searches backward. Both return the index + position of the character or substring if they find it; otherwise, + they return -1. For example, here's a typical loop that finds all + occurrences of a particular substring: + + \snippet doc/src/snippets/qstring/main.cpp 6 + + QString provides many functions for converting numbers into + strings and strings into numbers. See the arg() functions, the + setNum() functions, the number() static functions, and the + toInt(), toDouble(), and similar functions. + + To get an upper- or lowercase version of a string use toUpper() or + toLower(). + + Lists of strings are handled by the QStringList class. You can + split a string into a list of strings using the split() function, + and join a list of strings into a single string with an optional + separator using QStringList::join(). You can obtain a list of + strings from a string list that contain a particular substring or + that match a particular QRegExp using the QStringList::find() + function. +: + \section1 Querying String Data + + If you want to see if a QString starts or ends with a particular + substring use startsWith() or endsWith(). If you simply want to + check whether a QString contains a particular character or + substring, use the contains() function. If you want to find out + how many times a particular character or substring occurs in the + string, use count(). + + QStrings can be compared using overloaded operators such as \l + operator<(), \l operator<=(), \l operator==(), \l operator>=(), + and so on. Note that the comparison is based exclusively on the + numeric Unicode values of the characters. It is very fast, but is + not what a human would expect; the QString::localeAwareCompare() + function is a better choice for sorting user-interface strings. + + To obtain a pointer to the actual character data, call data() or + constData(). These functions return a pointer to the beginning of + the QChar data. The pointer is guaranteed to remain valid until a + non-const function is called on the QString. + + \section1 Converting Between 8-Bit Strings and Unicode Strings + + QString provides the following four functions that return a + \c{const char *} version of the string as QByteArray: toAscii(), + toLatin1(), toUtf8(), and toLocal8Bit(). + + \list + \o toAscii() returns an ASCII encoded 8-bit string. + \o toLatin1() returns a Latin-1 (ISO 8859-1) encoded 8-bit string. + \o toUtf8() returns a UTF-8 encoded 8-bit string. UTF-8 is a + superset of ASCII that supports the entire Unicode character + set through multibyte sequences. + \o toLocal8Bit() returns an 8-bit string using the system's local + encoding. + \endlist + + To convert from one of these encodings, QString provides + fromAscii(), fromLatin1(), fromUtf8(), and fromLocal8Bit(). Other + encodings are supported through the QTextCodec class. + + As mentioned above, QString provides a lot of functions and + operators that make it easy to interoperate with \c{const char *} + strings. But this functionality is a double-edged sword: It makes + QString more convenient to use if all strings are ASCII or + Latin-1, but there is always the risk that an implicit conversion + from or to \c{const char *} is done using the wrong 8-bit + encoding. To minimize these risks, you can turn off these implicit + conversions by defining the following two preprocessor symbols: + + \list + \o \c QT_NO_CAST_FROM_ASCII disables automatic conversions from + ASCII to Unicode. + \o \c QT_NO_CAST_TO_ASCII disables automatic conversion from QString + to ASCII. + \endlist + + One way to define these preprocessor symbols globally for your + application is to add the following entry to your + \l{qmake Project Files}{qmake project file}: + + \snippet doc/src/snippets/code/src_corelib_tools_qstring.cpp 0 + + You then need to explicitly call fromAscii(), fromLatin1(), + fromUtf8(), or fromLocal8Bit() to construct a QString from an + 8-bit string, or use the lightweight QLatin1String class, for + example: + + \snippet doc/src/snippets/code/src_corelib_tools_qstring.cpp 1 + + Similarly, you must call toAscii(), toLatin1(), toUtf8(), or + toLocal8Bit() explicitly to convert the QString to an 8-bit + string. (Other encodings are supported through the QTextCodec + class.) + + \table 100 % + \row + \o + \section1 Note for C Programmers + + Due to C++'s type system and the fact that QString is + \l{implicitly shared}, QStrings may be treated like \c{int}s or + other basic types. For example: + + \snippet doc/src/snippets/qstring/main.cpp 7 + + The \c result variable, is a normal variable allocated on the + stack. When \c return is called, and because we're returning by + value, the copy constructor is called and a copy of the string is + returned. No actual copying takes place thanks to the implicit + sharing. + + \endtable + + \section1 Distinction Between Null and Empty Strings + + For historical reasons, QString distinguishes between a null + string and an empty string. A \e null string is a string that is + initialized using QString's default constructor or by passing + (const char *)0 to the constructor. An \e empty string is any + string with size 0. A null string is always empty, but an empty + string isn't necessarily null: + + \snippet doc/src/snippets/qstring/main.cpp 8 + + All functions except isNull() treat null strings the same as empty + strings. For example, toAscii().constData() returns a pointer to a + '\\0' character for a null string (\e not a null pointer), and + QString() compares equal to QString(""). We recommend that you + always use the isEmpty() function and avoid isNull(). + + \section1 Argument Formats + + In member functions where an argument \e format can be specified + (e.g., arg(), number()), the argument \e format can be one of the + following: + + \table + \header \o Format \o Meaning + \row \o \c e \o format as [-]9.9e[+|-]999 + \row \o \c E \o format as [-]9.9E[+|-]999 + \row \o \c f \o format as [-]9.9 + \row \o \c g \o use \c e or \c f format, whichever is the most concise + \row \o \c G \o use \c E or \c f format, whichever is the most concise + \endtable + + A \e precision is also specified with the argument \e format. For + the 'e', 'E', and 'f' formats, the \e precision represents the + number of digits \e after the decimal point. For the 'g' and 'G' + formats, the \e precision represents the maximum number of + significant digits (trailing zeroes are omitted). + + \sa fromRawData(), QChar, QLatin1String, QByteArray, QStringRef +*/ + +/*! + \enum QString::SplitBehavior + + This enum specifies how the split() function should behave with + respect to empty strings. + + \value KeepEmptyParts If a field is empty, keep it in the result. + \value SkipEmptyParts If a field is empty, don't include it in the result. + + \sa split() +*/ + +QString::Data QString::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1), + 0, 0, shared_null.array, 0, 0, 0, 0, 0, 0, {0} }; +QString::Data QString::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), + 0, 0, shared_empty.array, 0, 0, 0, 0, 0, 0, {0} }; + +int QString::grow(int size) +{ + return qAllocMore(size * sizeof(QChar), sizeof(Data)) / sizeof(QChar); +} + +/*! \typedef QString::ConstIterator + + Qt-style synonym for QString::const_iterator. +*/ + +/*! \typedef QString::Iterator + + Qt-style synonym for QString::iterator. +*/ + +/*! \typedef QString::const_iterator + + The QString::const_iterator typedef provides an STL-style const + iterator for QString. + + \sa QString::iterator +*/ + +/*! \typedef QString::iterator + + The QString::iterator typedef provides an STL-style non-const + iterator for QString. + + \sa QString::const_iterator +*/ + +/*! \fn QString::iterator QString::begin() + + Returns an \l{STL-style iterator} pointing to the first character in + the string. + + \sa constBegin(), end() +*/ + +/*! \fn QString::const_iterator QString::begin() const + + \overload begin() +*/ + +/*! \fn QString::const_iterator QString::constBegin() const + + Returns a const \l{STL-style iterator} pointing to the first character + in the string. + + \sa begin(), constEnd() +*/ + +/*! \fn QString::iterator QString::end() + + Returns an \l{STL-style iterator} pointing to the imaginary character + after the last character in the string. + + \sa begin(), constEnd() +*/ + +/*! \fn QString::const_iterator QString::end() const + + \overload end() +*/ + +/*! \fn QString::const_iterator QString::constEnd() const + + Returns a const \l{STL-style iterator} pointing to the imaginary + item after the last item in the list. + + \sa constBegin(), end() +*/ + +/*! + \fn QString::QString() + + Constructs a null string. Null strings are also empty. + + \sa isEmpty() +*/ + +/*! \fn QString::QString(const char *str) + + Constructs a string initialized with the ASCII string \a str. The + given const char pointer is converted to Unicode using the + fromAscii() function. + + You can disable this constructor by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. + + \sa fromAscii(), fromLatin1(), fromLocal8Bit(), fromUtf8() +*/ + +/*! \fn QString QString::fromStdString(const std::string &str) + + Returns a copy of the \a str string. The given string is converted + to Unicode using the fromAscii() function. + + This constructor is only available if Qt is configured with STL + compatibility enabled. + + \sa fromAscii(), fromLatin1(), fromLocal8Bit(), fromUtf8() +*/ + +/*! \fn QString QString::fromStdWString(const std::wstring &str) + + Returns a copy of the \a str string. The given string is assumed + to be encoded in utf16 if the size of wchar_t is 2 bytes (e.g. on + windows) and ucs4 if the size of wchar_t is 4 bytes (most Unix + systems). + + This method is only available if Qt is configured with STL + compatibility enabled. + + \sa fromUtf16(), fromLatin1(), fromLocal8Bit(), fromUtf8(), fromUcs4() +*/ + +/*! + \since 4.2 + + Returns a copy of the \a string string encoded in ucs4. + + If \a size is -1 (default), the \a string has to be 0 terminated. + + \sa fromUtf16(), fromLatin1(), fromLocal8Bit(), fromUtf8(), fromUcs4(), fromStdWString() +*/ +QString QString::fromWCharArray(const wchar_t *string, int size) +{ + if (sizeof(wchar_t) == sizeof(QChar)) { + return fromUtf16((ushort *)string, size); + } else { + return fromUcs4((uint *)string, size); + } +} + +/*! \fn std::wstring QString::toStdWString() const + + Returns a std::wstring object with the data contained in this + QString. The std::wstring is encoded in utf16 on platforms where + wchar_t is 2 bytes wide (e.g. windows) and in ucs4 on platforms + where wchar_t is 4 bytes wide (most Unix systems). + + This operator is mostly useful to pass a QString to a function + that accepts a std::wstring object. + + This operator is only available if Qt is configured with STL + compatibility enabled. + + \sa utf16(), toAscii(), toLatin1(), toUtf8(), toLocal8Bit() +*/ + +/*! + \since 4.2 + + Fills the \a array with the data contained in this QString object. + The array is encoded in utf16 on platforms where + wchar_t is 2 bytes wide (e.g. windows) and in ucs4 on platforms + where wchar_t is 4 bytes wide (most Unix systems). + + \a array has to be allocated by the caller and contain enough space to + hold the complete string (allocating the array with the same length as the + string is always sufficient). + + returns the actual length of the string in \a array. + + \note This function does not append a null character to the array. + + \sa utf16(), toUcs4(), toAscii(), toLatin1(), toUtf8(), toLocal8Bit(), toStdWString() +*/ +int QString::toWCharArray(wchar_t *array) const +{ + if (sizeof(wchar_t) == sizeof(QChar)) { + memcpy(array, utf16(), sizeof(wchar_t)*length()); + return length(); + } else { + wchar_t *a = array; + const unsigned short *uc = utf16(); + for (int i = 0; i < length(); ++i) { + uint u = uc[i]; + if (u >= 0xd800 && u < 0xdc00 && i < length()-1) { + ushort low = uc[i+1]; + if (low >= 0xdc00 && low < 0xe000) { + ++i; + u = (u - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; + } + } + *a = wchar_t(u); + ++a; + } + return a - array; + } +} + +/*! \fn QString::QString(const QString &other) + + Constructs a copy of \a other. + + This operation takes \l{constant time}, because QString is + \l{implicitly shared}. This makes returning a QString from a + function very fast. If a shared instance is modified, it will be + copied (copy-on-write), and that takes \l{linear time}. + + \sa operator=() +*/ + +/*! + Constructs a string initialized with the first \a size characters + of the QChar array \a unicode. + + QString makes a deep copy of the string data. +*/ +QString::QString(const QChar *unicode, int size) +{ + if (!unicode) { + d = &shared_null; + d->ref.ref(); + } else if (size <= 0) { + d = &shared_empty; + d->ref.ref(); + } else { + d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar)); + d->ref = 1; + d->alloc = d->size = size; + d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0; + d->data = d->array; + memcpy(d->array, unicode, size * sizeof(QChar)); + d->array[size] = '\0'; + } +} + + +/*! + Constructs a string of the given \a size with every character set + to \a ch. + + \sa fill() +*/ +QString::QString(int size, QChar ch) +{ + if (size <= 0) { + d = &shared_empty; + d->ref.ref(); + } else { + d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar)); + d->ref = 1; + d->alloc = d->size = size; + d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0; + d->data = d->array; + d->array[size] = '\0'; + ushort *i = d->array + size; + ushort *b = d->array; + const ushort value = ch.unicode(); + while (i != b) + *--i = value; + } +} + +/*! \fn QString::QString(const QLatin1String &str) + + Constructs a copy of the Latin-1 string \a str. + + \sa fromLatin1() +*/ + +/*! + Constructs a string of size 1 containing the character \a ch. +*/ +QString::QString(QChar ch) +{ + d = (Data *)qMalloc(sizeof(Data) + sizeof(QChar)); + d->ref = 1; + d->alloc = d->size = 1; + d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0; + d->data = d->array; + d->array[0] = ch.unicode(); + d->array[1] = '\0'; +} + +/*! \fn QString::QString(const QByteArray &ba) + + Constructs a string initialized with the byte array \a ba. The + given byte array is converted to Unicode using fromAscii(). Stops + copying at the first 0 character, otherwise copies the entire byte + array. + + You can disable this constructor by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. + + \sa fromAscii(), fromLatin1(), fromLocal8Bit(), fromUtf8() +*/ + +/*! \fn QString::QString(const Null &) + \internal +*/ + +/*! \fn QString &QString::operator=(const Null &) + \internal +*/ + +/*! + \fn QString::~QString() + + Destroys the string. +*/ + + +/*! \fn void QString::detach() + + \internal +*/ + +/*! \fn void QString::isDetached() const + + \internal +*/ + +// ### Qt 5: rename freeData() to avoid confusion. See task 197625. +void QString::free(Data *d) +{ +#ifdef QT3_SUPPORT + if (d->asciiCache) { + Q_ASSERT(asciiCache); + asciiCache->remove(d); + } +#endif + qFree(d); +} + +/*! + Sets the size of the string to \a size characters. + + If \a size is greater than the current size, the string is + extended to make it \a size characters long with the extra + characters added to the end. The new characters are uninitialized. + + If \a size is less than the current size, characters are removed + from the end. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 45 + + If you want to append a certain number of identical characters to + the string, use \l operator+=() as follows rather than resize(): + + \snippet doc/src/snippets/qstring/main.cpp 46 + + If you want to expand the string so that it reaches a certain + width and fill the new positions with a particular character, use + the leftJustified() function: + + If \a size is negative, it is equivalent to passing zero. + + \snippet doc/src/snippets/qstring/main.cpp 47 + + \sa truncate(), reserve() +*/ + +void QString::resize(int size) +{ + if (size < 0) + size = 0; + + if (size == 0 && !d->capacity) { + Data *x = &shared_empty; + x->ref.ref(); + if (!d->ref.deref()) + QString::free(d); + d = x; + } else { + if (d->ref != 1 || size > d->alloc || + (!d->capacity && size < d->size && size < d->alloc >> 1)) + realloc(grow(size)); + if (d->alloc >= size) { + d->size = size; + if (d->data == d->array) { + d->array[size] = '\0'; + } + } + } +} + +/*! \fn int QString::capacity() const + + Returns the maximum number of characters that can be stored in + the string without forcing a reallocation. + + The sole purpose of this function is to provide a means of fine + tuning QString's memory usage. In general, you will rarely ever + need to call this function. If you want to know how many + characters are in the string, call size(). + + \sa reserve(), squeeze() +*/ + +/*! + \fn void QString::reserve(int size) + + Attempts to allocate memory for at least \a size characters. If + you know in advance how large the string will be, you can call + this function, and if you resize the string often you are likely + to get better performance. If \a size is an underestimate, the + worst that will happen is that the QString will be a bit slower. + + The sole purpose of this function is to provide a means of fine + tuning QString's memory usage. In general, you will rarely ever + need to call this function. If you want to change the size of the + string, call resize(). + + This function is useful for code that needs to build up a long + string and wants to avoid repeated reallocation. In this example, + we want to add to the string until some condition is true, and + we're fairly sure that size is large enough to make a call to + reserve() worthwhile: + + \snippet doc/src/snippets/qstring/main.cpp 44 + + \sa squeeze(), capacity() +*/ + +/*! + \fn void QString::squeeze() + + Releases any memory not required to store the character data. + + The sole purpose of this function is to provide a means of fine + tuning QString's memory usage. In general, you will rarely ever + need to call this function. + + \sa reserve(), capacity() +*/ + +// ### Qt 5: rename reallocData() to avoid confusion. 197625 +void QString::realloc(int alloc) +{ + if (d->ref != 1 || d->data != d->array) { + Data *x = static_cast<Data *>(qMalloc(sizeof(Data) + alloc * sizeof(QChar))); + if (!x) + return; + x->size = qMin(alloc, d->size); + ::memcpy(x->array, d->data, x->size * sizeof(QChar)); + x->array[x->size] = 0; + x->asciiCache = 0; + x->ref = 1; + x->alloc = alloc; + x->clean = d->clean; + x->simpletext = d->simpletext; + x->righttoleft = d->righttoleft; + x->capacity = d->capacity; + x->data = x->array; + if (!d->ref.deref()) + QString::free(d); + d = x; + } else { +#ifdef QT3_SUPPORT + if (d->asciiCache) { + Q_ASSERT(asciiCache); + asciiCache->remove(d); + } +#endif + Data *x = static_cast<Data *>(qRealloc(d, sizeof(Data) + alloc * sizeof(QChar))); + if (!x) + return; + x->alloc = alloc; + x->data = x->array; + d = x; + } +} + +void QString::realloc() +{ + realloc(d->size); +} + +void QString::expand(int i) +{ + int sz = d->size; + resize(qMax(i + 1, sz)); + if (d->size - 1 > sz) { + ushort *n = d->data + d->size - 1; + ushort *e = d->data + sz; + while (n != e) + * --n = ' '; + } +} + +/*! \fn void QString::clear() + + Clears the contents of the string and makes it empty. + + \sa resize(), isEmpty() +*/ + +/*! \fn QString &QString::operator=(const QString &other) + + Assigns \a other to this string and returns a reference to this + string. +*/ + +QString &QString::operator=(const QString &other) +{ + other.d->ref.ref(); + if (!d->ref.deref()) + QString::free(d); + d = other.d; + return *this; +} + + +/*! \fn QString &QString::operator=(const QLatin1String &str) + + \overload operator=() + + Assigns the Latin-1 string \a str to this string. +*/ + +/*! \fn QString &QString::operator=(const QByteArray &ba) + + \overload operator=() + + Assigns \a ba to this string. The byte array is converted to + Unicode using the fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! \fn QString &QString::operator=(const char *str) + + \overload operator=() + + Assigns \a str to this string. The const char pointer is converted + to Unicode using the fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! \fn QString &QString::operator=(char ch) + + \overload operator=() + + Assigns character \a ch to this string. The character is converted + to Unicode using the fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! + \overload operator=() + + Sets the string to contain the single character \a ch. +*/ +QString &QString::operator=(QChar ch) +{ + return operator=(QString(ch)); +} + +/*! + \fn QString& QString::insert(int position, const QString &str) + + Inserts the string \a str at the given index \a position and + returns a reference to this string. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 26 + + If the given \a position is greater than size(), the array is + first extended using resize(). + + \sa append(), prepend(), replace(), remove() +*/ + + +/*! + \fn QString &QString::insert(int position, const QLatin1String &str) + \overload insert() + + Inserts the Latin-1 string \a str at the given index \a position. +*/ +QString &QString::insert(int i, const QLatin1String &str) +{ + const uchar *s = (const uchar *)str.latin1(); + if (i < 0 || !s || !(*s)) + return *this; + + int len = qstrlen(str.latin1()); + expand(qMax(d->size, i) + len - 1); + + ::memmove(d->data + i + len, d->data + i, (d->size - i - len) * sizeof(QChar)); + for (int j = 0; j < len; ++j) + d->data[i + j] = s[j]; + return *this; +} + +/*! + \fn QString& QString::insert(int position, const QChar *unicode, int size) + \overload insert() + + Inserts the first \a size characters of the QChar array \a unicode + at the given index \a position in the string. +*/ +QString& QString::insert(int i, const QChar *unicode, int size) +{ + if (i < 0 || size <= 0) + return *this; + + const ushort *s = (const ushort *)unicode; + if (s >= d->data && s < d->data + d->alloc) { + // Part of me - take a copy + ushort *tmp = static_cast<ushort *>(qMalloc(size * sizeof(QChar))); + memcpy(tmp, s, size * sizeof(QChar)); + insert(i, reinterpret_cast<const QChar *>(tmp), size); + qFree(tmp); + return *this; + } + + expand(qMax(d->size, i) + size - 1); + + ::memmove(d->data + i + size, d->data + i, (d->size - i - size) * sizeof(QChar)); + memcpy(d->data + i, s, size * sizeof(QChar)); + return *this; +} + +/*! + \fn QString& QString::insert(int position, QChar ch) + \overload insert() + + Inserts \a ch at the given index \a position in the string. +*/ + +QString& QString::insert(int i, QChar ch) +{ + if (i < 0) + i += d->size; + if (i < 0) + return *this; + expand(qMax(i, d->size)); + ::memmove(d->data + i + 1, d->data + i, (d->size - i) * sizeof(QChar)); + d->data[i] = ch.unicode(); + return *this; +} + +/*! + Appends the string \a str onto the end of this string. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 9 + + This is the same as using the insert() function: + + \snippet doc/src/snippets/qstring/main.cpp 10 + + The append() function is typically very fast (\l{constant time}), + because QString preallocates extra space at the end of the string + data so it can grow without reallocating the entire string each + time. + + \sa operator+=(), prepend(), insert() +*/ +QString &QString::append(const QString &str) +{ + if (str.d != &shared_null) { + if (d == &shared_null) { + operator=(str); + } else { + if (d->ref != 1 || d->size + str.d->size > d->alloc) + realloc(grow(d->size + str.d->size)); + memcpy(d->data + d->size, str.d->data, str.d->size * sizeof(QChar)); + d->size += str.d->size; + d->data[d->size] = '\0'; + } + } + return *this; +} + +/*! + \overload append() + + Appends the Latin-1 string \a str to this string. +*/ +QString &QString::append(const QLatin1String &str) +{ + const uchar *s = (const uchar *)str.latin1(); + if (s) { + int len = qstrlen((char *)s); + if (d->ref != 1 || d->size + len > d->alloc) + realloc(grow(d->size + len)); + ushort *i = d->data + d->size; + while ((*i++ = *s++)) + ; + d->size += len; + } + return *this; +} + +/*! \fn QString &QString::append(const QByteArray &ba) + + \overload append() + + Appends the byte array \a ba to this string. The given byte array + is converted to Unicode using the fromAscii() function. + + You can disable this function by defining \c QT_NO_CAST_FROM_ASCII + when you compile your applications. This can be useful if you want + to ensure that all user-visible strings go through QObject::tr(), + for example. +*/ + +/*! \fn QString &QString::append(const char *str) + + \overload append() + + Appends the string \a str to this string. The given const char + pointer is converted to Unicode using the fromAscii() function. + + You can disable this function by defining \c QT_NO_CAST_FROM_ASCII + when you compile your applications. This can be useful if you want + to ensure that all user-visible strings go through QObject::tr(), + for example. +*/ + +/*! + \overload append() + + Appends the character \a ch to this string. +*/ +QString &QString::append(QChar ch) +{ + if (d->ref != 1 || d->size + 1 > d->alloc) + realloc(grow(d->size + 1)); + d->data[d->size++] = ch.unicode(); + d->data[d->size] = '\0'; + return *this; +} + +/*! \fn QString &QString::prepend(const QString &str) + + Prepends the string \a str to the beginning of this string and + returns a reference to this string. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 36 + + \sa append(), insert() +*/ + +/*! \fn QString &QString::prepend(const QLatin1String &str) + + \overload prepend() + + Prepends the Latin-1 string \a str to this string. +*/ + +/*! \fn QString &QString::prepend(const QByteArray &ba) + + \overload prepend() + + Prepends the byte array \a ba to this string. The byte array is + converted to Unicode using the fromAscii() function. + + You can disable this function by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! \fn QString &QString::prepend(const char *str) + + \overload prepend() + + Prepends the string \a str to this string. The const char pointer + is converted to Unicode using the fromAscii() function. + + You can disable this function by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! \fn QString &QString::prepend(QChar ch) + + \overload prepend() + + Prepends the character \a ch to this string. +*/ + +/*! + \fn QString &QString::remove(int position, int n) + + Removes \a n characters from the string, starting at the given \a + position index, and returns a reference to the string. + + If the specified \a position index is within the string, but \a + position + \a n is beyond the end of the string, the string is + truncated at the specified \a position. + + \snippet doc/src/snippets/qstring/main.cpp 37 + + \sa insert(), replace() +*/ +QString &QString::remove(int pos, int len) +{ + if (pos < 0) + pos += d->size; + if (pos < 0 || pos >= d->size) { + // range problems + } else if (pos + len >= d->size) { // pos ok + resize(pos); + } else if (len > 0) { + detach(); + memmove(d->data + pos, d->data + pos + len, + (d->size - pos - len + 1) * sizeof(ushort)); + d->size -= len; + } + return *this; +} + +/*! + Removes every occurrence of the given \a str string in this + string, and returns a reference to this string. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + This is the same as \c replace(str, "", cs). + + \sa replace() +*/ +QString &QString::remove(const QString &str, Qt::CaseSensitivity cs) +{ + if (str.d->size) { + int i = 0; + while ((i = indexOf(str, i, cs)) != -1) + remove(i, str.d->size); + } + return *this; +} + +/*! + Removes every occurrence of the character \a ch in this string, and + returns a reference to this string. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 38 + + This is the same as \c replace(ch, "", cs). + + \sa replace() +*/ +QString &QString::remove(QChar ch, Qt::CaseSensitivity cs) +{ + int i = 0; + ushort c = ch.unicode(); + if (cs == Qt::CaseSensitive) { + while (i < d->size) + if (d->data[i] == ch) + remove(i, 1); + else + i++; + } else { + c = foldCase(c); + while (i < d->size) + if (foldCase(d->data[i]) == c) + remove(i, 1); + else + i++; + } + return *this; +} + +/*! + \fn QString &QString::remove(const QRegExp &rx) + + Removes every occurrence of the regular expression \a rx in the + string, and returns a reference to the string. For example: + + \snippet doc/src/snippets/qstring/main.cpp 39 + + \sa indexOf(), lastIndexOf(), replace() +*/ + +/*! + \fn QString &QString::replace(int position, int n, const QString &after) + + Replaces \a n characters beginning at index \a position with + the string \a after and returns a reference to this string. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 40 + + \sa insert(), remove() +*/ +QString &QString::replace(int pos, int len, const QString &after) +{ + QString copy = after; + return replace(pos, len, copy.constData(), copy.length()); +} + +/*! + \fn QString &QString::replace(int position, int n, const QChar *unicode, int size) + \overload replace() + Replaces \a n characters beginning at index \a position with the + first \a size characters of the QChar array \a unicode and returns a + reference to this string. +*/ +QString &QString::replace(int pos, int len, const QChar *unicode, int size) +{ + if (pos < 0 || pos > d->size) + return *this; + if (pos + len > d->size) + len = d->size - pos; + + uint index = pos; + replace_helper(&index, 1, len, unicode, size); + return *this; +} + +/*! + \fn QString &QString::replace(int position, int n, QChar after) + \overload replace() + + Replaces \a n characters beginning at index \a position with the + character \a after and returns a reference to this string. +*/ +QString &QString::replace(int pos, int len, QChar after) +{ + uint index = pos; + replace_helper(&index, 1, len, &after, 1); + return *this; +} + +/*! + \overload replace() + Replaces every occurrence of the string \a before with the string \a + after and returns a reference to this string. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 41 + + \note The replacement text is not rescanned after it is inserted. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 86 +*/ +QString &QString::replace(const QString &before, const QString &after, Qt::CaseSensitivity cs) +{ + return replace(before.constData(), before.size(), after.constData(), after.size(), cs); +} + +/*! + \internal + */ +void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen) +{ + if (blen == alen) { + detach(); + for (int i = 0; i < nIndices; ++i) + memcpy(d->data + indices[i], after, alen * sizeof(QChar)); + } else if (alen < blen) { + detach(); + uint to = indices[0]; + if (alen) + memcpy(d->data+to, after, alen*sizeof(QChar)); + to += alen; + uint movestart = indices[0] + blen; + for (int i = 1; i < nIndices; ++i) { + int msize = indices[i] - movestart; + if (msize > 0) { + memmove(d->data + to, d->data + movestart, msize * sizeof(QChar)); + to += msize; + } + if (alen) { + memcpy(d->data + to, after, alen*sizeof(QChar)); + to += alen; + } + movestart = indices[i] + blen; + } + int msize = d->size - movestart; + if (msize > 0) + memmove(d->data + to, d->data + movestart, msize * sizeof(QChar)); + resize(d->size - nIndices*(blen-alen)); + } else { + // we have a table of replacement positions, use them for fast replacing + int adjust = nIndices*(alen-blen); + int newLen = d->size + adjust; + int moveend = d->size; + resize(newLen); + + while (nIndices) { + --nIndices; + int movestart = indices[nIndices] + blen; + int insertstart = indices[nIndices] + nIndices*(alen-blen); + int moveto = insertstart + alen; + memmove(d->data + moveto, d->data + movestart, + (moveend - movestart)*sizeof(QChar)); + memcpy(d->data + insertstart, after, alen*sizeof(QChar)); + moveend = movestart-blen; + } + } +} + +/*! + \since 4.5 + \overload replace() + + Replaces each occurrence in this string of the first \a blen + characters of \a before with the first \a alen characters of \a + after and returns a reference to this string. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. +*/ +QString &QString::replace(const QChar *before, int blen, + const QChar *after, int alen, + Qt::CaseSensitivity cs) +{ + if (d->size == 0) { + if (blen) + return *this; + } else { + if (cs == Qt::CaseSensitive && before == after && blen == alen) + return *this; + } + if (alen == 0 && blen == 0) + return *this; + + // protect against before or after being part of this + const QChar *a = after; + const QChar *b = before; + if (after >= (const QChar *)d->data && after < (const QChar *)d->data + d->size) { + QChar *copy = (QChar *)malloc(alen*sizeof(QChar)); + memcpy(copy, after, alen*sizeof(QChar)); + a = copy; + } + if (before >= (const QChar *)d->data && before < (const QChar *)d->data + d->size) { + QChar *copy = (QChar *)malloc(blen*sizeof(QChar)); + memcpy(copy, before, blen*sizeof(QChar)); + b = copy; + } + + QStringMatcher matcher(b, blen, cs); + + int index = 0; + while (1) { + uint indices[1024]; + uint pos = 0; + while (pos < 1023) { + index = matcher.indexIn(*this, index); + if (index == -1) + break; + indices[pos++] = index; + index += blen; + // avoid infinite loop + if (!blen) + index++; + } + if (!pos) + break; + + replace_helper(indices, pos, blen, a, alen); + + if (index == -1) + break; + // index has to be adjusted in case we get back into the loop above. + index += pos*(alen-blen); + } + + if (a != after) + ::free((QChar *)a); + if (b != before) + ::free((QChar *)b); + + return *this; +} + +/*! + \overload replace() + Replaces every occurrence of the character \a ch in the string with + \a after and returns a reference to this string. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. +*/ +QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs) +{ + if (after.d->size == 0) + return remove(ch, cs); + + if (after.d->size == 1) + return replace(ch, after.d->data[0], cs); + + if (d->size == 0) + return *this; + + ushort cc = (cs == Qt::CaseSensitive ? ch.unicode() : ch.toCaseFolded().unicode()); + + int index = 0; + while (1) { + uint indices[1024]; + uint pos = 0; + if (cs == Qt::CaseSensitive) { + while (pos < 1023 && index < d->size) { + if (d->data[index] == cc) + indices[pos++] = index; + index++; + } + } else { + while (pos < 1023 && index < d->size) { + if (QChar::toCaseFolded(d->data[index]) == cc) + indices[pos++] = index; + index++; + } + } + if (!pos) + break; + + replace_helper(indices, pos, 1, after.constData(), after.d->size); + + if (index == -1) + break; + // index has to be adjusted in case we get back into the loop above. + index += pos*(after.d->size - 1); + } + return *this; +} + +/*! + \overload replace() + Replaces every occurrence of the character \a before with the + character \a after and returns a reference to this string. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. +*/ +QString& QString::replace(QChar before, QChar after, Qt::CaseSensitivity cs) +{ + ushort a = after.unicode(); + ushort b = before.unicode(); + if (d->size) { + detach(); + ushort *i = d->data; + const ushort *e = i + d->size; + if (cs == Qt::CaseSensitive) { + for (; i != e; ++i) + if (*i == b) + *i = a; + } else { + b = foldCase(b); + for (; i != e; ++i) + if (foldCase(*i) == b) + *i = a; + } + } + return *this; +} + +/*! + \since 4.5 + \overload replace() + + Replaces every occurrence of the string \a before with the string \a + after and returns a reference to this string. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \note The text is not rescanned after a replacement. +*/ +QString &QString::replace(const QLatin1String &before, + const QLatin1String &after, + Qt::CaseSensitivity cs) +{ + int alen = qstrlen(after.latin1()); + QVarLengthArray<ushort> a(alen); + for (int i = 0; i < alen; ++i) + a[i] = (uchar)after.latin1()[i]; + int blen = qstrlen(before.latin1()); + QVarLengthArray<ushort> b(blen); + for (int i = 0; i < blen; ++i) + b[i] = (uchar)before.latin1()[i]; + return replace((const QChar *)b.data(), blen, (const QChar *)a.data(), alen, cs); +} + +/*! + \since 4.5 + \overload replace() + + Replaces every occurrence of the string \a before with the string \a + after and returns a reference to this string. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \note The text is not rescanned after a replacement. +*/ +QString &QString::replace(const QLatin1String &before, + const QString &after, + Qt::CaseSensitivity cs) +{ + int blen = qstrlen(before.latin1()); + QVarLengthArray<ushort> b(blen); + for (int i = 0; i < blen; ++i) + b[i] = (uchar)before.latin1()[i]; + return replace((const QChar *)b.data(), blen, after.constData(), after.d->size, cs); +} + +/*! + \since 4.5 + \overload replace() + + Replaces every occurrence of the string \a before with the string \a + after and returns a reference to this string. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \note The text is not rescanned after a replacement. +*/ +QString &QString::replace(const QString &before, + const QLatin1String &after, + Qt::CaseSensitivity cs) +{ + int alen = qstrlen(after.latin1()); + QVarLengthArray<ushort> a(alen); + for (int i = 0; i < alen; ++i) + a[i] = (uchar)after.latin1()[i]; + return replace(before.constData(), before.d->size, (const QChar *)a.data(), alen, cs); +} + +/*! + \since 4.5 + \overload replace() + + Replaces every occurrence of the character \a c with the string \a + after and returns a reference to this string. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \note The text is not rescanned after a replacement. +*/ +QString &QString::replace(QChar c, const QLatin1String &after, Qt::CaseSensitivity cs) +{ + int alen = qstrlen(after.latin1()); + QVarLengthArray<ushort> a(alen); + for (int i = 0; i < alen; ++i) + a[i] = (uchar)after.latin1()[i]; + return replace(&c, 1, (const QChar *)a.data(), alen, cs); +} + + +/*! + Returns true if string \a other is equal to this string; otherwise + returns false. + + The comparison is based exclusively on the numeric Unicode values of + the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings with + localeAwareCompare(). +*/ +bool QString::operator==(const QString &other) const +{ + return (size() == other.size()) && + (memcmp((char*)unicode(),(char*)other.unicode(), size()*sizeof(QChar))==0); +} + +/*! + \overload operator==() +*/ +bool QString::operator==(const QLatin1String &other) const +{ + const ushort *uc = d->data; + const ushort *e = uc + d->size; + const uchar *c = (uchar *)other.latin1(); + + if (!c) + return isEmpty(); + + while (*c) { + if (uc == e || *uc != *c) + return false; + ++uc; + ++c; + } + return (uc == e); +} + +/*! \fn bool QString::operator==(const QByteArray &other) const + + \overload operator==() + + The \a other byte array is converted to a QString using the + fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! \fn bool QString::operator==(const char *other) const + + \overload operator==() + + The \a other const char pointer is converted to a QString using + the fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! + Returns true if this string is lexically less than string \a + other; otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings using the + QString::localeAwareCompare() function. +*/ +bool QString::operator<(const QString &other) const +{ + return ucstrcmp(constData(), length(), other.constData(), other.length()) < 0; +} + +/*! + \overload operator<() +*/ +bool QString::operator<(const QLatin1String &other) const +{ + const ushort *uc = d->data; + const ushort *e = uc + d->size; + const uchar *c = (uchar *) other.latin1(); + + if (!c || *c == 0) + return false; + + while (*c) { + if (uc == e || *uc != *c) + break; + ++uc; + ++c; + } + return (uc == e ? *c : *uc < *c); +} + +/*! \fn bool QString::operator<(const QByteArray &other) const + + \overload operator<() + + The \a other byte array is converted to a QString using the + fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! \fn bool QString::operator<(const char *other) const + + \overload operator<() + + The \a other const char pointer is converted to a QString using + the fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! \fn bool QString::operator<=(const QString &other) const + + Returns true if this string is lexically less than or equal to + string \a other; otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings with + localeAwareCompare(). +*/ + +/*! \fn bool QString::operator<=(const QLatin1String &other) const + + \overload operator<=() +*/ + +/*! \fn bool QString::operator<=(const QByteArray &other) const + + \overload operator<=() + + The \a other byte array is converted to a QString using the + fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! \fn bool QString::operator<=(const char *other) const + + \overload operator<=() + + The \a other const char pointer is converted to a QString using + the fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! \fn bool QString::operator>(const QString &other) const + + Returns true if this string is lexically greater than string \a + other; otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings with + localeAwareCompare(). +*/ + +/*! + \overload operator>() +*/ +bool QString::operator>(const QLatin1String &other) const +{ + const ushort *uc = d->data;; + const ushort *e = uc + d->size; + const uchar *c = (uchar *) other.latin1(); + + if (!c || *c == '\0') + return !isEmpty(); + + while (*c) { + if (uc == e || *uc != *c) + break; + ++uc; + ++c; + } + return (uc == e ? false : *uc > *c); +} + +/*! \fn bool QString::operator>(const QByteArray &other) const + + \overload operator>() + + The \a other byte array is converted to a QString using the + fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! \fn bool QString::operator>(const char *other) const + + \overload operator>() + + The \a other const char pointer is converted to a QString using + the fromAscii() function. + + You can disable this operator by defining \c QT_NO_CAST_FROM_ASCII + when you compile your applications. This can be useful if you want + to ensure that all user-visible strings go through QObject::tr(), + for example. +*/ + +/*! \fn bool QString::operator>=(const QString &other) const + + Returns true if this string is lexically greater than or equal to + string \a other; otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings with + localeAwareCompare(). +*/ + +/*! \fn bool QString::operator>=(const QLatin1String &other) const + + \overload operator>=() +*/ + +/*! \fn bool QString::operator>=(const QByteArray &other) const + + \overload operator>=() + + The \a other byte array is converted to a QString using the + fromAscii() function. + + You can disable this operator by defining \c QT_NO_CAST_FROM_ASCII + when you compile your applications. This can be useful if you want + to ensure that all user-visible strings go through QObject::tr(), + for example. +*/ + +/*! \fn bool QString::operator>=(const char *other) const + + \overload operator>=() + + The \a other const char pointer is converted to a QString using + the fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! \fn bool QString::operator!=(const QString &other) const + + Returns true if this string is not equal to string \a other; + otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings with + localeAwareCompare(). +*/ + +/*! \fn bool QString::operator!=(const QLatin1String &other) const + + \overload operator!=() +*/ + +/*! \fn bool QString::operator!=(const QByteArray &other) const + + \overload operator!=() + + The \a other byte array is converted to a QString using the + fromAscii() function. + + You can disable this operator by defining \c QT_NO_CAST_FROM_ASCII + when you compile your applications. This can be useful if you want + to ensure that all user-visible strings go through QObject::tr(), + for example. +*/ + +/*! \fn bool QString::operator!=(const char *other) const + + \overload operator!=() + + The \a other const char pointer is converted to a QString using + the fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! + Returns the index position of the first occurrence of the string \a + str in this string, searching forward from index position \a + from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 24 + + If \a from is -1, the search starts at the last character; if it is + -2, at the next to last character and so on. + + \sa lastIndexOf(), contains(), count() +*/ +int QString::indexOf(const QString &str, int from, Qt::CaseSensitivity cs) const +{ + return qFindString(unicode(), length(), from, str.unicode(), str.length(), cs); +} + +/*! + \since 4.5 + Returns the index position of the first occurrence of the string \a + str in this string, searching forward from index position \a + from. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 24 + + If \a from is -1, the search starts at the last character; if it is + -2, at the next to last character and so on. + + \sa lastIndexOf(), contains(), count() +*/ +int QString::indexOf(const QLatin1String &str, int from, Qt::CaseSensitivity cs) const +{ + int len = qstrlen(str.latin1()); + QVarLengthArray<ushort> s(len); + for (int i = 0; i < len; ++i) + s[i] = str.latin1()[i]; + + return qFindString(unicode(), length(), from, (const QChar *)s.data(), len, cs); +} + +int qFindString( + const QChar *haystack0, int haystackLen, int from, + const QChar *needle0, int needleLen, Qt::CaseSensitivity cs) +{ + const int l = haystackLen; + const int sl = needleLen; + if (from < 0) + from += l; + if (uint(sl + from) > (uint)l) + return -1; + if (!sl) + return from; + if (!l) + return -1; + + if (sl == 1) + return findChar(haystack0, haystackLen, needle0[0], from, cs); + + /* + We use the Boyer-Moore algorithm in cases where the overhead + for the skip table should pay off, otherwise we use a simple + hash function. + */ + if (l > 500 && sl > 5) + return qFindStringBoyerMoore(haystack0, haystackLen, from, + needle0, needleLen, cs); + + /* + We use some hashing for efficiency's sake. Instead of + comparing strings, we compare the hash value of str with that + of a part of this QString. Only if that matches, we call + ucstrncmp() or ucstrnicmp(). + */ + const ushort *needle = (const ushort *)needle0; + const ushort *haystack = (const ushort *)haystack0 + from; + const ushort *end = (const ushort *)haystack0 + (l-sl); + const int sl_minus_1 = sl-1; + int hashNeedle = 0, hashHaystack = 0, idx; + + if (cs == Qt::CaseSensitive) { + for (idx = 0; idx < sl; ++idx) { + hashNeedle = ((hashNeedle<<1) + needle[idx]); + hashHaystack = ((hashHaystack<<1) + haystack[idx]); + } + hashHaystack -= haystack[sl_minus_1]; + + while (haystack <= end) { + hashHaystack += haystack[sl_minus_1]; + if (hashHaystack == hashNeedle + && ucstrncmp((const QChar *)needle, (const QChar *)haystack, sl) == 0) + return haystack - (const ushort *)haystack0; + + REHASH(*haystack); + ++haystack; + } + } else { + const ushort *haystack_start = (const ushort *)haystack0; + for (idx = 0; idx < sl; ++idx) { + hashNeedle = (hashNeedle<<1) + foldCase(needle + idx, needle); + hashHaystack = (hashHaystack<<1) + foldCase(haystack + idx, haystack_start); + } + hashHaystack -= foldCase(haystack + sl_minus_1, haystack_start); + + while (haystack <= end) { + hashHaystack += foldCase(haystack + sl_minus_1, haystack_start); + if (hashHaystack == hashNeedle && ucstrnicmp(needle, haystack, sl) == 0) + return haystack - (const ushort *)haystack0; + + REHASH(foldCase(haystack, haystack_start)); + ++haystack; + } + } + return -1; +} + +/*! + \overload indexOf() + + Returns the index position of the first occurrence of the + character \a ch in the string, searching forward from index + position \a from. Returns -1 if \a ch could not be found. +*/ +int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const +{ + return findChar(unicode(), length(), ch, from, cs); +} + +static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *needle, int sl, Qt::CaseSensitivity cs) +{ + /* + See indexOf() for explanations. + */ + + const ushort *end = haystack; + haystack += from; + const int sl_minus_1 = sl-1; + const ushort *n = needle+sl_minus_1; + const ushort *h = haystack+sl_minus_1; + int hashNeedle = 0, hashHaystack = 0, idx; + + if (cs == Qt::CaseSensitive) { + for (idx = 0; idx < sl; ++idx) { + hashNeedle = ((hashNeedle<<1) + *(n-idx)); + hashHaystack = ((hashHaystack<<1) + *(h-idx)); + } + hashHaystack -= *haystack; + + while (haystack >= end) { + hashHaystack += *haystack; + if (hashHaystack == hashNeedle + && ucstrncmp((const QChar *)needle, (const QChar *)haystack, sl) == 0) + return haystack - end; + --haystack; + REHASH(haystack[sl]); + } + } else { + for (idx = 0; idx < sl; ++idx) { + hashNeedle = ((hashNeedle<<1) + foldCase(n-idx, needle)); + hashHaystack = ((hashHaystack<<1) + foldCase(h-idx, end)); + } + hashHaystack -= foldCase(haystack, end); + + while (haystack >= end) { + hashHaystack += foldCase(haystack, end); + if (hashHaystack == hashNeedle && ucstrnicmp(needle, haystack, sl) == 0) + return haystack - end; + --haystack; + REHASH(foldCase(haystack + sl, end)); + } + } + return -1; +} + +/*! + Returns the index position of the last occurrence of the string \a + str in this string, searching backward from index position \a + from. If \a from is -1 (default), the search starts at the last + character; if \a from is -2, at the next to last character and so + on. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 29 + + \sa indexOf(), contains(), count() +*/ +int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const +{ + const int sl = str.d->size; + if (sl == 1) + return lastIndexOf(QChar(str.d->data[0]), from, cs); + + const int l = d->size; + if (from < 0) + from += l; + int delta = l-sl; + if (from == l && sl == 0) + return from; + if (from < 0 || from >= l || delta < 0) + return -1; + if (from > delta) + from = delta; + + + return lastIndexOfHelper(d->data, from, str.d->data, str.d->size, cs); +} + +/*! + \since 4.5 + Returns the index position of the last occurrence of the string \a + str in this string, searching backward from index position \a + from. If \a from is -1 (default), the search starts at the last + character; if \a from is -2, at the next to last character and so + on. Returns -1 if \a str is not found. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 29 + + \sa indexOf(), contains(), count() +*/ +int QString::lastIndexOf(const QLatin1String &str, int from, Qt::CaseSensitivity cs) const +{ + const int sl = qstrlen(str.latin1()); + if (sl == 1) + return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs); + + const int l = d->size; + if (from < 0) + from += l; + int delta = l-sl; + if (from == l && sl == 0) + return from; + if (from < 0 || from >= l || delta < 0) + return -1; + if (from > delta) + from = delta; + + QVarLengthArray<ushort> s(sl); + for (int i = 0; i < sl; ++i) + s[i] = str.latin1()[i]; + + return lastIndexOfHelper(d->data, from, s.data(), sl, cs); +} + +/*! + \overload lastIndexOf() + + Returns the index position of the last occurrence of the character + \a ch, searching backward from position \a from. +*/ +int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const +{ + ushort c = ch.unicode(); + if (from < 0) + from += d->size; + if (from < 0 || from >= d->size) + return -1; + if (from >= 0) { + const ushort *n = d->data + from; + const ushort *b = d->data; + if (cs == Qt::CaseSensitive) { + for (; n >= b; --n) + if (*n == c) + return n - b; + } else { + c = foldCase(c); + for (; n >= b; --n) + if (foldCase(*n) == c) + return n - b; + } + } + return -1; +} + +#ifndef QT_NO_REGEXP +struct QStringCapture +{ + int pos; + int len; + int no; +}; + +/*! + \overload replace() + + Replaces every occurrence of the regular expression \a rx in the + string with \a after. Returns a reference to the string. For + example: + + \snippet doc/src/snippets/qstring/main.cpp 42 + + For regular expressions containing \l{capturing parentheses}, + occurrences of \bold{\\1}, \bold{\\2}, ..., in \a after are replaced + with \a{rx}.cap(1), cap(2), ... + + \snippet doc/src/snippets/qstring/main.cpp 43 + + \sa indexOf(), lastIndexOf(), remove(), QRegExp::cap() +*/ +QString& QString::replace(const QRegExp &rx, const QString &after) +{ + QRegExp rx2(rx); + + if (isEmpty() && rx2.indexIn(*this) == -1) + return *this; + + realloc(); + + int index = 0; + int numCaptures = rx2.numCaptures(); + int al = after.length(); + QRegExp::CaretMode caretMode = QRegExp::CaretAtZero; + + if (numCaptures > 0) { + const QChar *uc = after.unicode(); + int numBackRefs = 0; + + for (int i = 0; i < al - 1; i++) { + if (uc[i] == QLatin1Char('\\')) { + int no = uc[i + 1].digitValue(); + if (no > 0 && no <= numCaptures) + numBackRefs++; + } + } + + /* + This is the harder case where we have back-references. + */ + if (numBackRefs > 0) { + QVarLengthArray<QStringCapture, 16> captures(numBackRefs); + int j = 0; + + for (int i = 0; i < al - 1; i++) { + if (uc[i] == QLatin1Char('\\')) { + int no = uc[i + 1].digitValue(); + if (no > 0 && no <= numCaptures) { + QStringCapture capture; + capture.pos = i; + capture.len = 2; + + if (i < al - 2) { + int secondDigit = uc[i + 2].digitValue(); + if (secondDigit != -1 && ((no * 10) + secondDigit) <= numCaptures) { + no = (no * 10) + secondDigit; + ++capture.len; + } + } + + capture.no = no; + captures[j++] = capture; + } + } + } + + while (index <= length()) { + index = rx2.indexIn(*this, index, caretMode); + if (index == -1) + break; + + QString after2(after); + for (j = numBackRefs - 1; j >= 0; j--) { + const QStringCapture &capture = captures[j]; + after2.replace(capture.pos, capture.len, rx2.cap(capture.no)); + } + + replace(index, rx2.matchedLength(), after2); + index += after2.length(); + + // avoid infinite loop on 0-length matches (e.g., QRegExp("[a-z]*")) + if (rx2.matchedLength() == 0) + ++index; + + caretMode = QRegExp::CaretWontMatch; + } + return *this; + } + } + + /* + This is the simple and optimized case where we don't have + back-references. + */ + while (index != -1) { + struct { + int pos; + int length; + } replacements[2048]; + + int pos = 0; + int adjust = 0; + while (pos < 2047) { + index = rx2.indexIn(*this, index, caretMode); + if (index == -1) + break; + int ml = rx2.matchedLength(); + replacements[pos].pos = index; + replacements[pos++].length = ml; + index += ml; + adjust += al - ml; + // avoid infinite loop + if (!ml) + index++; + } + if (!pos) + break; + replacements[pos].pos = d->size; + int newlen = d->size + adjust; + + // to continue searching at the right position after we did + // the first round of replacements + if (index != -1) + index += adjust; + QString newstring; + newstring.reserve(newlen + 1); + QChar *newuc = newstring.data(); + QChar *uc = newuc; + int copystart = 0; + int i = 0; + while (i < pos) { + int copyend = replacements[i].pos; + int size = copyend - copystart; + memcpy(uc, d->data + copystart, size * sizeof(QChar)); + uc += size; + memcpy(uc, after.d->data, al * sizeof(QChar)); + uc += al; + copystart = copyend + replacements[i].length; + i++; + } + memcpy(uc, d->data + copystart, (d->size - copystart) * sizeof(QChar)); + newstring.resize(newlen); + *this = newstring; + caretMode = QRegExp::CaretWontMatch; + } + return *this; +} +#endif + +/*! + Returns the number of (potentially overlapping) occurrences of + the string \a str in this string. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \sa contains(), indexOf() +*/ +int QString::count(const QString &str, Qt::CaseSensitivity cs) const +{ + int num = 0; + int i = -1; + if (d->size > 500 && str.d->size > 5) { + QStringMatcher matcher(str, cs); + while ((i = matcher.indexIn(*this, i + 1)) != -1) + ++num; + } else { + while ((i = indexOf(str, i + 1, cs)) != -1) + ++num; + } + return num; +} + +/*! + \overload count() + + Returns the number of occurrences of character \a ch in the string. +*/ +int QString::count(QChar ch, Qt::CaseSensitivity cs) const +{ + ushort c = ch.unicode(); + int num = 0; + const ushort *i = d->data + d->size; + const ushort *b = d->data; + if (cs == Qt::CaseSensitive) { + while (i != b) + if (*--i == c) + ++num; + } else { + c = foldCase(c); + while (i != b) + if (foldCase(*(--i)) == c) + ++num; + } + return num; +} + +/*! \fn bool QString::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + + Returns true if this string contains an occurrence of the string + \a str; otherwise returns false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + Example: + \snippet doc/src/snippets/qstring/main.cpp 17 + + \sa indexOf(), count() +*/ + +/*! \fn bool QString::contains(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + + \overload contains() + + Returns true if this string contains an occurrence of the + character \a ch; otherwise returns false. +*/ + +/*! \fn bool QString::contains(const QRegExp &rx) const + + \overload contains() + + Returns true if the regular expression \a rx matches somewhere in + this string; otherwise returns false. +*/ + +/*! \fn bool QString::contains(QRegExp &rx) const + \overload contains() + \since 4.5 + + Returns true if the regular expression \a rx matches somewhere in + this string; otherwise returns false. + + If there is a match, the \a rx regular expression will contain the + matched captures (see QRegExp::matchedLength, QRegExp::cap). +*/ + +#ifndef QT_NO_REGEXP +/*! + \overload indexOf() + + Returns the index position of the first match of the regular + expression \a rx in the string, searching forward from index + position \a from. Returns -1 if \a rx didn't match anywhere. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 25 +*/ +int QString::indexOf(const QRegExp& rx, int from) const +{ + QRegExp rx2(rx); + return rx2.indexIn(*this, from); +} + +/*! + \overload indexOf() + \since 4.5 + + Returns the index position of the first match of the regular + expression \a rx in the string, searching forward from index + position \a from. Returns -1 if \a rx didn't match anywhere. + + If there is a match, the \a rx regular expression will contain the + matched captures (see QRegExp::matchedLength, QRegExp::cap). + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 25 +*/ +int QString::indexOf(QRegExp& rx, int from) const +{ + return rx.indexIn(*this, from); +} + +/*! + \overload lastIndexOf() + + Returns the index position of the last match of the regular + expression \a rx in the string, searching backward from index + position \a from. Returns -1 if \a rx didn't match anywhere. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 30 +*/ +int QString::lastIndexOf(const QRegExp& rx, int from) const +{ + QRegExp rx2(rx); + return rx2.lastIndexIn(*this, from); +} + +/*! + \overload lastIndexOf() + \since 4.5 + + Returns the index position of the last match of the regular + expression \a rx in the string, searching backward from index + position \a from. Returns -1 if \a rx didn't match anywhere. + + If there is a match, the \a rx regular expression will contain the + matched captures (see QRegExp::matchedLength, QRegExp::cap). + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 30 +*/ +int QString::lastIndexOf(QRegExp& rx, int from) const +{ + return rx.lastIndexIn(*this, from); +} + +/*! + \overload count() + + Returns the number of times the regular expression \a rx matches + in the string. + + This function counts overlapping matches, so in the example + below, there are four instances of "ana" or "ama": + + \snippet doc/src/snippets/qstring/main.cpp 18 + +*/ +int QString::count(const QRegExp& rx) const +{ + QRegExp rx2(rx); + int count = 0; + int index = -1; + int len = length(); + while (index < len - 1) { // count overlapping matches + index = rx2.indexIn(*this, index + 1); + if (index == -1) + break; + count++; + } + return count; +} +#endif // QT_NO_REGEXP + +/*! \fn int QString::count() const + + \overload count() + + Same as size(). +*/ + + +/*! + \enum QString::SectionFlag + + This enum specifies flags that can be used to affect various + aspects of the section() function's behavior with respect to + separators and empty fields. + + \value SectionDefault Empty fields are counted, leading and + trailing separators are not included, and the separator is + compared case sensitively. + + \value SectionSkipEmpty Treat empty fields as if they don't exist, + i.e. they are not considered as far as \e start and \e end are + concerned. + + \value SectionIncludeLeadingSep Include the leading separator (if + any) in the result string. + + \value SectionIncludeTrailingSep Include the trailing separator + (if any) in the result string. + + \value SectionCaseInsensitiveSeps Compare the separator + case-insensitively. + + \sa section() +*/ + +/*! + \fn QString QString::section(QChar sep, int start, int end = -1, SectionFlags flags) const + + This function returns a section of the string. + + This string is treated as a sequence of fields separated by the + character, \a sep. The returned string consists of the fields from + position \a start to position \a end inclusive. If \a end is not + specified, all fields from position \a start to the end of the + string are included. Fields are numbered 0, 1, 2, etc., counting + from the left, and -1, -2, etc., counting from right to left. + + The \a flags argument can be used to affect some aspects of the + function's behavior, e.g. whether to be case sensitive, whether + to skip empty fields and how to deal with leading and trailing + separators; see \l{SectionFlags}. + + \snippet doc/src/snippets/qstring/main.cpp 52 + + If \a start or \a end is negative, we count fields from the right + of the string, the right-most field being -1, the one from + right-most field being -2, and so on. + + \snippet doc/src/snippets/qstring/main.cpp 53 + + \sa split() +*/ + +/*! + \overload section() + + \snippet doc/src/snippets/qstring/main.cpp 51 + \snippet doc/src/snippets/qstring/main.cpp 54 + + \sa split() +*/ + +QString QString::section(const QString &sep, int start, int end, SectionFlags flags) const +{ + QStringList sections = split(sep, KeepEmptyParts, + (flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive : Qt::CaseSensitive); + if (sections.isEmpty()) + return QString(); + if (!(flags & SectionSkipEmpty)) { + if (start < 0) + start += sections.count(); + if (end < 0) + end += sections.count(); + } else { + int skip = 0; + for (int k=0; k<sections.size(); ++k) { + if (sections.at(k).isEmpty()) + skip++; + } + if (start < 0) + start += sections.count() - skip; + if (end < 0) + end += sections.count() - skip; + } + int x = 0; + QString ret; + int first_i = start, last_i = end; + for (int i = 0; x <= end && i < sections.size(); ++i) { + QString section = sections.at(i); + const bool empty = section.isEmpty(); + if (x >= start) { + if(x == start) + first_i = i; + if(x == end) + last_i = i; + if(x > start) + ret += sep; + ret += section; + } + if (!empty || !(flags & SectionSkipEmpty)) + x++; + } + if((flags & SectionIncludeLeadingSep) && first_i) + ret.prepend(sep); + if((flags & SectionIncludeTrailingSep) && last_i < sections.size()-1) + ret += sep; + return ret; +} + +#ifndef QT_NO_REGEXP +class qt_section_chunk { +public: + qt_section_chunk(int l, QString s) { length = l; string = s; } + int length; + QString string; +}; + +/*! + \overload section() + + This string is treated as a sequence of fields separated by the + regular expression, \a reg. + + \snippet doc/src/snippets/qstring/main.cpp 55 + + \warning Using this QRegExp version is much more expensive than + the overloaded string and character versions. + + \sa split() simplified() +*/ +QString QString::section(const QRegExp ®, int start, int end, SectionFlags flags) const +{ + const QChar *uc = unicode(); + if(!uc) + return QString(); + + QRegExp sep(reg); + sep.setCaseSensitivity((flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive + : Qt::CaseSensitive); + + QList<qt_section_chunk> sections; + int n = length(), m = 0, last_m = 0, last_len = 0; + while ((m = sep.indexIn(*this, m)) != -1) { + sections.append(qt_section_chunk(last_len, QString(uc + last_m, m - last_m))); + last_m = m; + last_len = sep.matchedLength(); + m += qMax(sep.matchedLength(), 1); + } + sections.append(qt_section_chunk(last_len, QString(uc + last_m, n - last_m))); + + if(start < 0) + start += sections.count(); + if(end < 0) + end += sections.count(); + + QString ret; + int x = 0; + int first_i = start, last_i = end; + for (int i = 0; x <= end && i < sections.size(); ++i) { + const qt_section_chunk §ion = sections.at(i); + const bool empty = (section.length == section.string.length()); + if (x >= start) { + if(x == start) + first_i = i; + if(x == end) + last_i = i; + if(x != start) + ret += section.string; + else + ret += section.string.mid(section.length); + } + if (!empty || !(flags & SectionSkipEmpty)) + x++; + } + if((flags & SectionIncludeLeadingSep)) { + const qt_section_chunk §ion = sections.at(first_i); + ret.prepend(section.string.left(section.length)); + } + if((flags & SectionIncludeTrailingSep) && last_i+1 <= sections.size()-1) { + const qt_section_chunk §ion = sections.at(last_i+1); + ret += section.string.left(section.length); + } + return ret; +} +#endif + +/*! + Returns a substring that contains the \a n leftmost characters + of the string. + + The entire string is returned if \a n is greater than size() or + less than zero. + + \snippet doc/src/snippets/qstring/main.cpp 31 + + \sa right(), mid(), startsWith() +*/ +QString QString::left(int n) const +{ + if (n >= d->size || n < 0) + return *this; + return QString((const QChar*) d->data, n); +} + +/*! + Returns a substring that contains the \a n rightmost characters + of the string. + + The entire string is returned if \a n is greater than size() or + less than zero. + + \snippet doc/src/snippets/qstring/main.cpp 48 + + \sa left(), mid(), endsWith() +*/ +QString QString::right(int n) const +{ + if (n >= d->size || n < 0) + return *this; + return QString((const QChar*) d->data + d->size - n, n); +} + +/*! + Returns a string that contains \a n characters of this string, + starting at the specified \a position index. + + Returns a null string if the \a position index exceeds the + length of the string. If there are less than \a n characters + available in the string starting at the given \a position, or if + \a n is -1 (default), the function returns all characters that + are available from the specified \a position. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 34 + + \sa left(), right() +*/ + +QString QString::mid(int position, int n) const +{ + if (d == &shared_null || position >= d->size) + return QString(); + if (n < 0) + n = d->size - position; + if (position < 0) { + n += position; + position = 0; + } + if (n + position > d->size) + n = d->size - position; + if (position == 0 && n == d->size) + return *this; + return QString((const QChar*) d->data + position, n); +} + +/*! + Returns true if the string starts with \a s; otherwise returns + false. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + \snippet doc/src/snippets/qstring/main.cpp 65 + + \sa endsWith() +*/ +bool QString::startsWith(const QString& s, Qt::CaseSensitivity cs) const +{ + if (d == &shared_null) + return (s.d == &shared_null); + if (d->size == 0) + return s.d->size == 0; + if (s.d->size > d->size) + return false; + if (cs == Qt::CaseSensitive) { + return memcmp((char*)d->data, (char*)s.d->data, s.d->size*sizeof(QChar)) == 0; + } else { + uint last = 0; + uint olast = 0; + for (int i = 0; i < s.d->size; ++i) + if (foldCase(d->data[i], last) != foldCase(s.d->data[i], olast)) + return false; + } + return true; +} + +/*! + \overload startsWith() + */ +bool QString::startsWith(const QLatin1String& s, Qt::CaseSensitivity cs) const +{ + if (d == &shared_null) + return (s.latin1() == 0); + if (d->size == 0) + return !s.latin1() || *s.latin1() == 0; + int slen = qstrlen(s.latin1()); + if (slen > d->size) + return false; + const uchar *latin = (const uchar *)s.latin1(); + if (cs == Qt::CaseSensitive) { + for (int i = 0; i < slen; ++i) + if (d->data[i] != latin[i]) + return false; + } else { + for (int i = 0; i < slen; ++i) + if (foldCase(d->data[i]) != foldCase((ushort)latin[i])) + return false; + } + return true; +} + +/*! + \overload startsWith() + + Returns true if the string starts with \a c; otherwise returns + false. +*/ +bool QString::startsWith(const QChar &c, Qt::CaseSensitivity cs) const +{ + return d->size + && (cs == Qt::CaseSensitive + ? d->data[0] == c + : foldCase(d->data[0]) == foldCase(c.unicode())); +} + +/*! + Returns true if the string ends with \a s; otherwise returns + false. + + If \a cs is Qt::CaseSensitive (default), the search is case + sensitive; otherwise the search is case insensitive. + + \snippet doc/src/snippets/qstring/main.cpp 20 + + \sa startsWith() +*/ +bool QString::endsWith(const QString& s, Qt::CaseSensitivity cs) const +{ + if (d == &shared_null) + return (s.d == &shared_null); + if (d->size == 0) + return s.d->size == 0; + int pos = d->size - s.d->size; + if (pos < 0) + return false; + if (cs == Qt::CaseSensitive) { + return memcmp((char*)&d->data[pos], (char*)s.d->data, s.d->size*sizeof(QChar)) == 0; + } else { + uint last = 0; + uint olast = 0; + for (int i = 0; i < s.length(); i++) + if (foldCase(d->data[pos+i], last) != foldCase(s.d->data[i], olast)) + return false; + } + return true; +} + +/*! + \overload endsWith() +*/ +bool QString::endsWith(const QLatin1String& s, Qt::CaseSensitivity cs) const +{ + if (d == &shared_null) + return (s.latin1() == 0); + if (d->size == 0) + return !s.latin1() || *s.latin1() == 0; + int slen = qstrlen(s.latin1()); + int pos = d->size - slen; + const uchar *latin = (const uchar *)s.latin1(); + if (pos < 0) + return false; + if (cs == Qt::CaseSensitive) { + for (int i = 0; i < slen; i++) + if (d->data[pos+i] != latin[i]) + return false; + } else { + for (int i = 0; i < slen; i++) + if (foldCase(d->data[pos+i]) != foldCase((ushort)latin[i])) + return false; + } + return true; +} + +/*! + Returns true if the string ends with \a c; otherwise returns + false. + + \overload endsWith() + */ +bool QString::endsWith(const QChar &c, Qt::CaseSensitivity cs) const +{ + return d->size + && (cs == Qt::CaseSensitive + ? d->data[d->size - 1] == c + : foldCase(d->data[d->size - 1]) == foldCase(c.unicode())); +} + +/*! \fn const char *QString::ascii() const + \nonreentrant + + Use toAscii() instead. +*/ + +/*! \fn const char *QString::latin1() const + \nonreentrant + + Use toLatin1() instead. +*/ + +/*! \fn const char *QString::utf8() const + \nonreentrant + + Use toUtf8() instead. +*/ + +/*! \fn const char *QString::local8Bit() const + \nonreentrant + + Use toLocal8Bit() instead. +*/ + +static QByteArray toLatin1_helper(const QChar *data, int length) +{ + QByteArray ba; + if (length) { + ba.resize(length); + const ushort *i = reinterpret_cast<const ushort *>(data); + const ushort *e = i + length; + uchar *s = (uchar*) ba.data(); + while (i != e) { + *s++ = (*i>0xff) ? '?' : (uchar) *i; + ++i; + } + } + return ba; +} + +/*! + Returns a Latin-1 representation of the string as a QByteArray. + The returned byte array is undefined if the string contains + non-Latin1 characters. + + \sa fromLatin1(), toAscii(), toUtf8(), toLocal8Bit(), QTextCodec +*/ +QByteArray QString::toLatin1() const +{ + return toLatin1_helper(unicode(), length()); +} + +// ### Qt 5: Change the return type of at least toAscii(), +// toLatin1() and unicode() such that the use of Q_COMPILER_MANGLES_RETURN_TYPE +// isn't necessary in the header. See task 177402. + +/*! + Returns an 8-bit ASCII representation of the string as a QByteArray. + + If a codec has been set using QTextCodec::setCodecForCStrings(), + it is used to convert Unicode to 8-bit char; otherwise this + function does the same as toLatin1(). + + \sa fromAscii(), toLatin1(), toUtf8(), toLocal8Bit(), QTextCodec +*/ +QByteArray QString::toAscii() const +{ +#ifndef QT_NO_TEXTCODEC + if (codecForCStrings) + return codecForCStrings->fromUnicode(*this); +#endif // QT_NO_TEXTCODEC + return toLatin1(); +} + +#ifndef Q_WS_MAC +static QByteArray toLocal8Bit_helper(const QChar *data, int length) +{ +#ifndef QT_NO_TEXTCODEC + if (QTextCodec::codecForLocale()) + return QTextCodec::codecForLocale()->fromUnicode(data, length); +#endif // QT_NO_TEXTCODEC + return toLatin1_helper(data, length); +} +#endif + +/*! + Returns the local 8-bit representation of the string as a + QByteArray. The returned byte array is undefined if the string + contains characters not supported by the local 8-bit encoding. + + QTextCodec::codecForLocale() is used to perform the conversion + from Unicode. + + \sa fromLocal8Bit(), toAscii(), toLatin1(), toUtf8(), QTextCodec +*/ +QByteArray QString::toLocal8Bit() const +{ +#ifndef QT_NO_TEXTCODEC + if (QTextCodec::codecForLocale()) + return QTextCodec::codecForLocale()->fromUnicode(*this); +#endif // QT_NO_TEXTCODEC + return toLatin1(); +} + +/*! + Returns a UTF-8 representation of the string as a QByteArray. + + \sa fromUtf8(), toAscii(), toLatin1(), toLocal8Bit(), QTextCodec +*/ +QByteArray QString::toUtf8() const +{ + QByteArray ba; + if (d->size) { + int l = d->size; + int rlen = l*3+1; + ba.resize(rlen); + uchar *cursor = (uchar*)ba.data(); + const ushort *ch =d->data; + for (int i=0; i < l; i++) { + uint u = *ch; + if (u < 0x80) { + *cursor++ = (uchar)u; + } else { + if (u < 0x0800) { + *cursor++ = 0xc0 | ((uchar) (u >> 6)); + } else { + if (QChar(u).isHighSurrogate() && i < l-1) { + ushort low = ch[1]; + if (QChar(low).isLowSurrogate()) { + ++ch; + ++i; + u = QChar::surrogateToUcs4(u,low); + } + } + if (u > 0xffff) { + *cursor++ = 0xf0 | ((uchar) (u >> 18)); + *cursor++ = 0x80 | (((uchar) (u >> 12)) & 0x3f); + } else { + *cursor++ = 0xe0 | ((uchar) (u >> 12)); + } + *cursor++ = 0x80 | (((uchar) (u >> 6)) & 0x3f); + } + *cursor++ = 0x80 | ((uchar) (u&0x3f)); + } + ++ch; + } + ba.resize(cursor - (uchar*)ba.constData()); + } + return ba; +} + +/*! + \since 4.2 + + Returns a UCS-4 representation of the string as a QVector<uint>. + + \sa fromUtf8(), toAscii(), toLatin1(), toLocal8Bit(), QTextCodec, fromUcs4(), toWCharArray() +*/ +QVector<uint> QString::toUcs4() const +{ + QVector<uint> v(length()); + uint *a = v.data(); + const unsigned short *uc = utf16(); + for (int i = 0; i < length(); ++i) { + uint u = uc[i]; + if (QChar(u).isHighSurrogate() && i < length()-1) { + ushort low = uc[i+1]; + if (QChar(low).isLowSurrogate()) { + ++i; + u = QChar::surrogateToUcs4(u, low); + } + } + *a = u; + ++a; + } + v.resize(a - v.data()); + return v; +} + +QString::Data *QString::fromLatin1_helper(const char *str, int size) +{ + Data *d; + if (!str) { + d = &shared_null; + d->ref.ref(); + } else if (size == 0 || (!*str && size < 0)) { + d = &shared_empty; + d->ref.ref(); + } else { + if (size < 0) + size = qstrlen(str); + d = static_cast<Data *>(qMalloc(sizeof(Data) + size * sizeof(QChar))); + d->ref = 1; + d->alloc = d->size = size; + d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0; + d->data = d->array; + ushort *i = d->data; + d->array[size] = '\0'; + while (size--) + *i++ = (uchar)*str++; + } + return d; +} + +QString::Data *QString::fromAscii_helper(const char *str, int size) +{ +#ifndef QT_NO_TEXTCODEC + if (codecForCStrings) { + Data *d; + if (!str) { + d = &shared_null; + d->ref.ref(); + } else if (size == 0 || (!*str && size < 0)) { + d = &shared_empty; + d->ref.ref(); + } else { + if (size < 0) + size = qstrlen(str); + QString s = codecForCStrings->toUnicode(str, size); + d = s.d; + d->ref.ref(); + } + return d; + } +#endif + return fromLatin1_helper(str, size); +} + +/*! + Returns a QString initialized with the first \a size characters + of the Latin-1 string \a str. + + If \a size is -1 (default), it is taken to be qstrlen(\a + str). + + \sa toLatin1(), fromAscii(), fromUtf8(), fromLocal8Bit() +*/ +QString QString::fromLatin1(const char *str, int size) +{ + return QString(fromLatin1_helper(str, size), 0); +} + + +#ifdef QT3_SUPPORT + +/*! + \internal +*/ +const char *QString::ascii_helper() const +{ + if (!asciiCache) + asciiCache = new QHash<void *, QByteArray>(); + + d->asciiCache = true; + QByteArray ascii = toAscii(); + QByteArray old = asciiCache->value(d); + if (old == ascii) + return old.constData(); + asciiCache->insert(d, ascii); + return ascii.constData(); +} + +/*! + \internal +*/ +const char *QString::latin1_helper() const +{ + if (!asciiCache) + asciiCache = new QHash<void *, QByteArray>(); + + d->asciiCache = true; + QByteArray ascii = toLatin1(); + QByteArray old = asciiCache->value(d); + if (old == ascii) + return old.constData(); + asciiCache->insert(d, ascii); + return ascii.constData(); +} + +#endif + +QT_END_NAMESPACE + +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) +#include "qt_windows.h" + +QT_BEGIN_NAMESPACE + +QByteArray qt_winQString2MB(const QString& s, int uclen) +{ + if (uclen < 0) + uclen = s.length(); + if (s.isNull()) + return QByteArray(); + if (uclen == 0) + return QByteArray(""); + return qt_winQString2MB(s.constData(), uclen); +} + +QByteArray qt_winQString2MB(const QChar *ch, int uclen) +{ + if (!ch) + return QByteArray(); + if (uclen == 0) + return QByteArray(""); + BOOL used_def; + QByteArray mb(4096, 0); + int len; + while (!(len=WideCharToMultiByte(CP_ACP, 0, (const WCHAR*)ch, uclen, + mb.data(), mb.size()-1, 0, &used_def))) + { + int r = GetLastError(); + if (r == ERROR_INSUFFICIENT_BUFFER) { + mb.resize(1+WideCharToMultiByte(CP_ACP, 0, + (const WCHAR*)ch, uclen, + 0, 0, 0, &used_def)); + // and try again... + } else { +#ifndef QT_NO_DEBUG + // Fail. + qWarning("WideCharToMultiByte: Cannot convert multibyte text (error %d): %s (UTF-8)", + r, QString(ch, uclen).toLocal8Bit().data()); +#endif + break; + } + } + mb.resize(len); + return mb; +} + +QString qt_winMB2QString(const char *mb, int mblen) +{ + if (!mb || !mblen) + return QString(); + const int wclen_auto = 4096; + WCHAR wc_auto[wclen_auto]; + int wclen = wclen_auto; + WCHAR *wc = wc_auto; + int len; + while (!(len=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, + mb, mblen, wc, wclen))) + { + int r = GetLastError(); + if (r == ERROR_INSUFFICIENT_BUFFER) { + if (wc != wc_auto) { + qWarning("MultiByteToWideChar: Size changed"); + break; + } else { + wclen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, + mb, mblen, 0, 0); + wc = new WCHAR[wclen]; + // and try again... + } + } else { + // Fail. + qWarning("MultiByteToWideChar: Cannot convert multibyte text"); + break; + } + } + if (len <= 0) + return QString(); + if (wc[len-1] == 0) // len - 1: we don't want terminator + --len; + QString s((QChar*)wc, len); + if (wc != wc_auto) + delete [] wc; + return s; +} + +QT_END_NAMESPACE + +#endif // Q_OS_WIN32 + +QT_BEGIN_NAMESPACE + +/*! + Returns a QString initialized with the first \a size characters + of the 8-bit string \a str. + + If \a size is -1 (default), it is taken to be qstrlen(\a + str). + + QTextCodec::codecForLocale() is used to perform the conversion + from Unicode. + + \sa toLocal8Bit(), fromAscii(), fromLatin1(), fromUtf8() +*/ +QString QString::fromLocal8Bit(const char *str, int size) +{ + if (!str) + return QString(); + if (size == 0 || (!*str && size < 0)) + return QLatin1String(""); +#if defined(Q_OS_WIN32) + if(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { + return qt_winMB2QString(str, size); + } +#endif +#if !defined(QT_NO_TEXTCODEC) + if (size < 0) + size = qstrlen(str); + QTextCodec *codec = QTextCodec::codecForLocale(); + if (codec) + return codec->toUnicode(str, size); +#endif // !QT_NO_TEXTCODEC + return fromLatin1(str, size); +} + +/*! + Returns a QString initialized with the first \a size characters + of the 8-bit ASCII string \a str. + + If \a size is -1 (default), it is taken to be qstrlen(\a + str). + + If a codec has been set using QTextCodec::setCodecForCStrings(), + it is used to convert \a str to Unicode; otherwise this function + does the same as fromLatin1(). + + \sa toAscii(), fromLatin1(), fromUtf8(), fromLocal8Bit() +*/ +QString QString::fromAscii(const char *str, int size) +{ + return QString(fromAscii_helper(str, size), 0); +} + +/*! + Returns a QString initialized with the first \a size bytes + of the UTF-8 string \a str. + + If \a size is -1 (default), it is taken to be qstrlen(\a + str). + + \sa toUtf8(), fromAscii(), fromLatin1(), fromLocal8Bit() +*/ +QString QString::fromUtf8(const char *str, int size) +{ + if (!str) + return QString(); + if (size < 0) + size = qstrlen(str); + + QString result; + result.resize(size); // worst case + ushort *qch = result.d->data; + uint uc = 0; + uint min_uc = 0; + int need = 0; + int error = -1; + uchar ch; + int i = 0; + + // skip utf8-encoded byte order mark + if (size >= 3 + && (uchar)str[0] == 0xef && (uchar)str[1] == 0xbb && (uchar)str[2] == 0xbf) + i += 3; + + for (; i < size; ++i) { + ch = str[i]; + if (need) { + if ((ch&0xc0) == 0x80) { + uc = (uc << 6) | (ch & 0x3f); + need--; + if (!need) { + if (uc > 0xffffU && uc < 0x110000U) { + // surrogate pair + *qch++ = QChar::highSurrogate(uc); + uc = QChar::lowSurrogate(uc); + } else if ((uc < min_uc) || (uc >= 0xd800 && uc <= 0xdfff) || (uc >= 0xfffe)) { + // overlong seqence, UTF16 surrogate or BOM + uc = QChar::ReplacementCharacter; + } + *qch++ = uc; + } + } else { + i = error; + need = 0; + *qch++ = QChar::ReplacementCharacter; + } + } else { + if (ch < 128) { + *qch++ = ch; + } else if ((ch & 0xe0) == 0xc0) { + uc = ch & 0x1f; + need = 1; + error = i; + min_uc = 0x80; + } else if ((ch & 0xf0) == 0xe0) { + uc = ch & 0x0f; + need = 2; + error = i; + min_uc = 0x800; + } else if ((ch&0xf8) == 0xf0) { + uc = ch & 0x07; + need = 3; + error = i; + min_uc = 0x10000; + } else { + // Error + *qch++ = QChar::ReplacementCharacter; + } + } + } + if (need) { + // we have some invalid characters remaining we need to add to the string + for (int i = error; i < size; ++i) + *qch++ = QChar::ReplacementCharacter; + } + + result.truncate(qch - result.d->data); + return result; +} + +/*! + Returns a QString initialized with the first \a size characters + of the Unicode string \a unicode (ISO-10646-UTF-16 encoded). + + If \a size is -1 (default), \a unicode must be terminated + with a 0. + + QString makes a deep copy of the Unicode data. + + \sa utf16(), setUtf16() +*/ +QString QString::fromUtf16(const ushort *unicode, int size) +{ + if (!unicode) + return QString(); + if (size < 0) { + size = 0; + while (unicode[size] != 0) + ++size; + } + return QString((const QChar *)unicode, size); +} + + +/*! + \since 4.2 + + Returns a QString initialized with the first \a size characters + of the Unicode string \a unicode (ISO-10646-UCS-4 encoded). + + If \a size is -1 (default), \a unicode must be terminated + with a 0. + + \sa toUcs4(), fromUtf16(), utf16(), setUtf16(), fromWCharArray() +*/ +QString QString::fromUcs4(const uint *unicode, int size) +{ + if (!unicode) + return QString(); + if (size < 0) { + size = 0; + while (unicode[size] != 0) + ++size; + } + + QString s; + s.resize(size*2); // worst case + ushort *uc = s.d->data; + for (int i = 0; i < size; ++i) { + uint u = unicode[i]; + if (u > 0xffff) { + // decompose into a surrogate pair + *uc++ = QChar::highSurrogate(u); + u = QChar::lowSurrogate(u); + } + *uc++ = u; + } + s.resize(uc - s.d->data); + return s; +} + +/*! + Resizes the string to \a size characters and copies \a unicode + into the string. + + If \a unicode is 0, nothing is copied, but the string is still + resized to \a size. + + \sa unicode(), setUtf16() +*/ +QString& QString::setUnicode(const QChar *unicode, int size) +{ + resize(size); + if (unicode && size) + memcpy(d->data, unicode, size * sizeof(QChar)); + return *this; +} + +/*! + \fn QString &QString::setUtf16(const ushort *unicode, int size) + + Resizes the string to \a size characters and copies \a unicode + into the string. + + If \a unicode is 0, nothing is copied, but the string is still + resized to \a size. + + \sa utf16(), setUnicode() +*/ + +/*! + Returns a string that has whitespace removed from the start + and the end, and that has each sequence of internal whitespace + replaced with a single space. + + Whitespace means any character for which QChar::isSpace() returns + true. This includes the ASCII characters '\\t', '\\n', '\\v', + '\\f', '\\r', and ' '. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 57 + + \sa trimmed() +*/ +QString QString::simplified() const +{ + if (d->size == 0) + return *this; + QString result; + result.resize(d->size); + const QChar *from = (const QChar*) d->data; + const QChar *fromend = (const QChar*) from+d->size; + int outc=0; + QChar *to = (QChar*) result.d->data; + for (;;) { + while (from!=fromend && from->isSpace()) + from++; + while (from!=fromend && !from->isSpace()) + to[outc++] = *from++; + if (from!=fromend) + to[outc++] = QLatin1Char(' '); + else + break; + } + if (outc > 0 && to[outc-1] == QLatin1Char(' ')) + outc--; + result.truncate(outc); + return result; +} + +/*! + Returns a string that has whitespace removed from the start and + the end. + + Whitespace means any character for which QChar::isSpace() returns + true. This includes the ASCII characters '\\t', '\\n', '\\v', + '\\f', '\\r', and ' '. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 82 + + Unlike simplified(), trimmed() leaves internal whitespace alone. + + \sa simplified() +*/ +QString QString::trimmed() const +{ + if (d->size == 0) + return *this; + const QChar *s = (const QChar*)d->data; + if (!s->isSpace() && !s[d->size-1].isSpace()) + return *this; + int start = 0; + int end = d->size - 1; + while (start<=end && s[start].isSpace()) // skip white space from start + start++; + if (start <= end) { // only white space + while (end && s[end].isSpace()) // skip white space from end + end--; + } + int l = end - start + 1; + if (l <= 0) { + shared_empty.ref.ref(); + return QString(&shared_empty, 0); + } + return QString(s + start, l); +} + +/*! \fn const QChar QString::at(int position) const + + Returns the character at the given index \a position in the + string. + + The \a position must be a valid index position in the string + (i.e., 0 <= \a position < size()). + + \sa operator[]() +*/ + +/*! + \fn QCharRef QString::operator[](int position) + + Returns the character at the specified \a position in the string as a + modifiable reference. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 85 + + The return value is of type QCharRef, a helper class for QString. + When you get an object of type QCharRef, you can use it as if it + were a QChar &. If you assign to it, the assignment will apply to + the character in the QString from which you got the reference. + + \sa at() +*/ + +/*! + \fn const QChar QString::operator[](int position) const + + \overload operator[]() +*/ + +/*! \fn QCharRef QString::operator[](uint position) + +\overload operator[]() + +Returns the character at the specified \a position in the string as a +modifiable reference. Equivalent to \c at(position). +*/ + +/*! \fn const QChar QString::operator[](uint position) const + +\overload operator[]() +*/ + +/*! + \fn void QString::truncate(int position) + + Truncates the string at the given \a position index. + + If the specified \a position index is beyond the end of the + string, nothing happens. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 83 + + If \a position is negative, it is equivalent to passing zero. + + \sa chop(), resize(), left() +*/ + +void QString::truncate(int pos) +{ + if (pos < d->size) + resize(pos); +} + + +/*! + Removes \a n characters from the end of the string. + + If \a n is greater than size(), the result is an empty string. + + Example: + \snippet doc/src/snippets/qstring/main.cpp 15 + + If you want to remove characters from the \e beginning of the + string, use remove() instead. + + \sa truncate(), resize(), remove() +*/ +void QString::chop(int n) +{ + if (n > 0) + resize(d->size - n); +} + +/*! + Sets every character in the string to character \a ch. If \a size + is different from -1 (default), the string is resized to \a + size beforehand. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 21 + + \sa resize() +*/ + +QString& QString::fill(QChar ch, int size) +{ + resize(size < 0 ? d->size : size); + if (d->size) { + QChar *i = (QChar*)d->data + d->size; + QChar *b = (QChar*)d->data; + while (i != b) + *--i = ch; + } + return *this; +} + +/*! + \fn int QString::length() const + + Returns the number of characters in this string. Equivalent to + size(). + + \sa setLength() +*/ + +/*! + \fn int QString::size() const + + Returns the number of characters in this string. + + The last character in the string is at position size() - 1. In + addition, QString ensures that the character at position size() + is always '\\0', so that you can use the return value of data() + and constData() as arguments to functions that expect + '\\0'-terminated strings. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 58 + + \sa isEmpty(), resize() +*/ + +/*! \fn bool QString::isNull() const + + Returns true if this string is null; otherwise returns false. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 28 + + Qt makes a distinction between null strings and empty strings for + historical reasons. For most applications, what matters is + whether or not a string contains any data, and this can be + determined using the isEmpty() function. + + \sa isEmpty() +*/ + +/*! \fn bool QString::isEmpty() const + + Returns true if the string has no characters; otherwise returns + false. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 27 + + \sa size() +*/ + +/*! \fn QString &QString::operator+=(const QString &other) + + Appends the string \a other onto the end of this string and + returns a reference to this string. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 84 + + This operation is typically very fast (\l{constant time}), + because QString preallocates extra space at the end of the string + data so it can grow without reallocating the entire string each + time. + + \sa append(), prepend() +*/ + +/*! \fn QString &QString::operator+=(const QLatin1String &str) + + \overload operator+=() + + Appends the Latin-1 string \a str to this string. +*/ + +/*! \fn QString &QString::operator+=(const QByteArray &ba) + + \overload operator+=() + + Appends the byte array \a ba to this string. The byte array is + converted to Unicode using the fromAscii() function. + + You can disable this function by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! \fn QString &QString::operator+=(const char *str) + + \overload operator+=() + + Appends the string \a str to this string. The const char pointer + is converted to Unicode using the fromAscii() function. + + You can disable this function by defining \c QT_NO_CAST_FROM_ASCII + when you compile your applications. This can be useful if you want + to ensure that all user-visible strings go through QObject::tr(), + for example. +*/ + +/*! \fn QString &QString::operator+=(const QStringRef &str) + + \overload operator+=() + + Appends the string section referenced by \a str to this string. +*/ + +/*! \fn QString &QString::operator+=(char ch) + + \overload operator+=() + + Appends the character \a ch to this string. The character is + converted to Unicode using the fromAscii() function. + + You can disable this function by defining \c QT_NO_CAST_FROM_ASCII + when you compile your applications. This can be useful if you want + to ensure that all user-visible strings go through QObject::tr(), + for example. +*/ + +/*! \fn QString &QString::operator+=(QChar ch) + + \overload operator+=() + + Appends the character \a ch to the string. +*/ + +/*! \fn QString &QString::operator+=(QChar::SpecialCharacter c) + + \overload operator+=() + + \internal +*/ + +/*! + \fn bool operator==(const char *s1, const QString &s2) + + \overload operator==() + \relates QString + + Returns true if \a s1 is equal to \a s2; otherwise returns false. + Note that no string is equal to \a s1 being 0. + + Equivalent to \c {s1 != 0 && compare(s1, s2) == 0}. + + \sa QString::compare() +*/ + +/*! + \fn bool operator!=(const char *s1, const QString &s2) + \relates QString + + Returns true if \a s1 is not equal to \a s2; otherwise returns + false. + + For \a s1 != 0, this is equivalent to \c {compare(} \a s1, \a s2 + \c {) != 0}. Note that no string is equal to \a s1 being 0. + + \sa QString::compare() +*/ + +/*! + \fn bool operator<(const char *s1, const QString &s2) + \relates QString + + Returns true if \a s1 is lexically less than \a s2; otherwise + returns false. For \a s1 != 0, this is equivalent to \c + {compare(s1, s2) < 0}. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings using the + QString::localeAwareCompare() function. + + \sa QString::compare() +*/ + +/*! + \fn bool operator<=(const char *s1, const QString &s2) + \relates QString + + Returns true if \a s1 is lexically less than or equal to \a s2; + otherwise returns false. For \a s1 != 0, this is equivalent to \c + {compare(s1, s2) <= 0}. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings with + QString::localeAwareCompare(). + + \sa QString::compare() +*/ + +/*! + \fn bool operator>(const char *s1, const QString &s2) + \relates QString + + Returns true if \a s1 is lexically greater than \a s2; otherwise + returns false. Equivalent to \c {compare(s1, s2) > 0}. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings using the + QString::localeAwareCompare() function. + + \sa QString::compare() +*/ + +/*! + \fn bool operator>=(const char *s1, const QString &s2) + \relates QString + + Returns true if \a s1 is lexically greater than or equal to \a s2; + otherwise returns false. For \a s1 != 0, this is equivalent to \c + {compare(s1, s2) >= 0}. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings using the + QString::localeAwareCompare() function. +*/ + +/*! + \fn const QString operator+(const QString &s1, const QString &s2) + \relates QString + + Returns a string which is the result of concatenating \a s1 and \a + s2. +*/ + +/*! + \fn const QString operator+(const QString &s1, const char *s2) + \relates QString + + Returns a string which is the result of concatenating \a s1 and \a + s2 (\a s2 is converted to Unicode using the QString::fromAscii() + function). + + \sa QString::fromAscii() +*/ + +/*! + \fn const QString operator+(const char *s1, const QString &s2) + \relates QString + + Returns a string which is the result of concatenating \a s1 and \a + s2 (\a s1 is converted to Unicode using the QString::fromAscii() + function). + + \sa QString::fromAscii() +*/ + +/*! + \fn const QString operator+(const QString &s, char ch) + \relates QString + + Returns a string which is the result of concatenating the string + \a s and the character \a ch. +*/ + +/*! + \fn const QString operator+(char ch, const QString &s) + \relates QString + + Returns a string which is the result of concatenating the + character \a ch and the string \a s. +*/ + +/*! + \fn int QString::compare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs) + \since 4.2 + + Compares \a s1 with \a s2 and returns an integer less than, equal + to, or greater than zero if \a s1 is less than, equal to, or + greater than \a s2. + + If \a cs is Qt::CaseSensitive, the comparison is case sensitive; + otherwise the comparison is case insensitive. + + Case sensitive comparison is based exclusively on the numeric + Unicode values of the characters and is very fast, but is not what + a human would expect. Consider sorting user-visible strings with + localeAwareCompare(). + + \snippet doc/src/snippets/qstring/main.cpp 16 + + \sa operator==(), operator<(), operator>() +*/ + +/*! + \fn int QString::compare(const QString & s1, const QString & s2) + + \overload compare() + + Performs a case sensitive compare of \a s1 and \a s2. +*/ + +/*! + \fn int QString::compare(const QString &s1, const QLatin1String &s2, Qt::CaseSensitivity cs) + \since 4.2 + \overload compare() + + Performs a comparison of \a s1 and \a s2, using the case + sensitivity setting \a cs. +*/ + +/*! + \fn int QString::compare(const QLatin1String &s1, const QString &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive) + + \since 4.2 + \overload compare() + + Performs a comparison of \a s1 and \a s2, using the case + sensitivity setting \a cs. +*/ + +/*! + \overload compare() + + Lexically compares this string with the \a other string and + returns an integer less than, equal to, or greater than zero if + this string is less than, equal to, or greater than the other + string. + + Equivalent to \c {compare(*this, other)}. +*/ +int QString::compare(const QString &other) const +{ + return ucstrcmp(constData(), length(), other.constData(), other.length()); +} + +/*! + \overload compare() + \since 4.2 + + Same as compare(*this, \a other, \a cs). +*/ +int QString::compare(const QString &other, Qt::CaseSensitivity cs) const +{ + if (cs == Qt::CaseSensitive) + return ucstrcmp(constData(), length(), other.constData(), other.length()); + return ucstricmp(d->data, d->data + d->size, other.d->data, other.d->data + other.d->size); +} + +/*! + \internal + \since 4.5 +*/ +int QString::compare_helper(const QChar *data1, int length1, const QChar *data2, int length2, + Qt::CaseSensitivity cs) +{ + if (cs == Qt::CaseSensitive) + return ucstrcmp(data1, length1, data2, length2); + register const ushort *s1 = reinterpret_cast<const ushort *>(data1); + register const ushort *s2 = reinterpret_cast<const ushort *>(data2); + return ucstricmp(s1, s1 + length1, s2, s2 + length2); +} + +/*! + \overload compare() + \since 4.2 + + Same as compare(*this, \a other, \a cs). +*/ +int QString::compare(const QLatin1String &other, Qt::CaseSensitivity cs) const +{ + return compare_helper(unicode(), length(), other, cs); +} + +/*! + \fn int QString::compare(const QStringRef &ref, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + \overload compare() + + Compares the string reference, \a ref, with the string and returns + an integer less than, equal to, or greater than zero if the string + is less than, equal to, or greater than \a ref. +*/ + +/*! + \fn int QString::compare(const QString &s1, const QStringRef &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive) + \overload compare() +*/ + +/*! + \internal + \since 4.5 +*/ +int QString::compare_helper(const QChar *data1, int length1, QLatin1String s2, + Qt::CaseSensitivity cs) +{ + const ushort *uc = reinterpret_cast<const ushort *>(data1); + const ushort *e = uc + length1; + const uchar *c = (uchar *)s2.latin1(); + + if (!c) + return length1; + + if (cs == Qt::CaseSensitive) { + while (uc != e && *c && *uc == *c) + uc++, c++; + + return *uc - *c; + } else { + return ucstricmp(uc, e, c); + } +} + +/*! + \fn int QString::localeAwareCompare(const QString & s1, const QString & s2) + + Compares \a s1 with \a s2 and returns an integer less than, equal + to, or greater than zero if \a s1 is less than, equal to, or + greater than \a s2. + + The comparison is performed in a locale- and also + platform-dependent manner. Use this function to present sorted + lists of strings to the user. + + On Mac OS X since Qt 4.3, this function compares according the + "Order for sorted lists" setting in the International prefereces panel. + + \sa compare(), QTextCodec::locale() +*/ + +/*! + \fn int QString::localeAwareCompare(const QStringRef &other) const + \since 4.5 + \overload localeAwareCompare() + + Compares this string with the \a other string and returns an + integer less than, equal to, or greater than zero if this string + is less than, equal to, or greater than the \a other string. + + The comparison is performed in a locale- and also + platform-dependent manner. Use this function to present sorted + lists of strings to the user. + + Same as \c {localeAwareCompare(*this, other)}. +*/ + +/*! + \fn int QString::localeAwareCompare(const QString &s1, const QStringRef &s2) + \since 4.5 + \overload localeAwareCompare() + + Compares \a s1 with \a s2 and returns an integer less than, equal + to, or greater than zero if \a s1 is less than, equal to, or + greater than \a s2. + + The comparison is performed in a locale- and also + platform-dependent manner. Use this function to present sorted + lists of strings to the user. +*/ + + +#if !defined(CSTR_LESS_THAN) +#define CSTR_LESS_THAN 1 +#define CSTR_EQUAL 2 +#define CSTR_GREATER_THAN 3 +#endif + +/*! + \overload localeAwareCompare() + + Compares this string with the \a other string and returns an + integer less than, equal to, or greater than zero if this string + is less than, equal to, or greater than the \a other string. + + The comparison is performed in a locale- and also + platform-dependent manner. Use this function to present sorted + lists of strings to the user. + + Same as \c {localeAwareCompare(*this, other)}. +*/ +int QString::localeAwareCompare(const QString &other) const +{ + return localeAwareCompare_helper(constData(), length(), other.constData(), other.length()); +} + +/*! + \internal + \since 4.5 +*/ +int QString::localeAwareCompare_helper(const QChar *data1, int length1, + const QChar *data2, int length2) +{ + // do the right thing for null and empty + if (length1 == 0 || length2 == 0) + return ucstrcmp(data1, length1, data2, length2); + +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) + int res; + QT_WA({ + const TCHAR* s1 = (TCHAR*)data1; + const TCHAR* s2 = (TCHAR*)data2; + res = CompareStringW(GetUserDefaultLCID(), 0, s1, length1, s2, length2); + } , { + QByteArray s1 = toLocal8Bit_helper(data1, length1); + QByteArray s2 = toLocal8Bit_helper(data2, length2); + res = CompareStringA(GetUserDefaultLCID(), 0, s1.data(), s1.length(), s2.data(), s2.length()); + }); + + switch (res) { + case CSTR_LESS_THAN: + return -1; + case CSTR_GREATER_THAN: + return 1; + default: + return 0; + } +#elif defined (Q_OS_MAC) + // Use CFStringCompare for comparing strings on Mac. This makes Qt order + // strings the same way as native applications do, and also respects + // the "Order for sorted lists" setting in the International preferences + // panel. + const CFStringRef thisString = + CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, + reinterpret_cast<const UniChar *>(data1), length1, kCFAllocatorNull); + const CFStringRef otherString = + CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, + reinterpret_cast<const UniChar *>(data2), length2, kCFAllocatorNull); + + const int result = CFStringCompare(thisString, otherString, kCFCompareLocalized); + CFRelease(thisString); + CFRelease(otherString); + return result; +#elif defined(Q_OS_UNIX) + // declared in <string.h> + int delta = strcoll(toLocal8Bit_helper(data1, length1), toLocal8Bit_helper(data2, length2)); + if (delta == 0) + delta = ucstrcmp(data1, length1, data2, length2); + return delta; +#else + return ucstrcmp(data1, length1, data2, length2); +#endif +} + + +/*! + \fn const QChar *QString::unicode() const + + Returns a '\\0'-terminated Unicode representation of the string. + The result remains valid until the string is modified. + + \sa utf16() +*/ + +/*! + \fn const ushort *QString::utf16() const + + Returns the QString as a '\\0\'-terminated array of unsigned + shorts. The result remains valid until the string is modified. + + \sa unicode() +*/ + +const ushort *QString::utf16() const +{ + if (d->data != d->array) { + QString *that = const_cast<QString*>(this); + that->realloc(); // ensure '\\0'-termination for ::fromRawData strings + return that->d->data; + } + return d->array; +} + +/*! + Returns a string of size \a width that contains this string + padded by the \a fill character. + + If \a truncate is false and the size() of the string is more than + \a width, then the returned string is a copy of the string. + + \snippet doc/src/snippets/qstring/main.cpp 32 + + If \a truncate is true and the size() of the string is more than + \a width, then any characters in a copy of the string after + position \a width are removed, and the copy is returned. + + \snippet doc/src/snippets/qstring/main.cpp 33 + + \sa rightJustified() +*/ + +QString QString::leftJustified(int width, QChar fill, bool truncate) const +{ + QString result; + int len = length(); + int padlen = width - len; + if (padlen > 0) { + result.resize(len+padlen); + if (len) + memcpy(result.d->data, d->data, sizeof(QChar)*len); + QChar *uc = (QChar*)result.d->data + len; + while (padlen--) + * uc++ = fill; + } else { + if (truncate) + result = left(width); + else + result = *this; + } + return result; +} + +/*! + Returns a string of size() \a width that contains the \a fill + character followed by the string. For example: + + \snippet doc/src/snippets/qstring/main.cpp 49 + + If \a truncate is false and the size() of the string is more than + \a width, then the returned string is a copy of the string. + + If \a truncate is true and the size() of the string is more than + \a width, then the resulting string is truncated at position \a + width. + + \snippet doc/src/snippets/qstring/main.cpp 50 + + \sa leftJustified() +*/ + +QString QString::rightJustified(int width, QChar fill, bool truncate) const +{ + QString result; + int len = length(); + int padlen = width - len; + if (padlen > 0) { + result.resize(len+padlen); + QChar *uc = (QChar*)result.d->data; + while (padlen--) + * uc++ = fill; + if (len) + memcpy(uc, d->data, sizeof(QChar)*len); + } else { + if (truncate) + result = left(width); + else + result = *this; + } + return result; +} + +/*! + Returns a lowercase copy of the string. + + \snippet doc/src/snippets/qstring/main.cpp 75 + + \sa toUpper() +*/ + +QString QString::toLower() const +{ + const ushort *p = d->data; + if (!p) + return *this; + if (!d->size) + return *this; + + const ushort *e = d->data + d->size; + + // this avoids one out of bounds check in the loop + if (QChar(*p).isLowSurrogate()) + ++p; + + while (p != e) { + uint c = *p; + if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate()) + c = QChar::surrogateToUcs4(*(p - 1), c); + const QUnicodeTables::Properties *prop = qGetProp(c); + if (prop->lowerCaseDiff || prop->lowerCaseSpecial) { + QString s; + s.resize(d->size); + memcpy(s.d->data, d->data, (p - d->data)*sizeof(ushort)); + ushort *pp = s.d->data + (p - d->data); + while (p < e) { + uint c = *p; + if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate()) + c = QChar::surrogateToUcs4(*(p - 1), c); + prop = qGetProp(c); + if (prop->lowerCaseSpecial) { + int pos = pp - s.d->data; + s.resize(s.d->size + SPECIAL_CASE_MAX_LEN); + pp = s.d->data + pos; + const ushort *specialCase = specialCaseMap + prop->lowerCaseDiff; + while (*specialCase) + *pp++ = *specialCase++; + } else { + *pp++ = *p + prop->lowerCaseDiff; + } + ++p; + } + s.truncate(pp - s.d->data); + return s; + } + ++p; + } + return *this; +} + +/*! + Returns the case folded equivalent of the string. For most Unicode + characters this is the same as toLower(). +*/ +QString QString::toCaseFolded() const +{ + if (!d->size) + return *this; + + const ushort *p = d->data; + if (!p) + return *this; + + const ushort *e = d->data + d->size; + + uint last = 0; + while (p < e) { + ushort folded = foldCase(*p, last); + if (folded != *p) { + QString s(*this); + s.detach(); + ushort *pp = s.d->data + (p - d->data); + const ushort *ppe = s.d->data + s.d->size; + last = pp > s.d->data ? *(pp - 1) : 0; + while (pp < ppe) { + *pp = foldCase(*pp, last); + ++pp; + } + return s; + } + p++; + } + return *this; +} + +/*! + Returns an uppercase copy of the string. + + \snippet doc/src/snippets/qstring/main.cpp 81 + + \sa toLower() +*/ + +QString QString::toUpper() const +{ + const ushort *p = d->data; + if (!p) + return *this; + if (!d->size) + return *this; + + const ushort *e = d->data + d->size; + + // this avoids one out of bounds check in the loop + if (QChar(*p).isLowSurrogate()) + ++p; + + while (p != e) { + uint c = *p; + if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate()) + c = QChar::surrogateToUcs4(*(p - 1), c); + const QUnicodeTables::Properties *prop = qGetProp(c); + if (prop->upperCaseDiff || prop->upperCaseSpecial) { + QString s; + s.resize(d->size); + memcpy(s.d->data, d->data, (p - d->data)*sizeof(ushort)); + ushort *pp = s.d->data + (p - d->data); + while (p < e) { + uint c = *p; + if (QChar(c).isLowSurrogate() && QChar(*(p - 1)).isHighSurrogate()) + c = QChar::surrogateToUcs4(*(p - 1), c); + prop = qGetProp(c); + if (prop->upperCaseSpecial) { + int pos = pp - s.d->data; + s.resize(s.d->size + SPECIAL_CASE_MAX_LEN); + pp = s.d->data + pos; + const ushort *specialCase = specialCaseMap + prop->upperCaseDiff; + while (*specialCase) + *pp++ = *specialCase++; + } else { + *pp++ = *p + prop->upperCaseDiff; + } + ++p; + } + s.truncate(pp - s.d->data); + return s; + } + ++p; + } + return *this; +} + +// ### Qt 5: Consider whether this function shouldn't be removed See task 202871. +/*! + Safely builds a formatted string from the format string \a cformat + and an arbitrary list of arguments. + + The %lc escape sequence expects a unicode character of type ushort + (as returned by QChar::unicode()). The %ls escape sequence expects + a pointer to a zero-terminated array of unicode characters of type + ushort (as returned by QString::utf16()). + + \note This function expects a UTF-8 string for %s. + + The format string supports most of the conversion specifiers + provided by printf() in the standard C++ library. It doesn't + honor the length modifiers (e.g. \c h for \c short, \c ll for + \c{long long}). If you need those, use the standard snprintf() + function instead: + + \snippet doc/src/snippets/qstring/main.cpp 63 + + \warning We do not recommend using QString::sprintf() in new Qt + code. Instead, consider using QTextStream or arg(), both of + which support Unicode strings seamlessly and are type-safe. + Here's an example that uses QTextStream: + + \snippet doc/src/snippets/qstring/main.cpp 64 + + For \l {QObject::tr()}{translations}, especially if the strings + contains more than one escape sequence, you should consider using + the arg() function instead. This allows the order of the + replacements to be controlled by the translator. + + \sa arg() +*/ + +QString &QString::sprintf(const char *cformat, ...) +{ + va_list ap; + va_start(ap, cformat); + QString &s = vsprintf(cformat, ap); + va_end(ap); + return s; +} + +/*! + Equivalent method to sprintf(), but takes a va_list \a ap + instead a list of variable arguments. See the sprintf() + documentation for an explanation of \a cformat. + + This method does not call the va_end macro, the caller + is responsible to call va_end on \a ap. + + \sa sprintf() +*/ + +QString &QString::vsprintf(const char* cformat, va_list ap) +{ + QLocale locale(QLocale::C); + + if (!cformat || !*cformat) { + // Qt 1.x compat + *this = fromLatin1(""); + return *this; + } + + // Parse cformat + + QString result; + const char *c = cformat; + for (;;) { + // Copy non-escape chars to result + while (*c != '\0' && *c != '%') + result.append(QLatin1Char(*c++)); + + if (*c == '\0') + break; + + // Found '%' + const char *escape_start = c; + ++c; + + if (*c == '\0') { + result.append(QLatin1Char('%')); // a % at the end of the string - treat as non-escape text + break; + } + if (*c == '%') { + result.append(QLatin1Char('%')); // %% + ++c; + continue; + } + + // Parse flag characters + uint flags = 0; + bool no_more_flags = false; + do { + switch (*c) { + case '#': flags |= QLocalePrivate::Alternate; break; + case '0': flags |= QLocalePrivate::ZeroPadded; break; + case '-': flags |= QLocalePrivate::LeftAdjusted; break; + case ' ': flags |= QLocalePrivate::BlankBeforePositive; break; + case '+': flags |= QLocalePrivate::AlwaysShowSign; break; + case '\'': flags |= QLocalePrivate::ThousandsGroup; break; + default: no_more_flags = true; break; + } + + if (!no_more_flags) + ++c; + } while (!no_more_flags); + + if (*c == '\0') { + result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text + break; + } + + // Parse field width + int width = -1; // -1 means unspecified + if (qIsDigit(*c)) { + QString width_str; + while (*c != '\0' && qIsDigit(*c)) + width_str.append(QLatin1Char(*c++)); + + // can't be negative - started with a digit + // contains at least one digit + width = width_str.toInt(); + } + else if (*c == '*') { + width = va_arg(ap, int); + if (width < 0) + width = -1; // treat all negative numbers as unspecified + ++c; + } + + if (*c == '\0') { + result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text + break; + } + + // Parse precision + int precision = -1; // -1 means unspecified + if (*c == '.') { + ++c; + if (qIsDigit(*c)) { + QString precision_str; + while (*c != '\0' && qIsDigit(*c)) + precision_str.append(QLatin1Char(*c++)); + + // can't be negative - started with a digit + // contains at least one digit + precision = precision_str.toInt(); + } + else if (*c == '*') { + precision = va_arg(ap, int); + if (precision < 0) + precision = -1; // treat all negative numbers as unspecified + ++c; + } + } + + if (*c == '\0') { + result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text + break; + } + + // Parse the length modifier + enum LengthMod { lm_none, lm_hh, lm_h, lm_l, lm_ll, lm_L, lm_j, lm_z, lm_t }; + LengthMod length_mod = lm_none; + switch (*c) { + case 'h': + ++c; + if (*c == 'h') { + length_mod = lm_hh; + ++c; + } + else + length_mod = lm_h; + break; + + case 'l': + ++c; + if (*c == 'l') { + length_mod = lm_ll; + ++c; + } + else + length_mod = lm_l; + break; + + case 'L': + ++c; + length_mod = lm_L; + break; + + case 'j': + ++c; + length_mod = lm_j; + break; + + case 'z': + case 'Z': + ++c; + length_mod = lm_z; + break; + + case 't': + ++c; + length_mod = lm_t; + break; + + default: break; + } + + if (*c == '\0') { + result.append(QLatin1String(escape_start)); // incomplete escape, treat as non-escape text + break; + } + + // Parse the conversion specifier and do the conversion + QString subst; + switch (*c) { + case 'd': + case 'i': { + qint64 i; + switch (length_mod) { + case lm_none: i = va_arg(ap, int); break; + case lm_hh: i = va_arg(ap, int); break; + case lm_h: i = va_arg(ap, int); break; + case lm_l: i = va_arg(ap, long int); break; + case lm_ll: i = va_arg(ap, qint64); break; + case lm_j: i = va_arg(ap, long int); break; + case lm_z: i = va_arg(ap, size_t); break; + case lm_t: i = va_arg(ap, int); break; + default: i = 0; break; + } + subst = locale.d()->longLongToString(i, precision, 10, width, flags); + ++c; + break; + } + case 'o': + case 'u': + case 'x': + case 'X': { + quint64 u; + switch (length_mod) { + case lm_none: u = va_arg(ap, uint); break; + case lm_hh: u = va_arg(ap, uint); break; + case lm_h: u = va_arg(ap, uint); break; + case lm_l: u = va_arg(ap, ulong); break; + case lm_ll: u = va_arg(ap, quint64); break; + case lm_z: u = va_arg(ap, size_t); break; + default: u = 0; break; + } + + if (qIsUpper(*c)) + flags |= QLocalePrivate::CapitalEorX; + + int base = 10; + switch (qToLower(*c)) { + case 'o': + base = 8; break; + case 'u': + base = 10; break; + case 'x': + base = 16; break; + default: break; + } + subst = locale.d()->unsLongLongToString(u, precision, base, width, flags); + ++c; + break; + } + case 'E': + case 'e': + case 'F': + case 'f': + case 'G': + case 'g': + case 'A': + case 'a': { + double d; + if (length_mod == lm_L) + d = va_arg(ap, long double); // not supported - converted to a double + else + d = va_arg(ap, double); + + if (qIsUpper(*c)) + flags |= QLocalePrivate::CapitalEorX; + + QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal; + switch (qToLower(*c)) { + case 'e': form = QLocalePrivate::DFExponent; break; + case 'a': // not supported - decimal form used instead + case 'f': form = QLocalePrivate::DFDecimal; break; + case 'g': form = QLocalePrivate::DFSignificantDigits; break; + default: break; + } + subst = locale.d()->doubleToString(d, precision, form, width, flags); + ++c; + break; + } + case 'c': { + if (length_mod == lm_l) + subst = QChar((ushort) va_arg(ap, int)); + else + subst = QLatin1Char((uchar) va_arg(ap, int)); + ++c; + break; + } + case 's': { + if (length_mod == lm_l) { + const ushort *buff = va_arg(ap, const ushort*); + const ushort *ch = buff; + while (*ch != 0) + ++ch; + subst.setUtf16(buff, ch - buff); + } else + subst = QString::fromUtf8(va_arg(ap, const char*)); + if (precision != -1) + subst.truncate(precision); + ++c; + break; + } + case 'p': { + void *arg = va_arg(ap, void*); +#ifdef Q_OS_WIN64 + quint64 i = reinterpret_cast<quint64>(arg); +#else + quint64 i = reinterpret_cast<unsigned long>(arg); +#endif + flags |= QLocalePrivate::Alternate; + subst = locale.d()->unsLongLongToString(i, precision, 16, width, flags); + ++c; + break; + } + case 'n': + switch (length_mod) { + case lm_hh: { + signed char *n = va_arg(ap, signed char*); + *n = result.length(); + break; + } + case lm_h: { + short int *n = va_arg(ap, short int*); + *n = result.length(); + break; + } + case lm_l: { + long int *n = va_arg(ap, long int*); + *n = result.length(); + break; + } + case lm_ll: { + qint64 *n = va_arg(ap, qint64*); + volatile uint tmp = result.length(); // egcs-2.91.66 gets internal + *n = tmp; // compiler error without volatile + break; + } + default: { + int *n = va_arg(ap, int*); + *n = result.length(); + break; + } + } + ++c; + break; + + default: // bad escape, treat as non-escape text + for (const char *cc = escape_start; cc != c; ++cc) + result.append(QLatin1Char(*cc)); + continue; + } + + if (flags & QLocalePrivate::LeftAdjusted) + result.append(subst.leftJustified(width)); + else + result.append(subst.rightJustified(width)); + } + + *this = result; + + return *this; +} + +/*! + Returns the string converted to a \c{long long} using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + Returns 0 if the conversion fails. + + If a conversion error occurs, *\a{ok} is set to false; otherwise + *\a{ok} is set to true. + + If \a base is 0, the C language convention is used: If the string + begins with "0x", base 16 is used; if the string begins with "0", + base 8 is used; otherwise, base 10 is used. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 74 + + \sa number(), toULongLong(), toInt() +*/ + +qint64 QString::toLongLong(bool *ok, int base) const +{ +#if defined(QT_CHECK_RANGE) + if (base != 0 && (base < 2 || base > 36)) { + qWarning("QString::toLongLong: Invalid base (%d)", base); + base = 10; + } +#endif + + bool my_ok; + QLocale def_locale; + qint64 result = def_locale.d()->stringToLongLong(*this, base, &my_ok, QLocalePrivate::FailOnGroupSeparators); + if (my_ok) { + if (ok != 0) + *ok = true; + return result; + } + + QLocale c_locale(QLocale::C); + return c_locale.d()->stringToLongLong(*this, base, ok, QLocalePrivate::FailOnGroupSeparators); +} + +/*! + Returns the string converted to an \c{unsigned long long} using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + Returns 0 if the conversion fails. + + If a conversion error occurs, *\a{ok} is set to false; otherwise + *\a{ok} is set to true. + + If \a base is 0, the C language convention is used: If the string + begins with "0x", base 16 is used; if the string begins with "0", + base 8 is used; otherwise, base 10 is used. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 79 + + \sa number(), toLongLong() +*/ + +quint64 QString::toULongLong(bool *ok, int base) const +{ +#if defined(QT_CHECK_RANGE) + if (base != 0 && (base < 2 || base > 36)) { + qWarning("QString::toULongLong: Invalid base (%d)", base); + base = 10; + } +#endif + + bool my_ok; + QLocale def_locale; + quint64 result = def_locale.d()->stringToUnsLongLong(*this, base, &my_ok, QLocalePrivate::FailOnGroupSeparators); + if (my_ok) { + if (ok != 0) + *ok = true; + return result; + } + + QLocale c_locale(QLocale::C); + return c_locale.d()->stringToUnsLongLong(*this, base, ok, QLocalePrivate::FailOnGroupSeparators); +} + +/*! + \fn long QString::toLong(bool *ok, int base) const + + Returns the string converted to a \c long using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + Returns 0 if the conversion fails. + + If a conversion error occurs, *\a{ok} is set to false; otherwise + *\a{ok} is set to true. + + If \a base is 0, the C language convention is used: If the string + begins with "0x", base 16 is used; if the string begins with "0", + base 8 is used; otherwise, base 10 is used. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 73 + + \sa number(), toULong(), toInt() +*/ + +long QString::toLong(bool *ok, int base) const +{ + qint64 v = toLongLong(ok, base); + if (v < LONG_MIN || v > LONG_MAX) { + if (ok) + *ok = false; + v = 0; + } + return (long)v; +} + +/*! + \fn ulong QString::toULong(bool *ok, int base) const + + Returns the string converted to an \c{unsigned long} using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + Returns 0 if the conversion fails. + + If a conversion error occurs, *\a{ok} is set to false; otherwise + *\a{ok} is set to true. + + If \a base is 0, the C language convention is used: If the string + begins with "0x", base 16 is used; if the string begins with "0", + base 8 is used; otherwise, base 10 is used. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 78 + + \sa number() +*/ + +ulong QString::toULong(bool *ok, int base) const +{ + quint64 v = toULongLong(ok, base); + if (v > ULONG_MAX) { + if (ok) + *ok = false; + v = 0; + } + return (ulong)v; +} + + +/*! + Returns the string converted to an \c int using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + Returns 0 if the conversion fails. + + If a conversion error occurs, *\a{ok} is set to false; otherwise + *\a{ok} is set to true. + + If \a base is 0, the C language convention is used: If the string + begins with "0x", base 16 is used; if the string begins with "0", + base 8 is used; otherwise, base 10 is used. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 72 + + \sa number(), toUInt(), toDouble() +*/ + +int QString::toInt(bool *ok, int base) const +{ + qint64 v = toLongLong(ok, base); + if (v < INT_MIN || v > INT_MAX) { + if (ok) + *ok = false; + v = 0; + } + return v; +} + +/*! + Returns the string converted to an \c{unsigned int} using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + Returns 0 if the conversion fails. + + If a conversion error occurs, *\a{ok} is set to false; otherwise + *\a{ok} is set to true. + + If \a base is 0, the C language convention is used: If the string + begins with "0x", base 16 is used; if the string begins with "0", + base 8 is used; otherwise, base 10 is used. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 77 + + \sa number(), toInt() +*/ + +uint QString::toUInt(bool *ok, int base) const +{ + quint64 v = toULongLong(ok, base); + if (v > UINT_MAX) { + if (ok) + *ok = false; + v = 0; + } + return (uint)v; +} + +/*! + Returns the string converted to a \c short using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + Returns 0 if the conversion fails. + + If a conversion error occurs, *\a{ok} is set to false; otherwise + *\a{ok} is set to true. + + If \a base is 0, the C language convention is used: If the string + begins with "0x", base 16 is used; if the string begins with "0", + base 8 is used; otherwise, base 10 is used. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 76 + + \sa number(), toUShort(), toInt() +*/ + +short QString::toShort(bool *ok, int base) const +{ + long v = toLongLong(ok, base); + if (v < SHRT_MIN || v > SHRT_MAX) { + if (ok) + *ok = false; + v = 0; + } + return (short)v; +} + +/*! + Returns the string converted to an \c{unsigned short} using base \a + base, which is 10 by default and must be between 2 and 36, or 0. + Returns 0 if the conversion fails. + + If a conversion error occurs, *\a{ok} is set to false; otherwise + *\a{ok} is set to true. + + If \a base is 0, the C language convention is used: If the string + begins with "0x", base 16 is used; if the string begins with "0", + base 8 is used; otherwise, base 10 is used. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 80 + + \sa number(), toShort() +*/ + +ushort QString::toUShort(bool *ok, int base) const +{ + ulong v = toULongLong(ok, base); + if (v > USHRT_MAX) { + if (ok) + *ok = false; + v = 0; + } + return (ushort)v; +} + + +/*! + Returns the string converted to a \c double value. + + Returns 0.0 if the conversion fails. + + If a conversion error occurs, \c{*}\a{ok} is set to false; + otherwise \c{*}\a{ok} is set to true. + + \snippet doc/src/snippets/qstring/main.cpp 66 + + Various string formats for floating point numbers can be converted + to double values: + + \snippet doc/src/snippets/qstring/main.cpp 67 + + This function tries to interpret the string according to the + current locale. The current locale is determined from the + system at application startup and can be changed by calling + QLocale::setDefault(). If the string cannot be interpreted + according to the current locale, this function falls back + on the "C" locale. + + \snippet doc/src/snippets/qstring/main.cpp 69 + \snippet doc/src/snippets/qstring/main.cpp 70 + + Due to the ambiguity between the decimal point and thousands group + separator in various locales, this function does not handle + thousands group separators. If you need to convert such numbers, + see QLocale::toDouble(). + + \snippet doc/src/snippets/qstring/main.cpp 68 + + \sa number() QLocale::setDefault() QLocale::toDouble() trimmed() +*/ + +double QString::toDouble(bool *ok) const +{ + bool my_ok; + QLocale def_locale; + double result = def_locale.d()->stringToDouble(*this, &my_ok, QLocalePrivate::FailOnGroupSeparators); + if (my_ok) { + if (ok != 0) + *ok = true; + return result; + } + + QLocale c_locale(QLocale::C); + return c_locale.d()->stringToDouble(*this, ok, QLocalePrivate::FailOnGroupSeparators); +} + +/*! + Returns the string converted to a \c float value. + + If a conversion error occurs, *\a{ok} is set to false; otherwise + *\a{ok} is set to true. Returns 0.0 if the conversion fails. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 71 + + \sa number(), toDouble(), toInt() +*/ + +#define QT_MAX_FLOAT 3.4028234663852886e+38 + +float QString::toFloat(bool *ok) const +{ + bool myOk; + double d = toDouble(&myOk); + if (!myOk || d > QT_MAX_FLOAT || d < -QT_MAX_FLOAT) { + if (ok != 0) + *ok = false; + return 0.0; + } + if (ok != 0) + *ok = true; + return (float) d; +} + +/*! \fn QString &QString::setNum(int n, int base) + + Sets the string to the printed value of \a n in the specified \a + base, and returns a reference to the string. + + The base is 10 by default and must be between 2 and 36. For bases + other than 10, \a n is treated as an unsigned integer. + + \snippet doc/src/snippets/qstring/main.cpp 56 + + The formatting always uses QLocale::C, i.e., English/UnitedStates. + To get a localized string representation of a number, use + QLocale::toString() with the appropriate locale. +*/ + +/*! \fn QString &QString::setNum(uint n, int base) + + \overload +*/ + +/*! \fn QString &QString::setNum(long n, int base) + + \overload +*/ + +/*! \fn QString &QString::setNum(ulong n, int base) + + \overload +*/ + +/*! + \overload +*/ +QString &QString::setNum(qlonglong n, int base) +{ +#if defined(QT_CHECK_RANGE) + if (base < 2 || base > 36) { + qWarning("QString::setNum: Invalid base (%d)", base); + base = 10; + } +#endif + QLocale locale(QLocale::C); + *this = locale.d()->longLongToString(n, -1, base); + return *this; +} + +/*! + \overload +*/ +QString &QString::setNum(qulonglong n, int base) +{ +#if defined(QT_CHECK_RANGE) + if (base < 2 || base > 36) { + qWarning("QString::setNum: Invalid base (%d)", base); + base = 10; + } +#endif + QLocale locale(QLocale::C); + *this = locale.d()->unsLongLongToString(n, -1, base); + return *this; +} + +/*! \fn QString &QString::setNum(short n, int base) + + \overload +*/ + +/*! \fn QString &QString::setNum(ushort n, int base) + + \overload +*/ + +/*! + \fn QString &QString::setNum(double n, char format, int precision) + \overload + + Sets the string to the printed value of \a n, formatted according + to the given \a format and \a precision, and returns a reference + to the string. + + The \a format can be 'f', 'F', 'e', 'E', 'g' or 'G' (see the + arg() function documentation for an explanation of the formats). + + Unlike QLocale::toString(), this function doesn't honor the + user's locale settings. +*/ + +QString &QString::setNum(double n, char f, int prec) +{ + QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal; + uint flags = 0; + + if (qIsUpper(f)) + flags = QLocalePrivate::CapitalEorX; + f = qToLower(f); + + switch (f) { + case 'f': + form = QLocalePrivate::DFDecimal; + break; + case 'e': + form = QLocalePrivate::DFExponent; + break; + case 'g': + form = QLocalePrivate::DFSignificantDigits; + break; + default: +#if defined(QT_CHECK_RANGE) + qWarning("QString::setNum: Invalid format char '%c'", f); +#endif + break; + } + + QLocale locale(QLocale::C); + *this = locale.d()->doubleToString(n, prec, form, -1, flags); + return *this; +} + +/*! + \fn QString &QString::setNum(float n, char format, int precision) + \overload + + Sets the string to the printed value of \a n, formatted according + to the given \a format and \a precision, and returns a reference + to the string. +*/ + + +/*! + \fn QString QString::number(long n, int base) + + Returns a string equivalent of the number \a n according to the + specified \a base. + + The base is 10 by default and must be between 2 + and 36. For bases other than 10, \a n is treated as an + unsigned integer. + + \snippet doc/src/snippets/qstring/main.cpp 35 + + \sa setNum() +*/ + +QString QString::number(long n, int base) +{ + QString s; + s.setNum(n, base); + return s; +} + +/*! + \fn QString QString::number(ulong n, int base) + + \overload +*/ +QString QString::number(ulong n, int base) +{ + QString s; + s.setNum(n, base); + return s; +} + +/*! + \overload +*/ +QString QString::number(int n, int base) +{ + QString s; + s.setNum(n, base); + return s; +} + +/*! + \overload +*/ +QString QString::number(uint n, int base) +{ + QString s; + s.setNum(n, base); + return s; +} + +/*! + \overload +*/ +QString QString::number(qlonglong n, int base) +{ + QString s; + s.setNum(n, base); + return s; +} + +/*! + \overload +*/ +QString QString::number(qulonglong n, int base) +{ + QString s; + s.setNum(n, base); + return s; +} + + +/*! + \fn QString QString::number(double n, char format, int precision) + + Returns a string equivalent of the number \a n, formatted + according to the specified \a format and \a precision. See + \l{Argument Formats} for details. + + Unlike QLocale::toString(), this function does not honor the + user's locale settings. + + \sa setNum(), QLocale::toString() +*/ +QString QString::number(double n, char f, int prec) +{ + QString s; + s.setNum(n, f, prec); + return s; +} + +/*! + Splits the string into substrings wherever \a sep occurs, and + returns the list of those strings. If \a sep does not match + anywhere in the string, split() returns a single-element list + containing this string. + + \a cs specifies whether \a sep should be matched case + sensitively or case insensitively. + + If \a behavior is QString::SkipEmptyParts, empty entries don't + appear in the result. By default, empty entries are kept. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 62 + + \sa QStringList::join(), section() +*/ +QStringList QString::split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const +{ + QStringList list; + int start = 0; + int extra = 0; + int end; + while ((end = indexOf(sep, start + extra, cs)) != -1) { + if (start != end || behavior == KeepEmptyParts) + list.append(mid(start, end - start)); + start = end + sep.size(); + extra = (sep.size() == 0 ? 1 : 0); + } + if (start != size() || behavior == KeepEmptyParts) + list.append(mid(start)); + return list; +} + +/*! + \overload +*/ +QStringList QString::split(const QChar &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const +{ + QStringList list; + int start = 0; + int end; + while ((end = indexOf(sep, start, cs)) != -1) { + if (start != end || behavior == KeepEmptyParts) + list.append(mid(start, end - start)); + start = end + 1; + } + if (start != size() || behavior == KeepEmptyParts) + list.append(mid(start)); + return list; +} + +#ifndef QT_NO_REGEXP +/*! + \overload + + Splits the string into substrings wherever the regular expression + \a rx matches, and returns the list of those strings. If \a rx + does not match anywhere in the string, split() returns a + single-element list containing this string. + + Here's an example where we extract the words in a sentence + using one or more whitespace characters as the separator: + + \snippet doc/src/snippets/qstring/main.cpp 59 + + Here's a similar example, but this time we use any sequence of + non-word characters as the separator: + + \snippet doc/src/snippets/qstring/main.cpp 60 + + Here's a third example where we use a zero-length assertion, + \bold{\\b} (word boundary), to split the string into an + alternating sequence of non-word and word tokens: + + \snippet doc/src/snippets/qstring/main.cpp 61 + + \sa QStringList::join(), section() +*/ +QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const +{ + QRegExp rx2(rx); + QStringList list; + int start = 0; + int extra = 0; + int end; + while ((end = rx2.indexIn(*this, start + extra)) != -1) { + int matchedLen = rx2.matchedLength(); + if (start != end || behavior == KeepEmptyParts) + list.append(mid(start, end - start)); + start = end + matchedLen; + extra = (matchedLen == 0) ? 1 : 0; + } + if (start != size() || behavior == KeepEmptyParts) + list.append(mid(start)); + return list; +} +#endif + +/*! + \enum QString::NormalizationForm + + This enum describes the various normalized forms of Unicode text. + + \value NormalizationForm_D Canonical Decomposition + \value NormalizationForm_C Canonical Decomposition followed by Canonical Composition + \value NormalizationForm_KD Compatibility Decomposition + \value NormalizationForm_KC Compatibility Decomposition followed by Canonical Composition + + \sa normalized(), + {http://www.unicode.org/reports/tr15/}{Unicode Standard Annex #15} +*/ + +/*! + \fn QString QString::normalized(NormalizationForm mode) const + Returns the string in the given Unicode normalization \a mode. +*/ +QString QString::normalized(QString::NormalizationForm mode) const +{ + return normalized(mode, CURRENT_VERSION); +} + +/*! + \since 4.5 + + Returns a copy of this string repeated the specified number of \a times. + + If \a times is less than 1, an empty string is returned. + + Example: + + \code + QString str("ab"); + str.repeated(4); // returns "abababab" + \endcode +*/ +QString QString::repeated(int times) const +{ + if (d->size == 0) + return *this; + + if (times <= 1) { + if (times == 1) + return *this; + return QString(); + } + + const int resultSize = times * d->size; + + QString result; + result.reserve(resultSize); + if (result.d->alloc != resultSize) + return QString(); // not enough memory + + qMemCopy(result.d->data, d->data, d->size * sizeof(ushort)); + + int sizeSoFar = d->size; + ushort *end = result.d->data + sizeSoFar; + + const int halfResultSize = resultSize >> 1; + while (sizeSoFar <= halfResultSize) { + qMemCopy(end, result.d->data, sizeSoFar * sizeof(ushort)); + end += sizeSoFar; + sizeSoFar <<= 1; + } + qMemCopy(end, result.d->data, (resultSize - sizeSoFar) * sizeof(ushort)); + result.d->data[resultSize] = '\0'; + result.d->size = resultSize; + return result; +} + +/*! + \overload + \fn QString QString::normalized(NormalizationForm mode, QChar::UnicodeVersion version) const + + Returns the string in the given Unicode normalization \a mode, + according to the given \a version of the Unicode standard. +*/ +QString QString::normalized(QString::NormalizationForm mode, QChar::UnicodeVersion version) const +{ + bool simple = true; + for (int i = 0; i < d->size; ++i) { + if (d->data[i] >= 0x80) { + simple = false; + break; + } + } + if (simple) + return *this; + + QString s = *this; + if (version != CURRENT_VERSION) { + for (int i = 0; i < NumNormalizationCorrections; ++i) { + const NormalizationCorrection &n = uc_normalization_corrections[i]; + if (n.version > version) { + if (n.ucs4 > 0xffff) { + ushort ucs4High = QChar::highSurrogate(n.ucs4); + ushort ucs4Low = QChar::lowSurrogate(n.ucs4); + ushort oldHigh = QChar::highSurrogate(n.old_mapping); + ushort oldLow = QChar::lowSurrogate(n.old_mapping); + int pos = 0; + while (pos < s.d->size - 1) { + if (s.d->data[pos] == ucs4High && s.d->data[pos + 1] == ucs4Low) { + s.detach(); + s.d->data[pos] = oldHigh; + s.d->data[pos + 1] = oldLow; + ++pos; + } + ++pos; + } + } else { + int pos = 0; + while (pos < s.d->size) { + if (s.d->data[pos] == n.ucs4) { + s.detach(); + s.d->data[pos] = n.old_mapping; + } + ++pos; + } + } + } + } + } + s = decomposeHelper(s, mode < QString::NormalizationForm_KD, version); + + s = canonicalOrderHelper(s, version); + + if (mode == QString::NormalizationForm_D || mode == QString::NormalizationForm_KD) + return s; + + return composeHelper(s); + +} + + +struct ArgEscapeData +{ + int min_escape; // lowest escape sequence number + int occurrences; // number of occurrences of the lowest escape sequence number + int locale_occurrences; // number of occurrences of the lowest escape sequence number that + // contain 'L' + int escape_len; // total length of escape sequences which will be replaced +}; + +static ArgEscapeData findArgEscapes(const QString &s) +{ + const QChar *uc_begin = s.unicode(); + const QChar *uc_end = uc_begin + s.length(); + + ArgEscapeData d; + + d.min_escape = INT_MAX; + d.occurrences = 0; + d.escape_len = 0; + d.locale_occurrences = 0; + + const QChar *c = uc_begin; + while (c != uc_end) { + while (c != uc_end && c->unicode() != '%') + ++c; + + if (c == uc_end) + break; + const QChar *escape_start = c; + if (++c == uc_end) + break; + + bool locale_arg = false; + if (c->unicode() == 'L') { + locale_arg = true; + if (++c == uc_end) + break; + } + + if (c->digitValue() == -1) + continue; + + int escape = c->digitValue(); + ++c; + + if (c != uc_end && c->digitValue() != -1) { + escape = (10 * escape) + c->digitValue(); + ++c; + } + + if (escape > d.min_escape) + continue; + + if (escape < d.min_escape) { + d.min_escape = escape; + d.occurrences = 0; + d.escape_len = 0; + d.locale_occurrences = 0; + } + + ++d.occurrences; + if (locale_arg) + ++d.locale_occurrences; + d.escape_len += c - escape_start; + } + return d; +} + +static QString replaceArgEscapes(const QString &s, const ArgEscapeData &d, int field_width, + const QString &arg, const QString &larg, const QChar &fillChar = QLatin1Char(' ')) +{ + const QChar *uc_begin = s.unicode(); + const QChar *uc_end = uc_begin + s.length(); + + int abs_field_width = qAbs(field_width); + int result_len = s.length() + - d.escape_len + + (d.occurrences - d.locale_occurrences) + *qMax(abs_field_width, arg.length()) + + d.locale_occurrences + *qMax(abs_field_width, larg.length()); + + QString result; + result.resize(result_len); + QChar *result_buff = (QChar*) result.unicode(); + + QChar *rc = result_buff; + const QChar *c = uc_begin; + int repl_cnt = 0; + while (c != uc_end) { + /* We don't have to check if we run off the end of the string with c, + because as long as d.occurrences > 0 we KNOW there are valid escape + sequences. */ + + const QChar *text_start = c; + + while (c->unicode() != '%') + ++c; + + const QChar *escape_start = c++; + + bool locale_arg = false; + if (c->unicode() == 'L') { + locale_arg = true; + ++c; + } + + int escape = c->digitValue(); + if (escape != -1) { + if (c + 1 != uc_end && (c + 1)->digitValue() != -1) { + escape = (10 * escape) + (c + 1)->digitValue(); + ++c; + } + } + + if (escape != d.min_escape) { + memcpy(rc, text_start, (c - text_start)*sizeof(QChar)); + rc += c - text_start; + } + else { + ++c; + + memcpy(rc, text_start, (escape_start - text_start)*sizeof(QChar)); + rc += escape_start - text_start; + + uint pad_chars; + if (locale_arg) + pad_chars = qMax(abs_field_width, larg.length()) - larg.length(); + else + pad_chars = qMax(abs_field_width, arg.length()) - arg.length(); + + if (field_width > 0) { // left padded + for (uint i = 0; i < pad_chars; ++i) + (rc++)->unicode() = fillChar.unicode(); + } + + if (locale_arg) { + memcpy(rc, larg.unicode(), larg.length()*sizeof(QChar)); + rc += larg.length(); + } + else { + memcpy(rc, arg.unicode(), arg.length()*sizeof(QChar)); + rc += arg.length(); + } + + if (field_width < 0) { // right padded + for (uint i = 0; i < pad_chars; ++i) + (rc++)->unicode() = fillChar.unicode(); + } + + if (++repl_cnt == d.occurrences) { + memcpy(rc, c, (uc_end - c)*sizeof(QChar)); + rc += uc_end - c; + Q_ASSERT(rc - result_buff == result_len); + c = uc_end; + } + } + } + Q_ASSERT(rc == result_buff + result_len); + + return result; +} + +/*! + Returns a copy of this string with the lowest numbered place marker + replaced by string \a a, i.e., \c %1, \c %2, ..., \c %99. + + \a fieldWidth specifies the minimum amount of space that argument \a + a shall occupy. If \a a requires less space than \a fieldWidth, it + is padded to \a fieldWidth with character \a fillChar. A positive + \a fieldWidth produces right-aligned text. A negative \a fieldWidth + produces left-aligned text. + + This example shows how we might create a \c status string for + reporting progress while processing a list of files: + + \snippet doc/src/snippets/qstring/main.cpp 11 + + First, \c arg(i) replaces \c %1. Then \c arg(total) replaces \c + %2. Finally, \c arg(fileName) replaces \c %3. + + One advantage of using arg() over sprintf() is that the order of the + numbered place markers can change, if the application's strings are + translated into other languages, but each arg() will still replace + the lowest numbered unreplaced place marker, no matter where it + appears. Also, if place marker \c %i appears more than once in the + string, the arg() replaces all of them. + + If there is no unreplaced place marker remaining, a warning message + is output and the result is undefined. Place marker numbers must be + in the range 1 to 99. +*/ +QString QString::arg(const QString &a, int fieldWidth, const QChar &fillChar) const +{ + ArgEscapeData d = findArgEscapes(*this); + + if (d.occurrences == 0) { + qWarning("QString::arg: Argument missing: %s, %s", toLocal8Bit().data(), + a.toLocal8Bit().data()); + return *this; + } + return replaceArgEscapes(*this, d, fieldWidth, a, a, fillChar); +} + +/*! + \fn QString QString::arg(const QString& a1, const QString& a2) const + \overload arg() + + This is the same as \c {str.arg(a1).arg(a2)}, except that the + strings \a a1 and \a a2 are replaced in one pass. This can make a + difference if \a a1 contains e.g. \c{%1}: + + \snippet doc/src/snippets/qstring/main.cpp 13 +*/ + +/*! + \fn QString QString::arg(const QString& a1, const QString& a2, const QString& a3) const + \overload arg() + + This is the same as calling \c str.arg(a1).arg(a2).arg(a3), except + that the strings \a a1, \a a2 and \a a3 are replaced in one pass. +*/ + +/*! + \fn QString QString::arg(const QString& a1, const QString& a2, const QString& a3, const QString& a4) const + \overload arg() + + This is the same as calling \c + {str.arg(a1).arg(a2).arg(a3).arg(a4)}, except that the strings \a + a1, \a a2, \a a3 and \a a4 are replaced in one pass. +*/ + +/*! + \fn QString QString::arg(const QString& a1, const QString& a2, const QString& a3, const QString& a4, const QString& a5) const + \overload arg() + + This is the same as calling \c + {str.arg(a1).arg(a2).arg(a3).arg(a4).arg(a5)}, except that the strings + \a a1, \a a2, \a a3, \a a4, and \a a5 are replaced in one pass. +*/ + +/*! + \fn QString QString::arg(const QString& a1, const QString& a2, const QString& a3, const QString& a4, const QString& a5, const QString& a6) const + \overload arg() + + This is the same as calling \c + {str.arg(a1).arg(a2).arg(a3).arg(a4).arg(a5).arg(a6))}, except that + the strings \a a1, \a a2, \a a3, \a a4, \a a5, and \a a6 are + replaced in one pass. +*/ + +/*! + \fn QString QString::arg(const QString& a1, const QString& a2, const QString& a3, const QString& a4, const QString& a5, const QString& a6, const QString& a7) const + \overload arg() + + This is the same as calling \c + {str.arg(a1).arg(a2).arg(a3).arg(a4).arg(a5).arg(a6).arg(a7)}, + except that the strings \a a1, \a a2, \a a3, \a a4, \a a5, \a a6, + and \a a7 are replaced in one pass. +*/ + +/*! + \fn QString QString::arg(const QString& a1, const QString& a2, const QString& a3, const QString& a4, const QString& a5, const QString& a6, const QString& a7, const QString& a8) const + \overload arg() + + This is the same as calling \c + {str.arg(a1).arg(a2).arg(a3).arg(a4).arg(a5).arg(a6).arg(a7).arg(a8)}, + except that the strings \a a1, \a a2, \a a3, \a a4, \a a5, \a a6, \a + a7, and \a a8 are replaced in one pass. +*/ + +/*! + \fn QString QString::arg(const QString& a1, const QString& a2, const QString& a3, const QString& a4, const QString& a5, const QString& a6, const QString& a7, const QString& a8, const QString& a9) const + \overload arg() + + This is the same as calling \c + {str.arg(a1).arg(a2).arg(a3).arg(a4).arg(a5).arg(a6).arg(a7).arg(a8).arg(a9)}, + except that the strings \a a1, \a a2, \a a3, \a a4, \a a5, \a a6, \a + a7, \a a8, and \a a9 are replaced in one pass. +*/ + +/*! \fn QString QString::arg(int a, int fieldWidth, int base, const QChar &fillChar) const + \overload arg() + + The \a a argument is expressed in base \a base, which is 10 by + default and must be between 2 and 36. For bases other than 10, \a a + is treated as an unsigned integer. + + \a fieldWidth specifies the minimum amount of space that \a a is + padded to and filled with the character \a fillChar. A positive + value produces right-aligned text; a negative value produces + left-aligned text. + + The '%' can be followed by an 'L', in which case the sequence is + replaced with a localized representation of \a a. The conversion + uses the default locale, set by QLocale::setDefault(). If no default + locale was specified, the "C" locale is used. The 'L' flag is + ignored if \a base is not 10. + + \snippet doc/src/snippets/qstring/main.cpp 12 + \snippet doc/src/snippets/qstring/main.cpp 14 + + If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is + used. For negative numbers, zero padding might appear before the + minus sign. +*/ + +/*! \fn QString QString::arg(uint a, int fieldWidth, int base, const QChar &fillChar) const + \overload arg() + + The \a base argument specifies the base to use when converting the + integer \a a into a string. The base must be between 2 and 36. + + If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is + used. For negative numbers, zero padding might appear before the + minus sign. +*/ + +/*! \fn QString QString::arg(long a, int fieldWidth, int base, const QChar &fillChar) const + \overload arg() + + \a fieldWidth specifies the minimum amount of space that \a a is + padded to and filled with the character \a fillChar. A positive + value produces right-aligned text; a negative value produces + left-aligned text. + + The \a a argument is expressed in the given \a base, which is 10 by + default and must be between 2 and 36. + + The '%' can be followed by an 'L', in which case the sequence is + replaced with a localized representation of \a a. The conversion + uses the default locale. The default locale is determined from the + system's locale settings at application startup. It can be changed + using QLocale::setDefault(). The 'L' flag is ignored if \a base is + not 10. + + \snippet doc/src/snippets/qstring/main.cpp 12 + \snippet doc/src/snippets/qstring/main.cpp 14 + + If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is + used. For negative numbers, zero padding might appear before the + minus sign. +*/ + +/*! \fn QString QString::arg(ulong a, int fieldWidth, int base, const QChar &fillChar) const + \overload arg() + + \a fieldWidth specifies the minimum amount of space that \a a is + padded to and filled with the character \a fillChar. A positive + value produces right-aligned text; a negative value produces + left-aligned text. + + The \a base argument specifies the base to use when converting the + integer \a a to a string. The base must be between 2 and 36, with 8 + giving octal, 10 decimal, and 16 hexadecimal numbers. + + If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is + used. For negative numbers, zero padding might appear before the + minus sign. +*/ + +/*! + \overload arg() + + \a fieldWidth specifies the minimum amount of space that \a a is + padded to and filled with the character \a fillChar. A positive + value produces right-aligned text; a negative value produces + left-aligned text. + + The \a base argument specifies the base to use when converting the + integer \a a into a string. The base must be between 2 and 36, with + 8 giving octal, 10 decimal, and 16 hexadecimal numbers. + + If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is + used. For negative numbers, zero padding might appear before the + minus sign. +*/ +QString QString::arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const +{ + ArgEscapeData d = findArgEscapes(*this); + + if (d.occurrences == 0) { + qWarning("QString::arg: Argument missing: %s, %lld", toLocal8Bit().data(), a); + return *this; + } + + unsigned flags = QLocalePrivate::NoFlags; + if (fillChar == QLatin1Char('0')) + flags = QLocalePrivate::ZeroPadded; + + QString arg; + if (d.occurrences > d.locale_occurrences) + arg = QLocale::c().d()->longLongToString(a, -1, base, fieldWidth, flags); + + QString locale_arg; + if (d.locale_occurrences > 0) { + QLocale locale; + locale_arg = locale.d()->longLongToString(a, -1, base, fieldWidth, + flags | QLocalePrivate::ThousandsGroup); + } + + return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar); +} + +/*! + \overload arg() + + \a fieldWidth specifies the minimum amount of space that \a a is + padded to and filled with the character \a fillChar. A positive + value produces right-aligned text; a negative value produces + left-aligned text. + + The \a base argument specifies the base to use when converting the + integer \a a into a string. \a base must be between 2 and 36, with 8 + giving octal, 10 decimal, and 16 hexadecimal numbers. + + If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is + used. For negative numbers, zero padding might appear before the + minus sign. +*/ +QString QString::arg(qulonglong a, int fieldWidth, int base, const QChar &fillChar) const +{ + ArgEscapeData d = findArgEscapes(*this); + + if (d.occurrences == 0) { + qWarning("QString::arg: Argument missing: %s, %llu", toLocal8Bit().data(), a); + return *this; + } + + unsigned flags = QLocalePrivate::NoFlags; + if (fillChar == QLatin1Char('0')) + flags = QLocalePrivate::ZeroPadded; + + QString arg; + if (d.occurrences > d.locale_occurrences) + arg = QLocale::c().d()->unsLongLongToString(a, -1, base, fieldWidth, flags); + + QString locale_arg; + if (d.locale_occurrences > 0) { + QLocale locale; + locale_arg = locale.d()->unsLongLongToString(a, -1, base, fieldWidth, + flags | QLocalePrivate::ThousandsGroup); + } + + return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar); +} + +/*! + \overload arg() + + \fn QString QString::arg(short a, int fieldWidth, int base, const QChar &fillChar) const + + \a fieldWidth specifies the minimum amount of space that \a a is + padded to and filled with the character \a fillChar. A positive + value produces right-aligned text; a negative value produces + left-aligned text. + + The \a base argument specifies the base to use when converting the + integer \a a into a string. The base must be between 2 and 36, with + 8 giving octal, 10 decimal, and 16 hexadecimal numbers. + + If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is + used. For negative numbers, zero padding might appear before the + minus sign. +*/ + +/*! + \fn QString QString::arg(ushort a, int fieldWidth, int base, const QChar &fillChar) const + \overload arg() + + \a fieldWidth specifies the minimum amount of space that \a a is + padded to and filled with the character \a fillChar. A positive + value produces right-aligned text; a negative value produces + left-aligned text. + + The \a base argument specifies the base to use when converting the + integer \a a into a string. The base must be between 2 and 36, with + 8 giving octal, 10 decimal, and 16 hexadecimal numbers. + + If \a fillChar is '0' (the number 0, ASCII 48), the locale's zero is + used. For negative numbers, zero padding might appear before the + minus sign. +*/ + +/*! + \overload arg() +*/ +QString QString::arg(QChar a, int fieldWidth, const QChar &fillChar) const +{ + QString c; + c += a; + return arg(c, fieldWidth, fillChar); +} + +/*! + \overload arg() + + The \a a argument is interpreted as a Latin-1 character. +*/ +QString QString::arg(char a, int fieldWidth, const QChar &fillChar) const +{ + QString c; + c += QLatin1Char(a); + return arg(c, fieldWidth, fillChar); +} + +/*! + \fn QString QString::arg(double a, int fieldWidth, char format, int precision, const QChar &fillChar) const + \overload arg() + + Argument \a a is formatted according to the specified \a format and + \a precision. See \l{Argument Formats} for details. + + \a fieldWidth specifies the minimum amount of space that \a a is + padded to and filled with the character \a fillChar. A positive + value produces right-aligned text; a negative value produces + left-aligned text. + + \snippet doc/src/snippets/code/src_corelib_tools_qstring.cpp 2 + + The '%' can be followed by an 'L', in which case the sequence is + replaced with a localized representation of \a a. The conversion + uses the default locale, set by QLocale::setDefaultLocale(). If no + default locale was specified, the "C" locale is used. + + If \a fillChar is '0' (the number 0, ASCII 48), this function will + use the locale's zero to pad. For negative numbers, the zero padding + will probably appear before the minus sign. + + \sa QLocale::toString() +*/ +QString QString::arg(double a, int fieldWidth, char fmt, int prec, const QChar &fillChar) const +{ + ArgEscapeData d = findArgEscapes(*this); + + if (d.occurrences == 0) { + qWarning("QString::arg: Argument missing: %s, %g", toLocal8Bit().data(), a); + return *this; + } + + unsigned flags = QLocalePrivate::NoFlags; + if (fillChar == QLatin1Char('0')) + flags = QLocalePrivate::ZeroPadded; + + if (qIsUpper(fmt)) + flags |= QLocalePrivate::CapitalEorX; + fmt = qToLower(fmt); + + QLocalePrivate::DoubleForm form = QLocalePrivate::DFDecimal; + switch (fmt) { + case 'f': + form = QLocalePrivate::DFDecimal; + break; + case 'e': + form = QLocalePrivate::DFExponent; + break; + case 'g': + form = QLocalePrivate::DFSignificantDigits; + break; + default: +#if defined(QT_CHECK_RANGE) + qWarning("QString::arg: Invalid format char '%c'", fmt); +#endif + break; + } + + QString arg; + if (d.occurrences > d.locale_occurrences) + arg = QLocale::c().d()->doubleToString(a, prec, form, fieldWidth, flags); + + QString locale_arg; + if (d.locale_occurrences > 0) { + QLocale locale; + + flags |= QLocalePrivate::ThousandsGroup; + locale_arg = locale.d()->doubleToString(a, prec, form, fieldWidth, flags); + } + + return replaceArgEscapes(*this, d, fieldWidth, arg, locale_arg, fillChar); +} + +static int getEscape(const QChar *uc, int *pos, int len, int maxNumber = 999) +{ + int i = *pos; + ++i; + if (i < len && uc[i] == QLatin1Char('L')) + ++i; + if (i < len) { + int escape = uc[i].unicode() - '0'; + if (uint(escape) >= 10U) + return -1; + ++i; + while (i < len) { + int digit = uc[i].unicode() - '0'; + if (uint(digit) >= 10U) + break; + escape = (escape * 10) + digit; + ++i; + } + if (escape <= maxNumber) { + *pos = i; + return escape; + } + } + return -1; +} + +QString QString::multiArg(int numArgs, const QString **args) const +{ + QString result; + QMap<int, int> numbersUsed; + const QChar *uc = (const QChar *) d->data; + const int len = d->size; + const int end = len - 1; + int lastNumber = -1; + int i = 0; + + // populate the numbersUsed map with the %n's that actually occur in the string + while (i < end) { + if (uc[i] == QLatin1Char('%')) { + int number = getEscape(uc, &i, len); + if (number != -1) { + numbersUsed.insert(number, -1); + continue; + } + } + ++i; + } + + // assign an argument number to each of the %n's + QMap<int, int>::iterator j = numbersUsed.begin(); + QMap<int, int>::iterator jend = numbersUsed.end(); + int arg = 0; + while (j != jend && arg < numArgs) { + *j = arg++; + lastNumber = j.key(); + ++j; + } + + // sanity + if (numArgs > arg) { + qWarning("QString::arg: %d argument(s) missing in %s", numArgs - arg, toLocal8Bit().data()); + numArgs = arg; + } + + i = 0; + while (i < len) { + if (uc[i] == QLatin1Char('%') && i != end) { + int number = getEscape(uc, &i, len, lastNumber); + int arg = numbersUsed[number]; + if (number != -1 && arg != -1) { + result += *args[arg]; + continue; + } + } + result += uc[i++]; + } + return result; +} + +/*! \internal + */ +void QString::updateProperties() const +{ + ushort *p = d->data; + ushort *end = p + d->size; + d->simpletext = true; + while (p < end) { + ushort uc = *p; + // sort out regions of complex text formatting + if (uc > 0x058f && (uc < 0x1100 || uc > 0xfb0f)) { + d->simpletext = false; + } + p++; + } + + p = d->data; + d->righttoleft = false; + while (p < end) { + switch(QChar::direction(*p)) + { + case QChar::DirL: + case QChar::DirLRO: + case QChar::DirLRE: + goto end; + case QChar::DirR: + case QChar::DirAL: + case QChar::DirRLO: + case QChar::DirRLE: + d->righttoleft = true; + goto end; + default: + break; + } + ++p; + } + end: + d->clean = true; + return; +} + +/*! \fn bool QString::isSimpleText() const + + \internal +*/ + +/*! \fn bool QString::isRightToLeft() const + + \internal +*/ + + +/*! \fn QChar *QString::data() + + Returns a pointer to the data stored in the QString. The pointer + can be used to access and modify the characters that compose the + string. For convenience, the data is '\\0'-terminated. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp 19 + + Note that the pointer remains valid only as long as the string is + not modified by other means. For read-only access, constData() is + faster because it never causes a \l{deep copy} to occur. + + \sa constData(), operator[]() +*/ + +/*! \fn const QChar *QString::data() const + + \overload +*/ + +/*! \fn const QChar *QString::constData() const + + Returns a pointer to the data stored in the QString. The pointer + can be used to access the characters that compose the string. For + convenience, the data is '\\0'-terminated. + + Note that the pointer remains valid only as long as the string is + not modified. + + \sa data(), operator[]() +*/ + +/*! \fn void QString::push_front(const QString &other) + + This function is provided for STL compatibility, prepending the + given \a other string to the beginning of this string. It is + equivalent to \c prepend(other). + + \sa prepend() +*/ + +/*! \fn void QString::push_front(QChar ch) + + \overload + + Prepends the given \a ch character to the beginning of this string. +*/ + +/*! \fn void QString::push_back(const QString &other) + + This function is provided for STL compatibility, appending the + given \a other string onto the end of this string. It is + equivalent to \c append(other). + + \sa append() +*/ + +/*! \fn void QString::push_back(QChar ch) + + \overload + + Appends the given \a ch character onto the end of this string. +*/ + +/*! + \fn std::string QString::toStdString() const + + Returns a std::string object with the data contained in this + QString. The Unicode data is converted into 8-bit characters using + the toAscii() function. + + This operator is mostly useful to pass a QString to a function + that accepts a std::string object. + + If the QString contains non-ASCII Unicode characters, using this + operator can lead to loss of information, since the implementation + calls toAscii(). + + This operator is only available if Qt is configured with STL + compatibility enabled. + + \sa toAscii(), toLatin1(), toUtf8(), toLocal8Bit() +*/ + +/*! + Constructs a QString that uses the first \a size Unicode characters + in the array \a unicode. The data in \a unicode is \e not + copied. The caller must be able to guarantee that \a unicode will + not be deleted or modified as long as the QString (or an + unmodified copy of it) exists. + + Any attempts to modify the QString or copies of it will cause it + to create a deep copy of the data, ensuring that the raw data + isn't modified. + + Here's an example of how we can use a QRegExp on raw data in + memory without requiring to copy the data into a QString: + + \snippet doc/src/snippets/qstring/main.cpp 22 + \snippet doc/src/snippets/qstring/main.cpp 23 + + \warning A string created with fromRawData() is \e not + '\\0'-terminated, unless the raw data contains a '\\0' character + at position \a size. This means unicode() will \e not return a + '\\0'-terminated string (although utf16() does, at the cost of + copying the raw data). + + \sa fromUtf16() +*/ +QString QString::fromRawData(const QChar *unicode, int size) +{ + Data *x = static_cast<Data *>(qMalloc(sizeof(Data))); + if (unicode) { + x->data = (ushort *)unicode; + } else { + x->data = x->array; + size = 0; + } + x->ref = 1; + x->alloc = x->size = size; + *x->array = '\0'; + x->clean = x->asciiCache = x->simpletext = x->righttoleft = x->capacity = 0; + return QString(x, 0); +} + +/*! \class QLatin1String + \brief The QLatin1String class provides a thin wrapper around an ASCII/Latin-1 encoded string literal. + + \ingroup text + \reentrant + + Many of QString's member functions are overloaded to accept + \c{const char *} instead of QString. This includes the copy + constructor, the assignment operator, the comparison operators, + and various other functions such as \link QString::insert() + insert() \endlink, \link QString::replace() replace()\endlink, + and \link QString::indexOf() indexOf()\endlink. These functions + are usually optimized to avoid constructing a QString object for + the \c{const char *} data. For example, assuming \c str is a + QString, + + \snippet doc/src/snippets/code/src_corelib_tools_qstring.cpp 3 + + is much faster than + + \snippet doc/src/snippets/code/src_corelib_tools_qstring.cpp 4 + + because it doesn't construct four temporary QString objects and + make a deep copy of the character data. + + Applications that define \c QT_NO_CAST_FROM_ASCII (as explained + in the QString documentation) don't have access to QString's + \c{const char *} API. To provide an efficient way of specifying + constant Latin-1 strings, Qt provides the QLatin1String, which is + just a very thin wrapper around a \c{const char *}. Using + QLatin1String, the example code above becomes + + \snippet doc/src/snippets/code/src_corelib_tools_qstring.cpp 5 + + This is a bit longer to type, but it provides exactly the same + benefits as the first version of the code, and is faster than + converting the Latin-1 strings using QString::fromLatin1(). + + Thanks to the QString(const QLatin1String &) constructor, + QLatin1String can be used everywhere a QString is expected. For + example: + + \snippet doc/src/snippets/code/src_corelib_tools_qstring.cpp 6 + + \sa QString, QLatin1Char +*/ + +/*! \fn QLatin1String::QLatin1String(const char *str) + + Constructs a QLatin1String object that stores \a str. Note that if + \a str is 0, an empty string is created; this case is handled by + QString. + + The string data is \e not copied. The caller must be able to + guarantee that \a str will not be deleted or modified as long as + the QLatin1String object exists. + + \sa latin1() +*/ + +/*! + \since 4.1 + \fn QLatin1String &QLatin1String::operator=(const QLatin1String &other) + + Constructs a copy of \a other. +*/ + +/*! \fn const char *QLatin1String::latin1() const + + Returns the Latin-1 string stored in this object. +*/ + +/*! \fn bool QLatin1String::operator==(const QString &other) const + + Returns true if this string is equal to string \a other; + otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings with + QString::localeAwareCompare(). +*/ + +/*! + \fn bool QLatin1String::operator==(const char *other) const + \since 4.3 + \overload + + The \a other const char pointer is converted to a QLatin1String using + the QString::fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! \fn bool QLatin1String::operator!=(const QString &other) const + + Returns true if this string is not equal to string \a other; + otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings with + QString::localeAwareCompare(). +*/ + +/*! + \fn bool QLatin1String::operator!=(const char *other) const + \since 4.3 + \overload operator!=() + + The \a other const char pointer is converted to a QLatin1String using + the QString::fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! + \fn bool QLatin1String::operator>(const QString &other) const + + Returns true if this string is lexically greater than string \a + other; otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings with + QString::localeAwareCompare(). +*/ + +/*! + \fn bool QLatin1String::operator>(const char *other) const + \since 4.3 + \overload + + The \a other const char pointer is converted to a QLatin1String using + the QString::fromAscii() function. + + You can disable this operator by defining \c QT_NO_CAST_FROM_ASCII + when you compile your applications. This can be useful if you want + to ensure that all user-visible strings go through QObject::tr(), + for example. +*/ + +/*! + \fn bool QLatin1String::operator<(const QString &other) const + + Returns true if this string is lexically less than the \a other + string; otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings using the + QString::localeAwareCompare() function. +*/ + +/*! + \fn bool QLatin1String::operator<(const char *other) const + \since 4.3 + \overload + + The \a other const char pointer is converted to a QLatin1String using + the QString::fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! + \fn bool QLatin1String::operator>=(const QString &other) const + + Returns true if this string is lexically greater than or equal + to string \a other; otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings with + QString::localeAwareCompare(). +*/ + +/*! + \fn bool QLatin1String::operator>=(const char *other) const + \since 4.3 + \overload + + The \a other const char pointer is converted to a QLatin1String using + the QString::fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + +/*! \fn bool QLatin1String::operator<=(const QString &other) const + + Returns true if this string is lexically less than or equal + to string \a other; otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings with + QString::localeAwareCompare(). +*/ + +/*! + \fn bool QLatin1String::operator<=(const char *other) const + \since 4.3 + \overload + + The \a other const char pointer is converted to a QString using + the QString::fromAscii() function. + + You can disable this operator by defining \c + QT_NO_CAST_FROM_ASCII when you compile your applications. This + can be useful if you want to ensure that all user-visible strings + go through QObject::tr(), for example. +*/ + + + +/* \fn bool operator==(const QLatin1String &s1, const QLatin1String &s2) + \relates QLatin1String + + Returns true if string \a s1 is lexically equal to string \a s2; otherwise + returns false. +*/ +/* \fn bool operator!=(const QLatin1String &s1, const QLatin1String &s2) + \relates QLatin1String + + Returns true if string \a s1 is lexically unequal to string \a s2; otherwise + returns false. +*/ +/* \fn bool operator<(const QLatin1String &s1, const QLatin1String &s2) + \relates QLatin1String + + Returns true if string \a s1 is lexically smaller than string \a s2; otherwise + returns false. +*/ +/* \fn bool operator<=(const QLatin1String &s1, const QLatin1String &s2) + \relates QLatin1String + + Returns true if string \a s1 is lexically smaller than or equal to string \a s2; otherwise + returns false. +*/ +/* \fn bool operator>(const QLatin1String &s1, const QLatin1String &s2) + \relates QLatin1String + + Returns true if string \a s1 is lexically greater than string \a s2; otherwise + returns false. +*/ +/* \fn bool operator>=(const QLatin1String &s1, const QLatin1String &s2) + \relates QLatin1String + + Returns true if string \a s1 is lexically greater than or equal to + string \a s2; otherwise returns false. +*/ + + +#ifndef QT_NO_DATASTREAM +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QString &string) + \relates QString + + Writes the given \a string to the specified \a stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator<<(QDataStream &out, const QString &str) +{ + if (out.version() == 1) { + out << str.toLatin1(); + } else { + if (!str.isNull() || out.version() < 3) { + int byteOrder = out.byteOrder(); + const QChar* ub = str.unicode(); + static const uint auto_size = 1024; + char t[auto_size]; + char *b; + if (str.length()*sizeof(QChar) > auto_size) { + b = new char[str.length()*sizeof(QChar)]; + } else { + b = t; + } + int l = str.length(); + char *c=b; + while (l--) { + if (byteOrder == QDataStream::BigEndian) { + *c++ = (char)ub->row(); + *c++ = (char)ub->cell(); + } else { + *c++ = (char)ub->cell(); + *c++ = (char)ub->row(); + } + ub++; + } + out.writeBytes(b, sizeof(QChar)*str.length()); + if (str.length()*sizeof(QChar) > auto_size) + delete [] b; + } else { + // write null marker + out << (quint32)0xffffffff; + } + } + return out; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QString &string) + \relates QString + + Reads a string from the specified \a stream into the given \a string. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator>>(QDataStream &in, QString &str) +{ +#ifdef QT_QSTRING_UCS_4 +#if defined(Q_CC_GNU) +#warning "operator>> not working properly" +#endif +#endif + + if (in.version() == 1) { + QByteArray l; + in >> l; + str = QString::fromLatin1(l); + } else { + quint32 bytes = 0; + in >> bytes; // read size of string + if (bytes == 0xffffffff) { // null string + str.clear(); + } else if (bytes > 0) { // not empty + if (bytes & 0x1) { + str.clear(); + in.setStatus(QDataStream::ReadCorruptData); + return in; + } + + const quint32 Step = 1024 * 1024; + quint32 len = bytes / 2; + quint32 allocated = 0; + + while (allocated < len) { + int blockSize = qMin(Step, len - allocated); + str.resize(allocated + blockSize); + if (in.readRawData(reinterpret_cast<char *>(str.data()) + allocated * 2, + blockSize * 2) != blockSize * 2) { + str.clear(); + in.setStatus(QDataStream::ReadPastEnd); + return in; + } + allocated += blockSize; + } + + if ((in.byteOrder() == QDataStream::BigEndian) + != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) { + ushort *data = reinterpret_cast<ushort *>(str.data()); + while (len--) { + *data = (*data >> 8) | (*data << 8); + ++data; + } + } + } else { + str = QLatin1String(""); + } + } + return in; +} +#endif // QT_NO_DATASTREAM + +/*! + \fn void QString::setLength(int nl) + + Use resize() instead. +*/ + +/*! + \fn QString QString::copy() const + + Use simple assignment instead. QString is implicitly shared so if + a copy is modified only the copy is changed. +*/ + +/*! + \fn QString &QString::remove(QChar c, bool cs) + + Use the remove(QChar, Qt::CaseSensitive) overload instead. +*/ + +/*! + \fn QString &QString::remove(const QString &s, bool cs) + + Use the remove(QString, Qt::CaseSensitive) overload instead. +*/ + +/*! + \fn QString &QString::replace(QChar c, const QString &after, bool cs) + + Use the replace(QChar, QString, Qt::CaseSensitive) overload instead. +*/ + +/*! + \fn QString &QString::replace(const QString &before, const QString &after, bool cs) + + Use the replace(QString, QString, Qt::CaseSensitive) overload instead. +*/ + +/*! + \fn QString &QString::replace(char c, const QString &after, bool cs) + + Use the replace(QChar, QString, Qt::CaseSensitive) overload instead. +*/ + +/*! + \fn QString &QString::replace(char c, const QString &after, Qt::CaseSensitivity cs) + + Use the replace(QChar, QString, Qt::CaseSensitive) overload instead. +*/ + +/*! + \fn int QString::find(QChar c, int i = 0, bool cs = true) const + + Use indexOf() instead. +*/ + +/*! + \fn int QString::find(const QString &s, int i = 0, bool cs = true) const + + Use indexOf() instead. +*/ + +/*! + \fn int QString::findRev(QChar c, int i = -1, bool cs = true) const + + Use lastIndexOf() instead. +*/ + +/*! + \fn int QString::findRev(const QString &s, int i = -1, bool cs = true) const + + Use lastIndexOf() instead. +*/ + +/*! + \fn int QString::find(const QRegExp &rx, int i=0) const + + Use indexOf() instead. +*/ + +/*! + \fn int QString::find(QRegExp &rx, int i=0) const + \internal + \since 4.5 + + Use indexOf() instead. +*/ + +/*! + \fn int QString::findRev(const QRegExp &rx, int i=-1) const + + Use lastIndexOf() instead. +*/ + +/*! + \fn int QString::findRev(QRegExp &rx, int i=0) const + \internal + \since 4.5 + + Use lastIndexOf() instead. +*/ + +/*! + \fn QBool QString::contains(QChar c, bool cs) const + + Use the contains(QChar, Qt::CaseSensitive) overload instead. +*/ + +/*! + \fn QBool QString::contains(const QString &s, bool cs) const + + Use the contains(QString, Qt::CaseSensitive) overload instead. +*/ + +/*! + \fn bool QString::startsWith(const QString &s, bool cs) const + + Use the startsWith(QString, Qt::CaseSensitive) overload instead. +*/ + +/*! + \fn bool QString::endsWith(const QString &s, bool cs) const + + Use the endsWith(QString, Qt::CaseSensitive) overload instead. +*/ + +/*! + \fn QString QString::leftJustify(int width, QChar fill = QLatin1Char(' '), bool trunc=false) const + + Use leftJustified() instead. +*/ + +/*! + \fn QString QString::rightJustify(int width, QChar fill = QLatin1Char(' '), bool trunc=false) const + + Use rightJustified() instead. +*/ + +/*! + \fn QString QString::lower() const + + Use toLower() instead. +*/ + +/*! + \fn QString QString::upper() const + + Use toUpper() instead. +*/ + +/*! + \fn QString QString::stripWhiteSpace() const + + Use trimmed() instead. +*/ + +/*! + \fn QString QString::simplifyWhiteSpace() const + + Use simplified() instead. +*/ + +/*! + \fn QString &QString::setUnicodeCodes(const ushort *unicode_as_ushorts, int size) + + Use setUtf16() instead. +*/ + +/*! + \fn ushort *QString::ucs2() const + + Use utf16() instead. +*/ + +/*! + \fn QString QString::fromUcs2(const ushort *unicode, int size = -1) + + Use fromUtf16() instead. +*/ + +/*! + \fn QString &QString::setAscii(const char *str, int len = -1) + + Use fromAscii() instead. +*/ + +/*! + \fn QString &QString::setLatin1(const char *str, int len = -1) + + Use fromLatin1() instead. +*/ + +/*! + \fn QChar QString::constref(uint i) const + + Use at() instead. +*/ + +/*! + \fn QChar &QString::ref(uint i); + + Use operator[]() instead. +*/ + +/*! + \fn QString::operator const char *() const + + Use toAscii().constData() instead. +*/ + +/*! + \class QConstString + \brief The QConstString class is a wrapper for constant Unicode string data. + \compat + + In Qt 4, QConstString is replaced by QString::fromRawData(), a + static function that constructs a QString object based on Unicode + string data. + + Because QString::fromRawData() has slightly more stringent + constraints than QConstString had in Qt 3, the new QConstString + class takes a deep copy of the string data. + + \sa QString::fromRawData() +*/ + +/*! + \fn QConstString::QConstString(const QChar *unicode, int size) + + Use QString(\a unicode, \a size) or + QString::fromRawData(\a unicode, \a size) instead. +*/ + +/*! + \fn const QString &QConstString::string() const + + Returns \c *this. Not necessary in Qt 4. +*/ + + + +/*! + \class QStringRef + \since 4.3 + \brief The QStringRef class provides a thin wrapper around QString substrings. + \reentrant + \ingroup tools + \ingroup text + + QStringRef provides a read-only subset of the QString API. + + A string reference explicitly references a portion of a string() + with a given size(), starting at a specific position(). Calling + toString() returns a copy of the data as a real QString instance. + + This class is designed to improve the performance of substring + handling when manipulating substrings obtained from existing QString + instances. QStringRef avoids the memory allocation and reference + counting overhead of a standard QString by simply referencing a + part of the original string. This can prove to be advantageous in + low level code, such as that used in a parser, at the expense of + potentially more complex code. + + For most users, there are no semantic benefits to using QStringRef + instead of QString since QStringRef requires attention to be paid + to memory management issues, potentially making code more complex + to write and maintain. + + \warning A QStringRef is only valid as long as the referenced + string exists. If the original string is deleted, the string + reference points to an invalid memory location. + + We suggest that you only use this class in stable code where profiling + has clearly identified that performance improvements can be made by + replacing standard string operations with the optimized substring + handling provided by this class. + + \sa {Implicitly Shared Classes} +*/ + + +/*! + \fn QStringRef::QStringRef() + + Constructs an empty string reference. +*/ + +/*! \fn QStringRef::QStringRef(const QString *string, int position, int length) + +Constructs a string reference to the range of characters in the given +\a string specified by the starting \a position and \a length in characters. + +\warning This function exists to improve performance as much as possible, +and performs no bounds checking. For program correctness, \a position and +\a length must describe a valid substring of \a string. + +This means that the starting \a position must be positive or 0 and smaller +than \a string's length, and \a length must be positive or 0 but smaller than +the string's length minus the starting \a position; +i.e, 0 <= position < string->length() and +0 <= length <= string->length() - position must both be satisfied. +*/ + +/*! \fn QStringRef::QStringRef(const QString *string) + +Constructs a string reference to the given \a string. +*/ + +/*! \fn QStringRef::QStringRef(const QStringRef &other) + +Constructs a copy of the \a other string reference. + */ +/*! +\fn QStringRef::~QStringRef() + +Destroys the string reference. + +Since this class is only used to refer to string data, and does not take +ownership of it, no memory is freed when instances are destroyed. +*/ + + +/*! + \fn int QStringRef::position() const + + Returns the starting position in the referenced string that is referred to + by the string reference. + + \sa size(), string() +*/ + +/*! + \fn int QStringRef::size() const + + Returns the number of characters referred to by the string reference. + Equivalent to length() and count(). + + \sa position(), string() +*/ +/*! + \fn int QStringRef::count() const + Returns the number of characters referred to by the string reference. + Equivalent to size() and length(). + + \sa position(), string() +*/ +/*! + \fn int QStringRef::length() const + Returns the number of characters referred to by the string reference. + Equivalent to size() and count(). + + \sa position(), string() +*/ + + +/*! + \fn bool QStringRef::isEmpty() const + + Returns true if the string reference has no characters; otherwise returns + false. + + A string reference is empty if its size is zero. + + \sa size() +*/ + +/*! + \fn bool QStringRef::isNull() const + + Returns true if string() returns a null pointer or a pointer to a + null string; otherwise returns true. + + \sa size() +*/ + +/*! + \fn const QString *QStringRef::string() const + + Returns a pointer to the string referred to by the string reference, or + 0 if it does not reference a string. + + \sa unicode() +*/ + + +/*! + \fn const QChar *QStringRef::unicode() const + + Returns a Unicode representation of the string reference. Since + the data stems directly from the referenced string, it is not + null-terminated unless the string reference includes the string's + null terminator. + + \sa string() +*/ + +/*! + \fn const QChar *QStringRef::data() const + + Same as unicode(). +*/ + +/*! + \fn const QChar *QStringRef::constData() const + + Same as unicode(). +*/ + +/*! + Returns a copy of the string reference as a QString object. + + If the string reference is not a complete reference of the string + (meaning that position() is 0 and size() equals string()->size()), + this function will allocate a new string to return. + + \sa string() +*/ + +QString QStringRef::toString() const { + if (!m_string) + return QString(); + if (m_size && m_position == 0 && m_size == m_string->size()) + return *m_string; + return QString::fromUtf16(reinterpret_cast<const ushort*>(m_string->unicode() + m_position), m_size); +} + + +/*! \relates QStringRef + + Returns true if string reference \a s1 is lexically equal to string reference \a s2; otherwise + returns false. +*/ +bool operator==(const QStringRef &s1,const QStringRef &s2) +{ return (s1.size() == s2.size() && + (memcmp((char*)s1.unicode(), (char*)s2.unicode(), s1.size()*sizeof(QChar))==0)); } + +/*! \relates QStringRef + + Returns true if string \a s1 is lexically equal to string reference \a s2; otherwise + returns false. +*/ +bool operator==(const QString &s1,const QStringRef &s2) +{ return (s1.size() == s2.size() && + (memcmp((char*)s1.unicode(), (char*)s2.unicode(), s1.size()*sizeof(QChar))==0)); } + +/*! \relates QStringRef + + Returns true if string \a s1 is lexically equal to string reference \a s2; otherwise + returns false. +*/ +bool operator==(const QLatin1String &s1, const QStringRef &s2) +{ + const ushort *uc = reinterpret_cast<const ushort *>(s2.unicode()); + const ushort *e = uc + s2.size(); + const uchar *c = reinterpret_cast<const uchar *>(s1.latin1()); + if (!c) + return s2.isEmpty(); + + while (*c) { + if (uc == e || *uc != *c) + return false; + ++uc; + ++c; + } + return (uc == e); +} + +/*! + \relates QStringRef + + Returns true if string reference \a s1 is lexically less than + string reference \a s2; otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings using the + QString::localeAwareCompare() function. +*/ +bool operator<(const QStringRef &s1,const QStringRef &s2) +{ + return ucstrcmp(s1.constData(), s1.length(), s2.constData(), s2.length()) < 0; +} + +/*!\fn bool operator<=(const QStringRef &s1,const QStringRef &s2) + + \relates QStringRef + + Returns true if string reference \a s1 is lexically less than + or equal to string reference \a s2; otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings using the + QString::localeAwareCompare() function. +*/ + +/*!\fn bool operator>=(const QStringRef &s1,const QStringRef &s2) + + \relates QStringRef + + Returns true if string reference \a s1 is lexically greater than + or equal to string reference \a s2; otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings using the + QString::localeAwareCompare() function. +*/ + +/*!\fn bool operator>(const QStringRef &s1,const QStringRef &s2) + + \relates QStringRef + + Returns true if string reference \a s1 is lexically greater than + string reference \a s2; otherwise returns false. + + The comparison is based exclusively on the numeric Unicode values + of the characters and is very fast, but is not what a human would + expect. Consider sorting user-interface strings using the + QString::localeAwareCompare() function. +*/ + + +/*! + \fn const QChar QStringRef::at(int position) const + + Returns the character at the given index \a position in the + string reference. + + The \a position must be a valid index position in the string + (i.e., 0 <= \a position < size()). +*/ + +/*! + \fn void QStringRef::clear() + + Clears the contents of the string reference by making it null and empty. + + \sa isEmpty(), isNull() +*/ + +/*! + \fn QStringRef &QStringRef::operator=(const QStringRef &other) + + Assigns the \a other string reference to this string reference, and + returns the result. +*/ + +/*! + \fn QStringRef &QStringRef::operator=(const QString *string) + + Constructs a string reference to the given \a string and assigns it to + this string reference, returning the result. +*/ + +/*! + \typedef QString::DataPtr + \internal +*/ + +/*! + \fn DataPtr & QString::data_ptr() + \internal +*/ + + + +/*! Appends the string reference to \a string, and returns a new +reference to the combined string data. + */ +QStringRef QStringRef::appendTo(QString *string) const +{ + if (!string) + return QStringRef(); + int pos = string->size(); + string->insert(pos, unicode(), size()); + return QStringRef(string, pos, size()); +} + +/*! + \fn int QStringRef::compare(const QStringRef &s1, const QString &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive) + \since 4.5 + + Compares the string \a s1 with the string \a s2 and returns an + integer less than, equal to, or greater than zero if \a s1 + is less than, equal to, or greater than \a s2. + + If \a cs is Qt::CaseSensitive, the comparison is case sensitive; + otherwise the comparison is case insensitive. +*/ + +/*! + \fn int QStringRef::compare(const QStringRef &s1, const QStringRef &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive) + \since 4.5 + \overload + + Compares the string \a s1 with the string \a s2 and returns an + integer less than, equal to, or greater than zero if \a s1 + is less than, equal to, or greater than \a s2. + + If \a cs is Qt::CaseSensitive, the comparison is case sensitive; + otherwise the comparison is case insensitive. +*/ + +/*! + \fn int QStringRef::compare(const QStringRef &s1, QLatin1String s2, Qt::CaseSensitivity cs = Qt::CaseSensitive) + \since 4.5 + \overload + + Compares the string \a s1 with the string \a s2 and returns an + integer less than, equal to, or greater than zero if \a s1 + is less than, equal to, or greater than \a s2. + + If \a cs is Qt::CaseSensitive, the comparison is case sensitive; + otherwise the comparison is case insensitive. +*/ + +/*! + \overload + \fn int QStringRef::compare(const QString &other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + \since 4.5 + + Compares this string with the \a other string and returns an + integer less than, equal to, or greater than zero if this string + is less than, equal to, or greater than the \a other string. + + If \a cs is Qt::CaseSensitive, the comparison is case sensitive; + otherwise the comparison is case insensitive. + + Equivalent to \c {compare(*this, other, cs)}. + + \sa QString::compare() +*/ + +/*! + \overload + \fn int QStringRef::compare(const QStringRef &other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + \since 4.5 + + Compares this string with the \a other string and returns an + integer less than, equal to, or greater than zero if this string + is less than, equal to, or greater than the \a other string. + + If \a cs is Qt::CaseSensitive, the comparison is case sensitive; + otherwise the comparison is case insensitive. + + Equivalent to \c {compare(*this, other, cs)}. + + \sa QString::compare() +*/ + +/*! + \overload + \fn int QStringRef::compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const + \since 4.5 + + Compares this string with the \a other string and returns an + integer less than, equal to, or greater than zero if this string + is less than, equal to, or greater than the \a other string. + + If \a cs is Qt::CaseSensitive, the comparison is case sensitive; + otherwise the comparison is case insensitive. + + Equivalent to \c {compare(*this, other, cs)}. + + \sa QString::compare() +*/ + +/*! + \fn int QStringRef::localeAwareCompare(const QStringRef &s1, const QString & s2) + \since 4.5 + + Compares \a s1 with \a s2 and returns an integer less than, equal + to, or greater than zero if \a s1 is less than, equal to, or + greater than \a s2. + + The comparison is performed in a locale- and also + platform-dependent manner. Use this function to present sorted + lists of strings to the user. + + On Mac OS X, this function compares according the + "Order for sorted lists" setting in the International prefereces panel. + + \sa compare(), QTextCodec::locale() +*/ + +/*! + \fn int QStringRef::localeAwareCompare(const QStringRef &s1, const QStringRef & s2) + \since 4.5 + \overload + + Compares \a s1 with \a s2 and returns an integer less than, equal + to, or greater than zero if \a s1 is less than, equal to, or + greater than \a s2. + + The comparison is performed in a locale- and also + platform-dependent manner. Use this function to present sorted + lists of strings to the user. + +*/ + +/*! + \fn int QStringRef::localeAwareCompare(const QString &other) const + \since 4.5 + \overload + + Compares this string with the \a other string and returns an + integer less than, equal to, or greater than zero if this string + is less than, equal to, or greater than the \a other string. + + The comparison is performed in a locale- and also + platform-dependent manner. Use this function to present sorted + lists of strings to the user. +*/ + +/*! + \fn int QStringRef::localeAwareCompare(const QStringRef &other) const + \since 4.5 + \overload + + Compares this string with the \a other string and returns an + integer less than, equal to, or greater than zero if this string + is less than, equal to, or greater than the \a other string. + + The comparison is performed in a locale- and also + platform-dependent manner. Use this function to present sorted + lists of strings to the user. +*/ + +/*! + \fn QString &QString::append(const QStringRef &reference) + \since 4.4 + + Appends the given string \a reference to this string and returns the result. + */ +QString &QString::append(const QStringRef &str) +{ + if (str.string() == this) { + str.appendTo(this); + } else if (str.string()) { + int oldSize = size(); + resize(oldSize + str.size()); + memcpy(data() + oldSize, str.unicode(), str.size() * sizeof(QChar)); + } + return *this; +} + +/*! + \since 4.4 + + Returns a substring reference to the \a n leftmost characters + of the string. + + If \a n is greater than size() or less than zero, a reference to the entire + string is returned. + + \snippet doc/src/snippets/qstring/main.cpp leftRef + + \sa left(), rightRef(), midRef(), startsWith() +*/ +QStringRef QString::leftRef(int n) const +{ + if (n >= d->size || n < 0) + n = d->size; + return QStringRef(this, 0, n); +} + +/*! + \since 4.4 + + Returns a substring reference to the \a n rightmost characters + of the string. + + If \a n is greater than size() or less than zero, a reference to the entire + string is returned. + + \snippet doc/src/snippets/qstring/main.cpp rightRef + + \sa right(), leftRef(), midRef(), endsWith() +*/ +QStringRef QString::rightRef(int n) const +{ + if (n >= d->size || n < 0) + n = d->size; + return QStringRef(this, d->size - n, n); +} + +/*! + \since 4.4 + + Returns a substring reference to \a n characters of this string, + starting at the specified \a position. + + If the \a position exceeds the length of the string, an empty + reference is returned. + + If there are less than \a n characters available in the string, + starting at the given \a position, or if \a n is -1 (default), the + function returns all characters from the specified \a position + onwards. + + Example: + + \snippet doc/src/snippets/qstring/main.cpp midRef + + \sa mid(), leftRef(), rightRef() +*/ + +QStringRef QString::midRef(int position, int n) const +{ + if (d == &shared_null || position >= d->size) + return QStringRef(); + if (n < 0) + n = d->size - position; + if (position < 0) { + n += position; + position = 0; + } + if (n + position > d->size) + n = d->size - position; + return QStringRef(this, position, n); +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h new file mode 100644 index 0000000..1493dce --- /dev/null +++ b/src/corelib/tools/qstring.h @@ -0,0 +1,1234 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTRING_H +#define QSTRING_H + +#include <QtCore/qchar.h> +#include <QtCore/qbytearray.h> +#include <QtCore/qatomic.h> +#include <QtCore/qnamespace.h> +#ifdef QT_INCLUDE_COMPAT +#include <Qt3Support/q3cstring.h> +#endif + +#ifndef QT_NO_STL +# if defined (Q_CC_MSVC_NET) && _MSC_VER < 1310 // Avoids nasty warning for xlocale, line 450 +# pragma warning (push) +# pragma warning (disable : 4189) +# include <string> +# pragma warning (pop) +# else +# include <string> +# endif + +# ifndef QT_NO_STL_WCHAR +// workaround for some headers not typedef'ing std::wstring +typedef std::basic_string<wchar_t> QStdWString; +# endif // QT_NO_STL_WCHAR + +#endif // QT_NO_STL + +#include <stdarg.h> + +#ifdef truncate +#error qstring.h must be included before any header file that defines truncate +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class QCharRef; +class QRegExp; +class QStringList; +class QTextCodec; +class QLatin1String; +class QStringRef; +template <typename T> class QVector; + +class Q_CORE_EXPORT QString +{ +public: + inline QString(); + QString(const QChar *unicode, int size); + QString(QChar c); + QString(int size, QChar c); + inline QString(const QLatin1String &latin1); + inline QString(const QString &); + inline ~QString(); + QString &operator=(QChar c); + QString &operator=(const QString &); + inline QString &operator=(const QLatin1String &); + + inline int size() const { return d->size; } + inline int count() const { return d->size; } + inline int length() const; + inline bool isEmpty() const; + void resize(int size); + + QString &fill(QChar c, int size = -1); + void truncate(int pos); + void chop(int n); + + int capacity() const; + inline void reserve(int size); + inline void squeeze() { if (d->size < d->alloc) realloc(); d->capacity = 0;} + + inline const QChar *unicode() const; + inline QChar *data(); + inline const QChar *data() const; + inline const QChar *constData() const; + + inline void detach(); + inline bool isDetached() const; + void clear(); + + inline const QChar at(int i) const; + const QChar operator[](int i) const; + QCharRef operator[](int i); + const QChar operator[](uint i) const; + QCharRef operator[](uint i); + + QString arg(qlonglong a, int fieldwidth=0, int base=10, + const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT; + QString arg(qulonglong a, int fieldwidth=0, int base=10, + const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT; + QString arg(long a, int fieldwidth=0, int base=10, + const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT; + QString arg(ulong a, int fieldwidth=0, int base=10, + const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT; + QString arg(int a, int fieldWidth = 0, int base = 10, + const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT; + QString arg(uint a, int fieldWidth = 0, int base = 10, + const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT; + QString arg(short a, int fieldWidth = 0, int base = 10, + const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT; + QString arg(ushort a, int fieldWidth = 0, int base = 10, + const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT; + QString arg(double a, int fieldWidth = 0, char fmt = 'g', int prec = -1, + const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT; + QString arg(char a, int fieldWidth = 0, + const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT; + QString arg(QChar a, int fieldWidth = 0, + const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT; + QString arg(const QString &a, int fieldWidth = 0, + const QChar &fillChar = QLatin1Char(' ')) const Q_REQUIRED_RESULT; + QString arg(const QString &a1, const QString &a2) const Q_REQUIRED_RESULT; + QString arg(const QString &a1, const QString &a2, const QString &a3) const Q_REQUIRED_RESULT; + QString arg(const QString &a1, const QString &a2, const QString &a3, + const QString &a4) const Q_REQUIRED_RESULT; + QString arg(const QString &a1, const QString &a2, const QString &a3, + const QString &a4, const QString &a5) const Q_REQUIRED_RESULT; + QString arg(const QString &a1, const QString &a2, const QString &a3, + const QString &a4, const QString &a5, const QString &a6) const Q_REQUIRED_RESULT; + QString arg(const QString &a1, const QString &a2, const QString &a3, + const QString &a4, const QString &a5, const QString &a6, + const QString &a7) const Q_REQUIRED_RESULT; + QString arg(const QString &a1, const QString &a2, const QString &a3, + const QString &a4, const QString &a5, const QString &a6, + const QString &a7, const QString &a8) const Q_REQUIRED_RESULT; + QString arg(const QString &a1, const QString &a2, const QString &a3, + const QString &a4, const QString &a5, const QString &a6, + const QString &a7, const QString &a8, const QString &a9) const Q_REQUIRED_RESULT; + + QString &vsprintf(const char *format, va_list ap) +#if defined(Q_CC_GNU) && !defined(__INSURE__) + __attribute__ ((format (printf, 2, 0))) +#endif + ; + QString &sprintf(const char *format, ...) +#if defined(Q_CC_GNU) && !defined(__INSURE__) + __attribute__ ((format (printf, 2, 3))) +#endif + ; + + int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(const QString &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int indexOf(const QLatin1String &s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(const QString &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int lastIndexOf(const QLatin1String &s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + inline QBool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QBool contains(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int count(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int count(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + +#ifndef QT_NO_REGEXP + int indexOf(const QRegExp &, int from = 0) const; + int lastIndexOf(const QRegExp &, int from = -1) const; + inline QBool contains(const QRegExp &rx) const { return QBool(indexOf(rx) != -1); } + int count(const QRegExp &) const; + + int indexOf(QRegExp &, int from = 0) const; + int lastIndexOf(QRegExp &, int from = -1) const; + inline QBool contains(QRegExp &rx) const { return QBool(indexOf(rx) != -1); } +#endif + + enum SectionFlag { + SectionDefault = 0x00, + SectionSkipEmpty = 0x01, + SectionIncludeLeadingSep = 0x02, + SectionIncludeTrailingSep = 0x04, + SectionCaseInsensitiveSeps = 0x08 + }; + Q_DECLARE_FLAGS(SectionFlags, SectionFlag) + + QString section(QChar sep, int start, int end = -1, SectionFlags flags = SectionDefault) const; + QString section(const QString &in_sep, int start, int end = -1, SectionFlags flags = SectionDefault) const; +#ifndef QT_NO_REGEXP + QString section(const QRegExp ®, int start, int end = -1, SectionFlags flags = SectionDefault) const; +#endif + + QString left(int n) const Q_REQUIRED_RESULT; + QString right(int n) const Q_REQUIRED_RESULT; + QString mid(int position, int n = -1) const Q_REQUIRED_RESULT; + QStringRef leftRef(int n) const Q_REQUIRED_RESULT; + QStringRef rightRef(int n) const Q_REQUIRED_RESULT; + QStringRef midRef(int position, int n = -1) const Q_REQUIRED_RESULT; + + bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool startsWith(const QLatin1String &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool startsWith(const QChar &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(const QLatin1String &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + bool endsWith(const QChar &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + QString leftJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const Q_REQUIRED_RESULT; + QString rightJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const Q_REQUIRED_RESULT; + + QString toLower() const Q_REQUIRED_RESULT; + QString toUpper() const Q_REQUIRED_RESULT; + QString toCaseFolded() const Q_REQUIRED_RESULT; + + QString trimmed() const Q_REQUIRED_RESULT; + QString simplified() const Q_REQUIRED_RESULT; + + QString &insert(int i, QChar c); + QString &insert(int i, const QChar *uc, int len); + inline QString &insert(int i, const QString &s) { return insert(i, s.constData(), s.length()); } + QString &insert(int i, const QLatin1String &s); + QString &append(QChar c); + QString &append(const QString &s); + QString &append(const QStringRef &s); + QString &append(const QLatin1String &s); + inline QString &prepend(QChar c) { return insert(0, c); } + inline QString &prepend(const QString &s) { return insert(0, s); } + inline QString &prepend(const QLatin1String &s) { return insert(0, s); } + + inline QString &operator+=(QChar c) { + if (d->ref != 1 || d->size + 1 > d->alloc) + realloc(grow(d->size + 1)); + d->data[d->size++] = c.unicode(); + d->data[d->size] = '\0'; + return *this; + } + + inline QString &operator+=(QChar::SpecialCharacter c) { return append(QChar(c)); } + inline QString &operator+=(const QString &s) { return append(s); } + inline QString &operator+=(const QStringRef &s) { return append(s); } + inline QString &operator+=(const QLatin1String &s) { return append(s); } + + QString &remove(int i, int len); + QString &remove(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive); + QString &remove(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive); + QString &replace(int i, int len, QChar after); + QString &replace(int i, int len, const QChar *s, int slen); + QString &replace(int i, int len, const QString &after); + QString &replace(QChar before, QChar after, Qt::CaseSensitivity cs = Qt::CaseSensitive); + QString &replace(const QChar *before, int blen, const QChar *after, int alen, Qt::CaseSensitivity cs = Qt::CaseSensitive); + QString &replace(const QLatin1String &before, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); + QString &replace(const QLatin1String &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); + QString &replace(const QString &before, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); + QString &replace(const QString &before, const QString &after, + Qt::CaseSensitivity cs = Qt::CaseSensitive); + QString &replace(QChar c, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); + QString &replace(QChar c, const QLatin1String &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); +#ifndef QT_NO_REGEXP + QString &replace(const QRegExp &rx, const QString &after); + inline QString &remove(const QRegExp &rx) + { return replace(rx, QString()); } +#endif + + enum SplitBehavior { KeepEmptyParts, SkipEmptyParts }; + + QStringList split(const QString &sep, SplitBehavior behavior = KeepEmptyParts, + Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT; + QStringList split(const QChar &sep, SplitBehavior behavior = KeepEmptyParts, + Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT; +#ifndef QT_NO_REGEXP + QStringList split(const QRegExp &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT; +#endif + + enum NormalizationForm { + NormalizationForm_D, + NormalizationForm_C, + NormalizationForm_KD, + NormalizationForm_KC + }; + QString normalized(NormalizationForm mode) const Q_REQUIRED_RESULT; + QString normalized(NormalizationForm mode, QChar::UnicodeVersion version) const Q_REQUIRED_RESULT; + + QString repeated(int times) const; + + const ushort *utf16() const; + + QByteArray toAscii() const Q_REQUIRED_RESULT; + QByteArray toLatin1() const Q_REQUIRED_RESULT; + QByteArray toUtf8() const Q_REQUIRED_RESULT; + QByteArray toLocal8Bit() const Q_REQUIRED_RESULT; + QVector<uint> toUcs4() const Q_REQUIRED_RESULT; + + static QString fromAscii(const char *, int size = -1); + static QString fromLatin1(const char *, int size = -1); + static QString fromUtf8(const char *, int size = -1); + static QString fromLocal8Bit(const char *, int size = -1); + static QString fromUtf16(const ushort *, int size = -1); + static QString fromUcs4(const uint *, int size = -1); + static QString fromRawData(const QChar *, int size); + + int toWCharArray(wchar_t *array) const; + static QString fromWCharArray(const wchar_t *, int size = -1); + + QString &setUnicode(const QChar *unicode, int size); + inline QString &setUtf16(const ushort *utf16, int size); + + // ### Qt 5: merge these two functions + int compare(const QString &s) const; + int compare(const QString &s, Qt::CaseSensitivity cs) const; + + int compare(const QLatin1String &other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + // ### Qt 5: merge these two functions + static inline int compare(const QString &s1, const QString &s2) + { return s1.compare(s2); } + static inline int compare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs) + { return s1.compare(s2, cs); } + + static inline int compare(const QString& s1, const QLatin1String &s2, + Qt::CaseSensitivity cs = Qt::CaseSensitive) + { return s1.compare(s2, cs); } + static inline int compare(const QLatin1String& s1, const QString &s2, + Qt::CaseSensitivity cs = Qt::CaseSensitive) + { return -s2.compare(s1, cs); } + + int compare(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + static int compare(const QString &s1, const QStringRef &s2, + Qt::CaseSensitivity = Qt::CaseSensitive); + + int localeAwareCompare(const QString& s) const; + static int localeAwareCompare(const QString& s1, const QString& s2) + { return s1.localeAwareCompare(s2); } + + int localeAwareCompare(const QStringRef &s) const; + static int localeAwareCompare(const QString& s1, const QStringRef& s2); + + short toShort(bool *ok=0, int base=10) const; + ushort toUShort(bool *ok=0, int base=10) const; + int toInt(bool *ok=0, int base=10) const; + uint toUInt(bool *ok=0, int base=10) const; + long toLong(bool *ok=0, int base=10) const; + ulong toULong(bool *ok=0, int base=10) const; + qlonglong toLongLong(bool *ok=0, int base=10) const; + qulonglong toULongLong(bool *ok=0, int base=10) const; + float toFloat(bool *ok=0) const; + double toDouble(bool *ok=0) const; + + QString &setNum(short, int base=10); + QString &setNum(ushort, int base=10); + QString &setNum(int, int base=10); + QString &setNum(uint, int base=10); + QString &setNum(long, int base=10); + QString &setNum(ulong, int base=10); + QString &setNum(qlonglong, int base=10); + QString &setNum(qulonglong, int base=10); + QString &setNum(float, char f='g', int prec=6); + QString &setNum(double, char f='g', int prec=6); + + static QString number(int, int base=10); + static QString number(uint, int base=10); + static QString number(long, int base=10); + static QString number(ulong, int base=10); + static QString number(qlonglong, int base=10); + static QString number(qulonglong, int base=10); + static QString number(double, char f='g', int prec=6); + + bool operator==(const QString &s) const; + bool operator<(const QString &s) const; + inline bool operator>(const QString &s) const { return s < *this; } + inline bool operator!=(const QString &s) const { return !operator==(s); } + inline bool operator<=(const QString &s) const { return !operator>(s); } + inline bool operator>=(const QString &s) const { return !operator<(s); } + + bool operator==(const QLatin1String &s) const; + bool operator<(const QLatin1String &s) const; + bool operator>(const QLatin1String &s) const; + inline bool operator!=(const QLatin1String &s) const { return !operator==(s); } + inline bool operator<=(const QLatin1String &s) const { return !operator>(s); } + inline bool operator>=(const QLatin1String &s) const { return !operator<(s); } + + // ASCII compatibility +#ifndef QT_NO_CAST_FROM_ASCII + inline QT_ASCII_CAST_WARN_CONSTRUCTOR QString(const char *ch) : d(fromAscii_helper(ch)) + {} + inline QT_ASCII_CAST_WARN_CONSTRUCTOR QString(const QByteArray &a) + : d(fromAscii_helper(a.constData(), qstrnlen(a.constData(), a.size()))) + {} + inline QT_ASCII_CAST_WARN QString &operator=(const char *ch) + { return (*this = fromAscii(ch)); } + inline QT_ASCII_CAST_WARN QString &operator=(const QByteArray &a) + { return (*this = fromAscii(a.constData(), qstrnlen(a.constData(), a.size()))); } + inline QT_ASCII_CAST_WARN QString &operator=(char c) + { return (*this = QChar::fromAscii(c)); } + + // these are needed, so it compiles with STL support enabled + inline QT_ASCII_CAST_WARN QString &prepend(const char *s) + { return prepend(QString::fromAscii(s)); } + inline QT_ASCII_CAST_WARN QString &prepend(const QByteArray &s) + { return prepend(QString::fromAscii(s.constData(), qstrnlen(s.constData(), s.size()))); } + inline QT_ASCII_CAST_WARN QString &append(const char *s) + { return append(QString::fromAscii(s)); } + inline QT_ASCII_CAST_WARN QString &append(const QByteArray &s) + { return append(QString::fromAscii(s.constData(), qstrnlen(s.constData(), s.size()))); } + inline QT_ASCII_CAST_WARN QString &operator+=(const char *s) + { return append(QString::fromAscii(s)); } + inline QT_ASCII_CAST_WARN QString &operator+=(const QByteArray &s) + { return append(QString::fromAscii(s.constData(), qstrnlen(s.constData(), s.size()))); } + inline QT_ASCII_CAST_WARN QString &operator+=(char c) + { return append(QChar::fromAscii(c)); } + + inline QT_ASCII_CAST_WARN bool operator==(const char *s) const; + inline QT_ASCII_CAST_WARN bool operator!=(const char *s) const; + inline QT_ASCII_CAST_WARN bool operator<(const char *s) const; + inline QT_ASCII_CAST_WARN bool operator<=(const char *s2) const; + inline QT_ASCII_CAST_WARN bool operator>(const char *s2) const; + inline QT_ASCII_CAST_WARN bool operator>=(const char *s2) const; + + inline QT_ASCII_CAST_WARN bool operator==(const QByteArray &s) const; + inline QT_ASCII_CAST_WARN bool operator!=(const QByteArray &s) const; + inline QT_ASCII_CAST_WARN bool operator<(const QByteArray &s) const + { return *this < QString::fromAscii(s.constData(), s.size()); } + inline QT_ASCII_CAST_WARN bool operator>(const QByteArray &s) const + { return *this > QString::fromAscii(s.constData(), s.size()); } + inline QT_ASCII_CAST_WARN bool operator<=(const QByteArray &s) const + { return *this <= QString::fromAscii(s.constData(), s.size()); } + inline QT_ASCII_CAST_WARN bool operator>=(const QByteArray &s) const + { return *this >= QString::fromAscii(s.constData(), s.size()); } +#endif + + typedef QChar *iterator; + typedef const QChar *const_iterator; + typedef iterator Iterator; + typedef const_iterator ConstIterator; + iterator begin(); + const_iterator begin() const; + const_iterator constBegin() const; + iterator end(); + const_iterator end() const; + const_iterator constEnd() const; + + // STL compatibility + inline void push_back(QChar c) { append(c); } + inline void push_back(const QString &s) { append(s); } + inline void push_front(QChar c) { prepend(c); } + inline void push_front(const QString &s) { prepend(s); } + +#ifndef QT_NO_STL + static inline QString fromStdString(const std::string &s); + inline std::string toStdString() const; +# ifdef qdoc + static inline QString fromStdWString(const std::wstring &s); + inline std::wstring toStdWString() const; +# else +# ifndef QT_NO_STL_WCHAR + static inline QString fromStdWString(const QStdWString &s); + inline QStdWString toStdWString() const; +# endif // QT_NO_STL_WCHAR +# endif // qdoc +#endif + + // compatibility + struct Null { }; + static const Null null; + inline QString(const Null &): d(&shared_null) { d->ref.ref(); } + inline QString &operator=(const Null &) { *this = QString(); return *this; } + inline bool isNull() const { return d == &shared_null; } + +#ifdef QT3_SUPPORT + inline QT3_SUPPORT const char *ascii() const { return ascii_helper(); } + inline QT3_SUPPORT const char *latin1() const { return latin1_helper(); } + inline QT3_SUPPORT QByteArray utf8() const { return toUtf8(); } + inline QT3_SUPPORT QByteArray local8Bit() const{ return toLocal8Bit(); } + inline QT3_SUPPORT void setLength(int nl) { resize(nl); } + inline QT3_SUPPORT QString copy() const { return *this; } + inline QT3_SUPPORT QString &remove(QChar c, bool cs) + { return remove(c, cs?Qt::CaseSensitive:Qt::CaseInsensitive); } + inline QT3_SUPPORT QString &remove(const QString &s, bool cs) + { return remove(s, cs?Qt::CaseSensitive:Qt::CaseInsensitive); } + inline QT3_SUPPORT QString &replace(QChar c, const QString &after, bool cs) + { return replace(c, after, cs?Qt::CaseSensitive:Qt::CaseInsensitive); } + inline QT3_SUPPORT QString &replace(const QString &before, const QString &after, bool cs) + { return replace(before, after, cs?Qt::CaseSensitive:Qt::CaseInsensitive); } +#ifndef QT_NO_CAST_FROM_ASCII + inline QT3_SUPPORT QString &replace(char c, const QString &after, bool cs) + { return replace(QChar::fromAscii(c), after, cs ? Qt::CaseSensitive : Qt::CaseInsensitive); } + // strange overload, required to avoid GCC 3.3 error + inline QT3_SUPPORT QString &replace(char c, const QString &after, Qt::CaseSensitivity cs) + { return replace(QChar::fromAscii(c), after, cs ? Qt::CaseSensitive : Qt::CaseInsensitive); } +#endif + inline QT3_SUPPORT int find(QChar c, int i = 0, bool cs = true) const + { return indexOf(c, i, cs?Qt::CaseSensitive:Qt::CaseInsensitive); } + inline QT3_SUPPORT int find(const QString &s, int i = 0, bool cs = true) const + { return indexOf(s, i, cs?Qt::CaseSensitive:Qt::CaseInsensitive); } + inline QT3_SUPPORT int findRev(QChar c, int i = -1, bool cs = true) const + { return lastIndexOf(c, i, cs?Qt::CaseSensitive:Qt::CaseInsensitive); } + inline QT3_SUPPORT int findRev(const QString &s, int i = -1, bool cs = true) const + { return lastIndexOf(s, i, cs?Qt::CaseSensitive:Qt::CaseInsensitive); } +#ifndef QT_NO_REGEXP + inline QT3_SUPPORT int find(const QRegExp &rx, int i=0) const + { return indexOf(rx, i); } + inline QT3_SUPPORT int findRev(const QRegExp &rx, int i=-1) const + { return lastIndexOf(rx, i); } + inline QT3_SUPPORT int find(QRegExp &rx, int i=0) const + { return indexOf(rx, i); } + inline QT3_SUPPORT int findRev(QRegExp &rx, int i=-1) const + { return lastIndexOf(rx, i); } +#endif + inline QT3_SUPPORT QBool contains(QChar c, bool cs) const + { return contains(c, cs?Qt::CaseSensitive:Qt::CaseInsensitive); } + inline QT3_SUPPORT QBool contains(const QString &s, bool cs) const + { return contains(s, cs?Qt::CaseSensitive:Qt::CaseInsensitive); } + inline QT3_SUPPORT bool startsWith(const QString &s, bool cs) const + { return startsWith(s, cs?Qt::CaseSensitive:Qt::CaseInsensitive); } + inline QT3_SUPPORT bool endsWith(const QString &s, bool cs) const + { return endsWith(s, cs?Qt::CaseSensitive:Qt::CaseInsensitive); } + inline QT3_SUPPORT QChar constref(uint i) const + { return at(i); } + QT3_SUPPORT QChar &ref(uint i); + inline QT3_SUPPORT QString leftJustify(int width, QChar aFill = QLatin1Char(' '), bool trunc=false) const + { return leftJustified(width, aFill, trunc); } + inline QT3_SUPPORT QString rightJustify(int width, QChar aFill = QLatin1Char(' '), bool trunc=false) const + { return rightJustified(width, aFill, trunc); } + inline QT3_SUPPORT QString lower() const { return toLower(); } + inline QT3_SUPPORT QString upper() const { return toUpper(); } + inline QT3_SUPPORT QString stripWhiteSpace() const { return trimmed(); } + inline QT3_SUPPORT QString simplifyWhiteSpace() const { return simplified(); } + inline QT3_SUPPORT QString &setUnicodeCodes(const ushort *unicode_as_ushorts, int aSize) + { return setUtf16(unicode_as_ushorts, aSize); } + inline QT3_SUPPORT const ushort *ucs2() const { return utf16(); } + inline static QT3_SUPPORT QString fromUcs2(const ushort *unicode, int size = -1) + { return fromUtf16(unicode, size); } + inline QT3_SUPPORT QString &setAscii(const char *str, int len = -1) + { *this = fromAscii(str, len); return *this; } + inline QT3_SUPPORT QString &setLatin1(const char *str, int len = -1) + { *this = fromLatin1(str, len); return *this; } +protected: + friend class QObject; + const char *ascii_helper() const; + const char *latin1_helper() const; +public: +#ifndef QT_NO_CAST_TO_ASCII + inline QT3_SUPPORT operator const char *() const { return ascii_helper(); } +private: + QT3_SUPPORT operator QNoImplicitBoolCast() const; +public: +#endif +#endif + + bool isSimpleText() const { if (!d->clean) updateProperties(); return d->simpletext; } + bool isRightToLeft() const { if (!d->clean) updateProperties(); return d->righttoleft; } + +private: +#if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED) + QString &operator+=(const char *s); + QString &operator+=(const QByteArray &s); + QString(const char *ch); + QString(const QByteArray &a); + QString &operator=(const char *ch); + QString &operator=(const QByteArray &a); +#endif + + struct Data { + QBasicAtomicInt ref; + int alloc, size; + ushort *data; + ushort clean : 1; + ushort simpletext : 1; + ushort righttoleft : 1; + ushort asciiCache : 1; + ushort capacity : 1; + ushort reserved : 11; + ushort array[1]; + }; + static Data shared_null; + static Data shared_empty; + Data *d; + QString(Data *dd, int /*dummy*/) : d(dd) {} +#ifndef QT_NO_TEXTCODEC + static QTextCodec *codecForCStrings; +#endif + static int grow(int); + static void free(Data *); + void realloc(); + void realloc(int alloc); + void expand(int i); + void updateProperties() const; + QString multiArg(int numArgs, const QString **args) const; + static int compare_helper(const QChar *data1, int length1, + const QChar *data2, int length2, + Qt::CaseSensitivity cs = Qt::CaseSensitive); + static int compare_helper(const QChar *data1, int length1, + QLatin1String s2, + Qt::CaseSensitivity cs = Qt::CaseSensitive); + static int localeAwareCompare_helper(const QChar *data1, int length1, + const QChar *data2, int length2); + static Data *fromLatin1_helper(const char *str, int size = -1); + static Data *fromAscii_helper(const char *str, int size = -1); + void replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen); + friend class QCharRef; + friend class QTextCodec; + friend class QStringRef; + friend inline bool qStringComparisonHelper(const QString &s1, const char *s2); + friend inline bool qStringComparisonHelper(const QStringRef &s1, const char *s2); +public: + typedef Data * DataPtr; + inline DataPtr &data_ptr() { return d; } +}; + + +class Q_CORE_EXPORT QLatin1String +{ +public: + inline explicit QLatin1String(const char *s) : chars(s) {} + inline QLatin1String &operator=(const QLatin1String &other) + { chars = other.chars; return *this; } + + inline const char *latin1() const { return chars; } + + inline bool operator==(const QString &s) const + { return s == *this; } + inline bool operator!=(const QString &s) const + { return s != *this; } + inline bool operator>(const QString &s) const + { return s < *this; } + inline bool operator<(const QString &s) const + { return s > *this; } + inline bool operator>=(const QString &s) const + { return s <= *this; } + inline bool operator<=(const QString &s) const + { return s >= *this; } + + inline QT_ASCII_CAST_WARN bool operator==(const char *s) const + { return QString::fromAscii(s) == *this; } + inline QT_ASCII_CAST_WARN bool operator!=(const char *s) const + { return QString::fromAscii(s) != *this; } + inline QT_ASCII_CAST_WARN bool operator<(const char *s) const + { return QString::fromAscii(s) > *this; } + inline QT_ASCII_CAST_WARN bool operator>(const char *s) const + { return QString::fromAscii(s) < *this; } + inline QT_ASCII_CAST_WARN bool operator<=(const char *s) const + { return QString::fromAscii(s) >= *this; } + inline QT_ASCII_CAST_WARN bool operator>=(const char *s) const + { return QString::fromAscii(s) <= *this; } +private: + const char *chars; +}; + + + +inline QString::QString(const QLatin1String &aLatin1) : d(fromLatin1_helper(aLatin1.latin1())) +{ } +inline int QString::length() const +{ return d->size; } +inline const QChar QString::at(int i) const +{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; } +inline const QChar QString::operator[](int i) const +{ Q_ASSERT(i >= 0 && i < size()); return d->data[i]; } +inline const QChar QString::operator[](uint i) const +{ Q_ASSERT(i < uint(size())); return d->data[i]; } +inline bool QString::isEmpty() const +{ return d->size == 0; } +inline const QChar *QString::unicode() const +{ return reinterpret_cast<const QChar*>(d->data); } +inline const QChar *QString::data() const +{ return reinterpret_cast<const QChar*>(d->data); } +inline QChar *QString::data() +{ detach(); return reinterpret_cast<QChar*>(d->data); } +inline const QChar *QString::constData() const +{ return reinterpret_cast<const QChar*>(d->data); } +inline void QString::detach() +{ if (d->ref != 1 || d->data != d->array) realloc(); } +inline bool QString::isDetached() const +{ return d->ref == 1; } +inline QString &QString::operator=(const QLatin1String &s) +{ + *this = fromLatin1(s.latin1()); + return *this; +} +inline void QString::clear() +{ if (!isNull()) *this = QString(); } +inline QString::QString(const QString &other) : d(other.d) +{ Q_ASSERT(&other != this); d->ref.ref(); } +inline int QString::capacity() const +{ return d->alloc; } +inline QString &QString::setNum(short n, int base) +{ return setNum(qlonglong(n), base); } +inline QString &QString::setNum(ushort n, int base) +{ return setNum(qulonglong(n), base); } +inline QString &QString::setNum(int n, int base) +{ return setNum(qlonglong(n), base); } +inline QString &QString::setNum(uint n, int base) +{ return setNum(qulonglong(n), base); } +inline QString &QString::setNum(long n, int base) +{ return setNum(qlonglong(n), base); } +inline QString &QString::setNum(ulong n, int base) +{ return setNum(qulonglong(n), base); } +inline QString &QString::setNum(float n, char f, int prec) +{ return setNum(double(n),f,prec); } +inline QString QString::arg(int a, int fieldWidth, int base, const QChar &fillChar) const +{ return arg(qlonglong(a), fieldWidth, base, fillChar); } +inline QString QString::arg(uint a, int fieldWidth, int base, const QChar &fillChar) const +{ return arg(qulonglong(a), fieldWidth, base, fillChar); } +inline QString QString::arg(long a, int fieldWidth, int base, const QChar &fillChar) const +{ return arg(qlonglong(a), fieldWidth, base, fillChar); } +inline QString QString::arg(ulong a, int fieldWidth, int base, const QChar &fillChar) const +{ return arg(qulonglong(a), fieldWidth, base, fillChar); } +inline QString QString::arg(short a, int fieldWidth, int base, const QChar &fillChar) const +{ return arg(qlonglong(a), fieldWidth, base, fillChar); } +inline QString QString::arg(ushort a, int fieldWidth, int base, const QChar &fillChar) const +{ return arg(qulonglong(a), fieldWidth, base, fillChar); } +inline QString QString::arg(const QString &a1, const QString &a2) const +{ const QString *args[2] = { &a1, &a2 }; return multiArg(2, args); } +inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3) const +{ const QString *args[3] = { &a1, &a2, &a3 }; return multiArg(3, args); } +inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3, + const QString &a4) const +{ const QString *args[4] = { &a1, &a2, &a3, &a4 }; return multiArg(4, args); } +inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3, + const QString &a4, const QString &a5) const +{ const QString *args[5] = { &a1, &a2, &a3, &a4, &a5 }; return multiArg(5, args); } +inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3, + const QString &a4, const QString &a5, const QString &a6) const +{ const QString *args[6] = { &a1, &a2, &a3, &a4, &a5, &a6 }; return multiArg(6, args); } +inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3, + const QString &a4, const QString &a5, const QString &a6, + const QString &a7) const +{ const QString *args[7] = { &a1, &a2, &a3, &a4, &a5, &a6, &a7 }; return multiArg(7, args); } +inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3, + const QString &a4, const QString &a5, const QString &a6, + const QString &a7, const QString &a8) const +{ const QString *args[8] = { &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8 }; return multiArg(8, args); } +inline QString QString::arg(const QString &a1, const QString &a2, const QString &a3, + const QString &a4, const QString &a5, const QString &a6, + const QString &a7, const QString &a8, const QString &a9) const +{ const QString *args[9] = { &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9 }; return multiArg(9, args); } + +inline QString QString::section(QChar asep, int astart, int aend, SectionFlags aflags) const +{ return section(QString(asep), astart, aend, aflags); } + + +class Q_CORE_EXPORT QCharRef { + QString &s; + int i; + inline QCharRef(QString &str, int idx) + : s(str),i(idx) {} + friend class QString; +public: + + // most QChar operations repeated here + + // all this is not documented: We just say "like QChar" and let it be. + inline operator QChar() const + { return i < s.d->size ? s.d->data[i] : 0; } + inline QCharRef &operator=(const QChar &c) + { if (i >= s.d->size) s.expand(i); else s.detach(); + s.d->data[i] = c.unicode(); return *this; } + + // An operator= for each QChar cast constructors +#ifndef QT_NO_CAST_FROM_ASCII + inline QT_ASCII_CAST_WARN QCharRef &operator=(char c) + { return operator=(QChar::fromAscii(c)); } + inline QT_ASCII_CAST_WARN QCharRef &operator=(uchar c) + { return operator=(QChar::fromAscii(c)); } +#endif + inline QCharRef &operator=(const QCharRef &c) { return operator=(QChar(c)); } + inline QCharRef &operator=(ushort rc) { return operator=(QChar(rc)); } + inline QCharRef &operator=(short rc) { return operator=(QChar(rc)); } + inline QCharRef &operator=(uint rc) { return operator=(QChar(rc)); } + inline QCharRef &operator=(int rc) { return operator=(QChar(rc)); } + + // each function... + inline bool isNull() const { return QChar(*this).isNull(); } + inline bool isPrint() const { return QChar(*this).isPrint(); } + inline bool isPunct() const { return QChar(*this).isPunct(); } + inline bool isSpace() const { return QChar(*this).isSpace(); } + inline bool isMark() const { return QChar(*this).isMark(); } + inline bool isLetter() const { return QChar(*this).isLetter(); } + inline bool isNumber() const { return QChar(*this).isNumber(); } + inline bool isLetterOrNumber() { return QChar(*this).isLetterOrNumber(); } + inline bool isDigit() const { return QChar(*this).isDigit(); } + inline bool isLower() const { return QChar(*this).isLower(); } + inline bool isUpper() const { return QChar(*this).isUpper(); } + inline bool isTitleCase() const { return QChar(*this).isTitleCase(); } + + inline int digitValue() const { return QChar(*this).digitValue(); } + QChar toLower() const { return QChar(*this).toLower(); } + QChar toUpper() const { return QChar(*this).toUpper(); } + QChar toTitleCase () const { return QChar(*this).toTitleCase(); } + + QChar::Category category() const { return QChar(*this).category(); } + QChar::Direction direction() const { return QChar(*this).direction(); } + QChar::Joining joining() const { return QChar(*this).joining(); } + bool hasMirrored() const { return QChar(*this).hasMirrored(); } + QChar mirroredChar() const { return QChar(*this).mirroredChar(); } + QString decomposition() const { return QChar(*this).decomposition(); } + QChar::Decomposition decompositionTag() const { return QChar(*this).decompositionTag(); } + uchar combiningClass() const { return QChar(*this).combiningClass(); } + + QChar::UnicodeVersion unicodeVersion() const { return QChar(*this).unicodeVersion(); } + + inline uchar cell() const { return QChar(*this).cell(); } + inline uchar row() const { return QChar(*this).row(); } + inline void setCell(uchar cell); + inline void setRow(uchar row); + +#ifdef Q_COMPILER_MANGLES_RETURN_TYPE + const char toAscii() const { return QChar(*this).toAscii(); } + const char toLatin1() const { return QChar(*this).toLatin1(); } + const ushort unicode() const { return QChar(*this).unicode(); } +#else + char toAscii() const { return QChar(*this).toAscii(); } + char toLatin1() const { return QChar(*this).toLatin1(); } + ushort unicode() const { return QChar(*this).unicode(); } +#endif + ushort& unicode() { return s.data()[i].unicode(); } + +#ifdef QT3_SUPPORT + inline QT3_SUPPORT bool mirrored() const { return hasMirrored(); } + inline QT3_SUPPORT QChar lower() const { return QChar(*this).toLower(); } + inline QT3_SUPPORT QChar upper() const { return QChar(*this).toUpper(); } +#ifdef Q_COMPILER_MANGLES_RETURN_TYPE + const QT3_SUPPORT char latin1() const { return QChar(*this).toLatin1(); } + const QT3_SUPPORT char ascii() const { return QChar(*this).toAscii(); } +#else + QT3_SUPPORT char latin1() const { return QChar(*this).toLatin1(); } + QT3_SUPPORT char ascii() const { return QChar(*this).toAscii(); } +#endif +#endif +}; + +inline void QCharRef::setRow(uchar arow) { QChar(*this).setRow(arow); } +inline void QCharRef::setCell(uchar acell) { QChar(*this).setCell(acell); } + + +inline QString::QString() : d(&shared_null) { d->ref.ref(); } +inline QString::~QString() { if (!d->ref.deref()) free(d); } +inline void QString::reserve(int asize) { if (d->ref != 1 || asize > d->alloc) realloc(asize); d->capacity = 1;} +inline QString &QString::setUtf16(const ushort *autf16, int asize) +{ return setUnicode(reinterpret_cast<const QChar *>(autf16), asize); } +inline QCharRef QString::operator[](int i) +{ Q_ASSERT(i >= 0); return QCharRef(*this, i); } +inline QCharRef QString::operator[](uint i) +{ return QCharRef(*this, i); } +inline QString::iterator QString::begin() +{ detach(); return reinterpret_cast<QChar*>(d->data); } +inline QString::const_iterator QString::begin() const +{ return reinterpret_cast<const QChar*>(d->data); } +inline QString::const_iterator QString::constBegin() const +{ return reinterpret_cast<const QChar*>(d->data); } +inline QString::iterator QString::end() +{ detach(); return reinterpret_cast<QChar*>(d->data + d->size); } +inline QString::const_iterator QString::end() const +{ return reinterpret_cast<const QChar*>(d->data + d->size); } +inline QString::const_iterator QString::constEnd() const +{ return reinterpret_cast<const QChar*>(d->data + d->size); } +inline QBool QString::contains(const QString &s, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(s, 0, cs) != -1); } +inline QBool QString::contains(QChar c, Qt::CaseSensitivity cs) const +{ return QBool(indexOf(c, 0, cs) != -1); } + + +inline bool operator==(QString::Null, QString::Null) { return true; } +inline bool operator==(QString::Null, const QString &s) { return s.isNull(); } +inline bool operator==(const QString &s, QString::Null) { return s.isNull(); } +inline bool operator!=(QString::Null, QString::Null) { return false; } +inline bool operator!=(QString::Null, const QString &s) { return !s.isNull(); } +inline bool operator!=(const QString &s, QString::Null) { return !s.isNull(); } + +#ifndef QT_NO_CAST_FROM_ASCII +inline bool qStringComparisonHelper(const QString &s1, const char *s2) +{ +# ifndef QT_NO_TEXTCODEC + if (QString::codecForCStrings) return (s1 == QString::fromAscii(s2)); +# endif + return (s1 == QLatin1String(s2)); +} +inline bool QString::operator==(const char *s) const +{ return qStringComparisonHelper(*this, s); } +inline bool QString::operator!=(const char *s) const +{ return !qStringComparisonHelper(*this, s); } +inline bool QString::operator<(const char *s) const +{ return *this < QString::fromAscii(s); } +inline bool QString::operator>(const char *s) const +{ return *this > QString::fromAscii(s); } +inline bool QString::operator<=(const char *s) const +{ return *this <= QString::fromAscii(s); } +inline bool QString::operator>=(const char *s) const +{ return *this >= QString::fromAscii(s); } + +inline QT_ASCII_CAST_WARN bool operator==(const char *s1, const QString &s2) +{ return qStringComparisonHelper(s2, s1); } +inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, const QString &s2) +{ return !qStringComparisonHelper(s2, s1); } +inline QT_ASCII_CAST_WARN bool operator<(const char *s1, const QString &s2) +{ return (QString::fromAscii(s1) < s2); } +inline QT_ASCII_CAST_WARN bool operator>(const char *s1, const QString &s2) +{ return (QString::fromAscii(s1) > s2); } +inline QT_ASCII_CAST_WARN bool operator<=(const char *s1, const QString &s2) +{ return (QString::fromAscii(s1) <= s2); } +inline QT_ASCII_CAST_WARN bool operator>=(const char *s1, const QString &s2) +{ return (QString::fromAscii(s1) >= s2); } + +inline QT_ASCII_CAST_WARN bool operator==(const char *s1, const QLatin1String &s2) +{ return QString::fromAscii(s1) == s2; } +inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, const QLatin1String &s2) +{ return QString::fromAscii(s1) != s2; } +inline QT_ASCII_CAST_WARN bool operator<(const char *s1, const QLatin1String &s2) +{ return (QString::fromAscii(s1) < s2); } +inline QT_ASCII_CAST_WARN bool operator>(const char *s1, const QLatin1String &s2) +{ return (QString::fromAscii(s1) > s2); } +inline QT_ASCII_CAST_WARN bool operator<=(const char *s1, const QLatin1String &s2) +{ return (QString::fromAscii(s1) <= s2); } +inline QT_ASCII_CAST_WARN bool operator>=(const char *s1, const QLatin1String &s2) +{ return (QString::fromAscii(s1) >= s2); } + +inline bool operator==(const QLatin1String &s1, const QLatin1String &s2) +{ return (qstrcmp(s1.latin1(), s2.latin1()) == 0); } +inline bool operator!=(const QLatin1String &s1, const QLatin1String &s2) +{ return (qstrcmp(s1.latin1(), s2.latin1()) != 0); } +inline bool operator<(const QLatin1String &s1, const QLatin1String &s2) +{ return (qstrcmp(s1.latin1(), s2.latin1()) < 0); } +inline bool operator<=(const QLatin1String &s1, const QLatin1String &s2) +{ return (qstrcmp(s1.latin1(), s2.latin1()) <= 0); } +inline bool operator>(const QLatin1String &s1, const QLatin1String &s2) +{ return (qstrcmp(s1.latin1(), s2.latin1()) > 0); } +inline bool operator>=(const QLatin1String &s1, const QLatin1String &s2) +{ return (qstrcmp(s1.latin1(), s2.latin1()) >= 0); } + + +inline bool QString::operator==(const QByteArray &s) const +{ return qStringComparisonHelper(*this, s.constData()); } +inline bool QString::operator!=(const QByteArray &s) const +{ return !qStringComparisonHelper(*this, s.constData()); } + +inline bool QByteArray::operator==(const QString &s) const +{ return qStringComparisonHelper(s, constData()); } +inline bool QByteArray::operator!=(const QString &s) const +{ return !qStringComparisonHelper(s, constData()); } +inline bool QByteArray::operator<(const QString &s) const +{ return QString::fromAscii(constData(), size()) < s; } +inline bool QByteArray::operator>(const QString &s) const +{ return QString::fromAscii(constData(), size()) > s; } +inline bool QByteArray::operator<=(const QString &s) const +{ return QString::fromAscii(constData(), size()) <= s; } +inline bool QByteArray::operator>=(const QString &s) const +{ return QString::fromAscii(constData(), size()) >= s; } +#endif // QT_NO_CAST_FROM_ASCII + +#ifndef QT_NO_CAST_TO_ASCII +inline QByteArray &QByteArray::append(const QString &s) +{ return append(s.toAscii()); } +inline QByteArray &QByteArray::insert(int i, const QString &s) +{ return insert(i, s.toAscii()); } +inline QByteArray &QByteArray::replace(char c, const QString &after) +{ return replace(c, after.toAscii()); } +inline QByteArray &QByteArray::replace(const QString &before, const char *after) +{ return replace(before.toAscii(), after); } +inline QByteArray &QByteArray::replace(const QString &before, const QByteArray &after) +{ return replace(before.toAscii(), after); } +inline QByteArray &QByteArray::operator+=(const QString &s) +{ return operator+=(s.toAscii()); } +inline int QByteArray::indexOf(const QString &s, int from) const +{ return indexOf(s.toAscii(), from); } +inline int QByteArray::lastIndexOf(const QString &s, int from) const +{ return lastIndexOf(s.toAscii(), from); } +# ifdef QT3_SUPPORT +inline int QByteArray::find(const QString &s, int from) const +{ return indexOf(s.toAscii(), from); } +inline int QByteArray::findRev(const QString &s, int from) const +{ return lastIndexOf(s.toAscii(), from); } +# endif // QT3_SUPPORT +#endif // QT_NO_CAST_TO_ASCII + +inline const QString operator+(const QString &s1, const QString &s2) +{ QString t(s1); t += s2; return t; } +inline const QString operator+(const QString &s1, QChar s2) +{ QString t(s1); t += s2; return t; } +inline const QString operator+(QChar s1, const QString &s2) +{ QString t(s1); t += s2; return t; } +#ifndef QT_NO_CAST_FROM_ASCII +inline QT_ASCII_CAST_WARN const QString operator+(const QString &s1, const char *s2) +{ QString t(s1); t += QString::fromAscii(s2); return t; } +inline QT_ASCII_CAST_WARN const QString operator+(const char *s1, const QString &s2) +{ QString t = QString::fromAscii(s1); t += s2; return t; } +inline QT_ASCII_CAST_WARN const QString operator+(char c, const QString &s) +{ QString t = s; t.prepend(QChar::fromAscii(c)); return t; } +inline QT_ASCII_CAST_WARN const QString operator+(const QString &s, char c) +{ QString t = s; t += QChar::fromAscii(c); return t; } +inline QT_ASCII_CAST_WARN const QString operator+(const QByteArray &ba, const QString &s) +{ QString t = QString::fromAscii(ba.constData(), qstrnlen(ba.constData(), ba.size())); t += s; return t; } +inline QT_ASCII_CAST_WARN const QString operator+(const QString &s, const QByteArray &ba) +{ QString t(s); t += QString::fromAscii(ba.constData(), qstrnlen(ba.constData(), ba.size())); return t; } +#endif + +#ifndef QT_NO_STL +inline std::string QString::toStdString() const +{ const QByteArray asc = toAscii(); return std::string(asc.constData(), asc.length()); } + +inline QString QString::fromStdString(const std::string &s) +{ return fromAscii(s.data(), int(s.size())); } + +# ifndef QT_NO_STL_WCHAR +inline QStdWString QString::toStdWString() const +{ + QStdWString str; + str.resize(length()); + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + // VS2005 crashes if the string is empty + if (!length()) + return str; +#endif + + str.resize(toWCharArray(&(*str.begin()))); + return str; +} +inline QString QString::fromStdWString(const QStdWString &s) +{ return fromWCharArray(s.data(), int(s.size())); } +# endif +#endif + +#ifdef QT3_SUPPORT +inline QChar &QString::ref(uint i) +{ + if (int(i) > d->size || d->ref != 1) + resize(qMax(int(i), d->size)); + return reinterpret_cast<QChar&>(d->data[i]); +} +#endif + +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QString &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QString &); +#endif + +#ifdef QT3_SUPPORT +class QConstString : public QString +{ +public: + inline QT3_SUPPORT_CONSTRUCTOR QConstString(const QChar *aUnicode, int aSize) + :QString(aUnicode, aSize){} // cannot use fromRawData() due to changed semantics + inline QT3_SUPPORT const QString &string() const { return *this; } +}; +#endif + +Q_DECLARE_TYPEINFO(QString, Q_MOVABLE_TYPE); +Q_DECLARE_SHARED(QString) +Q_DECLARE_OPERATORS_FOR_FLAGS(QString::SectionFlags) + +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) +extern Q_CORE_EXPORT QByteArray qt_winQString2MB(const QString& s, int len=-1); +extern Q_CORE_EXPORT QByteArray qt_winQString2MB(const QChar *ch, int len); +extern Q_CORE_EXPORT QString qt_winMB2QString(const char* mb, int len=-1); +#endif + + +class Q_CORE_EXPORT QStringRef { + const QString *m_string; + int m_position; + int m_size; +public: + inline QStringRef():m_string(0), m_position(0), m_size(0){} + inline QStringRef(const QString *string, int position, int size); + inline QStringRef(const QString *string); + inline QStringRef(const QStringRef &other) + :m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) + {} + + inline ~QStringRef(){} + inline const QString *string() const { return m_string; } + inline int position() const { return m_position; } + inline int size() const { return m_size; } + inline int count() const { return m_size; } + inline int length() const { return m_size; } + + inline QStringRef &operator=(const QStringRef &other) { + m_string = other.m_string; m_position = other.m_position; + m_size = other.m_size; return *this; + } + + inline QStringRef &operator=(const QString *string); + + inline const QChar *unicode() const { + if (!m_string) + return reinterpret_cast<const QChar *>(QString::shared_null.data); + return m_string->unicode() + m_position; + } + inline const QChar *data() const { return unicode(); } + inline const QChar *constData() const { return unicode(); } + + inline void clear() { m_string = 0; m_position = m_size = 0; } + QString toString() const; + inline bool isEmpty() const { return m_size == 0; } + inline bool isNull() const { return m_string == 0 || m_string->isNull(); } + + QStringRef appendTo(QString *string) const; + + inline const QChar at(int i) const + { Q_ASSERT(i >= 0 && i < size()); return m_string->at(i + m_position); } + + int compare(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int compare(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + int compare(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + static int compare(const QStringRef &s1, const QString &s2, + Qt::CaseSensitivity = Qt::CaseSensitive); + static int compare(const QStringRef &s1, const QStringRef &s2, + Qt::CaseSensitivity = Qt::CaseSensitive); + static int compare(const QStringRef &s1, QLatin1String s2, + Qt::CaseSensitivity cs = Qt::CaseSensitive); + + int localeAwareCompare(const QString &s) const; + int localeAwareCompare(const QStringRef &s) const; + static int localeAwareCompare(const QStringRef &s1, const QString &s2); + static int localeAwareCompare(const QStringRef &s1, const QStringRef &s2); +}; + +inline QStringRef &QStringRef::operator=(const QString *aString) +{ m_string = aString; m_position = 0; m_size = aString?aString->size():0; return *this; } + +inline QStringRef::QStringRef(const QString *aString, int aPosition, int aSize) + :m_string(aString), m_position(aPosition), m_size(aSize){} + +inline QStringRef::QStringRef(const QString *aString) + :m_string(aString), m_position(0), m_size(aString?aString->size() : 0){} + +Q_CORE_EXPORT bool operator==(const QStringRef &s1,const QStringRef &s2); +inline bool operator!=(const QStringRef &s1,const QStringRef &s2) +{ return !(s1 == s2); } +Q_CORE_EXPORT bool operator==(const QString &s1,const QStringRef &s2); +inline bool operator!=(const QString &s1,const QStringRef &s2) +{ return !(s1 == s2); } +inline bool operator==(const QStringRef &s1,const QString &s2) +{ return s2 == s1; } +inline bool operator!=(const QStringRef &s1,const QString &s2) +{ return s2 != s1; } +Q_CORE_EXPORT bool operator==(const QLatin1String &s1, const QStringRef &s2); +inline bool operator!=(const QLatin1String &s1,const QStringRef &s2) +{ return !(s1 == s2); } +inline bool operator==(const QStringRef &s1,const QLatin1String &s2) +{ return s2 == s1; } +inline bool operator!=(const QStringRef &s1,const QLatin1String &s2) +{ return s2 != s1; } + +Q_CORE_EXPORT bool operator<(const QStringRef &s1,const QStringRef &s2); +inline bool operator>(const QStringRef &s1, const QStringRef &s2) +{ return s2 < s1; } +inline bool operator<=(const QStringRef &s1, const QStringRef &s2) +{ return !(s1 > s2); } +inline bool operator>=(const QStringRef &s1, const QStringRef &s2) +{ return !(s1 < s2); } + +inline bool qStringComparisonHelper(const QStringRef &s1, const char *s2) +{ +# ifndef QT_NO_TEXTCODEC + if (QString::codecForCStrings) return (s1 == QString::fromAscii(s2)); +# endif + return (s1 == QLatin1String(s2)); +} + +inline QT_ASCII_CAST_WARN bool operator==(const char *s1, const QStringRef &s2) +{ return qStringComparisonHelper(s2, s1); } +inline QT_ASCII_CAST_WARN bool operator==(const QStringRef &s1, const char *s2) +{ return qStringComparisonHelper(s1, s2); } +inline QT_ASCII_CAST_WARN bool operator!=(const char *s1, const QStringRef &s2) +{ return !qStringComparisonHelper(s2, s1); } +inline QT_ASCII_CAST_WARN bool operator!=(const QStringRef &s1, const char *s2) +{ return !qStringComparisonHelper(s1, s2); } + +inline int QString::compare(const QStringRef &s, Qt::CaseSensitivity cs) const +{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); } +inline int QString::compare(const QString &s1, const QStringRef &s2, Qt::CaseSensitivity cs) +{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); } +inline int QStringRef::compare(const QString &s, Qt::CaseSensitivity cs) const +{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); } +inline int QStringRef::compare(const QStringRef &s, Qt::CaseSensitivity cs) const +{ return QString::compare_helper(constData(), length(), s.constData(), s.length(), cs); } +inline int QStringRef::compare(QLatin1String s, Qt::CaseSensitivity cs) const +{ return QString::compare_helper(constData(), length(), s, cs); } +inline int QStringRef::compare(const QStringRef &s1, const QString &s2, Qt::CaseSensitivity cs) +{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); } +inline int QStringRef::compare(const QStringRef &s1, const QStringRef &s2, Qt::CaseSensitivity cs) +{ return QString::compare_helper(s1.constData(), s1.length(), s2.constData(), s2.length(), cs); } +inline int QStringRef::compare(const QStringRef &s1, QLatin1String s2, Qt::CaseSensitivity cs) +{ return QString::compare_helper(s1.constData(), s1.length(), s2, cs); } + +inline int QString::localeAwareCompare(const QStringRef &s) const +{ return localeAwareCompare_helper(constData(), length(), s.constData(), s.length()); } +inline int QString::localeAwareCompare(const QString& s1, const QStringRef& s2) +{ return localeAwareCompare_helper(s1.constData(), s1.length(), s2.constData(), s2.length()); } +inline int QStringRef::localeAwareCompare(const QString &s) const +{ return QString::localeAwareCompare_helper(constData(), length(), s.constData(), s.length()); } +inline int QStringRef::localeAwareCompare(const QStringRef &s) const +{ return QString::localeAwareCompare_helper(constData(), length(), s.constData(), s.length()); } +inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QString &s2) +{ return QString::localeAwareCompare_helper(s1.constData(), s1.length(), s2.constData(), s2.length()); } +inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QStringRef &s2) +{ return QString::localeAwareCompare_helper(s1.constData(), s1.length(), s2.constData(), s2.length()); } + + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSTRING_H diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp new file mode 100644 index 0000000..386321f1 --- /dev/null +++ b/src/corelib/tools/qstringlist.cpp @@ -0,0 +1,673 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qstringlist.h> +#include <qset.h> + +QT_BEGIN_NAMESPACE + +/*! \typedef QStringListIterator + \relates QStringList + + The QStringListIterator type definition provides a Java-style const + iterator for QStringList. + + QStringList provides both \l{Java-style iterators} and + \l{STL-style iterators}. The Java-style const iterator is simply + a type definition for QListIterator<QString>. + + \sa QMutableStringListIterator, QStringList::const_iterator +*/ + +/*! \typedef QMutableStringListIterator + \relates QStringList + + The QStringListIterator type definition provides a Java-style + non-const iterator for QStringList. + + QStringList provides both \l{Java-style iterators} and + \l{STL-style iterators}. The Java-style non-const iterator is + simply a type definition for QMutableListIterator<QString>. + + \sa QStringListIterator, QStringList::iterator +*/ + +/*! + \class QStringList + \brief The QStringList class provides a list of strings. + + \ingroup tools + \ingroup shared + \ingroup text + \mainclass + \reentrant + + QStringList inherits from QList<QString>. Like QList, QStringList is + \l{implicitly shared}. It provides fast index-based access as well as fast + insertions and removals. Passing string lists as value parameters is both + fast and safe. + + All of QList's functionality also applies to QStringList. For example, you + can use isEmpty() to test whether the list is empty, and you can call + functions like append(), prepend(), insert(), replace(), removeAll(), + removeAt(), removeFirst(), removeLast(), and removeOne() to modify a + QStringList. In addition, QStringList provides a few convenience + functions that make handling lists of strings easier: + + \tableofcontents + + \section1 Adding strings + + Strings can be added to a list using the \l + {QList::append()}{append()}, \l + {QList::operator+=()}{operator+=()} and \l + {QStringList::operator<<()}{operator<<()} functions. For example: + + \snippet doc/src/snippets/qstringlist/main.cpp 0 + + \section1 Iterating over the strings + + To iterate over a list, you can either use index positions or + QList's Java-style and STL-style iterator types: + + Indexing: + + \snippet doc/src/snippets/qstringlist/main.cpp 1 + + Java-style iterator: + + \snippet doc/src/snippets/qstringlist/main.cpp 2 + + STL-style iterator: + + \snippet doc/src/snippets/qstringlist/main.cpp 3 + + The QStringListIterator class is simply a type definition for + QListIterator<QString>. QStringList also provide the + QMutableStringListIterator class which is a type definition for + QMutableListIterator<QString>. + + \section1 Manipulating the strings + + QStringList provides several functions allowing you to manipulate + the contents of a list. You can concatenate all the strings in a + string list into a single string (with an optional separator) + using the join() function. For example: + + \snippet doc/src/snippets/qstringlist/main.cpp 4 + + To break up a string into a string list, use the QString::split() + function: + + \snippet doc/src/snippets/qstringlist/main.cpp 6 + + The argument to split can be a single character, a string, or a + QRegExp. + + In addition, the \l {QStringList::operator+()}{operator+()} + function allows you to concatenate two string lists into one. To + sort a string list, use the sort() function. + + QString list also provides the filter() function which lets you + to extract a new list which contains only those strings which + contain a particular substring (or match a particular regular + expression): + + \snippet doc/src/snippets/qstringlist/main.cpp 7 + + The contains() function tells you whether the list contains a + given string, while the indexOf() function returns the index of + the first occurrence of the given string. The lastIndexOf() + function on the other hand, returns the index of the last + occurrence of the string. + + Finally, the replaceInStrings() function calls QString::replace() + on each string in the string list in turn. For example: + + \snippet doc/src/snippets/qstringlist/main.cpp 8 + + \sa QString +*/ + +/*! + \fn QStringList::QStringList() + + Constructs an empty string list. +*/ + +/*! + \fn QStringList::QStringList(const QString &str) + + Constructs a string list that contains the given string, \a + str. Longer lists are easily created like this: + + \snippet doc/src/snippets/qstringlist/main.cpp 9 + + \sa append() +*/ + +/*! + \fn QStringList::QStringList(const QStringList &other) + + Constructs a copy of the \a other string list. + + This operation takes \l{constant time} because QStringList is + \l{implicitly shared}, making the process of returning a + QStringList from a function very fast. If a shared instance is + modified, it will be copied (copy-on-write), and that takes + \l{linear time}. + + \sa operator=() +*/ + +/*! + \fn QStringList::QStringList(const QList<QString> &other) + + Constructs a copy of \a other. + + This operation takes \l{constant time}, because QStringList is + \l{implicitly shared}. This makes returning a QStringList from a + function very fast. If a shared instance is modified, it will be + copied (copy-on-write), and that takes \l{linear time}. + + \sa operator=() +*/ + +/*! + \fn void QStringList::sort() + + Sorts the list of strings in ascending order (case sensitively). + + Sorting is performed using Qt's qSort() algorithm, + which operates in \l{linear-logarithmic time}, i.e. O(\e{n} log \e{n}). + + If you want to sort your strings in an arbitrary order, consider + using the QMap class. For example, you could use a QMap<QString, + QString> to create a case-insensitive ordering (e.g. with the keys + being lower-case versions of the strings, and the values being the + strings), or a QMap<int, QString> to sort the strings by some + integer index. + + \sa qSort() +*/ +void QtPrivate::QStringList_sort(QStringList *that) +{ + qSort(*that); +} + + +#ifdef QT3_SUPPORT +/*! + \fn QStringList QStringList::split(const QChar &sep, const QString &str, bool allowEmptyEntries) + + \overload + + This version of the function uses a QChar as separator. + + \sa join() QString::section() +*/ + +/*! + \fn QStringList QStringList::split(const QString &sep, const QString &str, bool allowEmptyEntries) + + \overload + + This version of the function uses a QString as separator. + + \sa join() QString::section() +*/ +#ifndef QT_NO_REGEXP +/*! + \fn QStringList QStringList::split(const QRegExp &sep, const QString &str, bool allowEmptyEntries) + + Use QString::split(\a sep, QString::SkipEmptyParts) or + QString::split(\a sep, QString::KeepEmptyParts) instead. + + Be aware that the QString::split()'s return value is a + QStringList that always contains at least one element, even if \a + str is empty. + + \sa join() QString::section() +*/ +#endif +#endif // QT3_SUPPORT + +/*! + \fn QStringList QStringList::filter(const QString &str, Qt::CaseSensitivity cs) const + + Returns a list of all the strings containing the substring \a str. + + If \a cs is \l Qt::CaseSensitive (the default), the string + comparison is case sensitive; otherwise the comparison is case + insensitive. + + \snippet doc/src/snippets/qstringlist/main.cpp 5 + \snippet doc/src/snippets/qstringlist/main.cpp 10 + + This is equivalent to + + \snippet doc/src/snippets/qstringlist/main.cpp 11 + \snippet doc/src/snippets/qstringlist/main.cpp 12 + + \sa contains() +*/ +QStringList QtPrivate::QStringList_filter(const QStringList *that, const QString &str, + Qt::CaseSensitivity cs) +{ + QStringMatcher matcher(str, cs); + QStringList res; + for (int i = 0; i < that->size(); ++i) + if (matcher.indexIn(that->at(i)) != -1) + res << that->at(i); + return res; +} + + +/*! + \fn QBool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) const + + Returns true if the list contains the string \a str; otherwise + returns false. The search is case insensitive if \a cs is + Qt::CaseInsensitive; the search is case sensitive by default. + + \sa indexOf(), lastIndexOf(), QString::contains() + */ +QBool QtPrivate::QStringList_contains(const QStringList *that, const QString &str, + Qt::CaseSensitivity cs) +{ + for (int i = 0; i < that->size(); ++i) { + const QString & string = that->at(i); + if (string.length() == str.length() && str.compare(string, cs) == 0) + return QBool(true); + } + return QBool(false); +} + +#ifndef QT_NO_REGEXP +/*! + \fn QStringList QStringList::filter(const QRegExp &rx) const + + \overload + + Returns a list of all the strings that match the regular + expression \a rx. +*/ +QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegExp &rx) +{ + QStringList res; + for (int i = 0; i < that->size(); ++i) + if (that->at(i).contains(rx)) + res << that->at(i); + return res; +} +#endif + +/*! + \fn QStringList &QStringList::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs) + + Returns a string list where every string has had the \a before + text replaced with the \a after text wherever the \a before text + is found. The \a before text is matched case-sensitively or not + depending on the \a cs flag. + + For example: + + \snippet doc/src/snippets/qstringlist/main.cpp 5 + \snippet doc/src/snippets/qstringlist/main.cpp 13 + + \sa QString::replace() +*/ +void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QString &before, + const QString &after, Qt::CaseSensitivity cs) +{ + for (int i = 0; i < that->size(); ++i) + (*that)[i].replace(before, after, cs); +} + + +#ifndef QT_NO_REGEXP +/*! + \fn QStringList &QStringList::replaceInStrings(const QRegExp &rx, const QString &after) + \overload + + Replaces every occurrence of the regexp \a rx, in each of the + string lists's strings, with \a after. Returns a reference to the + string list. + + For example: + + \snippet doc/src/snippets/qstringlist/main.cpp 5 + \snippet doc/src/snippets/qstringlist/main.cpp 14 + + For regular expressions that contain \l{capturing parentheses}, + occurrences of \bold{\\1}, \bold{\\2}, ..., in \a after are + replaced with \a{rx}.cap(1), \a{rx}.cap(2), ... + + For example: + + \snippet doc/src/snippets/qstringlist/main.cpp 5 + \snippet doc/src/snippets/qstringlist/main.cpp 15 +*/ +void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegExp &rx, const QString &after) +{ + for (int i = 0; i < that->size(); ++i) + (*that)[i].replace(rx, after); +} +#endif + +/*! + \fn QString QStringList::join(const QString &separator) const + + Joins all the string list's strings into a single string with each + element separated by the the given \a separator (which can be an + empty string). + + \sa QString::split() +*/ +QString QtPrivate::QStringList_join(const QStringList *that, const QString &sep) +{ + QString res; + for (int i = 0; i < that->size(); ++i) { + if (i) + res += sep; + res += that->at(i); + } + return res; +} + +/*! + \fn QStringList QStringList::operator+(const QStringList &other) const + + Returns a string list that is the concatenation of this string + list with the \a other string list. + + \sa append() +*/ + +/*! + \fn QStringList &QStringList::operator<<(const QString &str) + + Appends the given string, \a str, to this string list and returns + a reference to the string list. + + \sa append() +*/ + +/*! + \fn QStringList &QStringList::operator<<(const QStringList &other) + + \overload + + Appends the \a other string list to the string list and returns a reference to + the latter string list. +*/ + +#ifndef QT_NO_DATASTREAM +/*! + \fn QDataStream &operator>>(QDataStream &in, QStringList &list) + \relates QStringList + + Reads a string list from the given \a in stream into the specified + \a list. + + \sa {Format of the QDataStream Operators} +*/ + +/*! + \fn QDataStream &operator<<(QDataStream &out, const QStringList &list) + \relates QStringList + + Writes the given string \a list to the specified \a out stream. + + \sa {Format of the QDataStream Operators} +*/ +#endif // QT_NO_DATASTREAM + +/*! + \fn QStringList QStringList::grep(const QString &str, bool cs = true) const + + Use filter() instead. +*/ + +/*! + \fn QStringList QStringList::grep(const QRegExp &rx) const + + Use filter() instead. +*/ + +/*! + \fn QStringList &QStringList::gres(const QString &before, const QString &after, bool cs = true) + + Use replaceInStrings() instead. +*/ + +/*! + \fn QStringList &QStringList::gres(const QRegExp &rx, const QString &after) + + Use replaceInStrings() instead. +*/ + +/*! + \fn Iterator QStringList::fromLast() + + Use end() instead. + + \oldcode + QStringList::Iterator i = list.fromLast(); + \newcode + QStringList::Iterator i = list.isEmpty() ? list.end() : --list.end(); + \endcode +*/ + +/*! + \fn ConstIterator QStringList::fromLast() const + + Use end() instead. + + \oldcode + QStringList::ConstIterator i = list.fromLast(); + \newcode + QStringList::ConstIterator i = list.isEmpty() ? list.end() : --list.end(); + \endcode +*/ + + +#ifndef QT_NO_REGEXP +static int indexOfMutating(const QStringList *that, QRegExp &rx, int from) +{ + if (from < 0) + from = qMax(from + that->size(), 0); + for (int i = from; i < that->size(); ++i) { + if (rx.exactMatch(that->at(i))) + return i; + } + return -1; +} + +static int lastIndexOfMutating(const QStringList *that, QRegExp &rx, int from) +{ + if (from < 0) + from += that->size(); + else if (from >= that->size()) + from = that->size() - 1; + for (int i = from; i >= 0; --i) { + if (rx.exactMatch(that->at(i))) + return i; + } + return -1; +} + +/*! + \fn int QStringList::indexOf(const QRegExp &rx, int from) const + + Returns the index position of the first exact match of \a rx in + the list, searching forward from index position \a from. Returns + -1 if no item matched. + + By default, this function is case sensitive. + + \sa lastIndexOf(), contains(), QRegExp::exactMatch() +*/ +int QtPrivate::QStringList_indexOf(const QStringList *that, const QRegExp &rx, int from) +{ + QRegExp rx2(rx); + return indexOfMutating(that, rx2, from); +} + +/*! + \fn int QStringList::indexOf(QRegExp &rx, int from) const + \overload indexOf() + \since 4.5 + + Returns the index position of the first exact match of \a rx in + the list, searching forward from index position \a from. Returns + -1 if no item matched. + + By default, this function is case sensitive. + + If an item matched, the \a rx regular expression will contain the + matched objects (see QRegExp::matchedLength, QRegExp::cap). + + \sa lastIndexOf(), contains(), QRegExp::exactMatch() +*/ +int QtPrivate::QStringList_indexOf(const QStringList *that, QRegExp &rx, int from) +{ + return indexOfMutating(that, rx, from); +} + +/*! + \fn int QStringList::lastIndexOf(const QRegExp &rx, int from) const + + Returns the index position of the last exact match of \a rx in + the list, searching backward from index position \a from. If \a + from is -1 (the default), the search starts at the last item. + Returns -1 if no item matched. + + By default, this function is case sensitive. + + \sa indexOf(), contains(), QRegExp::exactMatch() +*/ +int QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegExp &rx, int from) +{ + QRegExp rx2(rx); + return lastIndexOfMutating(that, rx2, from); +} + +/*! + \fn int QStringList::lastIndexOf(QRegExp &rx, int from) const + \overload lastIndexOf() + \since 4.5 + + Returns the index position of the last exact match of \a rx in + the list, searching backward from index position \a from. If \a + from is -1 (the default), the search starts at the last item. + Returns -1 if no item matched. + + By default, this function is case sensitive. + + If an item matched, the \a rx regular expression will contain the + matched objects (see QRegExp::matchedLength, QRegExp::cap). + + \sa indexOf(), contains(), QRegExp::exactMatch() +*/ +int QtPrivate::QStringList_lastIndexOf(const QStringList *that, QRegExp &rx, int from) +{ + return lastIndexOfMutating(that, rx, from); +} +#endif + +/*! + \fn int QStringList::indexOf(const QString &value, int from = 0) const + + Returns the index position of the first occurrence of \a value in + the list, searching forward from index position \a from. Returns + -1 if no item matched. + + By default, this function is case sensitive. + + \sa lastIndexOf(), contains(), QList::indexOf() +*/ + +/*! + \fn int QStringList::lastIndexOf(const QString &value, int from = -1) const + + Returns the index position of the last occurrence of \a value in + the list, searching backward from index position \a from. If \a + from is -1 (the default), the search starts at the last item. + Returns -1 if no item matched. + + By default, this function is case sensitive. + + \sa indexOf(), QList::lastIndexOf() +*/ + +/*! + \fn int QStringList::removeDuplicates() + + \since 4.5 + + This function removes duplicate entries from a list. + The entries do not have to be sorted. They will retain their + original order. + + Returns the number of removed entries. +*/ +int QtPrivate::QStringList_removeDuplicates(QStringList *that) +{ + int n = that->size(); + int j = 0; + QSet<QString> seen; + seen.reserve(n); + for (int i = 0; i < n; ++i) { + const QString &s = that->at(i); + if (seen.contains(s)) + continue; + seen.insert(s); + if (j != i) + (*that)[j] = s; + ++j; + } + if (n != j) + that->erase(that->begin() + j, that->end()); + return n - j; +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h new file mode 100644 index 0000000..37f7ff2 --- /dev/null +++ b/src/corelib/tools/qstringlist.h @@ -0,0 +1,259 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTRINGLIST_H +#define QSTRINGLIST_H + +#include <QtCore/qalgorithms.h> +#include <QtCore/qdatastream.h> +#include <QtCore/qlist.h> +#include <QtCore/qregexp.h> +#include <QtCore/qstring.h> +#include <QtCore/qstringmatcher.h> +#ifdef QT_INCLUDE_COMPAT +#include <Qt3Support/q3valuelist.h> +#endif + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class QRegExp; + +typedef QListIterator<QString> QStringListIterator; +typedef QMutableListIterator<QString> QMutableStringListIterator; + +class QStringList : public QList<QString> +{ +public: + inline QStringList() { } + inline explicit QStringList(const QString &i) { append(i); } + inline QStringList(const QStringList &l) : QList<QString>(l) { } + inline QStringList(const QList<QString> &l) : QList<QString>(l) { } + + inline void sort(); + inline int removeDuplicates(); + + inline QString join(const QString &sep) const; + + inline QStringList filter(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + inline QBool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + inline QStringList &replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); + + inline QStringList operator+(const QStringList &other) const + { QStringList n = *this; n += other; return n; } + inline QStringList &operator<<(const QString &str) + { append(str); return *this; } + inline QStringList &operator<<(const QStringList &l) + { *this += l; return *this; } + +#ifndef QT_NO_REGEXP + inline QStringList filter(const QRegExp &rx) const; + inline QStringList &replaceInStrings(const QRegExp &rx, const QString &after); + inline int indexOf(const QRegExp &rx, int from = 0) const; + inline int lastIndexOf(const QRegExp &rx, int from = -1) const; + inline int indexOf(QRegExp &rx, int from = 0) const; + inline int lastIndexOf(QRegExp &rx, int from = -1) const; +#endif +#if !defined(Q_NO_USING_KEYWORD) + using QList<QString>::indexOf; + using QList<QString>::lastIndexOf; +#else + inline int indexOf(const QString &str, int from = 0) const + { return QList<QString>::indexOf(str, from); } + inline int lastIndexOf(const QString &str, int from = -1) const + { return QList<QString>::lastIndexOf(str, from); } +#endif +#ifdef QT3_SUPPORT + static inline QT3_SUPPORT QStringList split(const QString &sep, const QString &str, bool allowEmptyEntries = false); + static inline QT3_SUPPORT QStringList split(const QChar &sep, const QString &str, bool allowEmptyEntries = false); + inline QT3_SUPPORT QStringList grep(const QString &str, bool cs = true) const + { return filter(str, cs ? Qt::CaseSensitive : Qt::CaseInsensitive); } + +#ifndef QT_NO_REGEXP + static inline QT3_SUPPORT QStringList split(const QRegExp &sep, const QString &str, bool allowEmptyEntries = false); + inline QT3_SUPPORT QStringList grep(const QRegExp &rx) const { return filter(rx); } + inline QT3_SUPPORT QStringList &gres(const QRegExp &rx, const QString &after) + { return replaceInStrings(rx, after); } +#endif + inline QT3_SUPPORT QStringList &gres(const QString &before, const QString &after, bool cs = true) + { return replaceInStrings(before, after, cs ? Qt::CaseSensitive : Qt::CaseInsensitive); } + + inline Iterator QT3_SUPPORT fromLast() { return (isEmpty() ? end() : --end()); } + inline ConstIterator QT3_SUPPORT fromLast() const { return (isEmpty() ? end() : --end()); } +#endif +}; + +namespace QtPrivate { + void Q_CORE_EXPORT QStringList_sort(QStringList *that); + int Q_CORE_EXPORT QStringList_removeDuplicates(QStringList *that); + QString Q_CORE_EXPORT QStringList_join(const QStringList *that, const QString &sep); + QStringList Q_CORE_EXPORT QStringList_filter(const QStringList *that, const QString &str, + Qt::CaseSensitivity cs); + + QBool Q_CORE_EXPORT QStringList_contains(const QStringList *that, const QString &str, Qt::CaseSensitivity cs); + void Q_CORE_EXPORT QStringList_replaceInStrings(QStringList *that, const QString &before, const QString &after, + Qt::CaseSensitivity cs); + +#ifndef QT_NO_REGEXP + void Q_CORE_EXPORT QStringList_replaceInStrings(QStringList *that, const QRegExp &rx, const QString &after); + QStringList Q_CORE_EXPORT QStringList_filter(const QStringList *that, const QRegExp &re); + int Q_CORE_EXPORT QStringList_indexOf(const QStringList *that, const QRegExp &rx, int from); + int Q_CORE_EXPORT QStringList_lastIndexOf(const QStringList *that, const QRegExp &rx, int from); + int Q_CORE_EXPORT QStringList_indexOf(const QStringList *that, QRegExp &rx, int from); + int Q_CORE_EXPORT QStringList_lastIndexOf(const QStringList *that, QRegExp &rx, int from); +#endif +} + +inline void QStringList::sort() +{ + QtPrivate::QStringList_sort(this); +} + +inline int QStringList::removeDuplicates() +{ + return QtPrivate::QStringList_removeDuplicates(this); +} + +inline QString QStringList::join(const QString &sep) const +{ + return QtPrivate::QStringList_join(this, sep); +} + +inline QStringList QStringList::filter(const QString &str, Qt::CaseSensitivity cs) const +{ + return QtPrivate::QStringList_filter(this, str, cs); +} + +inline QBool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) const +{ + return QtPrivate::QStringList_contains(this, str, cs); +} + +inline QStringList &QStringList::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs) +{ + QtPrivate::QStringList_replaceInStrings(this, before, after, cs); + return *this; +} + +#ifndef QT_NO_REGEXP +inline QStringList &QStringList::replaceInStrings(const QRegExp &rx, const QString &after) +{ + QtPrivate::QStringList_replaceInStrings(this, rx, after); + return *this; +} + +inline QStringList QStringList::filter(const QRegExp &rx) const +{ + return QtPrivate::QStringList_filter(this, rx); +} + +inline int QStringList::indexOf(const QRegExp &rx, int from) const +{ + return QtPrivate::QStringList_indexOf(this, rx, from); +} + +inline int QStringList::lastIndexOf(const QRegExp &rx, int from) const +{ + return QtPrivate::QStringList_lastIndexOf(this, rx, from); +} + +inline int QStringList::indexOf(QRegExp &rx, int from) const +{ + return QtPrivate::QStringList_indexOf(this, rx, from); +} + +inline int QStringList::lastIndexOf(QRegExp &rx, int from) const +{ + return QtPrivate::QStringList_lastIndexOf(this, rx, from); +} +#endif + + +#ifdef QT3_SUPPORT +inline QStringList QStringList::split(const QChar &sep, const QString &str, bool allowEmptyEntries) +{ + if (str.isEmpty()) + return QStringList(); + return str.split(sep, allowEmptyEntries ? QString::KeepEmptyParts + : QString::SkipEmptyParts); +} + +inline QStringList QStringList::split(const QString &sep, const QString &str, bool allowEmptyEntries) +{ + if (str.isEmpty()) + return QStringList(); + return str.split(sep, allowEmptyEntries ? QString::KeepEmptyParts + : QString::SkipEmptyParts); +} + +#ifndef QT_NO_REGEXP +inline QStringList QStringList::split(const QRegExp &sep, const QString &str, bool allowEmptyEntries) +{ + if (str.isEmpty()) + return QStringList(); + return str.split(sep, allowEmptyEntries ? QString::KeepEmptyParts + : QString::SkipEmptyParts); +} +#endif // QT_NO_REGEXP + +#endif // QT3_SUPPORT + + +#ifndef QT_NO_DATASTREAM +inline QDataStream &operator>>(QDataStream &in, QStringList &list) +{ + return operator>>(in, static_cast<QList<QString> &>(list)); +} +inline QDataStream &operator<<(QDataStream &out, const QStringList &list) +{ + return operator<<(out, static_cast<const QList<QString> &>(list)); +} +#endif // QT_NO_DATASTREAM + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSTRINGLIST_H diff --git a/src/corelib/tools/qstringmatcher.cpp b/src/corelib/tools/qstringmatcher.cpp new file mode 100644 index 0000000..badc4c6 --- /dev/null +++ b/src/corelib/tools/qstringmatcher.cpp @@ -0,0 +1,323 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qstringmatcher.h" +#include "qunicodetables_p.h" + +QT_BEGIN_NAMESPACE + +static void bm_init_skiptable(const ushort *uc, int len, uchar *skiptable, Qt::CaseSensitivity cs) +{ + int l = qMin(len, 255); + memset(skiptable, l, 256*sizeof(uchar)); + uc += len - l; + if (cs == Qt::CaseSensitive) { + while (l--) { + skiptable[*uc & 0xff] = l; + uc++; + } + } else { + const ushort *start = uc; + while (l--) { + skiptable[foldCase(uc, start) & 0xff] = l; + uc++; + } + } +} + +static inline int bm_find(const ushort *uc, uint l, int index, const ushort *puc, uint pl, + const uchar *skiptable, Qt::CaseSensitivity cs) +{ + if (pl == 0) + return index > (int)l ? -1 : index; + const uint pl_minus_one = pl - 1; + + register const ushort *current = uc + index + pl_minus_one; + const ushort *end = uc + l; + if (cs == Qt::CaseSensitive) { + while (current < end) { + uint skip = skiptable[*current & 0xff]; + if (!skip) { + // possible match + while (skip < pl) { + if (*(current - skip) != puc[pl_minus_one-skip]) + break; + skip++; + } + if (skip > pl_minus_one) // we have a match + return (current - uc) - pl_minus_one; + + // in case we don't have a match we are a bit inefficient as we only skip by one + // when we have the non matching char in the string. + if (skiptable[*(current - skip) & 0xff] == pl) + skip = pl - skip; + else + skip = 1; + } + if (current > end - skip) + break; + current += skip; + } + } else { + while (current < end) { + uint skip = skiptable[foldCase(current, uc) & 0xff]; + if (!skip) { + // possible match + while (skip < pl) { + if (foldCase(current - skip, uc) != foldCase(puc + pl_minus_one - skip, puc)) + break; + skip++; + } + if (skip > pl_minus_one) // we have a match + return (current - uc) - pl_minus_one; + // in case we don't have a match we are a bit inefficient as we only skip by one + // when we have the non matching char in the string. + if (skiptable[foldCase(current - skip, uc) & 0xff] == pl) + skip = pl - skip; + else + skip = 1; + } + if (current > end - skip) + break; + current += skip; + } + } + return -1; // not found +} + +/*! + \class QStringMatcher + \brief The QStringMatcher class holds a sequence of characters that + can be quickly matched in a Unicode string. + + \ingroup tools + \ingroup text + + This class is useful when you have a sequence of \l{QChar}s that + you want to repeatedly match against some strings (perhaps in a + loop), or when you want to search for the same sequence of + characters multiple times in the same string. Using a matcher + object and indexIn() is faster than matching a plain QString with + QString::indexOf() if repeated matching takes place. This class + offers no benefit if you are doing one-off string matches. + + Create the QStringMatcher with the QString you want to search + for. Then call indexIn() on the QString that you want to search. + + \sa QString, QByteArrayMatcher, QRegExp +*/ + +/*! + Constructs an empty string matcher that won't match anything. + Call setPattern() to give it a pattern to match. +*/ +QStringMatcher::QStringMatcher() + : d_ptr(0), q_cs(Qt::CaseSensitive) +{ + qMemSet(q_data, 0, sizeof(q_data)); +} + +/*! + Constructs a string matcher that will search for \a pattern, with + case sensitivity \a cs. + + Call indexIn() to perform a search. +*/ +QStringMatcher::QStringMatcher(const QString &pattern, Qt::CaseSensitivity cs) + : d_ptr(0), q_pattern(pattern), q_cs(cs) +{ + p.uc = pattern.unicode(); + p.len = pattern.size(); + bm_init_skiptable((const ushort *)p.uc, p.len, p.q_skiptable, cs); +} + +/*! + \fn QStringMatcher::QStringMatcher(const QChar *uc, int length, Qt::CaseSensitivity cs) + \since 4.5 + + Constructs a string matcher that will search for the pattern referred to + by \a uc with the given \a length and case sensitivity specified by \a cs. +*/ +QStringMatcher::QStringMatcher(const QChar *uc, int len, Qt::CaseSensitivity cs) + : d_ptr(0), q_cs(cs) +{ + p.uc = uc; + p.len = len; + bm_init_skiptable((const ushort *)p.uc, len, p.q_skiptable, cs); +} + +/*! + Copies the \a other string matcher to this string matcher. +*/ +QStringMatcher::QStringMatcher(const QStringMatcher &other) + : d_ptr(0) +{ + operator=(other); +} + +/*! + Destroys the string matcher. +*/ +QStringMatcher::~QStringMatcher() +{ +} + +/*! + Assigns the \a other string matcher to this string matcher. +*/ +QStringMatcher &QStringMatcher::operator=(const QStringMatcher &other) +{ + if (this != &other) { + q_pattern = other.q_pattern; + q_cs = other.q_cs; + qMemCopy(q_data, other.q_data, sizeof(q_data)); + } + return *this; +} + +/*! + Sets the string that this string matcher will search for to \a + pattern. + + \sa pattern(), setCaseSensitivity(), indexIn() +*/ +void QStringMatcher::setPattern(const QString &pattern) +{ + q_pattern = pattern; + p.uc = pattern.unicode(); + p.len = pattern.size(); + bm_init_skiptable((const ushort *)pattern.unicode(), pattern.size(), p.q_skiptable, q_cs); +} + +/*! + \fn QString QStringMatcher::pattern() const + + Returns the string pattern that this string matcher will search + for. + + \sa setPattern() +*/ + +QString QStringMatcher::pattern() const +{ + if (!q_pattern.isEmpty()) + return q_pattern; + return QString(p.uc, p.len); +} + +/*! + Sets the case sensitivity setting of this string matcher to \a + cs. + + \sa caseSensitivity(), setPattern(), indexIn() +*/ +void QStringMatcher::setCaseSensitivity(Qt::CaseSensitivity cs) +{ + if (cs == q_cs) + return; + bm_init_skiptable((const ushort *)q_pattern.unicode(), q_pattern.size(), p.q_skiptable, cs); + q_cs = cs; +} + +/*! + Searches the string \a str from character position \a from + (default 0, i.e. from the first character), for the string + pattern() that was set in the constructor or in the most recent + call to setPattern(). Returns the position where the pattern() + matched in \a str, or -1 if no match was found. + + \sa setPattern(), setCaseSensitivity() +*/ +int QStringMatcher::indexIn(const QString &str, int from) const +{ + if (from < 0) + from = 0; + return bm_find((const ushort *)str.unicode(), str.size(), from, + (const ushort *)p.uc, p.len, + p.q_skiptable, q_cs); +} + +/*! + \since 4.5 + + Searches the string starting at \a str (of length \a length) from + character position \a from (default 0, i.e. from the first + character), for the string pattern() that was set in the + constructor or in the most recent call to setPattern(). Returns + the position where the pattern() matched in \a str, or -1 if no + match was found. + + \sa setPattern(), setCaseSensitivity() +*/ +int QStringMatcher::indexIn(const QChar *str, int length, int from) const +{ + if (from < 0) + from = 0; + return bm_find((const ushort *)str, length, from, + (const ushort *)p.uc, p.len, + p.q_skiptable, q_cs); +} + +/*! + \fn Qt::CaseSensitivity QStringMatcher::caseSensitivity() const + + Returns the case sensitivity setting for this string matcher. + + \sa setCaseSensitivity() +*/ + +/*! + \internal +*/ + +int qFindStringBoyerMoore( + const QChar *haystack, int haystackLen, int haystackOffset, + const QChar *needle, int needleLen, Qt::CaseSensitivity cs) +{ + uchar skiptable[256]; + bm_init_skiptable((const ushort *)needle, needleLen, skiptable, cs); + if (haystackOffset < 0) + haystackOffset = 0; + return bm_find((const ushort *)haystack, haystackLen, haystackOffset, + (const ushort *)needle, needleLen, skiptable, cs); +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qstringmatcher.h b/src/corelib/tools/qstringmatcher.h new file mode 100644 index 0000000..26fe0dc --- /dev/null +++ b/src/corelib/tools/qstringmatcher.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSTRINGMATCHER_H +#define QSTRINGMATCHER_H + +#include <QtCore/qstring.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class QStringMatcherPrivate; + +class Q_CORE_EXPORT QStringMatcher +{ +public: + QStringMatcher(); + QStringMatcher(const QString &pattern, + Qt::CaseSensitivity cs = Qt::CaseSensitive); + QStringMatcher(const QChar *uc, int len, + Qt::CaseSensitivity cs = Qt::CaseSensitive); + QStringMatcher(const QStringMatcher &other); + ~QStringMatcher(); + + QStringMatcher &operator=(const QStringMatcher &other); + + void setPattern(const QString &pattern); + void setCaseSensitivity(Qt::CaseSensitivity cs); + + int indexIn(const QString &str, int from = 0) const; + int indexIn(const QChar *str, int length, int from = 0) const; + QString pattern() const; + inline Qt::CaseSensitivity caseSensitivity() const { return q_cs; } + +private: + QStringMatcherPrivate *d_ptr; + QString q_pattern; + Qt::CaseSensitivity q_cs; +#ifdef Q_CC_RVCT +// explicitely allow anonymous unions for RVCT to prevent compiler warnings +#pragma anon_unions +#endif + union { + uint q_data[256]; + struct { + uchar q_skiptable[256]; + const QChar *uc; + int len; + } p; + }; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QSTRINGMATCHER_H diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/tools/qtextboundaryfinder.cpp new file mode 100644 index 0000000..bc9b675 --- /dev/null +++ b/src/corelib/tools/qtextboundaryfinder.cpp @@ -0,0 +1,476 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "private/qharfbuzz_p.h" +#include <QtCore/qtextboundaryfinder.h> +#include <QtCore/qvarlengtharray.h> +#include <private/qunicodetables_p.h> +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + +class QTextBoundaryFinderPrivate +{ +public: + HB_CharAttributes attributes[1]; +}; + +static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int length, HB_CharAttributes *attributes) +{ + QVarLengthArray<HB_ScriptItem> scriptItems; + + const ushort *string = reinterpret_cast<const ushort *>(chars); + const ushort *unicode = string; + // correctly assign script, isTab and isObject to the script analysis + const ushort *uc = unicode; + const ushort *e = uc + length; + int script = QUnicodeTables::Common; + int lastScript = QUnicodeTables::Common; + const ushort *start = uc; + while (uc < e) { + int s = QUnicodeTables::script(*uc); + if (s != QUnicodeTables::Inherited) + script = s; + if (*uc == QChar::ObjectReplacementCharacter || *uc == QChar::LineSeparator || *uc == 9) + script = QUnicodeTables::Common; + if (script != lastScript) { + if (uc != start) { + HB_ScriptItem item; + item.pos = start - string; + item.length = uc - start; + item.script = (HB_Script)lastScript; + item.bidiLevel = 0; // ### what's the proper value? + scriptItems.append(item); + start = uc; + } + lastScript = script; + } + ++uc; + } + if (uc != start) { + HB_ScriptItem item; + item.pos = start - string; + item.length = uc - start; + item.script = (HB_Script)lastScript; + item.bidiLevel = 0; // ### what's the proper value? + scriptItems.append(item); + } + + qGetCharAttributes(string, length, scriptItems.data(), scriptItems.count(), attributes); + if (type == QTextBoundaryFinder::Word) + HB_GetWordBoundaries(string, length, scriptItems.data(), scriptItems.count(), attributes); + else if (type == QTextBoundaryFinder::Sentence) + HB_GetSentenceBoundaries(string, length, scriptItems.data(), scriptItems.count(), attributes); +} + +/*! \class QTextBoundaryFinder + + \brief The QTextBoundaryFinder class provides a way of finding Unicode text boundaries in a string. + + \since 4.4 + \ingroup tools + \ingroup shared + \ingroup text + \reentrant + + QTextBoundaryFinder allows to find Unicode text boundaries in a + string, similar to the Unicode text boundary specification (see + http://www.unicode.org/reports/tr29/tr29-11.html). + + QTextBoundaryFinder can operate on a QString in four possible + modes depending on the value of \a BoundaryType. + + Units of Unicode characters that make up what the user thinks of + as a character or basic unit of the language are here called + Grapheme clusters. The two unicode characters 'A' + diaeresis do + for example form one grapheme cluster as the user thinks of them + as one character, yet it is in this case represented by two + unicode code points. + + Word boundaries are there to locate the start and end of what a + language considers to be a word. + + Line break boundaries give possible places where a line break + might happen and sentence boundaries will show the beginning and + end of whole sentences. +*/ + +/*! + \enum QTextBoundaryFinder::BoundaryType + + \value Grapheme Finds a grapheme which is the smallest boundary. It + including letters, punctation marks, numerals and more. + \value Word Finds a word. + \value Line Finds possible positions for breaking the text into multiple + lines. + \value Sentence Finds sentence boundaries. These include periods, question + marks etc. +*/ + +/*! + \enum QTextBoundaryFinder::BoundaryReason + + \value NotAtBoundary The boundary finder is not at a boundary position. + \value StartWord The boundary finder is at the start of a word. + \value EndWord The boundary finder is at the end of a word. +*/ + +/*! + Constructs an invalid QTextBoundaryFinder object. +*/ +QTextBoundaryFinder::QTextBoundaryFinder() + : t(Grapheme) + , chars(0) + , length(0) + , freePrivate(true) + , d(0) +{ +} + +/*! + Copies the QTextBoundaryFinder object, \a other. +*/ +QTextBoundaryFinder::QTextBoundaryFinder(const QTextBoundaryFinder &other) + : t(other.t) + , s(other.s) + , chars(other.chars) + , length(other.length) + , pos(other.pos) + , freePrivate(true) +{ + d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes)); + memcpy(d, other.d, length*sizeof(HB_CharAttributes)); +} + +/*! + Assigns the object, \a other, to another QTextBoundaryFinder object. +*/ +QTextBoundaryFinder &QTextBoundaryFinder::operator=(const QTextBoundaryFinder &other) +{ + if (&other == this) + return *this; + + t = other.t; + s = other.s; + chars = other.chars; + length = other.length; + pos = other.pos; + freePrivate = true; + + d = (QTextBoundaryFinderPrivate *) realloc(d, length*sizeof(HB_CharAttributes)); + memcpy(d, other.d, length*sizeof(HB_CharAttributes)); + + return *this; +} + +/*! + Destructs the QTextBoundaryFinder object. +*/ +QTextBoundaryFinder::~QTextBoundaryFinder() +{ + if (freePrivate) + free(d); +} + +/*! + Creates a QTextBoundaryFinder object of \a type operating on \a string. +*/ +QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, const QString &string) + : t(type) + , s(string) + , chars(string.unicode()) + , length(string.length()) + , pos(0) + , freePrivate(true) +{ + d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes)); + init(t, chars, length, d->attributes); +} + +/*! + Creates a QTextBoundaryFinder object of \a type operating on \a chars + with \a length. + + \a buffer is an optional working buffer of size \a bufferSize you can pass to + the QTextBoundaryFinder. If the buffer is large enough to hold the working + data required, it will use this instead of allocating its own buffer. + + \warning QTextBoundaryFinder does not create a copy of \a chars. It is the + application programmer's responsability to ensure the array is allocated for + as long as the QTextBoundaryFinder object stays alive. The same applies to + \a buffer. +*/ +QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, const QChar *chars, int length, unsigned char *buffer, int bufferSize) + : t(type) + , chars(chars) + , length(length) + , pos(0) +{ + if (buffer && (uint)bufferSize >= length*sizeof(HB_CharAttributes)) { + d = (QTextBoundaryFinderPrivate *)buffer; + freePrivate = false; + } else { + d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes)); + freePrivate = true; + } + init(t, chars, length, d->attributes); +} + +/*! + Moves the finder to the start of the string. This is equivalent to setPosition(0). + + \sa setPosition(), position() +*/ +void QTextBoundaryFinder::toStart() +{ + pos = 0; +} + +/*! + Moves the finder to the end of the string. This is equivalent to setPosition(string.length()). + + \sa setPosition(), position() +*/ +void QTextBoundaryFinder::toEnd() +{ + pos = length; +} + +/*! + Returns the current position of the QTextBoundaryFinder. + + The range is from 0 (the beginning of the string) to the length of + the string inclusive. + + \sa setPosition() +*/ +int QTextBoundaryFinder::position() const +{ + return pos; +} + +/*! + Sets the current position of the QTextBoundaryFinder to \a position. + + If \a position is out of bounds, it will be bound to only valid + positions. In this case, valid positions are from 0 to the length of + the string inclusive. + + \sa position() +*/ +void QTextBoundaryFinder::setPosition(int position) +{ + pos = qBound(0, position, length); +} + +/*! \fn QTextBoundaryFinder::BoundaryType QTextBoundaryFinder::type() const + + Returns the type of the QTextBoundaryFinder. +*/ + +/*! \fn bool QTextBoundaryFinder::isValid() const + + Returns true if the text boundary finder is valid; otherwise returns false. + A default QTextBoundaryFinder is invalid. +*/ + +/*! + Returns the string the QTextBoundaryFinder object operates on. +*/ +QString QTextBoundaryFinder::string() const +{ + if (chars == s.unicode() && length == s.length()) + return s; + return QString(chars, length); +} + + +/*! + Moves the QTextBoundaryFinder to the next boundary position and returns that position. + + Returns -1 is there is no next boundary. +*/ +int QTextBoundaryFinder::toNextBoundary() +{ + if (!d) { + pos = -1; + return pos; + } + + if (pos < 0 || pos >= length) { + pos = -1; + return pos; + } + ++pos; + if (pos == length) + return pos; + + switch(t) { + case Grapheme: + while (pos < length && !d->attributes[pos].charStop) + ++pos; + break; + case Word: + while (pos < length && !d->attributes[pos].wordBoundary) + ++pos; + break; + case Sentence: + while (pos < length && !d->attributes[pos].sentenceBoundary) + ++pos; + break; + case Line: + while (pos < length && d->attributes[pos].lineBreakType < HB_Break) + ++pos; + break; + } + + return pos; +} + +/*! + Moves the QTextBoundaryFinder to the previous boundary position and returns that position. + + Returns -1 is there is no previous boundary. +*/ +int QTextBoundaryFinder::toPreviousBoundary() +{ + if (!d) { + pos = -1; + return pos; + } + + if (pos <= 0 || pos > length) { + pos = -1; + return pos; + } + --pos; + if (pos == 0) + return pos; + + switch(t) { + case Grapheme: + while (pos > 0 && !d->attributes[pos].charStop) + --pos; + break; + case Word: + while (pos > 0 && !d->attributes[pos].wordBoundary) + --pos; + break; + case Sentence: + while (pos > 0 && !d->attributes[pos].sentenceBoundary) + --pos; + break; + case Line: + while (pos > 0 && d->attributes[pos].lineBreakType < HB_Break) + --pos; + break; + } + + return pos; +} + +/*! + Returns true if the object's position() is currently at a valid text boundary. +*/ +bool QTextBoundaryFinder::isAtBoundary() const +{ + if (!d || pos < 0) + return false; + + if (pos == length) + return true; + + switch(t) { + case Grapheme: + return d->attributes[pos].charStop; + case Word: + return d->attributes[pos].wordBoundary; + case Line: + return d->attributes[pos].lineBreakType >= HB_Break; + case Sentence: + return d->attributes[pos].sentenceBoundary; + } + return false; +} + +/*! + Returns the reasons for the boundary finder to have chosen the current position as a boundary. +*/ +QTextBoundaryFinder::BoundaryReasons QTextBoundaryFinder::boundaryReasons() const +{ + if (!d) + return NotAtBoundary; + if (! isAtBoundary()) + return NotAtBoundary; + if (pos == 0) { + if (d->attributes[pos].whiteSpace) + return NotAtBoundary; + return StartWord; + } + if (pos >= length - 1) { + if (d->attributes[length-1].whiteSpace) + return NotAtBoundary; + return EndWord; + } + + BoundaryReasons answer; + const bool nextIsSpace = d->attributes[pos + 1].whiteSpace; + const bool prevIsSpace = d->attributes[pos - 1].whiteSpace; + + if (d->attributes[pos].whiteSpace) + answer = EndWord; + else if (!prevIsSpace) { + answer = StartWord; + answer |= EndWord; + } + + if (prevIsSpace) + answer |= StartWord; + if (nextIsSpace) + answer |= EndWord; + if (answer == 0) { + answer = StartWord; + answer |= EndWord; + } + + return answer; +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qtextboundaryfinder.h b/src/corelib/tools/qtextboundaryfinder.h new file mode 100644 index 0000000..095e290 --- /dev/null +++ b/src/corelib/tools/qtextboundaryfinder.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTEXTBOUNDARYFINDER_H +#define QTEXTBOUNDARYFINDER_H + +#include <QtCore/qchar.h> +#include <QtCore/qstring.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class QTextBoundaryFinderPrivate; + +class Q_CORE_EXPORT QTextBoundaryFinder +{ +public: + QTextBoundaryFinder(); + QTextBoundaryFinder(const QTextBoundaryFinder &other); + QTextBoundaryFinder &operator=(const QTextBoundaryFinder &other); + ~QTextBoundaryFinder(); + + enum BoundaryType { + Grapheme, + Word, + Line, + Sentence + }; + + enum BoundaryReason { + NotAtBoundary = 0, + StartWord = 1, + EndWord = 2 + //Hyphen + }; + Q_DECLARE_FLAGS( BoundaryReasons, BoundaryReason ) + + QTextBoundaryFinder(BoundaryType type, const QString &string); + QTextBoundaryFinder(BoundaryType type, const QChar *chars, int length, unsigned char *buffer = 0, int bufferSize = 0); + + inline bool isValid() const { return d; } + + inline BoundaryType type() const { return t; } + QString string() const; + + void toStart(); + void toEnd(); + int position() const; + void setPosition(int position); + + int toNextBoundary(); + int toPreviousBoundary(); + + bool isAtBoundary() const; + BoundaryReasons boundaryReasons() const; + +private: + BoundaryType t; + QString s; + const QChar *chars; + int length; + int pos; + uint freePrivate : 1; + uint unused : 31; + QTextBoundaryFinderPrivate *d; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif + diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp new file mode 100644 index 0000000..2979a09 --- /dev/null +++ b/src/corelib/tools/qtimeline.cpp @@ -0,0 +1,773 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtimeline.h" + +#include <private/qobject_p.h> +#include <QtCore/qdatetime.h> +#include <QtCore/qcoreevent.h> +#include <QtCore/qmath.h> + +QT_BEGIN_NAMESPACE + +static const qreal pi = qreal(3.14159265359); +static const qreal halfPi = pi / qreal(2.0); + + +static inline qreal qt_sinProgress(qreal value) +{ + return qSin((value * pi) - halfPi) / 2 + qreal(0.5); +} + +static inline qreal qt_smoothBeginEndMixFactor(qreal value) +{ + return qMin(qMax(1 - value * 2 + qreal(0.3), qreal(0.0)), qreal(1.0)); +} + +class QTimeLinePrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QTimeLine) +public: + inline QTimeLinePrivate() + : startTime(0), duration(1000), startFrame(0), endFrame(0), + updateInterval(1000 / 25), + totalLoopCount(1), currentLoopCount(0), currentTime(0), timerId(0), + direction(QTimeLine::Forward), curveShape(QTimeLine::EaseInOutCurve), + state(QTimeLine::NotRunning) + { } + + int startTime; + int duration; + int startFrame; + int endFrame; + int updateInterval; + int totalLoopCount; + int currentLoopCount; + + int currentTime; + int elapsedTime; + int timerId; + QTime timer; + + QTimeLine::Direction direction; + QTimeLine::CurveShape curveShape; + QTimeLine::State state; + inline void setState(QTimeLine::State newState) + { + Q_Q(QTimeLine); + if (newState != state) + emit q->stateChanged(state = newState); + } + + void setCurrentTime(int msecs); +}; + +/*! + \internal +*/ +void QTimeLinePrivate::setCurrentTime(int msecs) +{ + Q_Q(QTimeLine); + + qreal lastValue = q->currentValue(); + int lastFrame = q->currentFrame(); + + // Determine if we are looping. + int elapsed = (direction == QTimeLine::Backward) ? (-msecs + duration) : msecs; + int loopCount = elapsed / duration; + + bool looping = (loopCount != currentLoopCount); +#ifdef QTIMELINE_DEBUG + qDebug() << "QTimeLinePrivate::setCurrentTime:" << msecs << duration << "with loopCount" << loopCount + << "currentLoopCount" << currentLoopCount + << "looping" << looping; +#endif + if (looping) + currentLoopCount = loopCount; + + // Normalize msecs to be between 0 and duration, inclusive. + currentTime = elapsed % duration; + if (direction == QTimeLine::Backward) + currentTime = duration - currentTime; + + // Check if we have reached the end of loopcount. + bool finished = false; + if (totalLoopCount && currentLoopCount >= totalLoopCount) { + finished = true; + currentTime = (direction == QTimeLine::Backward) ? 0 : duration; + currentLoopCount = totalLoopCount - 1; + } + + int currentFrame = q->frameForTime(currentTime); +#ifdef QTIMELINE_DEBUG + qDebug() << "QTimeLinePrivate::setCurrentTime: frameForTime" << currentTime << currentFrame; +#endif + if (lastValue != q->currentValue()) + emit q->valueChanged(q->currentValue()); + if (lastFrame != currentFrame) { + const int transitionframe = (direction == QTimeLine::Forward ? endFrame : startFrame); + if (looping && !finished && transitionframe != currentFrame) { +#ifdef QTIMELINE_DEBUG + qDebug() << "QTimeLinePrivate::setCurrentTime: transitionframe"; +#endif + emit q->frameChanged(transitionframe); + } +#ifdef QTIMELINE_DEBUG + else { + QByteArray reason; + if (!looping) + reason += " not looping"; + if (finished) { + if (!reason.isEmpty()) + reason += " and"; + reason += " finished"; + } + if (transitionframe == currentFrame) { + if (!reason.isEmpty()) + reason += " and"; + reason += " transitionframe is equal to currentFrame: " + QByteArray::number(currentFrame); + } + qDebug("QTimeLinePrivate::setCurrentTime: not transitionframe because %s", reason.constData()); + } +#endif + emit q->frameChanged(currentFrame); + } + if (finished && state == QTimeLine::Running) { + q->stop(); + emit q->finished(); + } +} + +/*! + \class QTimeLine + \brief The QTimeLine class provides a timeline for controlling animations. + \since 4.2 + \ingroup multimedia + + It's most commonly used to animate a GUI control by calling a slot + periodically. You can construct a timeline by passing its duration in + milliseconds to QTimeLine's constructor. The timeline's duration describes + for how long the animation will run. Then you set a suitable frame range + by calling setFrameRange(). Finally connect the frameChanged() signal to a + suitable slot in the widget you wish to animate (e.g., setValue() in + QProgressBar). When you proceed to calling start(), QTimeLine will enter + Running state, and start emitting frameChanged() at regular intervals, + causing your widget's connected property's value to grow from the lower + end to the upper and of your frame range, at a steady rate. You can + specify the update interval by calling setUpdateInterval(). When done, + QTimeLine enters NotRunning state, and emits finished(). + + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qtimeline.cpp 0 + + You can also use QTimeLine with the + \l{Graphics View}{Graphics View framework} for + animations. The QGraphicsItemAnimation class implements animation + of \l{QGraphicsItem}{QGraphicsItems} with a timeline. + + By default the timeline runs once, from the beginning and towards the end, + upon which you must call start() again to restart from the beginning. To + make the timeline loop, you can call setLoopCount(), passing the number of + times the timeline should run before finishing. The direction can also be + changed, causing the timeline to run backward, by calling + setDirection(). You can also pause and unpause the timeline while it's + running by calling setPaused(). For interactive control, the + setCurrentTime() function is provided, which sets the time position of the + time line directly. Although most useful in NotRunning state, (e.g., + connected to a valueChanged() signal in a QSlider,) this function can be + called at any time. + + The frame interface is useful for standard widgets, but QTimeLine can be + used to control any type of animation. The heart of QTimeLine lies in the + valueForTime() function, which generates a \e value between 0 and 1 for a + given time. This value is typically used to describe the steps of an + animation, where 0 is the first step of an animation, and 1 is the last + step. When running, QTimeLine generates values between 0 and 1 by calling + valueForTime() and emitting valueChanged(). By default, valueForTime() + applies an interpolation algorithm to generate these value. You can choose + from a set of predefined timeline algorithms by calling + setCurveShape(). By default, QTimeLine uses the EaseInOut curve shape, + which provides a value that grows slowly, then grows steadily, and + finally grows slowly. For a custom timeline, you can reimplement + valueForTime(), in which case QTimeLine's curveShape property is ignored. + + \sa QProgressBar, QProgressDialog, QGraphicsItemAnimation +*/ + +/*! + \enum QTimeLine::State + + This enum describes the state of the timeline. + + \value NotRunning The timeline is not running. This is the initial state + of QTimeLine, and the state QTimeLine reenters when finished. The current + time, frame and value remain unchanged until either setCurrentTime() is + called, or the timeline is started by calling start(). + + \value Paused The timeline is paused (i.e., temporarily + suspended). Calling setPaused(false) will resume timeline activity. + + \value Running The timeline is running. While control is in the event + loop, QTimeLine will update its current time at regular intervals, + emitting valueChanged() and frameChanged() when appropriate. + + \sa state(), stateChanged() +*/ + +/*! + \enum QTimeLine::Direction + + This enum describes the direction of the timeline when in \l Running state. + + \value Forward The current time of the timeline increases with time (i.e., + moves from 0 and towards the end / duration). + + \value Backward The current time of the timeline decreases with time (i.e., + moves from the end / duration and towards 0). + + \sa setDirection() +*/ + +/*! + \enum QTimeLine::CurveShape + + This enum describes the default shape of QTimeLine's value curve. The + default, shape is EaseInOutCurve. The curve defines the relation + between the value and the timeline. + + \value EaseInCurve The value starts growing slowly, then increases in speed. + \value EaseOutCurve The value starts growing steadily, then ends slowly. + \value EaseInOutCurve The value starts growing slowly, then runs steadily, then grows slowly again. + \value LinearCurve The value grows linearly (e.g., if the duration is 1000 ms, + the value at time 500 ms is 0.5). + \value SineCurve The value grows sinusoidally. + \value CosineCurve The value grows cosinusoidally. + + \sa setCurveShape() +*/ + +/*! + \fn QTimeLine::valueChanged(qreal value) + + QTimeLine emits this signal at regular intervals when in \l Running state, + but only if the current value changes. \a value is the current value. \a value is + a number between 0.0 and 1.0 + + \sa QTimeLine::setDuration(), QTimeLine::valueForTime(), QTimeLine::updateInterval +*/ + +/*! + \fn QTimeLine::frameChanged(int frame) + + QTimeLine emits this signal at regular intervals when in \l Running state, + but only if the current frame changes. \a frame is the current frame number. + + \sa QTimeLine::setFrameRange(), QTimeLine::updateInterval +*/ + +/*! + \fn QTimeLine::stateChanged(QTimeLine::State newState) + + This signal is emitted whenever QTimeLine's state changes. The new state + is \a newState. +*/ + +/*! + \fn QTimeLine::finished() + + This signal is emitted when QTimeLine finishes (i.e., reaches the end of + its time line), and does not loop. +*/ + +/*! + Constructs a timeline with a duration of \a duration milliseconds. \a + parent is passed to QObject's constructor. The default duration is 1000 + milliseconds. + */ +QTimeLine::QTimeLine(int duration, QObject *parent) + : QObject(*new QTimeLinePrivate, parent) +{ + setDuration(duration); +} + +/*! + Destroys the timeline. + */ +QTimeLine::~QTimeLine() +{ + Q_D(QTimeLine); + + if (d->state == Running) + stop(); +} + +/*! + Returns the state of the timeline. + + \sa start(), setPaused(), stop() +*/ +QTimeLine::State QTimeLine::state() const +{ + Q_D(const QTimeLine); + return d->state; +} + +/*! + \property QTimeLine::loopCount + \brief the number of times the timeline should loop before it's finished. + + A loop count of of 0 means that the timeline will loop forever. + + By default, this property contains a value of 1. +*/ +int QTimeLine::loopCount() const +{ + Q_D(const QTimeLine); + return d->totalLoopCount; +} +void QTimeLine::setLoopCount(int count) +{ + Q_D(QTimeLine); + d->totalLoopCount = count; +} + +/*! + \property QTimeLine::direction + \brief the direction of the timeline when QTimeLine is in \l Running + state. + + This direction indicates whether the time moves from 0 towards the + timeline duration, or from the value of the duration and towards 0 after + start() has been called. + + By default, this property is set to \l Forward. +*/ +QTimeLine::Direction QTimeLine::direction() const +{ + Q_D(const QTimeLine); + return d->direction; +} +void QTimeLine::setDirection(Direction direction) +{ + Q_D(QTimeLine); + d->direction = direction; + d->startTime = d->currentTime; + d->timer.start(); +} + +/*! + \property QTimeLine::duration + \brief the total duration of the timeline in milliseconds. + + By default, this value is 1000 (i.e., 1 second), but you can change this + by either passing a duration to QTimeLine's constructor, or by calling + setDuration(). The duration must be larger than 0. +*/ +int QTimeLine::duration() const +{ + Q_D(const QTimeLine); + return d->duration; +} +void QTimeLine::setDuration(int duration) +{ + Q_D(QTimeLine); + if (duration <= 0) { + qWarning("QTimeLine::setDuration: cannot set duration <= 0"); + return; + } + d->duration = duration; +} + +/*! + Returns the start frame, which is the frame corresponding to the start of + the timeline (i.e., the frame for which the current value is 0). + + \sa setStartFrame(), setFrameRange() +*/ +int QTimeLine::startFrame() const +{ + Q_D(const QTimeLine); + return d->startFrame; +} + +/*! + Sets the start frame, which is the frame corresponding to the start of the + timeline (i.e., the frame for which the current value is 0), to \a frame. + + \sa startFrame(), endFrame(), setFrameRange() +*/ +void QTimeLine::setStartFrame(int frame) +{ + Q_D(QTimeLine); + d->startFrame = frame; +} + +/*! + Returns the end frame, which is the frame corresponding to the end of the + timeline (i.e., the frame for which the current value is 1). + + \sa setEndFrame(), setFrameRange() +*/ +int QTimeLine::endFrame() const +{ + Q_D(const QTimeLine); + return d->endFrame; +} + +/*! + Sets the end frame, which is the frame corresponding to the end of the + timeline (i.e., the frame for which the current value is 1), to \a frame. + + \sa endFrame(), startFrame(), setFrameRange() +*/ +void QTimeLine::setEndFrame(int frame) +{ + Q_D(QTimeLine); + d->endFrame = frame; +} + +/*! + Sets the timeline's frame counter to start at \a startFrame, and end and + \a endFrame. For each time value, QTimeLine will find the corresponding + frame when you call currentFrame() or frameForTime() by interpolating, + using the return value of valueForTime(). + + When in Running state, QTimeLine also emits the frameChanged() signal when + the frame changes. + + \sa startFrame(), endFrame(), start(), currentFrame() +*/ +void QTimeLine::setFrameRange(int startFrame, int endFrame) +{ + Q_D(QTimeLine); + d->startFrame = startFrame; + d->endFrame = endFrame; +} + +/*! + \property QTimeLine::updateInterval + \brief the time in milliseconds between each time QTimeLine updates its + current time. + + When updating the current time, QTimeLine will emit valueChanged() if the + current value changed, and frameChanged() if the frame changed. + + By default, the interval is 40 ms, which corresponds to a rate of 25 + updates per second. +*/ +int QTimeLine::updateInterval() const +{ + Q_D(const QTimeLine); + return d->updateInterval; +} +void QTimeLine::setUpdateInterval(int interval) +{ + Q_D(QTimeLine); + d->updateInterval = interval; +} + +/*! + \property QTimeLine::curveShape + \brief the shape of the timeline curve. + + The curve shape describes the relation between the time and value for the + base implementation of valueForTime(). + + If you have reimplemented valueForTime(), this value is ignored. + + By default, this property is set to \l EaseInOutCurve. + + \sa valueForTime() +*/ +QTimeLine::CurveShape QTimeLine::curveShape() const +{ + Q_D(const QTimeLine); + return d->curveShape; +} +void QTimeLine::setCurveShape(CurveShape shape) +{ + Q_D(QTimeLine); + d->curveShape = shape; +} + +/*! + \property QTimeLine::currentTime + \brief the current time of the time line. + + When QTimeLine is in Running state, this value is updated continuously as + a function of the duration and direction of the timeline. Otherwise, it is + value that was current when stop() was called last, or the value set by + setCurrentTime(). + + By default, this property contains a value of 0. +*/ +int QTimeLine::currentTime() const +{ + Q_D(const QTimeLine); + return d->currentTime; +} +void QTimeLine::setCurrentTime(int msec) +{ + Q_D(QTimeLine); + d->startTime = 0; + d->currentLoopCount = 0; + d->timer.restart(); + d->setCurrentTime(msec); +} + +/*! + Returns the frame corresponding to the current time. + + \sa currentTime(), frameForTime(), setFrameRange() +*/ +int QTimeLine::currentFrame() const +{ + Q_D(const QTimeLine); + return frameForTime(d->currentTime); +} + +/*! + Returns the value corresponding to the current time. + + \sa valueForTime(), currentFrame() +*/ +qreal QTimeLine::currentValue() const +{ + Q_D(const QTimeLine); + return valueForTime(d->currentTime); +} + +/*! + Returns the frame corresponding to the time \a msec. This value is + calculated using a linear interpolation of the start and end frame, based + on the value returned by valueForTime(). + + \sa valueForTime(), setFrameRange() +*/ +int QTimeLine::frameForTime(int msec) const +{ + Q_D(const QTimeLine); + if (d->direction == Forward) + return d->startFrame + int((d->endFrame - d->startFrame) * valueForTime(msec)); + return d->startFrame + qCeil((d->endFrame - d->startFrame) * valueForTime(msec)); +} + +/*! + Returns the timeline value for the time \a msec. The returned value, which + varies depending on the curve shape, is always between 0 and 1. If \a msec + is 0, the default implementation always returns 0. + + Reimplement this function to provide a custom curve shape for your + timeline. + + \sa CurveShape, frameForTime() +*/ +qreal QTimeLine::valueForTime(int msec) const +{ + Q_D(const QTimeLine); + msec = qMin(qMax(msec, 0), d->duration); + + // Simple linear interpolation + qreal value = msec / qreal(d->duration); + + switch (d->curveShape) { + case EaseInOutCurve: + value = qt_sinProgress(value); + break; + // SmoothBegin blends Smooth and Linear Interpolation. + // Progress 0 - 0.3 : Smooth only + // Progress 0.3 - ~ 0.5 : Mix of Smooth and Linear + // Progress ~ 0.5 - 1 : Linear only + case EaseInCurve: { + const qreal sinProgress = qt_sinProgress(value); + const qreal linearProgress = value; + const qreal mix = qt_smoothBeginEndMixFactor(value); + value = sinProgress * mix + linearProgress * (1 - mix); + break; + } + case EaseOutCurve: { + const qreal sinProgress = qt_sinProgress(value); + const qreal linearProgress = value; + const qreal mix = qt_smoothBeginEndMixFactor(1 - value); + value = sinProgress * mix + linearProgress * (1 - mix); + break; + } + case SineCurve: + value = (qSin(((msec * pi * 2) / d->duration) - pi/2) + 1) / 2; + break; + case CosineCurve: + value = (qCos(((msec * pi * 2) / d->duration) - pi/2) + 1) / 2; + break; + default: + break; + } + + return value; +} + +/*! + Starts the timeline. QTimeLine will enter Running state, and once it + enters the event loop, it will update its current time, frame and value at + regular intervals. The default interval is 40 ms (i.e., 25 times per + second). You can change the update interval by calling + setUpdateInterval(). + + If you want to resume a stopped timeline without restarting, you can call + resume() instead. + + \sa resume(), updateInterval(), frameChanged(), valueChanged() +*/ +void QTimeLine::start() +{ + Q_D(QTimeLine); + if (d->timerId) { + qWarning("QTimeLine::start: already running"); + return; + } + int curTime = d->currentTime; + if (curTime == d->duration && d->direction == Forward) + curTime = 0; + else if (curTime == 0 && d->direction == Backward) + curTime = d->duration; + d->timerId = startTimer(d->updateInterval); + d->startTime = curTime; + d->currentLoopCount = 0; + d->timer.start(); + d->setState(Running); + d->setCurrentTime(curTime); +} + +/*! + Resumes the timeline from the current time. QTimeLine will reenter Running + state, and once it enters the event loop, it will update its current time, + frame and value at regular intervals. + + In contrast to start(), this function does not restart the timeline before + is resumes. + + \sa start(), updateInterval(), frameChanged(), valueChanged() +*/ +void QTimeLine::resume() +{ + Q_D(QTimeLine); + if (d->timerId) { + qWarning("QTimeLine::resume: already running"); + return; + } + d->timerId = startTimer(d->updateInterval); + d->startTime = d->currentTime; + d->timer.start(); + d->setState(Running); +} + +/*! + Stops the timeline, causing QTimeLine to enter NotRunning state. + + \sa start() +*/ +void QTimeLine::stop() +{ + Q_D(QTimeLine); + if (d->timerId) + killTimer(d->timerId); + d->setState(NotRunning); + d->timerId = 0; +} + +/*! + If \a paused is true, the timeline is paused, causing QTimeLine to enter + Paused state. No updates will be signaled until either start() or + setPaused(false) is called. If \a paused is false, the timeline is resumed + and continues where it left. + + \sa state(), start() +*/ +void QTimeLine::setPaused(bool paused) +{ + Q_D(QTimeLine); + if (d->state == NotRunning) { + qWarning("QTimeLine::setPaused: Not running"); + return; + } + if (paused && d->state != Paused) { + d->startTime = d->currentTime; + killTimer(d->timerId); + d->timerId = 0; + d->setState(Paused); + } else if (!paused && d->state == Paused) { + d->timerId = startTimer(d->updateInterval); + d->setState(Running); + } +} + +/*! + Toggles the direction of the timeline. If the direction was Forward, it + becomes Backward, and vice verca. + + \sa setDirection() +*/ +void QTimeLine::toggleDirection() +{ + Q_D(QTimeLine); + setDirection(d->direction == Forward ? Backward : Forward); +} + +/*! + \reimp +*/ +void QTimeLine::timerEvent(QTimerEvent *event) +{ + Q_D(QTimeLine); + if (event->timerId() != d->timerId) { + event->ignore(); + return; + } + event->accept(); + + if (d->direction == Forward) { + d->setCurrentTime(d->startTime + d->timer.elapsed()); + } else { + d->setCurrentTime(d->startTime - d->timer.elapsed()); + } +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qtimeline.h b/src/corelib/tools/qtimeline.h new file mode 100644 index 0000000..18c3980 --- /dev/null +++ b/src/corelib/tools/qtimeline.h @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTIMELINE_H +#define QTIMELINE_H + +#include <QtCore/qobject.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class QTimeLinePrivate; +class Q_CORE_EXPORT QTimeLine : public QObject +{ + Q_OBJECT + Q_PROPERTY(int duration READ duration WRITE setDuration) + Q_PROPERTY(int updateInterval READ updateInterval WRITE setUpdateInterval) + Q_PROPERTY(int currentTime READ currentTime WRITE setCurrentTime) + Q_PROPERTY(Direction direction READ direction WRITE setDirection) + Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount) + Q_PROPERTY(CurveShape curveShape READ curveShape WRITE setCurveShape) +public: + enum State { + NotRunning, + Paused, + Running + }; + enum Direction { + Forward, + Backward + }; + enum CurveShape { + EaseInCurve, + EaseOutCurve, + EaseInOutCurve, + LinearCurve, + SineCurve, + CosineCurve + }; + + explicit QTimeLine(int duration = 1000, QObject *parent = 0); + virtual ~QTimeLine(); + + State state() const; + + int loopCount() const; + void setLoopCount(int count); + + Direction direction() const; + void setDirection(Direction direction); + + int duration() const; + void setDuration(int duration); + + int startFrame() const; + void setStartFrame(int frame); + int endFrame() const; + void setEndFrame(int frame); + void setFrameRange(int startFrame, int endFrame); + + int updateInterval() const; + void setUpdateInterval(int interval); + + CurveShape curveShape() const; + void setCurveShape(CurveShape shape); + + int currentTime() const; + int currentFrame() const; + qreal currentValue() const; + + int frameForTime(int msec) const; + virtual qreal valueForTime(int msec) const; + +public Q_SLOTS: + void start(); + void resume(); + void stop(); + void setPaused(bool paused); + void setCurrentTime(int msec); + void toggleDirection(); + +Q_SIGNALS: + void valueChanged(qreal x); + void frameChanged(int); + void stateChanged(QTimeLine::State newState); + void finished(); + +protected: + void timerEvent(QTimerEvent *event); + +private: + Q_DISABLE_COPY(QTimeLine) + Q_DECLARE_PRIVATE(QTimeLine) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif + diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h new file mode 100644 index 0000000..574928e --- /dev/null +++ b/src/corelib/tools/qtools_p.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTOOLS_P_H +#define QTOOLS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "QtCore/qglobal.h" + +QT_BEGIN_NAMESPACE + +// implemented in qbytearray.cpp +int Q_CORE_EXPORT qAllocMore(int alloc, int extra); + +QT_END_NAMESPACE + +#endif // QTOOLS_P_H diff --git a/src/corelib/tools/qunicodetables.cpp b/src/corelib/tools/qunicodetables.cpp new file mode 100644 index 0000000..0cfa26a --- /dev/null +++ b/src/corelib/tools/qunicodetables.cpp @@ -0,0 +1,9404 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* This file is autogenerated from the Unicode 5.0 database. Do not edit */ + +QT_BEGIN_NAMESPACE + +static const unsigned short uc_property_trie[] = { + // 0x11000 + + 6256, 6288, 6320, 6352, 6384, 6416, 6448, 6480, + 6512, 6544, 6576, 6608, 6640, 6672, 6704, 6736, + 6768, 6800, 6832, 6864, 6896, 6928, 6960, 6992, + 7024, 7056, 7088, 7120, 7152, 7184, 7216, 7248, + 7280, 7312, 7344, 6512, 7376, 6512, 7408, 7440, + 7472, 7504, 7536, 7568, 7600, 7632, 7664, 7696, + 7728, 7760, 7792, 7824, 7856, 7888, 7920, 7952, + 7984, 8016, 8048, 8080, 8112, 8144, 8176, 8208, + 8240, 8240, 8240, 8240, 8240, 8240, 8240, 8240, + 8272, 8304, 8336, 8368, 8400, 8432, 8464, 8496, + 8528, 8560, 8592, 8624, 8656, 8688, 8720, 8752, + 8400, 8784, 8816, 8848, 8880, 8912, 8944, 8976, + 9008, 9040, 9072, 9104, 9136, 9168, 9200, 9232, + 9136, 9264, 9296, 9104, 9328, 9360, 9392, 9424, + 9456, 9488, 9520, 9552, 9584, 9616, 9648, 9552, + 9680, 9712, 9744, 9776, 9808, 9840, 9872, 9552, + + 9904, 9936, 9968, 9552, 9552, 10000, 10032, 10064, + 10096, 10096, 10128, 10160, 10160, 10192, 10224, 10256, + 10288, 10320, 10352, 10320, 10384, 10416, 10448, 10480, + 10512, 10320, 10544, 10576, 10608, 10320, 10320, 10640, + 10672, 10320, 10320, 10320, 10320, 10320, 10320, 10320, + 10320, 10320, 10320, 10320, 10320, 10320, 10320, 10320, + 10320, 10320, 10320, 10704, 10736, 10320, 10320, 10768, + 10800, 10832, 10864, 10896, 9904, 10928, 10960, 10992, + 11024, 10320, 11056, 11088, 10320, 11120, 9552, 9552, + 11152, 11184, 11216, 11248, 11280, 11312, 11344, 11376, + 11408, 9552, 9552, 9552, 9552, 9552, 9552, 9552, + 11440, 11472, 11504, 11536, 9552, 9552, 9552, 9552, + 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552, + 11568, 11600, 11632, 11664, 11696, 11728, 11760, 11792, + 6512, 6512, 6512, 6512, 11824, 6512, 6512, 11856, + 11888, 11920, 11952, 11984, 12016, 12048, 12080, 12112, + + 12144, 12176, 12208, 12240, 12272, 12304, 12336, 12368, + 12400, 12432, 12464, 12496, 12528, 12560, 12592, 12624, + 12656, 12688, 12720, 12752, 12784, 12816, 12848, 12880, + 12912, 12944, 12976, 13008, 13040, 13072, 13104, 13136, + 13168, 13200, 13232, 13264, 13296, 13328, 13360, 13392, + 13168, 13168, 13168, 13168, 13424, 13456, 13488, 13520, + 13552, 13168, 13168, 13584, 13616, 13648, 9552, 9552, + 13680, 13712, 13744, 13776, 13808, 13840, 13872, 13904, + 13936, 13936, 13936, 13936, 13936, 13936, 13936, 13936, + 13968, 13968, 13968, 13968, 14000, 14032, 14064, 14096, + 13968, 14128, 13968, 14160, 14192, 14224, 14256, 14288, + 14320, 14352, 9552, 9552, 9552, 9552, 9552, 9552, + 14384, 14416, 14448, 14480, 14512, 14512, 14512, 14544, + 14576, 14608, 14640, 14672, 14704, 14736, 14736, 9552, + 14768, 9552, 9552, 9552, 14800, 14832, 14832, 14864, + 14832, 14832, 14832, 14832, 14832, 14832, 14896, 14928, + + 14960, 14992, 15024, 15056, 15088, 15120, 15152, 15184, + 15216, 15248, 15280, 15280, 15312, 15344, 15376, 15408, + 15440, 15472, 15504, 15536, 15472, 15568, 15600, 15632, + 15664, 15664, 15664, 15696, 15664, 15664, 15728, 15760, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15792, 15792, 15792, + 15792, 15792, 15792, 15792, 15792, 15824, 11376, 11376, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 15856, 15856, 15856, 15856, 15888, 9552, 9552, + + 15920, 15952, 15952, 15952, 15952, 15952, 15952, 15952, + 15952, 15952, 15952, 15952, 15952, 15952, 15952, 15952, + 15952, 15952, 15952, 15952, 15952, 15952, 15952, 15952, + 15952, 15952, 15952, 15952, 15952, 15952, 15952, 15952, + 15952, 15952, 15952, 15952, 15984, 16016, 16048, 9552, + 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552, + 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552, + 16080, 16112, 9552, 9552, 9552, 9552, 9552, 9552, + 16144, 16176, 16208, 16240, 9552, 9552, 9552, 9552, + 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552, + 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552, + 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552, + 16272, 16304, 16336, 16368, 16400, 16432, 16464, 16272, + 16304, 16336, 16368, 16400, 16432, 16464, 16272, 16304, + 16336, 16368, 16400, 16432, 16464, 16272, 16304, 16336, + 16368, 16400, 16432, 16464, 16272, 16304, 16336, 16368, + + 16400, 16432, 16464, 16272, 16304, 16336, 16368, 16400, + 16432, 16464, 16272, 16304, 16336, 16368, 16400, 16432, + 16464, 16272, 16304, 16336, 16368, 16400, 16432, 16464, + 16272, 16304, 16336, 16368, 16400, 16432, 16464, 16272, + 16304, 16336, 16368, 16400, 16432, 16464, 16272, 16304, + 16336, 16368, 16400, 16432, 16464, 16272, 16304, 16336, + 16368, 16400, 16432, 16464, 16272, 16304, 16336, 16368, + 16400, 16432, 16464, 16272, 16304, 16336, 16368, 16400, + 16432, 16464, 16272, 16304, 16336, 16368, 16400, 16432, + 16464, 16272, 16304, 16336, 16368, 16400, 16432, 16464, + 16272, 16304, 16336, 16368, 16400, 16432, 16464, 16272, + 16304, 16336, 16368, 16400, 16432, 16464, 16272, 16304, + 16336, 16368, 16400, 16432, 16464, 16272, 16304, 16336, + 16368, 16400, 16432, 16464, 16272, 16304, 16336, 16368, + 16400, 16432, 16464, 16272, 16304, 16336, 16368, 16400, + 16432, 16464, 16272, 16304, 16336, 16368, 16400, 16432, + + 16464, 16272, 16304, 16336, 16368, 16400, 16432, 16464, + 16272, 16304, 16336, 16368, 16400, 16432, 16464, 16272, + 16304, 16336, 16368, 16400, 16432, 16464, 16272, 16304, + 16336, 16368, 16400, 16432, 16464, 16272, 16304, 16336, + 16368, 16400, 16432, 16464, 16272, 16304, 16336, 16368, + 16400, 16432, 16464, 16272, 16304, 16336, 16368, 16400, + 16432, 16464, 16272, 16304, 16336, 16368, 16400, 16432, + 16464, 16272, 16304, 16336, 16368, 16400, 16432, 16464, + 16272, 16304, 16336, 16368, 16400, 16432, 16464, 16272, + 16304, 16336, 16368, 16400, 16432, 16464, 16272, 16304, + 16336, 16368, 16400, 16432, 16464, 16272, 16304, 16336, + 16368, 16400, 16432, 16464, 16272, 16304, 16336, 16368, + 16400, 16432, 16464, 16272, 16304, 16336, 16368, 16400, + 16432, 16464, 16272, 16304, 16336, 16368, 16400, 16432, + 16464, 16272, 16304, 16336, 16368, 16400, 16432, 16464, + 16272, 16304, 16336, 16368, 16400, 16432, 16464, 16272, + + 16304, 16336, 16368, 16400, 16432, 16464, 16272, 16304, + 16336, 16368, 16400, 16432, 16464, 16272, 16304, 16336, + 16368, 16400, 16432, 16464, 16272, 16304, 16336, 16368, + 16400, 16432, 16464, 16272, 16304, 16336, 16368, 16400, + 16432, 16464, 16272, 16304, 16336, 16368, 16400, 16432, + 16464, 16272, 16304, 16336, 16368, 16400, 16432, 16464, + 16272, 16304, 16336, 16368, 16400, 16432, 16464, 16272, + 16304, 16336, 16368, 16400, 16432, 16496, 9552, 9552, + 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528, + 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528, + 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528, + 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528, + 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528, + 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528, + 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528, + 16528, 16528, 16528, 16528, 16528, 16528, 16528, 16528, + + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 16560, 16560, 16560, 16560, 16560, 16560, 16560, 16560, + 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, + 15856, 16592, 16624, 16656, 16688, 16688, 16720, 9552, + 16752, 16784, 16816, 16848, 16848, 16880, 16912, 16848, + 16848, 16848, 16848, 16848, 16848, 16848, 16848, 16848, + 16848, 16944, 16976, 16848, 17008, 16848, 17040, 17072, + 17104, 17136, 17168, 17200, 16848, 16848, 16848, 17232, + 17264, 17296, 17328, 17360, 17392, 17424, 17456, 17488, + + 17520, 17552, 17584, 9552, 17616, 17616, 17616, 17648, + 17680, 17712, 17744, 17776, 17808, 9552, 9552, 9552, + 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552, + 17840, 17872, 17904, 9552, 17936, 14640, 17968, 9552, + 18000, 18032, 18064, 17616, 18096, 18128, 9552, 9552, + 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552, + 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552, + 9552, 9552, 9552, 9552, 9552, 9552, 9552, 9552, + 18160, 18192, 8240, 8240, 8240, 8240, 8240, 8240, + 18224, 8240, 8240, 8240, 8240, 8240, 8240, 8240, + 18256, 18288, 18320, 8240, 8240, 8240, 8240, 8240, + 8240, 8240, 8240, 8240, 8240, 8240, 8240, 8240, + 8240, 8240, 8240, 8240, 8240, 8240, 8240, 8240, + 8240, 8240, 8240, 8240, 8240, 8240, 8240, 8240, + 8240, 8240, 8240, 8240, 8240, 8240, 8240, 8240, + 8240, 8240, 8240, 8240, 8240, 8240, 8240, 8240, + + // 0x11000 - 0x110000 + + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18608, 18608, 18608, 18864, 19120, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 19376, 19632, 19888, 20144, 20400, 20656, 20912, 21168, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21680, 21680, + 21680, 21680, 21680, 21680, 21680, 21680, 21936, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 21680, 21680, 22192, 18352, 18352, 18352, 18352, 21424, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424, + 22448, 22704, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 18352, + 18352, 18352, 18352, 18352, 18352, 18352, 18352, 21424, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 23216, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 22960, + 22960, 22960, 22960, 22960, 22960, 22960, 22960, 23216, + + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 3, 4, 5, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 6, 6, 7, + + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 14, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 9, + + 14, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 39, 40, 41, 42, 43, + + 42, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 39, 45, 41, 36, 0, + + 0, 0, 0, 0, 0, 46, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 47, 14, 48, 12, 12, 12, 49, 49, + 42, 49, 50, 51, 36, 52, 49, 42, + 53, 54, 55, 56, 57, 58, 49, 59, + 42, 60, 50, 61, 62, 62, 62, 14, + + 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 36, + 38, 38, 38, 38, 38, 38, 38, 63, + + 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 36, + 44, 44, 44, 44, 44, 44, 44, 64, + + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + 67, 68, 65, 66, 65, 66, 65, 66, + 50, 65, 66, 65, 66, 65, 66, 65, + + 66, 65, 66, 65, 66, 65, 66, 65, + 66, 69, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + 70, 65, 66, 65, 66, 65, 66, 71, + + 72, 73, 65, 66, 65, 66, 74, 65, + 66, 75, 75, 65, 66, 50, 76, 77, + 78, 65, 66, 75, 79, 80, 81, 82, + 65, 66, 83, 50, 81, 84, 85, 86, + + 65, 66, 65, 66, 65, 66, 87, 65, + 66, 87, 50, 50, 65, 66, 87, 65, + 66, 88, 88, 65, 66, 65, 66, 89, + 65, 66, 50, 90, 65, 66, 50, 91, + + 90, 90, 90, 90, 92, 93, 94, 92, + 93, 94, 92, 93, 94, 65, 66, 65, + 66, 65, 66, 65, 66, 65, 66, 65, + 66, 65, 66, 65, 66, 95, 65, 66, + + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + 96, 92, 93, 94, 65, 66, 97, 98, + 99, 100, 65, 66, 65, 66, 65, 66, + + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + 99, 100, 99, 100, 99, 100, 99, 100, + + 101, 102, 99, 100, 99, 100, 99, 100, + 99, 100, 99, 100, 99, 100, 99, 100, + 99, 100, 99, 100, 102, 102, 102, 103, + 103, 103, 104, 105, 106, 107, 108, 103, + + 103, 105, 109, 110, 111, 112, 113, 109, + 113, 109, 113, 109, 113, 109, 113, 109, + 50, 50, 50, 114, 115, 50, 116, 116, + 50, 117, 50, 118, 50, 50, 50, 50, + + 116, 50, 50, 119, 50, 50, 50, 50, + 120, 121, 50, 122, 50, 50, 50, 121, + 50, 50, 123, 50, 50, 124, 50, 50, + 50, 50, 50, 50, 50, 125, 50, 50, + + 126, 50, 50, 126, 50, 50, 50, 50, + 126, 127, 128, 128, 129, 50, 50, 50, + 50, 50, 130, 50, 90, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, + + 50, 50, 50, 50, 50, 50, 50, 50, + 50, 131, 131, 131, 131, 131, 102, 102, + 132, 132, 132, 132, 132, 132, 132, 132, + 132, 133, 133, 134, 134, 134, 134, 134, + + 132, 132, 42, 42, 42, 42, 133, 133, + 135, 133, 133, 133, 135, 133, 133, 133, + 134, 134, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 136, + + 132, 132, 132, 132, 132, 42, 42, 42, + 42, 42, 136, 136, 136, 136, 137, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + 138, 138, 138, 138, 138, 138, 138, 138, + + 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 140, 141, 141, + 141, 141, 140, 142, 141, 141, 141, 141, + + 141, 143, 143, 141, 141, 141, 141, 143, + 143, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 144, 144, 144, 144, + 144, 141, 141, 141, 141, 139, 139, 139, + + 139, 139, 139, 139, 139, 145, 146, 147, + 147, 147, 146, 146, 146, 147, 147, 148, + 149, 149, 149, 150, 150, 150, 150, 149, + 151, 152, 152, 153, 154, 155, 155, 156, + + 157, 157, 158, 159, 159, 159, 159, 159, + 159, 159, 159, 159, 159, 159, 159, 159, + 160, 160, 160, 160, 42, 42, 160, 160, + 160, 160, 132, 161, 161, 161, 34, 160, + + 160, 160, 160, 160, 42, 42, 162, 14, + 163, 163, 163, 160, 164, 160, 165, 165, + 166, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, + + 38, 38, 160, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 167, 168, 168, 168, + 169, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, + + 44, 44, 170, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 171, 172, 172, 160, + 173, 174, 175, 175, 175, 176, 177, 131, + 178, 179, 65, 100, 65, 100, 65, 100, + + 65, 100, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + 180, 181, 182, 50, 183, 184, 185, 186, + 187, 188, 186, 187, 103, 189, 189, 189, + + 190, 191, 191, 191, 191, 191, 191, 191, + 191, 191, 191, 191, 191, 190, 191, 191, + 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, + + 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, + 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, + + 44, 44, 44, 44, 44, 44, 44, 44, + 44, 44, 44, 44, 44, 44, 44, 44, + 192, 181, 181, 181, 181, 181, 181, 181, + 181, 181, 181, 181, 181, 192, 181, 181, + + 65, 66, 193, 139, 139, 139, 139, 160, + 194, 194, 178, 179, 99, 100, 99, 100, + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + + 195, 65, 66, 65, 66, 178, 179, 65, + 66, 178, 179, 65, 66, 178, 179, 196, + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 99, 100, 65, 66, + 65, 66, 65, 66, 65, 66, 105, 106, + 65, 66, 113, 109, 113, 109, 113, 109, + + 178, 179, 178, 179, 178, 179, 178, 179, + 178, 179, 178, 179, 178, 179, 178, 179, + 113, 109, 113, 109, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 197, 197, 197, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 197, 197, + + 197, 197, 197, 197, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 197, 160, + 160, 134, 198, 198, 199, 198, 199, 198, + + 160, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, + + 200, 200, 200, 200, 200, 200, 200, 201, + 160, 202, 203, 160, 160, 160, 160, 160, + 204, 205, 206, 206, 206, 206, 205, 206, + 206, 206, 207, 205, 206, 206, 206, 206, + + 206, 206, 152, 205, 205, 205, 205, 205, + 206, 206, 205, 206, 206, 207, 208, 206, + 209, 210, 211, 212, 213, 214, 215, 216, + 217, 218, 219, 220, 221, 222, 223, 224, + + 225, 226, 227, 225, 206, 152, 228, 229, + 204, 204, 204, 204, 204, 204, 204, 204, + 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, + + 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 204, 204, 204, 204, 204, + 230, 230, 230, 231, 232, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + + 233, 233, 233, 233, 234, 234, 234, 234, + 234, 234, 234, 235, 236, 237, 238, 238, + 149, 149, 149, 149, 149, 149, 234, 234, + 234, 234, 234, 239, 234, 234, 240, 241, + + 234, 242, 243, 243, 243, 243, 244, 243, + 244, 243, 244, 244, 244, 244, 244, 243, + 243, 243, 243, 244, 244, 244, 244, 244, + 244, 244, 244, 234, 234, 234, 234, 234, + + 245, 244, 244, 244, 244, 244, 244, 244, + 243, 244, 244, 246, 247, 248, 249, 250, + 251, 252, 253, 146, 146, 147, 150, 149, + 149, 153, 153, 153, 152, 153, 153, 234, + + 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 265, 266, 267, 267, + 268, 243, 243, 243, 242, 243, 243, 243, + 244, 244, 244, 244, 244, 244, 244, 244, + + 244, 244, 244, 244, 244, 244, 244, 244, + 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 243, 243, 243, 243, + 243, 243, 244, 244, 244, 244, 244, 244, + + 244, 244, 244, 244, 244, 244, 244, 244, + 244, 244, 244, 244, 244, 244, 244, 244, + 244, 244, 244, 244, 244, 244, 244, 244, + 269, 269, 244, 244, 244, 244, 244, 269, + + 243, 244, 244, 243, 243, 243, 243, 243, + 243, 243, 243, 243, 244, 243, 244, 270, + 244, 244, 243, 243, 241, 243, 139, 139, + 139, 139, 139, 139, 139, 271, 272, 139, + + 139, 139, 139, 141, 139, 273, 273, 139, + 139, 49, 141, 139, 139, 141, 274, 274, + 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 269, 269, 269, 275, 275, 276, + + 277, 277, 277, 278, 278, 278, 278, 278, + 278, 278, 278, 278, 278, 278, 234, 279, + 270, 280, 269, 269, 269, 270, 270, 270, + 270, 270, 269, 269, 269, 269, 270, 269, + + 269, 269, 269, 269, 269, 269, 269, 269, + 270, 269, 270, 269, 270, 276, 276, 274, + 146, 147, 146, 146, 147, 146, 146, 147, + 147, 147, 146, 147, 147, 146, 147, 146, + + 146, 146, 147, 146, 147, 146, 147, 146, + 147, 146, 146, 234, 234, 274, 276, 276, + 281, 281, 281, 281, 281, 281, 281, 281, + 281, 282, 282, 282, 281, 281, 281, 281, + + 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 282, 282, 281, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, + + 283, 283, 283, 283, 283, 283, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, + 284, 285, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + + 286, 287, 288, 289, 290, 291, 292, 293, + 294, 295, 296, 296, 296, 296, 296, 296, + 296, 296, 296, 296, 296, 296, 296, 296, + 296, 296, 296, 296, 296, 296, 296, 296, + + 296, 296, 296, 296, 296, 296, 296, 296, + 296, 296, 296, 297, 297, 297, 297, 297, + 297, 297, 298, 297, 299, 299, 300, 301, + 302, 303, 304, 204, 204, 204, 204, 204, + + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + 204, 204, 204, 204, 204, 204, 204, 204, + + 160, 305, 305, 306, 307, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 160, 160, 308, 90, 306, 306, + + 306, 305, 305, 305, 305, 305, 305, 305, + 305, 306, 306, 306, 306, 309, 160, 160, + 90, 139, 141, 139, 139, 160, 160, 160, + 90, 90, 90, 90, 90, 90, 90, 90, + + 90, 90, 305, 305, 310, 310, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, + 198, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 321, 321, 322, 321, 321, + + 160, 305, 306, 306, 160, 90, 90, 90, + 90, 90, 90, 90, 90, 160, 160, 90, + 90, 160, 160, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 160, 90, 90, 90, 90, 90, 90, + 90, 160, 90, 160, 160, 160, 90, 90, + 90, 90, 160, 160, 308, 307, 323, 306, + + 306, 305, 305, 305, 305, 160, 160, 306, + 306, 160, 160, 306, 306, 309, 322, 160, + 160, 160, 160, 160, 160, 160, 160, 323, + 160, 160, 160, 160, 90, 90, 160, 90, + + 90, 90, 305, 305, 160, 160, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, + 90, 90, 12, 12, 324, 324, 324, 324, + 324, 324, 193, 160, 160, 160, 160, 160, + + 160, 325, 305, 326, 160, 90, 90, 90, + 90, 90, 90, 160, 160, 160, 160, 90, + 90, 160, 160, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 160, 90, 90, 90, 90, 90, 90, + 90, 160, 90, 90, 160, 90, 90, 160, + 90, 90, 160, 160, 308, 160, 306, 306, + + 306, 305, 305, 160, 160, 160, 160, 305, + 305, 160, 160, 305, 305, 309, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 90, 90, 90, 90, 160, 90, 160, + + 160, 160, 160, 160, 160, 160, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, + 305, 305, 90, 90, 90, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 305, 305, 306, 160, 90, 90, 90, + 90, 90, 90, 90, 307, 90, 160, 90, + 90, 90, 160, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 160, 90, 90, 90, 90, 90, 90, + 90, 160, 90, 90, 160, 90, 90, 90, + 90, 90, 160, 160, 308, 90, 306, 306, + + 306, 305, 305, 305, 305, 305, 160, 305, + 305, 306, 160, 306, 306, 309, 160, 160, + 90, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 90, 307, 325, 325, 160, 160, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, + 160, 327, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 160, 90, 90, 90, 90, 90, 90, + 90, 160, 90, 90, 160, 307, 90, 90, + 90, 90, 160, 160, 308, 90, 323, 305, + + 306, 305, 305, 305, 160, 160, 160, 306, + 306, 160, 160, 306, 306, 309, 160, 160, + 160, 160, 160, 160, 160, 160, 305, 323, + 160, 160, 160, 160, 90, 90, 160, 90, + + 90, 90, 160, 160, 160, 160, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, + 193, 307, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 160, 305, 90, 160, 90, 90, 90, + 90, 90, 90, 160, 160, 160, 90, 90, + 90, 160, 90, 90, 90, 90, 160, 160, + 160, 90, 90, 160, 90, 160, 90, 90, + + 160, 160, 160, 90, 90, 160, 160, 160, + 90, 90, 90, 160, 160, 160, 90, 90, + 90, 90, 90, 90, 90, 90, 322, 90, + 90, 90, 160, 160, 160, 160, 323, 306, + + 305, 306, 306, 160, 160, 160, 306, 306, + 306, 160, 306, 306, 306, 309, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 323, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 160, 160, 160, 160, 160, 328, 312, + 313, 314, 315, 316, 317, 318, 319, 320, + 324, 324, 324, 238, 238, 238, 238, 238, + 238, 327, 238, 160, 160, 160, 160, 160, + + 160, 306, 306, 306, 160, 90, 90, 90, + 90, 90, 90, 90, 90, 160, 90, 90, + 90, 160, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 160, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 160, 90, 90, 90, + 90, 90, 160, 160, 160, 160, 305, 305, + + 305, 306, 306, 306, 306, 160, 305, 305, + 305, 160, 305, 305, 305, 309, 160, 160, + 160, 160, 160, 160, 160, 329, 330, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 90, 90, 160, 160, 160, 160, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 160, 306, 306, 160, 90, 90, 90, + 90, 90, 90, 90, 90, 160, 90, 90, + 90, 160, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 160, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 160, 90, 90, 90, + 90, 90, 160, 160, 331, 307, 306, 332, + + 306, 306, 323, 306, 306, 160, 332, 306, + 306, 160, 306, 306, 305, 309, 160, 160, + 160, 160, 160, 160, 160, 323, 323, 160, + 160, 160, 160, 160, 160, 160, 90, 160, + + 90, 90, 333, 333, 160, 160, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, + 160, 300, 300, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 160, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 160, 160, 160, 160, 323, 306, + + 306, 305, 305, 305, 160, 160, 306, 306, + 306, 160, 306, 306, 306, 309, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 323, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 160, 334, 334, 160, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 160, + 160, 160, 335, 335, 335, 335, 335, 335, + + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 160, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 160, 335, 160, 160, + + 335, 335, 335, 335, 335, 335, 335, 160, + 160, 160, 336, 160, 160, 160, 160, 337, + 334, 334, 284, 284, 284, 160, 284, 160, + 334, 334, 334, 334, 334, 334, 334, 337, + + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 334, 334, 338, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 339, 339, 339, 339, 339, 339, 339, + 339, 339, 339, 339, 339, 339, 339, 339, + 339, 339, 339, 339, 339, 339, 339, 339, + 339, 339, 339, 339, 339, 339, 339, 339, + + 339, 339, 339, 339, 339, 339, 339, 339, + 339, 339, 339, 339, 339, 339, 339, 339, + 339, 340, 339, 339, 340, 340, 340, 340, + 341, 341, 342, 160, 160, 160, 160, 12, + + 339, 339, 339, 339, 339, 339, 343, 340, + 344, 344, 344, 344, 340, 340, 340, 198, + 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 345, 345, 160, 160, 160, 160, + + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 339, 339, 160, 339, 160, 160, 339, + 339, 160, 339, 160, 160, 339, 160, 160, + 160, 160, 160, 160, 339, 339, 339, 339, + 160, 339, 339, 339, 339, 339, 339, 339, + + 160, 339, 339, 339, 160, 339, 160, 339, + 160, 160, 339, 339, 160, 339, 339, 339, + 339, 340, 339, 339, 340, 340, 340, 340, + 346, 346, 160, 340, 340, 339, 160, 160, + + 339, 339, 339, 339, 339, 160, 343, 160, + 347, 347, 347, 347, 340, 340, 160, 160, + 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 160, 160, 339, 339, 160, 160, + + 348, 349, 349, 349, 350, 351, 350, 350, + 352, 350, 350, 353, 352, 354, 354, 354, + 354, 354, 352, 355, 356, 355, 355, 355, + 205, 205, 355, 355, 355, 355, 355, 355, + + 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 367, 367, 367, 367, 367, + 367, 367, 367, 367, 368, 205, 355, 205, + 355, 369, 370, 371, 370, 371, 372, 372, + + 348, 348, 348, 348, 348, 348, 348, 348, + 160, 348, 348, 348, 348, 348, 348, 348, + 348, 348, 348, 348, 348, 348, 348, 348, + 348, 348, 348, 348, 348, 348, 348, 348, + + 348, 348, 348, 348, 348, 348, 348, 348, + 348, 348, 335, 160, 160, 160, 160, 160, + 160, 373, 374, 375, 376, 375, 375, 375, + 375, 375, 374, 374, 374, 374, 375, 377, + + 374, 375, 206, 206, 378, 353, 206, 206, + 348, 348, 348, 348, 160, 160, 160, 160, + 375, 375, 375, 375, 375, 375, 284, 375, + 160, 375, 375, 375, 375, 375, 375, 375, + + 375, 375, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 375, 375, 284, 284, + 284, 375, 375, 375, 375, 375, 375, 375, + 284, 375, 284, 284, 284, 160, 379, 379, + + 380, 380, 380, 380, 380, 380, 147, 380, + 380, 380, 380, 380, 380, 160, 160, 380, + 381, 381, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 382, + + 382, 382, 160, 382, 382, 382, 382, 382, + 160, 382, 382, 160, 383, 384, 384, 384, + 384, 383, 384, 160, 160, 160, 384, 385, + 383, 386, 160, 160, 160, 160, 160, 160, + + 387, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 397, 338, 338, 338, 338, + 382, 382, 382, 382, 382, 382, 383, 383, + 384, 384, 160, 160, 160, 160, 160, 160, + + 398, 398, 398, 398, 398, 398, 398, 398, + 398, 398, 398, 398, 398, 398, 398, 398, + 398, 398, 398, 398, 398, 398, 398, 398, + 398, 398, 398, 398, 398, 398, 398, 398, + + 398, 398, 398, 398, 398, 398, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 399, + 399, 322, 322, 198, 400, 160, 160, 160, + + 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, + + 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 160, 160, 160, 160, 160, 401, + + 402, 402, 402, 402, 402, 402, 402, 402, + 402, 402, 402, 402, 402, 402, 402, 402, + 402, 402, 402, 402, 402, 402, 402, 402, + 402, 402, 402, 402, 402, 402, 402, 402, + + 402, 402, 402, 160, 160, 160, 160, 160, + 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, + + 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, + + 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 160, 160, 160, 160, 160, 160, + + 335, 335, 335, 335, 335, 335, 335, 322, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + + 335, 335, 335, 335, 335, 335, 335, 322, + 335, 160, 335, 335, 335, 335, 160, 160, + 335, 335, 335, 335, 335, 335, 335, 160, + 335, 160, 335, 335, 335, 335, 160, 160, + + 335, 335, 335, 335, 335, 335, 335, 322, + 335, 160, 335, 335, 335, 335, 160, 160, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 322, + 335, 160, 335, 335, 335, 335, 160, 160, + 335, 335, 335, 335, 335, 335, 335, 160, + + 335, 160, 335, 335, 335, 335, 160, 160, + 335, 335, 335, 335, 335, 335, 335, 322, + 335, 335, 335, 335, 335, 335, 335, 160, + 335, 335, 335, 335, 335, 335, 335, 335, + + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 322, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 322, + 335, 160, 335, 335, 335, 335, 160, 160, + 335, 335, 335, 335, 335, 335, 335, 322, + + 335, 335, 335, 335, 335, 335, 335, 322, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 160, 160, 160, 160, 153, + + 404, 405, 406, 338, 338, 338, 338, 406, + 406, 407, 408, 409, 410, 411, 412, 413, + 414, 415, 416, 416, 416, 416, 416, 416, + 416, 416, 416, 416, 416, 160, 160, 160, + + 322, 322, 322, 322, 322, 322, 322, 322, + 322, 322, 322, 322, 322, 322, 322, 322, + 417, 417, 417, 417, 417, 417, 417, 417, + 417, 417, 160, 160, 160, 160, 160, 160, + + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 338, 406, 335, + 335, 335, 335, 335, 335, 335, 335, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 418, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 419, 420, 160, 160, 160, + + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 405, 405, 405, 421, 421, + 421, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 399, 399, 399, 399, 399, 399, 399, 399, + 399, 399, 399, 399, 399, 160, 399, 399, + 399, 399, 422, 422, 423, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 399, 399, 399, 399, 399, 399, 399, 399, + 399, 399, 399, 399, 399, 399, 399, 399, + 399, 399, 422, 422, 423, 424, 424, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 399, 399, 399, 399, 399, 399, 399, 399, + 399, 399, 399, 399, 399, 399, 399, 399, + 399, 399, 422, 422, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 399, 399, 399, 399, 399, 399, 399, 399, + 399, 399, 399, 399, 399, 160, 399, 399, + 399, 160, 422, 422, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, 382, 382, 425, 425, 383, 384, + 384, 384, 384, 384, 384, 384, 383, 383, + + 383, 383, 383, 383, 383, 383, 384, 383, + 383, 384, 384, 384, 384, 384, 384, 384, + 384, 384, 386, 384, 405, 405, 426, 427, + 405, 338, 405, 428, 382, 429, 160, 160, + + 387, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 160, 160, 160, 160, 160, 160, + 430, 430, 430, 430, 430, 430, 430, 430, + 430, 430, 160, 160, 160, 160, 160, 160, + + 431, 431, 432, 433, 432, 432, 434, 431, + 432, 433, 431, 284, 284, 284, 435, 160, + 387, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 160, 160, 160, 160, 160, 160, + + 335, 335, 335, 137, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 335, 335, + 160, 160, 160, 160, 160, 160, 160, 160, + + 335, 335, 335, 335, 335, 335, 335, 335, + 335, 436, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 160, 160, 160, + + 325, 325, 325, 326, 326, 326, 326, 325, + 325, 437, 437, 437, 160, 160, 160, 160, + 326, 326, 325, 326, 326, 326, 326, 326, + 326, 438, 149, 150, 160, 160, 160, 160, + + 238, 160, 160, 160, 439, 439, 440, 441, + 442, 443, 444, 445, 446, 447, 448, 449, + 450, 450, 450, 450, 450, 450, 450, 450, + 450, 450, 450, 450, 450, 450, 450, 450, + + 450, 450, 450, 450, 450, 450, 450, 450, + 450, 450, 450, 450, 450, 450, 160, 160, + 450, 450, 450, 450, 450, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 451, 451, 451, 451, 451, 451, 451, 451, + 451, 451, 451, 451, 451, 451, 451, 451, + 451, 451, 451, 451, 451, 451, 451, 451, + 451, 451, 451, 451, 451, 451, 451, 451, + + 451, 451, 451, 451, 451, 451, 451, 451, + 451, 451, 160, 160, 160, 160, 160, 160, + 452, 452, 452, 452, 452, 452, 452, 452, + 452, 452, 452, 452, 452, 452, 452, 452, + + 452, 451, 451, 451, 451, 451, 451, 451, + 452, 452, 160, 160, 160, 160, 160, 160, + 328, 453, 454, 455, 456, 457, 458, 459, + 460, 461, 160, 160, 160, 160, 462, 462, + + 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, + + 322, 322, 322, 322, 322, 322, 322, 322, + 322, 322, 322, 322, 322, 322, 322, 322, + 322, 322, 322, 322, 322, 322, 322, 153, + 152, 463, 463, 463, 160, 160, 464, 465, + + 333, 333, 333, 333, 466, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 467, 466, 333, 333, + 333, 333, 333, 466, 333, 466, 466, 466, + + 466, 466, 333, 466, 468, 321, 321, 321, + 321, 321, 321, 321, 160, 160, 160, 160, + 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 479, 480, 480, 479, 479, + + 480, 481, 481, 481, 481, 481, 481, 481, + 481, 481, 481, 297, 298, 297, 297, 297, + 297, 297, 297, 297, 481, 481, 481, 481, + 481, 481, 481, 481, 481, 160, 160, 160, + + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, + + 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 482, 482, 482, 482, + 482, 482, 482, 482, 482, 482, 482, 482, + 482, 482, 482, 482, 482, 482, 482, 482, + + 482, 482, 482, 482, 482, 482, 482, 482, + 482, 482, 482, 482, 482, 482, 482, 482, + 482, 482, 482, 482, 482, 482, 482, 482, + 482, 482, 482, 482, 482, 482, 482, 482, + + 482, 482, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 103, 103, 103, 103, + 103, 103, 103, 103, 103, 103, 103, 103, + 483, 103, 103, 103, 103, 484, 103, 103, + + 103, 103, 103, 103, 103, 103, 103, 103, + 103, 103, 103, 103, 103, 103, 103, 103, + 103, 103, 103, 103, 103, 103, 103, 103, + 103, 103, 103, 483, 483, 483, 483, 483, + + 483, 483, 483, 483, 483, 483, 483, 483, + 483, 483, 483, 483, 483, 483, 483, 483, + 483, 483, 483, 483, 483, 483, 483, 483, + 483, 483, 483, 483, 483, 483, 483, 483, + + 153, 153, 152, 153, 297, 297, 297, 297, + 297, 297, 298, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 297, 298, + + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 485, 486, + 487, 488, 489, 490, 160, 160, 160, 160, + + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 65, 66, 65, 66, 65, 66, + 65, 66, 160, 160, 160, 160, 160, 160, + + 491, 491, 491, 491, 491, 491, 491, 491, + 492, 492, 492, 492, 492, 492, 492, 492, + 491, 491, 491, 491, 491, 491, 160, 160, + 492, 492, 492, 492, 492, 492, 160, 160, + + 491, 491, 491, 491, 491, 491, 491, 491, + 492, 492, 492, 492, 492, 492, 492, 492, + 491, 491, 491, 491, 491, 491, 491, 491, + 492, 492, 492, 492, 492, 492, 492, 492, + + 491, 491, 491, 491, 491, 491, 160, 160, + 492, 492, 492, 492, 492, 492, 160, 160, + 493, 491, 494, 491, 495, 491, 496, 491, + 160, 492, 160, 492, 160, 492, 160, 492, + + 491, 491, 491, 491, 491, 491, 491, 491, + 492, 492, 492, 492, 492, 492, 492, 492, + 497, 497, 498, 498, 498, 498, 499, 499, + 500, 500, 501, 501, 502, 502, 160, 160, + + 503, 504, 505, 506, 507, 508, 509, 510, + 511, 512, 513, 514, 515, 516, 517, 518, + 519, 520, 521, 522, 523, 524, 525, 526, + 527, 528, 529, 530, 531, 532, 533, 534, + + 535, 536, 537, 538, 539, 540, 541, 542, + 543, 544, 545, 546, 547, 548, 549, 550, + 491, 491, 551, 552, 553, 160, 554, 555, + 492, 492, 556, 556, 557, 42, 558, 42, + + 42, 42, 559, 560, 561, 160, 562, 563, + 564, 564, 564, 564, 565, 42, 42, 42, + 491, 491, 566, 567, 160, 160, 568, 569, + 492, 492, 570, 570, 160, 42, 42, 42, + + 491, 491, 571, 572, 573, 182, 574, 575, + 492, 492, 576, 576, 577, 42, 42, 42, + 160, 160, 578, 579, 580, 160, 581, 582, + 583, 583, 584, 584, 585, 42, 42, 160, + + 586, 586, 586, 586, 586, 586, 586, 587, + 586, 586, 586, 588, 589, 590, 591, 592, + 593, 594, 593, 593, 595, 596, 14, 14, + 597, 598, 599, 600, 597, 601, 599, 600, + + 14, 14, 14, 14, 602, 602, 602, 603, + 604, 605, 606, 607, 608, 609, 610, 611, + 13, 13, 13, 13, 13, 612, 612, 612, + 14, 597, 601, 14, 613, 613, 14, 43, + + 43, 14, 14, 14, 614, 16, 17, 615, + 616, 616, 431, 431, 431, 431, 617, 617, + 617, 617, 185, 618, 619, 620, 621, 617, + 621, 621, 621, 621, 620, 621, 621, 622, + + 623, 624, 624, 624, 160, 160, 160, 160, + 160, 160, 625, 625, 625, 625, 625, 625, + 626, 627, 160, 160, 628, 629, 630, 631, + 632, 633, 634, 634, 36, 16, 17, 50, + + 626, 60, 55, 56, 628, 629, 630, 631, + 632, 633, 634, 634, 36, 16, 17, 160, + 483, 483, 483, 483, 483, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 12, 12, 12, 12, 12, 12, 12, 48, + 12, 12, 12, 635, 636, 428, 428, 428, + 637, 637, 638, 638, 638, 638, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 139, 139, 144, 144, 139, 139, 139, 139, + 144, 144, 144, 139, 139, 272, 272, 272, + + 272, 139, 194, 194, 639, 640, 640, 159, + 641, 159, 640, 642, 298, 298, 298, 298, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 49, 49, 175, 643, 49, 49, 49, 175, + 49, 643, 50, 175, 175, 175, 50, 50, + 175, 175, 175, 50, 49, 175, 644, 49, + 49, 175, 175, 175, 175, 175, 49, 49, + + 49, 49, 49, 49, 175, 49, 645, 49, + 175, 49, 646, 647, 175, 175, 648, 50, + 175, 175, 649, 175, 50, 90, 90, 90, + 90, 131, 650, 238, 103, 627, 651, 651, + + 185, 185, 185, 185, 185, 651, 627, 627, + 627, 627, 652, 185, 417, 300, 653, 160, + 160, 160, 160, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, + + 654, 654, 654, 654, 654, 654, 654, 654, + 654, 654, 654, 654, 654, 654, 654, 654, + 655, 655, 655, 655, 655, 655, 655, 655, + 655, 655, 655, 655, 655, 655, 655, 655, + + 656, 656, 656, 99, 109, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 36, 36, 36, 36, 36, 49, 49, 49, + 49, 49, 36, 36, 49, 49, 49, 49, + + 36, 49, 49, 36, 49, 49, 36, 49, + 49, 49, 49, 49, 49, 49, 36, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 36, 36, + 49, 49, 36, 49, 36, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 650, 650, 650, 650, 650, + 650, 650, 650, 650, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, + + 36, 36, 36, 36, 36, 36, 36, 36, + 657, 657, 657, 658, 658, 658, 36, 36, + 36, 36, 18, 54, 36, 659, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 660, 661, 36, 36, + + 36, 36, 36, 662, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 660, 661, 660, 661, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, + + 36, 36, 36, 36, 660, 661, 660, 661, + 660, 661, 660, 661, 36, 36, 660, 661, + 660, 661, 660, 661, 660, 661, 660, 661, + 660, 661, 660, 661, 660, 661, 660, 661, + + 660, 661, 660, 661, 660, 661, 660, 661, + 660, 661, 660, 661, 36, 36, 36, 660, + 661, 660, 661, 36, 36, 36, 36, 36, + 663, 36, 36, 36, 36, 36, 36, 36, + + 36, 36, 660, 661, 36, 36, 664, 36, + 665, 666, 36, 666, 36, 36, 36, 36, + 660, 661, 660, 661, 660, 661, 660, 661, + 36, 36, 36, 36, 36, 36, 36, 36, + + 36, 36, 36, 36, 36, 36, 36, 36, + 36, 660, 661, 660, 661, 667, 36, 36, + 660, 661, 36, 36, 36, 36, 660, 661, + 660, 661, 660, 661, 660, 661, 660, 661, + + 660, 661, 660, 661, 660, 661, 660, 661, + 660, 661, 660, 661, 660, 661, 36, 36, + 660, 661, 668, 668, 668, 185, 669, 669, + 185, 185, 670, 670, 670, 671, 671, 185, + + 49, 650, 49, 49, 49, 49, 49, 49, + 660, 661, 660, 661, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + + 36, 36, 49, 49, 49, 49, 49, 49, + 49, 16, 17, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, + + 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, + + 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 650, 185, 650, 650, 650, + + 650, 650, 650, 650, 650, 650, 650, 650, + 650, 650, 650, 650, 650, 650, 650, 650, + 650, 650, 650, 650, 650, 380, 650, 650, + 650, 650, 650, 185, 185, 185, 185, 185, + + 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 652, 652, 652, 652, + 652, 652, 652, 652, 652, 652, 652, 652, + + 652, 652, 652, 652, 652, 652, 652, 652, + 652, 652, 652, 652, 652, 652, 652, 238, + 238, 417, 417, 417, 417, 417, 417, 417, + 417, 417, 417, 417, 672, 672, 672, 672, + + 672, 672, 300, 300, 300, 300, 300, 300, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + + 49, 49, 49, 49, 49, 650, 650, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 673, 674, 675, 676, 677, 678, 679, 680, + 681, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 673, 674, 675, 676, + 677, 678, 679, 680, 681, 62, 62, 62, + + 62, 62, 62, 62, 62, 62, 62, 62, + 60, 55, 56, 628, 629, 630, 631, 632, + 633, 682, 682, 682, 682, 682, 682, 682, + 682, 682, 682, 682, 193, 193, 193, 193, + + 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 683, 683, + 683, 683, 683, 683, 683, 683, 683, 683, + + 683, 683, 683, 683, 683, 683, 683, 683, + 683, 683, 683, 683, 683, 683, 683, 683, + 684, 684, 684, 684, 684, 684, 684, 684, + 684, 684, 684, 684, 684, 684, 684, 684, + + 684, 684, 684, 684, 684, 684, 684, 684, + 684, 684, 685, 686, 686, 686, 686, 686, + 686, 686, 686, 686, 686, 687, 688, 689, + 690, 691, 692, 693, 694, 695, 686, 696, + + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 652, 652, + 652, 652, 652, 652, 652, 652, 652, 652, + + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 36, + 49, 49, 49, 49, 49, 49, 49, 49, + + 49, 36, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 650, 650, 650, 650, 650, 650, 650, 650, + 185, 185, 185, 185, 185, 185, 185, 185, + + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 238, 238, 652, 652, + 417, 650, 49, 49, 49, 49, 49, 49, + + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 36, + 650, 650, 652, 652, 652, 652, 652, 652, + 652, 652, 652, 652, 652, 652, 417, 417, + + 652, 652, 652, 652, 652, 652, 652, 652, + 652, 652, 238, 238, 238, 238, 238, 238, + 238, 238, 417, 417, 417, 417, 417, 417, + 417, 417, 417, 417, 417, 160, 160, 160, + + 238, 238, 417, 417, 417, 417, 417, 417, + 417, 417, 417, 417, 404, 417, 417, 417, + 417, 417, 300, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 49, 49, 49, 49, 160, 49, 49, + 49, 49, 160, 160, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + + 49, 49, 49, 49, 49, 49, 49, 49, + 160, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 160, 49, 160, 49, + 49, 49, 49, 160, 160, 160, 49, 160, + 49, 49, 49, 697, 697, 697, 697, 160, + + 160, 49, 698, 698, 49, 49, 49, 49, + 699, 700, 699, 700, 699, 700, 699, 700, + 699, 700, 699, 700, 699, 700, 673, 674, + 675, 676, 677, 678, 679, 680, 681, 62, + + 673, 674, 675, 676, 677, 678, 679, 680, + 681, 62, 673, 674, 675, 676, 677, 678, + 679, 680, 681, 62, 49, 160, 160, 160, + 49, 49, 49, 49, 49, 49, 49, 49, + + 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, + 160, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 160, + + 701, 701, 701, 702, 703, 704, 705, 672, + 672, 672, 672, 160, 160, 160, 160, 160, + 185, 185, 185, 185, 185, 706, 707, 185, + 185, 185, 185, 185, 185, 706, 707, 185, + + 185, 185, 706, 707, 706, 707, 699, 700, + 699, 700, 699, 700, 160, 160, 160, 160, + 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, + + 380, 380, 380, 380, 380, 380, 380, 380, + 380, 380, 380, 380, 380, 380, 380, 380, + 380, 380, 380, 380, 380, 380, 380, 380, + 380, 380, 380, 380, 380, 380, 380, 380, + + 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, + + 185, 185, 185, 699, 700, 699, 700, 699, + 700, 699, 700, 699, 700, 708, 709, 710, + 711, 699, 700, 699, 700, 699, 700, 699, + 700, 185, 185, 185, 185, 185, 185, 185, + + 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, + 712, 185, 185, 185, 185, 185, 185, 185, + + 706, 707, 185, 185, 706, 707, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 706, + 707, 706, 707, 185, 706, 707, 185, 185, + 699, 700, 699, 700, 185, 185, 185, 185, + + 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 713, 185, 185, + 706, 707, 185, 185, 699, 700, 185, 185, + + 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 706, 707, 706, 707, 185, + 185, 185, 185, 185, 706, 707, 185, 185, + 185, 185, 185, 185, 706, 707, 185, 185, + + 185, 185, 185, 185, 706, 707, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 185, + 185, 706, 707, 185, 185, 706, 707, 706, + + 707, 706, 707, 706, 707, 185, 185, 185, + 185, 185, 185, 706, 707, 185, 185, 185, + 185, 706, 707, 706, 707, 706, 707, 706, + 707, 706, 707, 706, 707, 185, 185, 185, + + 185, 706, 707, 185, 185, 185, 706, 707, + 706, 707, 706, 707, 706, 707, 185, 706, + 707, 185, 185, 706, 707, 185, 185, 185, + 185, 185, 185, 706, 707, 706, 707, 706, + + 707, 706, 707, 706, 707, 706, 707, 185, + 185, 185, 185, 185, 185, 706, 707, 706, + 707, 706, 707, 706, 707, 706, 707, 185, + 185, 185, 185, 185, 185, 185, 714, 185, + + 185, 185, 185, 715, 716, 715, 185, 185, + 185, 185, 185, 185, 706, 707, 185, 185, + 185, 185, 185, 185, 185, 185, 185, 706, + 707, 706, 707, 185, 185, 185, 185, 185, + + 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 417, 417, + 417, 417, 417, 417, 300, 300, 300, 300, + 300, 300, 300, 160, 160, 160, 160, 160, + + 300, 300, 300, 300, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 717, 717, 717, 717, 717, 717, 717, 717, + 717, 717, 717, 717, 717, 717, 717, 717, + 717, 717, 717, 717, 717, 717, 717, 717, + 717, 717, 717, 717, 717, 717, 717, 717, + + 717, 717, 717, 717, 717, 717, 717, 717, + 717, 717, 717, 717, 717, 717, 717, 160, + 718, 718, 718, 718, 718, 718, 718, 718, + 718, 718, 718, 718, 718, 718, 718, 718, + + 718, 718, 718, 718, 718, 718, 718, 718, + 718, 718, 718, 718, 718, 718, 718, 718, + 718, 718, 718, 718, 718, 718, 718, 718, + 718, 718, 718, 718, 718, 718, 718, 160, + + 113, 109, 719, 720, 721, 722, 723, 113, + 109, 113, 109, 113, 109, 160, 160, 160, + 160, 160, 160, 160, 724, 113, 109, 724, + 160, 160, 160, 160, 160, 160, 160, 160, + + 105, 106, 105, 106, 105, 106, 105, 106, + 105, 106, 105, 106, 105, 106, 105, 106, + 105, 106, 105, 106, 105, 106, 105, 106, + 105, 106, 105, 106, 105, 106, 105, 106, + + 105, 106, 105, 106, 103, 417, 417, 417, + 417, 417, 417, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 621, 621, 621, 621, 725, 621, 621, + + 726, 726, 726, 726, 726, 726, 726, 726, + 726, 726, 726, 726, 726, 726, 726, 726, + 726, 726, 726, 726, 726, 726, 726, 726, + 726, 726, 726, 726, 726, 726, 726, 726, + + 726, 726, 726, 726, 726, 726, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 322, 322, 322, 322, 322, 322, 322, 322, + 322, 322, 322, 322, 322, 322, 322, 322, + + 322, 322, 322, 322, 322, 322, 322, 322, + 322, 322, 322, 322, 322, 322, 322, 322, + 322, 322, 322, 322, 322, 322, 322, 322, + 322, 322, 322, 322, 322, 322, 322, 322, + + 322, 322, 322, 322, 322, 322, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 400, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 322, 322, 322, 322, 322, 322, 322, 322, + 322, 322, 322, 322, 322, 322, 322, 322, + 322, 322, 322, 322, 322, 322, 322, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 322, 322, 322, 322, 322, 322, 322, 160, + 322, 322, 322, 322, 322, 322, 322, 160, + 322, 322, 322, 322, 322, 322, 322, 160, + 322, 322, 322, 322, 322, 322, 322, 160, + + 727, 727, 728, 729, 728, 729, 727, 727, + 727, 728, 729, 727, 728, 729, 621, 621, + 621, 621, 621, 621, 621, 621, 620, 730, + 160, 160, 160, 160, 728, 729, 160, 160, + + 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 160, 731, 731, 731, 731, 731, + + 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 731, 731, 731, 731, 731, 731, + + 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 731, 731, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 731, 731, 731, 731, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 731, 731, 160, 160, 160, 160, + + 732, 733, 734, 735, 736, 737, 738, 739, + 16, 17, 16, 17, 16, 17, 16, 17, + 16, 17, 736, 736, 16, 17, 16, 17, + 16, 17, 16, 17, 740, 16, 17, 741, + + 736, 739, 739, 739, 739, 739, 739, 739, + 739, 739, 742, 743, 140, 744, 745, 745, + 746, 747, 747, 747, 747, 747, 736, 736, + 748, 748, 748, 749, 750, 751, 731, 736, + + 160, 752, 738, 752, 738, 752, 738, 752, + 738, 752, 738, 738, 738, 738, 738, 738, + 738, 738, 738, 738, 738, 738, 738, 738, + 738, 738, 738, 738, 738, 738, 738, 738, + + 738, 738, 738, 752, 738, 738, 738, 738, + 738, 738, 738, 738, 738, 738, 738, 738, + 738, 738, 738, 738, 738, 738, 738, 738, + 738, 738, 738, 738, 738, 738, 738, 738, + + 738, 738, 738, 752, 738, 752, 738, 752, + 738, 738, 738, 738, 738, 738, 752, 738, + 738, 738, 738, 738, 738, 753, 753, 160, + 160, 754, 754, 755, 755, 756, 756, 757, + + 758, 759, 760, 759, 760, 759, 760, 759, + 760, 759, 760, 760, 760, 760, 760, 760, + 760, 760, 760, 760, 760, 760, 760, 760, + 760, 760, 760, 760, 760, 760, 760, 760, + + 760, 760, 760, 759, 760, 760, 760, 760, + 760, 760, 760, 760, 760, 760, 760, 760, + 760, 760, 760, 760, 760, 760, 760, 760, + 760, 760, 760, 760, 760, 760, 760, 760, + + 760, 760, 760, 759, 760, 759, 760, 759, + 760, 760, 760, 760, 760, 760, 759, 760, + 760, 760, 760, 760, 760, 759, 759, 760, + 760, 760, 760, 761, 762, 762, 762, 763, + + 160, 160, 160, 160, 160, 764, 764, 764, + 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 764, 764, 764, + + 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 160, 160, 160, + 160, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 764, 764, 764, + + 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 764, 764, 764, + + 764, 764, 764, 764, 764, 764, 764, 764, + 764, 764, 764, 764, 764, 764, 764, 160, + 765, 765, 766, 766, 766, 766, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + + 767, 767, 767, 767, 767, 767, 767, 767, + 767, 767, 767, 767, 767, 767, 767, 767, + 767, 767, 767, 767, 767, 767, 767, 767, + 160, 160, 160, 160, 160, 160, 160, 160, + + 768, 768, 768, 768, 768, 768, 768, 768, + 768, 768, 768, 768, 768, 768, 768, 768, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 769, 769, 769, 769, 769, 769, 769, 769, + 769, 769, 769, 769, 769, 769, 769, 769, + + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 770, 770, 160, + + 766, 766, 766, 766, 766, 766, 766, 766, + 766, 766, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + + 765, 765, 765, 765, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 770, 771, 771, 771, 771, 771, 771, 771, + 771, 771, 771, 771, 771, 771, 771, 771, + + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 770, 770, 768, 765, + + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 771, 771, 771, 771, 771, 771, 771, + 771, 771, 771, 771, 771, 771, 771, 771, + + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 770, 770, 770, 770, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 160, + + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 770, + 770, 770, 770, 765, 765, 765, 765, 765, + + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 770, 770, + + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 765, + 765, 765, 765, 765, 765, 765, 765, 770, + + 772, 772, 772, 772, 772, 772, 772, 772, + 772, 772, 772, 772, 772, 772, 772, 772, + 772, 772, 772, 772, 772, 772, 772, 772, + 772, 772, 772, 772, 772, 772, 772, 772, + + 772, 772, 772, 772, 772, 772, 772, 772, + 772, 772, 772, 772, 772, 772, 772, 772, + 772, 772, 772, 772, 772, 772, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 738, 738, 738, 738, 738, 738, 738, 738, + 738, 738, 738, 738, 738, 738, 738, 738, + 738, 738, 738, 738, 738, 738, 738, 738, + 738, 738, 738, 738, 738, 738, 738, 738, + + 738, 738, 738, 738, 738, 738, 773, 773, + 773, 773, 773, 773, 773, 773, 773, 773, + 773, 773, 773, 773, 773, 773, 773, 773, + 773, 773, 773, 773, 160, 160, 160, 160, + + 767, 767, 767, 767, 767, 767, 767, 767, + 767, 767, 767, 767, 767, 767, 767, 767, + 767, 767, 767, 767, 767, 774, 767, 767, + 767, 767, 767, 767, 767, 767, 767, 767, + + 767, 767, 767, 767, 767, 767, 767, 767, + 767, 767, 767, 767, 767, 767, 767, 767, + 767, 767, 767, 767, 767, 767, 767, 767, + 767, 767, 767, 767, 767, 767, 767, 767, + + 767, 767, 767, 767, 767, 767, 767, 767, + 767, 767, 767, 767, 767, 160, 160, 160, + 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 731, 731, 731, 731, 731, 731, + + 731, 731, 775, 775, 731, 731, 731, 731, + 731, 731, 731, 731, 731, 731, 731, 731, + 731, 731, 731, 731, 775, 731, 731, 731, + 731, 731, 731, 731, 731, 731, 731, 731, + + 731, 775, 731, 731, 731, 775, 731, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 776, + 776, 776, 776, 776, 776, 776, 776, 777, + 777, 777, 777, 160, 160, 160, 160, 160, + + 778, 778, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 322, 322, 779, 322, 322, 322, 780, 322, + 322, 322, 322, 781, 322, 322, 322, 322, + 322, 322, 322, 322, 322, 322, 322, 322, + 322, 322, 322, 322, 322, 322, 322, 322, + + 322, 322, 322, 463, 463, 781, 781, 463, + 417, 417, 417, 417, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 782, 782, 303, 303, + 160, 160, 160, 160, 160, 160, 160, 160, + + 783, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 783, 784, 784, 784, + + 784, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + 783, 784, 784, 784, 784, 784, 784, 784, + + 784, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 783, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + + 784, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + 783, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + + 784, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 783, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + + 784, 784, 784, 784, 784, 784, 784, 784, + 783, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + + 784, 784, 784, 784, 783, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + 784, 784, 784, 784, 784, 784, 784, 784, + + 784, 784, 784, 784, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 785, 785, 785, 785, 785, 785, 785, 785, + 785, 785, 785, 785, 785, 785, 785, 785, + 785, 785, 785, 785, 785, 785, 785, 785, + 785, 785, 785, 785, 785, 785, 785, 785, + + 786, 786, 786, 786, 786, 786, 786, 786, + 786, 786, 786, 786, 786, 786, 786, 786, + 786, 786, 786, 786, 786, 786, 786, 786, + 786, 786, 786, 786, 786, 786, 786, 786, + + 738, 738, 738, 738, 738, 738, 738, 738, + 738, 738, 738, 738, 738, 738, 160, 160, + 787, 787, 787, 787, 787, 787, 787, 787, + 787, 787, 787, 787, 787, 787, 787, 787, + + 787, 787, 787, 787, 787, 787, 787, 787, + 787, 787, 787, 787, 787, 787, 787, 787, + 787, 787, 787, 787, 787, 787, 787, 787, + 787, 787, 787, 787, 787, 787, 787, 787, + + 787, 787, 787, 787, 787, 787, 787, 787, + 787, 787, 787, 160, 160, 160, 160, 160, + 773, 773, 773, 773, 773, 773, 773, 773, + 773, 773, 773, 773, 773, 773, 773, 773, + + 773, 773, 773, 773, 773, 773, 773, 773, + 773, 773, 773, 773, 773, 773, 773, 773, + 773, 773, 773, 773, 773, 773, 773, 773, + 773, 773, 773, 773, 773, 773, 773, 773, + + 773, 773, 773, 773, 773, 773, 773, 773, + 773, 773, 773, 773, 773, 773, 773, 773, + 773, 773, 773, 773, 773, 773, 773, 773, + 773, 773, 160, 160, 160, 160, 160, 160, + + 788, 789, 790, 791, 792, 793, 794, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 795, 796, 797, 798, 799, + 160, 160, 160, 160, 160, 800, 801, 230, + + 230, 230, 230, 230, 230, 230, 230, 230, + 230, 634, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 204, + 230, 230, 230, 230, 230, 204, 230, 204, + + 230, 230, 204, 230, 230, 204, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 599, 741, + + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 234, 234, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + + 242, 242, 242, 242, 242, 242, 242, 242, + 234, 234, 234, 234, 234, 234, 234, 234, + 802, 802, 802, 802, 802, 802, 802, 802, + 802, 802, 802, 802, 802, 802, 802, 802, + + 802, 802, 802, 802, 802, 802, 802, 802, + 802, 802, 802, 802, 802, 802, 802, 802, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 803, 238, 234, 234, + + 422, 422, 422, 422, 422, 422, 422, 422, + 422, 422, 422, 422, 422, 422, 422, 422, + 804, 805, 805, 804, 804, 806, 806, 807, + 808, 809, 160, 160, 160, 160, 160, 160, + + 139, 139, 139, 139, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 735, 746, 746, 810, 810, 599, 741, 599, + 741, 599, 741, 599, 741, 599, 741, 599, + + 741, 599, 741, 599, 741, 751, 751, 811, + 812, 735, 735, 735, 735, 810, 810, 810, + 813, 735, 814, 160, 761, 815, 9, 9, + 746, 16, 17, 16, 17, 16, 17, 816, + + 735, 735, 817, 818, 819, 820, 821, 160, + 735, 12, 13, 735, 160, 160, 160, 160, + 242, 242, 242, 285, 242, 234, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 234, 234, 822, + + 160, 9, 735, 816, 12, 13, 735, 735, + 16, 17, 735, 817, 813, 818, 814, 823, + 824, 825, 826, 827, 828, 829, 830, 831, + 832, 833, 815, 761, 834, 821, 835, 9, + + 735, 836, 836, 836, 836, 836, 836, 836, + 836, 836, 836, 836, 836, 836, 836, 836, + 836, 836, 836, 836, 836, 836, 836, 836, + 836, 836, 836, 39, 735, 41, 837, 810, + + 837, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 39, 821, 41, 821, 699, + + 700, 734, 16, 17, 733, 761, 839, 759, + 759, 759, 759, 759, 759, 759, 759, 759, + 762, 839, 839, 839, 839, 839, 839, 839, + 839, 839, 839, 839, 839, 839, 839, 839, + + 839, 839, 839, 839, 839, 839, 839, 839, + 839, 839, 839, 839, 839, 839, 839, 839, + 839, 839, 839, 839, 839, 839, 839, 839, + 839, 839, 839, 839, 839, 839, 762, 762, + + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 160, + + 160, 160, 90, 90, 90, 90, 90, 90, + 160, 160, 90, 90, 90, 90, 90, 90, + 160, 160, 90, 90, 90, 90, 90, 90, + 160, 160, 90, 90, 90, 160, 160, 160, + + 48, 12, 821, 837, 736, 12, 12, 160, + 49, 36, 36, 36, 36, 49, 49, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 840, 840, 840, 841, 49, 842, 842, + + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 160, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + + 307, 307, 307, 307, 307, 307, 307, 160, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 160, 307, 307, 160, 307, + + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 160, 160, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 160, 160, + + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 160, 160, 160, 160, 160, + + 843, 844, 845, 160, 160, 160, 160, 846, + 846, 846, 846, 846, 846, 846, 846, 846, + 846, 846, 846, 846, 846, 846, 846, 846, + 846, 846, 846, 846, 846, 846, 846, 846, + + 846, 846, 846, 846, 846, 846, 846, 846, + 846, 846, 846, 846, 846, 846, 846, 846, + 846, 846, 846, 846, 160, 160, 160, 847, + 847, 847, 847, 847, 847, 847, 847, 847, + + 848, 848, 848, 848, 848, 848, 848, 848, + 848, 848, 848, 848, 848, 848, 848, 848, + 848, 848, 848, 848, 848, 848, 848, 848, + 848, 848, 848, 848, 848, 848, 848, 848, + + 848, 848, 848, 848, 848, 848, 848, 848, + 848, 848, 848, 848, 848, 848, 848, 848, + 848, 848, 848, 848, 848, 725, 725, 725, + 725, 417, 417, 417, 417, 417, 417, 417, + + 417, 417, 417, 417, 417, 417, 417, 417, + 417, 417, 725, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 849, 849, 849, 849, 849, 849, 849, 849, + 849, 849, 849, 849, 849, 849, 849, 849, + 849, 849, 849, 849, 849, 849, 849, 849, + 849, 849, 849, 849, 849, 849, 849, 160, + + 850, 850, 850, 850, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 849, 849, 849, 849, 849, 849, 849, 849, + 849, 849, 849, 849, 849, 849, 849, 849, + + 849, 851, 849, 849, 849, 849, 849, 849, + 849, 849, 851, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 160, 843, + + 322, 322, 322, 322, 160, 160, 160, 160, + 322, 322, 322, 322, 322, 322, 322, 322, + 464, 852, 852, 852, 852, 852, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 853, 853, 853, 853, 853, 853, 853, 853, + 853, 853, 853, 853, 853, 853, 853, 853, + 853, 853, 853, 853, 853, 853, 853, 853, + 853, 853, 853, 853, 853, 853, 853, 853, + + 853, 853, 853, 853, 853, 853, 854, 854, + 855, 855, 855, 855, 855, 855, 855, 855, + 855, 855, 855, 855, 855, 855, 855, 855, + 855, 855, 855, 855, 855, 855, 855, 855, + + 855, 855, 855, 855, 855, 855, 855, 855, + 855, 855, 855, 855, 855, 855, 856, 856, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 307, 307, + 307, 307, 307, 307, 307, 307, 160, 160, + + 440, 441, 442, 443, 444, 445, 446, 447, + 448, 449, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 857, 857, 857, 857, 857, 857, 204, 204, + 857, 204, 857, 857, 857, 857, 857, 857, + 857, 857, 857, 857, 857, 857, 857, 857, + 857, 857, 857, 857, 857, 857, 857, 857, + + 857, 857, 857, 857, 857, 857, 857, 857, + 857, 857, 857, 857, 857, 857, 857, 857, + 857, 857, 857, 857, 857, 857, 204, 857, + 857, 204, 204, 204, 857, 204, 204, 857, + + 858, 858, 858, 858, 858, 858, 858, 858, + 858, 858, 858, 858, 858, 858, 858, 858, + 858, 858, 858, 858, 858, 858, 859, 859, + 859, 859, 204, 204, 204, 204, 204, 860, + + 861, 781, 781, 781, 204, 781, 781, 204, + 204, 204, 204, 204, 781, 152, 781, 153, + 861, 861, 861, 861, 204, 861, 861, 861, + 204, 861, 861, 861, 861, 861, 861, 861, + + 861, 861, 861, 861, 861, 861, 861, 861, + 861, 861, 861, 861, 861, 861, 861, 861, + 861, 861, 861, 861, 204, 204, 204, 204, + 153, 642, 152, 204, 204, 204, 204, 780, + + 862, 863, 864, 865, 866, 866, 866, 866, + 204, 204, 204, 204, 204, 204, 204, 204, + 867, 867, 867, 867, 867, 867, 867, 867, + 868, 204, 204, 204, 204, 204, 204, 204, + + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 321, + 321, 321, 321, 321, 321, 321, 321, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 869, 869, 869, 869, 869, 869, 869, 869, + 869, 869, 869, 869, 869, 869, 869, 869, + 869, 869, 869, 869, 869, 869, 869, 869, + 869, 869, 869, 869, 869, 869, 869, 869, + 869, 869, 869, 869, 869, 869, 869, 869, + 869, 869, 869, 869, 869, 869, 869, 869, + 869, 869, 869, 869, 869, 869, 869, 869, + 869, 869, 869, 869, 869, 869, 869, 869, + 869, 869, 869, 869, 869, 869, 869, 869, + 869, 869, 869, 869, 869, 869, 869, 869, + 869, 869, 869, 869, 869, 869, 869, 869, + 869, 869, 869, 869, 869, 869, 869, 869, + 869, 869, 869, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 480, 480, 480, 480, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 160, + 160, 160, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 871, 872, 873, + 873, 873, 870, 870, 870, 874, 871, 871, + 871, 871, 871, 875, 875, 875, 875, 875, + 875, 875, 875, 876, 876, 876, 876, 876, + 876, 876, 876, 870, 870, 877, 877, 877, + 877, 877, 876, 876, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 877, 877, 877, 877, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 870, 870, + 870, 870, 870, 870, 870, 870, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 417, 417, 417, 417, 417, 417, 417, 417, + 417, 417, 417, 417, 417, 417, 417, 417, + 417, 417, 417, 417, 417, 417, 417, 417, + 417, 417, 417, 417, 417, 417, 417, 417, + 417, 417, 417, 417, 417, 417, 417, 417, + 417, 417, 417, 417, 417, 417, 417, 417, + 417, 417, 417, 417, 417, 417, 417, 417, + 417, 417, 417, 417, 417, 417, 417, 417, + 417, 417, 153, 153, 153, 417, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 238, + 238, 238, 238, 238, 238, 238, 238, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 878, 878, 878, 878, 878, 878, 878, 878, + 878, 878, 878, 878, 878, 878, 878, 878, + 878, 878, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 880, 880, + 880, 880, 880, 880, 880, 160, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 879, 160, 879, 879, + 160, 160, 879, 160, 160, 879, 879, 160, + 160, 879, 879, 879, 879, 160, 879, 879, + 879, 879, 879, 879, 879, 879, 880, 880, + 880, 880, 160, 880, 160, 880, 880, 880, + 880, 102, 880, 880, 160, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + + 880, 880, 880, 880, 879, 879, 160, 879, + 879, 879, 879, 160, 160, 879, 879, 879, + 879, 879, 879, 879, 879, 160, 879, 879, + 879, 879, 879, 879, 879, 160, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 879, 879, 160, 879, 879, 879, 879, 160, + 879, 879, 879, 879, 879, 160, 879, 160, + 160, 160, 879, 879, 879, 879, 879, 879, + 879, 160, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + + 880, 880, 880, 880, 880, 880, 880, 880, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 103, 103, 160, 160, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 881, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 881, 880, 880, 880, 880, + 880, 880, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 881, 880, 880, 880, 880, + + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 881, 880, 880, + 880, 880, 880, 880, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 881, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 881, + 880, 880, 880, 880, 880, 880, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 881, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 881, 880, 880, 880, 880, 880, 880, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 879, 879, 879, 879, 879, 879, 879, + 879, 881, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 880, 880, 880, 880, 880, + 880, 880, 880, 881, 880, 880, 880, 880, + 880, 880, 882, 724, 160, 160, 883, 884, + 885, 886, 887, 888, 889, 890, 891, 892, + 883, 884, 885, 886, 887, 888, 889, 890, + 891, 892, 883, 884, 885, 886, 887, 888, + 889, 890, 891, 892, 883, 884, 885, 886, + 887, 888, 889, 890, 891, 892, 883, 884, + 885, 886, 887, 888, 889, 890, 891, 892, + + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 893, 893, + + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 894, 894, + 894, 894, 894, 894, 894, 894, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 160, 875, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 875, 875, 875, 875, 875, 875, 875, 875, + 875, 875, 875, 875, 875, 875, 875, 875, + 875, 875, 875, 875, 875, 875, 875, 875, + 875, 875, 875, 875, 875, 875, 875, 875, + 875, 875, 875, 875, 875, 875, 875, 875, + 875, 875, 875, 875, 875, 875, 875, 875, + 875, 875, 875, 875, 875, 875, 875, 875, + 875, 875, 875, 875, 875, 875, 875, 875, + 875, 875, 875, 875, 875, 875, 875, 875, + 875, 875, 875, 875, 875, 875, 875, 875, + 875, 875, 875, 875, 875, 875, 875, 875, + 875, 875, 875, 875, 875, 875, 875, 875, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 325, 325, 325, + 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, + + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 895, 895, + 895, 895, 895, 895, 895, 895, 893, 893, +}; + +#define GET_PROP_INDEX(ucs4) \ + (ucs4 < 0x11000 \ + ? (uc_property_trie[uc_property_trie[ucs4>>5] + (ucs4 & 0x1f)]) \ + : (uc_property_trie[uc_property_trie[((ucs4 - 0x11000)>>8) + 0x880] + (ucs4 & 0xff)])) + +#define GET_PROP_INDEX_UCS2(ucs2) \ +(uc_property_trie[uc_property_trie[ucs2>>5] + (ucs2 & 0x1f)]) + +static const QUnicodeTables::Properties uc_properties [] = { + { 10, 19, 18, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0}, + { 10, 15, 8, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3}, + { 10, 30, 7, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1}, + { 10, 31, 8, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3}, + { 10, 31, 9, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3}, + { 10, 29, 7, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1}, + { 10, 19, 7, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0}, + { 10, 19, 8, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0}, + { 7, 28, 9, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, + { 26, 5, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 26, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, + { 26, 11, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 28, 8, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 9, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 10}, + { 22, 0, 10, 0, 0, -1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10}, + { 23, 1, 10, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10}, + { 27, 8, 3, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 7, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0}, + { 21, 14, 3, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 7, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8}, + { 26, 6, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 10, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 26, 7, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0}, + { 26, 7, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0}, + { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 32, 0, 0, 32, 0, 3, 5}, + { 22, 0, 10, 0, 0, -1, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 10}, + { 26, 8, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 23, 1, 10, 0, 0, -1, 1, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 10}, + { 29, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 20, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -32, -32, 0, 0, 3, 4}, + { 27, 15, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 10, 11, 7, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1}, + { 7, 3, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 28, 9, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 30, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4}, + { 24, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 10}, + { 11, 15, 18, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 30, 9, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 27, 8, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 2, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 2, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 29, 16, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 743, 743, 775, 0, 3, 4}, + { 26, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0}, + { 6, 11, 2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 25, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, -16, 0, 0, 0, 0, 0, 0, 10}, + { 6, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 3, 0, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 121, 121, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 1, 0, 0, 0, 0, 6, 0, 0, 0, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -232, -232, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 91, 88, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -121, 0, 0, -121, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -300, -300, -268, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 195, 195, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 210, 0, 0, 210, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 206, 0, 0, 206, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 205, 0, 0, 205, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 79, 0, 0, 79, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 202, 0, 0, 202, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 203, 0, 0, 203, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 207, 0, 0, 207, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 97, 97, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 211, 0, 0, 211, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 209, 0, 0, 209, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 163, 163, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 213, 0, 0, 213, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 130, 130, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 214, 0, 0, 214, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 218, 0, 0, 218, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 217, 0, 0, 217, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 219, 0, 0, 219, 0, 3, 5}, + { 19, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 56, 56, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 2, 0, 1, 2, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 1, -1, 0, 1, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -2, -1, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -79, -79, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 113, 110, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, -97, 0, 0, -97, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, -56, 0, 0, -56, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, -130, 0, 0, -130, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 10795, 0, 0, 10795, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, -163, 0, 0, -163, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 10792, 0, 0, 10792, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, -195, 0, 0, -195, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 69, 0, 0, 69, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 71, 0, 0, 71, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -210, -210, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -206, -206, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -205, -205, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -202, -202, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -203, -203, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -207, -207, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -209, -209, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -211, -211, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 10743, 10743, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -213, -213, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -214, -214, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 10727, 10727, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -218, -218, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -69, -69, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -217, -217, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -71, -71, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -219, -219, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4}, + { 18, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4}, + { 18, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 18, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 18, 16, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 29, 11, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 18, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 29, 11, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 1, 19, 17, 230, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 232, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 220, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 216, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 202, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 1, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 240, 0, -1, 1, 0, 0, 0, 0, 0, 0, 84, 84, 116, 4, 1, 0}, + { 1, 19, 17, 230, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 220, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 3, 17, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 230, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 220, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 232, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 220, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 230, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 3, 17, 233, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 3, 17, 234, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 3, 17, 233, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 3, 17, 234, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 3, 17, 233, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 230, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 0, 11, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 16, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 130, 130, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 38, 0, 0, 38, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 37, 0, 0, 37, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 64, 0, 0, 64, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 63, 0, 0, 63, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 98, 94, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -38, -38, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -37, -37, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 106, 102, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -31, -31, 1, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -64, -64, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -63, -63, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -62, -62, -30, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -57, -57, -25, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -47, -47, -15, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -54, -54, -22, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -86, -86, -54, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -80, -80, -48, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, -60, 0, 0, -60, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, -96, -96, -64, 0, 3, 4}, + { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 15, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, -7, 0, 0, -7, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, -130, 0, 0, -130, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 80, 0, 0, 80, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 80, 0, 0, 80, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, -80, -80, 0, 0, 3, 4}, + { 30, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 3, 19, 17, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 15, 0, 0, 15, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, -15, -15, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 48, 0, 0, 48, 0, 3, 5}, + { 26, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -48, -48, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 55, 52, 0, 0, 3, 4}, + { 26, 7, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 9}, + { 21, 15, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 11, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 1, 19, 17, 220, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 230, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 222, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 228, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 10, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 11, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 12, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 13, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 14, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 15, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 16, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 17, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 18, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 19, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 19, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 20, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 21, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 22, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 26, 15, 1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 1, 19, 17, 23, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 26, 11, 1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 1, 19, 17, 24, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 25, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 26, 5, 1, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 1, 19, 17, 18, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 19, 11, 1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 26, 11, 1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 26, 11, 1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0}, + { 11, 11, 13, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 0, 11, 13, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 28, 9, 13, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 5, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 7, 13, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0}, + { 30, 11, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 5, 13, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 5, 13, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 5, 13, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 19, 11, 13, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 19, 11, 13, 0, 2, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 19, 11, 13, 0, 1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 18, 11, 13, 0, 3, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 1, 19, 17, 27, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 28, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 29, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 30, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 31, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 32, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 33, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 34, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 4, 10, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 5, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 5, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 5, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 5, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 5, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 5, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 5, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 5, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 5, 0, 0, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 26, 5, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 10, 5, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 26, 11, 13, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 19, 11, 13, 0, 1, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 1, 19, 17, 35, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 19, 11, 13, 0, 1, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 19, 11, 13, 0, 2, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 11, 11, 13, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 3, 19, 17, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 18, 11, 13, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 19, 11, 13, 0, 2, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 30, 11, 13, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 19, 11, 13, 0, 1, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 26, 11, 13, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 26, 11, 13, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 11, 11, 18, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 1, 19, 17, 36, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 19, 11, 13, 0, 1, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 19, 11, 13, 0, 2, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 19, 11, 13, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 1, 19, 17, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 19, 11, 13, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 4, 10, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 1, 0, 0, 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 1, 0, 0, 2, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 1, 0, 0, 3, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 1, 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 1, 0, 0, 5, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 1, 0, 0, 6, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 1, 0, 0, 7, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 1, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 1, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 19, 11, 1, 0, 1, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 1, 19, 17, 230, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 220, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 18, 11, 1, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 30, 11, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 11, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 7, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0}, + { 26, 5, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 18, 11, 1, 0, 3, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 1, 19, 17, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 2, 19, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 19, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 1, 19, 17, 7, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 9, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 26, 15, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 4, 10, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 19, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 19, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 2, 19, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 6, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 1, 19, 17, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 2, 19, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 28, 8, 4, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 10, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 1, 19, 17, 84, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 91, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 7, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 2, 19, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 19, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 1, 19, 17, 9, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 2, 19, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 26, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 19, 26, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 1, 26, 17, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 26, 17, 103, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 26, 17, 9, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 18, 26, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 1, 26, 17, 107, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 26, 15, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 1, 26, 17, 118, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 26, 17, 122, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 19, 11, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 30, 16, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 16, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 11, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 3, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 15, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 5, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 30, 11, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 30, 5, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 10, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 7, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 8, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 6, 11, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 30, 15, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 1, 19, 17, 216, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 22, 0, 10, 0, 0, -1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10}, + { 23, 1, 10, 0, 0, -1, 2, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10}, + { 2, 19, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 1, 19, 17, 129, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 130, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 132, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 2, 15, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 1, 19, 17, 9, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 30, 15, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 30, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 16, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 19, 26, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 2, 26, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 1, 26, 17, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 26, 17, 7, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 26, 17, 9, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 4, 10, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 9, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 26, 15, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 7264, 0, 0, 7264, 0, 3, 5}, + { 19, 11, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 18, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 19, 23, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 3, 6}, + { 19, 24, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 6}, + { 19, 25, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 6}, + { 30, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 15, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 6, 11, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 0, 0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 0, 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 0, 0, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 0, 0, 0, 6, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 0, 0, 0, 7, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 0, 0, 0, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 0, 0, 0, 9, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 30, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 7, 15, 9, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, + { 22, 0, 10, 0, 0, -1, 4, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10}, + { 23, 1, 10, 0, 0, -1, 4, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10}, + { 5, 11, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 1, 19, 17, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 9, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 26, 15, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 11, 26, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 26, 4, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 18, 26, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 28, 8, 4, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 1, 26, 17, 230, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 6, 11, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 11, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 15, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 15, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 21, 16, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 7, 3, 9, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, + { 1, 19, 17, 228, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 2, 19, 17, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 1, 19, 17, 222, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 26, 5, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 4, 10, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 3, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 4, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 5, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 8, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 19, 26, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 19, 26, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 2, 26, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 4, 10, 0, 0, 0, 1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 2, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 5, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 9, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 26, 26, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 2, 19, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 26, 15, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 2, 19, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 1, 19, 17, 7, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 2, 19, 0, 9, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 10, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 2, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 3, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 5, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 6, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 7, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 26, 15, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 26, 15, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 30, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 18, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4}, + { 18, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 3814, 3814, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 119, 116, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 125, 122, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 131, 128, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 137, 134, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 143, 140, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, -59, -59, -58, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 8, 8, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -8, 0, 0, -8, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 149, 146, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 156, 152, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 164, 160, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 172, 168, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 74, 74, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 86, 86, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 100, 100, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 128, 128, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 112, 112, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 126, 126, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 244, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 247, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 250, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 253, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 256, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 259, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 262, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 265, 8, 0, 0, 3, 4}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 244, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 247, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 250, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 253, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 256, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 259, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 262, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 268, 0, -8, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 271, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 274, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 277, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 280, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 283, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 286, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 289, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 292, 8, 0, 0, 3, 4}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 271, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 274, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 277, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 280, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 283, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 286, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 289, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 295, 0, -8, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 298, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 301, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 304, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 307, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 310, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 313, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 316, 8, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 319, 8, 0, 0, 3, 4}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 298, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 301, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 304, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 307, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 310, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 313, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 316, 0, -8, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -8, 322, 0, -8, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 346, 343, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 325, 9, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 352, 349, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 179, 176, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 383, 379, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -74, 0, 0, -74, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -9, 328, 0, -9, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -7205, -7205, -7173, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 358, 355, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 331, 9, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 364, 361, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 185, 182, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 391, 387, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -86, 0, 0, -86, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -9, 334, 0, -9, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 192, 188, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 94, 94, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 199, 196, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 206, 202, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -100, 0, 0, -100, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 214, 210, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 102, 102, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 221, 218, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 227, 224, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 234, 230, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -112, 0, 0, -112, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -7, 0, 0, -7, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 370, 367, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, 0, 337, 9, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 376, 373, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 241, 238, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 399, 395, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -128, 0, 0, -128, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -126, 0, 0, -126, 0, 3, 5}, + { 17, 11, 0, 0, 0, -1, 1, 0, 1, 0, 0, 0, -9, 340, 0, -9, 0, 3, 5}, + { 7, 15, 9, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, + { 7, 3, 9, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, + { 11, 18, 18, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 11, 19, 18, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 11, 19, 18, 0, 3, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 11, 19, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 11, 19, 1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 21, 15, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 21, 3, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 21, 17, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 21, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 24, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10}, + { 25, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 4, 10}, + { 22, 0, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, + { 24, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, + { 25, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10}, + { 26, 13, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 15, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0}, + { 8, 31, 9, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1}, + { 9, 31, 7, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 1}, + { 11, 19, 11, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 11, 19, 14, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 11, 19, 16, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 11, 19, 12, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 11, 19, 15, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 7, 3, 6, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, + { 26, 9, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 4, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 27, 7, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0}, + { 26, 4, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 26, 4, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 26, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 11, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 20, 11, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0}, + { 26, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 15, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 7, 15, 9, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, + { 11, 20, 18, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 11, 11, 18, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 11, 19, 18, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 6, 11, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 16, 11, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4}, + { 6, 11, 2, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 2, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 2, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 2, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 2, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 3, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 28, 8, 4, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 28, 8, 4, 0, 0, -1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 28, 8, 4, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 28, 8, 4, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 3, 19, 17, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 1, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 220, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 1, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 30, 9, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 30, 8, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -7517, 0, 0, -7517, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -8383, 0, 0, -8383, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, -8262, 0, 0, -8262, 0, 3, 5}, + { 30, 11, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 15, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 28, 0, 0, 28, 0, 3, 5}, + { 30, 11, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 15, 11, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5}, + { 30, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 16, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, -28, -28, 0, 0, 3, 4}, + { 5, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 16, 0, 0, 16, 0, 3, 5}, + { 5, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -16, -16, 0, 0, 3, 4}, + { 5, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 1824, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 2104, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 2108, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, 2106, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 1, 0, 0, 0, 0, -138, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -8, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -7, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 2, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 30, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 26, 0, 0, 26, 0, 3, 5}, + { 30, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -26, -26, 0, 0, 3, 4}, + { 6, 11, 10, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 8, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 9, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 10, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 30, 2, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, + { 30, 5, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 22, 0, 10, 0, 0, -1, 6, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10}, + { 23, 1, 10, 0, 0, -1, 6, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10}, + { 27, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0}, + { 22, 0, 10, 0, 0, -1, 8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10}, + { 23, 1, 10, 0, 0, -1, 8, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10}, + { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0}, + { 22, 0, 10, 0, 0, -1, 6, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 10}, + { 23, 1, 10, 0, 0, -1, 6, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10}, + { 22, 0, 10, 0, 0, -1, 6, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10}, + { 23, 1, 10, 0, 0, -1, 6, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, 0, 10}, + { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -1824, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -2016, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -2104, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -2106, 0, 0, 0, 0, 0, 0, 0}, + { 27, 11, 10, 0, 0, -1, 6, 0, 0, 0, 0, -2108, 0, 0, 0, 0, 0, 0, 0}, + { 15, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 48, 0, 0, 48, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, -48, -48, 0, 0, 3, 4}, + { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, -10743, 0, 0, -10743, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, -3814, 0, 0, -3814, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, -10727, 0, 0, -10727, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, -10795, -10795, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, -10792, -10792, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4}, + { 6, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 16, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, -7264, -7264, 0, 0, 3, 4}, + { 26, 2, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, + { 24, 2, 10, 0, 0, -1, 8, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 10}, + { 25, 2, 10, 0, 0, -1, 8, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 10}, + { 21, 15, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 30, 12, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 7, 12, 9, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, + { 26, 1, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 1, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 26, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 30, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 18, 4, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 19, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 5, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 21, 4, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 23, 1, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, + { 1, 19, 17, 218, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 228, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 222, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 224, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 21, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 18, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6}, + { 5, 12, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 18, 4, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 19, 4, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 26, 12, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 19, 4, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 19, 4, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 1, 19, 17, 8, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 29, 4, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0}, + { 18, 4, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 19, 12, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 21, 4, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0}, + { 19, 4, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6}, + { 19, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6}, + { 26, 4, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 18, 4, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6}, + { 19, 12, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6}, + { 19, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 30, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 19, 12, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 30, 12, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 19, 4, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6}, + { 30, 12, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 12, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 19, 12, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 19, 12, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 18, 4, 0, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 30, 12, 10, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 29, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 18, 11, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 29, 11, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 2, 19, 17, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 1, 19, 17, 9, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 26, 16, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 19, 21, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 3, 6}, + { 19, 22, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 3, 6}, + { 12, 27, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 13, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 19, 12, 0, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 12, 9, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 18, 15, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 24, 21, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 31, 27, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 39, 35, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 46, 43, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 49, 43, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 61, 58, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 67, 64, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 73, 70, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 79, 76, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 1, 0, 1, 1, 0, 0, 0, 85, 82, 0, 0, 3, 4}, + { 19, 11, 1, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 1, 19, 17, 26, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 0, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 28, 9, 13, 0, 0, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 7, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0}, + { 26, 1, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 5, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 22, 0, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, + { 23, 1, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, + { 26, 13, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 20, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0}, + { 22, 0, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, + { 23, 1, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, + { 26, 1, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 1, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, + { 26, 4, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 12, 4, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 27, 12, 3, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 21, 12, 3, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 27, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, + { 27, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0}, + { 27, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 11, 20, 18, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 26, 12, 6, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 12, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 12, 2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 12, 2, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 12, 2, 0, 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 12, 2, 0, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 12, 2, 0, 0, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 12, 2, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 12, 2, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 12, 2, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 4, 12, 2, 0, 0, 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 27, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0}, + { 27, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0}, + { 15, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 32, 0, 0, 32, 0, 3, 5}, + { 29, 12, 10, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 16, 12, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, -32, -32, 0, 0, 3, 4}, + { 19, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6}, + { 11, 19, 10, 0, 0, -1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 30, 11, 10, 0, 0, -1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 11, 0, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 15, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 15, 10, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 30, 15, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 30, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 5, 11, 10, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 19, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 6, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 5, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 5, 11, 0, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 15, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 40, 0, 0, 40, 0, 3, 5}, + { 15, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 40, 0, 0, 40, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, -40, -40, 0, 0, 3, 4}, + { 16, 11, 0, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, -40, -40, 0, 0, 3, 4}, + { 19, 11, 1, 0, 0, -1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 19, 11, 1, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 6, 11, 1, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 15, 10, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 19, 11, 1, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 6, 11, 1, 0, 0, 1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 1, 0, 0, 2, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 1, 0, 0, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 1, 0, 0, 4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 6, 11, 1, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 15, 1, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 26, 11, 1, 0, 0, -1, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 5, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6}, + { 30, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 2, 19, 0, 216, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 2, 19, 0, 216, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 1, 19, 17, 1, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 2, 19, 0, 226, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 11, 19, 18, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2}, + { 1, 19, 17, 220, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 1, 19, 17, 230, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0}, + { 6, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 15, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5}, + { 16, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4}, + { 27, 11, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 15, 11, 0, 0, 0, -1, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5}, + { 4, 10, 2, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 3, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 7, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 8, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 4, 10, 2, 0, 0, 9, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7}, + { 0, 11, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + { 19, 12, 0, 0, 0, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, + { 13, 11, 0, 0, 0, -1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +}; + +static inline const QUnicodeTables::Properties *qGetProp(uint ucs4) +{ + int index = GET_PROP_INDEX(ucs4); + return uc_properties + index; +} + +static inline const QUnicodeTables::Properties *qGetProp(ushort ucs2) +{ + int index = GET_PROP_INDEX_UCS2(ucs2); + return uc_properties + index; +} + +Q_CORE_EXPORT const QUnicodeTables::Properties* QT_FASTCALL QUnicodeTables::properties(uint ucs4) +{ + int index = GET_PROP_INDEX(ucs4); + return uc_properties + index; +} + +Q_CORE_EXPORT const QUnicodeTables::Properties* QT_FASTCALL QUnicodeTables::properties(ushort ucs2) +{ + int index = GET_PROP_INDEX_UCS2(ucs2); + return uc_properties + index; +} + +#define CURRENT_VERSION QChar::Unicode_5_0 + +static const ushort specialCaseMap [] = { + 0x53, 0x73, 0x0, 0x53, 0x53, 0x0, 0x69, 0x307, 0x0, 0x46, 0x66, 0x0, 0x46, 0x46, 0x0, 0x46, + 0x69, 0x0, 0x46, 0x49, 0x0, 0x46, 0x6c, 0x0, 0x46, 0x4c, 0x0, 0x46, 0x66, 0x69, 0x0, 0x46, + 0x46, 0x49, 0x0, 0x46, 0x66, 0x6c, 0x0, 0x46, 0x46, 0x4c, 0x0, 0x53, 0x74, 0x0, 0x53, 0x54, + 0x0, 0x53, 0x54, 0x0, 0x535, 0x582, 0x0, 0x535, 0x552, 0x0, 0x544, 0x576, 0x0, 0x544, 0x546, 0x0, + 0x544, 0x565, 0x0, 0x544, 0x535, 0x0, 0x544, 0x56b, 0x0, 0x544, 0x53b, 0x0, 0x54e, 0x576, 0x0, 0x54e, + 0x546, 0x0, 0x544, 0x56d, 0x0, 0x544, 0x53d, 0x0, 0x2bc, 0x4e, 0x0, 0x2bc, 0x4e, 0x0, 0x399, 0x308, + 0x301, 0x0, 0x399, 0x308, 0x301, 0x0, 0x3a5, 0x308, 0x301, 0x0, 0x3a5, 0x308, 0x301, 0x0, 0x4a, 0x30c, + 0x0, 0x4a, 0x30c, 0x0, 0x48, 0x331, 0x0, 0x48, 0x331, 0x0, 0x54, 0x308, 0x0, 0x54, 0x308, 0x0, + 0x57, 0x30a, 0x0, 0x57, 0x30a, 0x0, 0x59, 0x30a, 0x0, 0x59, 0x30a, 0x0, 0x41, 0x2be, 0x0, 0x41, + 0x2be, 0x0, 0x3a5, 0x313, 0x0, 0x3a5, 0x313, 0x0, 0x3a5, 0x313, 0x300, 0x0, 0x3a5, 0x313, 0x300, 0x0, + 0x3a5, 0x313, 0x301, 0x0, 0x3a5, 0x313, 0x301, 0x0, 0x3a5, 0x313, 0x342, 0x0, 0x3a5, 0x313, 0x342, 0x0, + 0x391, 0x342, 0x0, 0x391, 0x342, 0x0, 0x397, 0x342, 0x0, 0x397, 0x342, 0x0, 0x399, 0x308, 0x300, 0x0, + 0x399, 0x308, 0x300, 0x0, 0x399, 0x342, 0x0, 0x399, 0x342, 0x0, 0x399, 0x308, 0x342, 0x0, 0x399, 0x308, + 0x342, 0x0, 0x3a5, 0x308, 0x300, 0x0, 0x3a5, 0x308, 0x300, 0x0, 0x3a1, 0x313, 0x0, 0x3a1, 0x313, 0x0, + 0x3a5, 0x342, 0x0, 0x3a5, 0x342, 0x0, 0x3a5, 0x308, 0x342, 0x0, 0x3a5, 0x308, 0x342, 0x0, 0x3a9, 0x342, + 0x0, 0x3a9, 0x342, 0x0, 0x1f08, 0x399, 0x0, 0x1f09, 0x399, 0x0, 0x1f0a, 0x399, 0x0, 0x1f0b, 0x399, 0x0, + 0x1f0c, 0x399, 0x0, 0x1f0d, 0x399, 0x0, 0x1f0e, 0x399, 0x0, 0x1f0f, 0x399, 0x0, 0x1f0f, 0x399, 0x0, 0x1f28, + 0x399, 0x0, 0x1f29, 0x399, 0x0, 0x1f2a, 0x399, 0x0, 0x1f2b, 0x399, 0x0, 0x1f2c, 0x399, 0x0, 0x1f2d, 0x399, + 0x0, 0x1f2e, 0x399, 0x0, 0x1f2f, 0x399, 0x0, 0x1f2f, 0x399, 0x0, 0x1f68, 0x399, 0x0, 0x1f69, 0x399, 0x0, + 0x1f6a, 0x399, 0x0, 0x1f6b, 0x399, 0x0, 0x1f6c, 0x399, 0x0, 0x1f6d, 0x399, 0x0, 0x1f6e, 0x399, 0x0, 0x1f6f, + 0x399, 0x0, 0x1f6f, 0x399, 0x0, 0x391, 0x399, 0x0, 0x391, 0x399, 0x0, 0x397, 0x399, 0x0, 0x397, 0x399, + 0x0, 0x3a9, 0x399, 0x0, 0x3a9, 0x399, 0x0, 0x1fba, 0x345, 0x0, 0x1fba, 0x399, 0x0, 0x386, 0x345, 0x0, + 0x386, 0x399, 0x0, 0x1fca, 0x345, 0x0, 0x1fca, 0x399, 0x0, 0x389, 0x345, 0x0, 0x389, 0x399, 0x0, 0x1ffa, + 0x345, 0x0, 0x1ffa, 0x399, 0x0, 0x38f, 0x345, 0x0, 0x38f, 0x399, 0x0, 0x391, 0x342, 0x345, 0x0, 0x391, + 0x342, 0x399, 0x0, 0x397, 0x342, 0x345, 0x0, 0x397, 0x342, 0x399, 0x0, 0x3a9, 0x342, 0x345, 0x0, 0x3a9, + 0x342, 0x399, 0x0 +}; +#define SPECIAL_CASE_MAX_LEN 3 + +static const unsigned short uc_decomposition_trie[] = { + // 0 - 0x3400 + + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1564, 1580, 1596, 1612, 1628, 1644, + 1660, 1676, 1692, 1708, 1724, 1740, 1756, 1772, + 1548, 1548, 1788, 1804, 1820, 1836, 1852, 1868, + 1884, 1900, 1916, 1932, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1948, 1548, 1964, 1980, 1548, + 1548, 1548, 1548, 1548, 1996, 1548, 1548, 2012, + 2028, 2044, 2060, 2076, 2092, 2108, 1548, 2124, + 2140, 2156, 1548, 2172, 1548, 2188, 1548, 2204, + 1548, 1548, 1548, 1548, 2220, 2236, 2252, 2268, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 2284, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 2300, 1548, 1548, 1548, 1548, 2316, + 1548, 1548, 1548, 1548, 2332, 2348, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 2364, 2380, 1548, 2396, 1548, 1548, + 1548, 1548, 1548, 1548, 2412, 2428, 1548, 1548, + 1548, 1548, 1548, 2444, 1548, 2460, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 2476, 2492, 1548, 1548, + 1548, 2508, 1548, 1548, 2524, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 2540, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 2556, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 2572, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 2588, 1548, 1548, + 1548, 1548, 1548, 2604, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 2620, 1548, 2636, 1548, 1548, + 2652, 1548, 1548, 1548, 2668, 2684, 2700, 2716, + 2732, 2748, 2764, 2780, 1548, 1548, 1548, 1548, + + 1548, 1548, 2796, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 2812, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 2828, 2844, 1548, 2860, 2876, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 2892, 2908, 2924, 2940, 2956, 2972, + 1548, 2988, 3004, 3020, 1548, 1548, 1548, 1548, + 3036, 3052, 3068, 3084, 3100, 3116, 3132, 3148, + 3164, 3180, 3196, 3212, 3228, 3244, 3260, 3276, + 3292, 3308, 3324, 3340, 3356, 3372, 3388, 3404, + 3420, 3436, 3452, 3468, 3484, 3500, 3516, 3532, + + 3548, 3564, 3580, 3596, 3612, 3628, 1548, 3644, + 3660, 3676, 3692, 1548, 1548, 1548, 1548, 1548, + 3708, 3724, 3740, 3756, 3772, 3788, 3804, 3820, + 1548, 3836, 3852, 1548, 3868, 1548, 1548, 1548, + 3884, 1548, 3900, 3916, 3932, 1548, 3948, 3964, + 3980, 1548, 3996, 1548, 1548, 1548, 4012, 1548, + 1548, 1548, 4028, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 4044, 4060, + 4076, 4092, 4108, 4124, 4140, 4156, 4172, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 4188, 1548, 1548, 1548, 1548, 1548, 1548, 4204, + 1548, 1548, 1548, 1548, 1548, 4220, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 4236, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 1548, 1548, 1548, 1548, 1548, 1548, 1548, + 1548, 4252, 1548, 1548, 1548, 1548, 1548, 4268, + 4284, 4300, 4316, 4332, 4348, 4364, 4380, 4396, + 4412, 4428, 4444, 4460, 4476, 4492, 1548, 1548, + + 4508, 1548, 1548, 4524, 4540, 4556, 4572, 4588, + 1548, 4604, 4620, 4636, 4652, 4668, 1548, 4684, + 1548, 1548, 1548, 4700, 4716, 4732, 4748, 4764, + 4780, 4796, 1548, 1548, 1548, 1548, 1548, 1548, + 4812, 4828, 4844, 4860, 4876, 4892, 4908, 4924, + 4940, 4956, 4972, 4988, 5004, 5020, 5036, 5052, + 5068, 5084, 5100, 5116, 5132, 5148, 5164, 5180, + 5196, 5212, 5228, 5244, 5260, 5276, 5292, 5308, + + // 0x3400 - 0x30000 + + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + + 5324, 5324, 5324, 5324, 5324, 5580, 5836, 6092, + 6348, 6604, 6860, 7116, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 7372, 5324, 5324, + 7628, 7884, 8140, 8396, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + 5324, 5324, 5324, 5324, 5324, 5324, 5324, 5324, + + 5324, 5324, 5324, 5324, 8652, 8908, 9164, 5324, + 5324, 5324, 5324, 5324, + + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x0, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x2, 0xffff, 0x5, 0xffff, 0xffff, 0xffff, 0xffff, 0x7, + + 0xffff, 0xffff, 0xa, 0xc, 0xe, 0x11, 0xffff, 0xffff, + 0x13, 0x16, 0x18, 0xffff, 0x1a, 0x1e, 0x22, 0xffff, + + 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x35, 0xffff, 0x38, + 0x3b, 0x3e, 0x41, 0x44, 0x47, 0x4a, 0x4d, 0x50, + + 0xffff, 0x53, 0x56, 0x59, 0x5c, 0x5f, 0x62, 0xffff, + 0xffff, 0x65, 0x68, 0x6b, 0x6e, 0x71, 0xffff, 0xffff, + + 0x74, 0x77, 0x7a, 0x7d, 0x80, 0x83, 0xffff, 0x86, + 0x89, 0x8c, 0x8f, 0x92, 0x95, 0x98, 0x9b, 0x9e, + + 0xffff, 0xa1, 0xa4, 0xa7, 0xaa, 0xad, 0xb0, 0xffff, + 0xffff, 0xb3, 0xb6, 0xb9, 0xbc, 0xbf, 0xffff, 0xc2, + + 0xc5, 0xc8, 0xcb, 0xce, 0xd1, 0xd4, 0xd7, 0xda, + 0xdd, 0xe0, 0xe3, 0xe6, 0xe9, 0xec, 0xef, 0xf2, + + 0xffff, 0xffff, 0xf5, 0xf8, 0xfb, 0xfe, 0x101, 0x104, + 0x107, 0x10a, 0x10d, 0x110, 0x113, 0x116, 0x119, 0x11c, + + 0x11f, 0x122, 0x125, 0x128, 0x12b, 0x12e, 0xffff, 0xffff, + 0x131, 0x134, 0x137, 0x13a, 0x13d, 0x140, 0x143, 0x146, + + 0x149, 0xffff, 0x14c, 0x14f, 0x152, 0x155, 0x158, 0x15b, + 0xffff, 0x15e, 0x161, 0x164, 0x167, 0x16a, 0x16d, 0x170, + + 0x173, 0xffff, 0xffff, 0x176, 0x179, 0x17c, 0x17f, 0x182, + 0x185, 0x188, 0xffff, 0xffff, 0x18b, 0x18e, 0x191, 0x194, + + 0x197, 0x19a, 0xffff, 0xffff, 0x19d, 0x1a0, 0x1a3, 0x1a6, + 0x1a9, 0x1ac, 0x1af, 0x1b2, 0x1b5, 0x1b8, 0x1bb, 0x1be, + + 0x1c1, 0x1c4, 0x1c7, 0x1ca, 0x1cd, 0x1d0, 0xffff, 0xffff, + 0x1d3, 0x1d6, 0x1d9, 0x1dc, 0x1df, 0x1e2, 0x1e5, 0x1e8, + + 0x1eb, 0x1ee, 0x1f1, 0x1f4, 0x1f7, 0x1fa, 0x1fd, 0x200, + 0x203, 0x206, 0x209, 0x20c, 0x20f, 0x212, 0x215, 0x218, + + 0x21a, 0x21d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x220, + + 0x223, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0x226, 0x229, 0x22c, 0x22f, + 0x232, 0x235, 0x238, 0x23b, 0x23e, 0x241, 0x244, 0x247, + + 0x24a, 0x24d, 0x250, 0x253, 0x256, 0x259, 0x25c, 0x25f, + 0x262, 0x265, 0x268, 0x26b, 0x26e, 0xffff, 0x271, 0x274, + + 0x277, 0x27a, 0x27d, 0x280, 0xffff, 0xffff, 0x283, 0x286, + 0x289, 0x28c, 0x28f, 0x292, 0x295, 0x298, 0x29b, 0x29e, + + 0x2a1, 0x2a4, 0x2a7, 0x2aa, 0x2ad, 0x2b0, 0xffff, 0xffff, + 0x2b3, 0x2b6, 0x2b9, 0x2bc, 0x2bf, 0x2c2, 0x2c5, 0x2c8, + + 0x2cb, 0x2ce, 0x2d1, 0x2d4, 0x2d7, 0x2da, 0x2dd, 0x2e0, + 0x2e3, 0x2e6, 0x2e9, 0x2ec, 0x2ef, 0x2f2, 0x2f5, 0x2f8, + + 0x2fb, 0x2fe, 0x301, 0x304, 0x307, 0x30a, 0x30d, 0x310, + 0x313, 0x316, 0x319, 0x31c, 0xffff, 0xffff, 0x31f, 0x322, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x325, 0x328, + 0x32b, 0x32e, 0x331, 0x334, 0x337, 0x33a, 0x33d, 0x340, + + 0x343, 0x346, 0x349, 0x34c, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x34f, 0x351, 0x353, 0x355, 0x357, 0x359, 0x35b, 0x35d, + 0x35f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x361, 0x364, 0x367, 0x36a, 0x36d, 0x370, 0xffff, 0xffff, + + 0x373, 0x375, 0x377, 0x379, 0x37b, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x37d, 0x37f, 0xffff, 0x381, 0x383, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0x386, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0x388, 0xffff, 0xffff, 0xffff, 0x38b, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0x38d, 0x390, 0x393, 0x396, + 0x398, 0x39b, 0x39e, 0xffff, 0x3a1, 0xffff, 0x3a4, 0x3a7, + + 0x3aa, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0x3ad, 0x3b0, 0x3b3, 0x3b6, 0x3b9, 0x3bc, + + 0x3bf, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0x3c2, 0x3c5, 0x3c8, 0x3cb, 0x3ce, 0xffff, + + 0x3d1, 0x3d3, 0x3d5, 0x3d7, 0x3da, 0x3dd, 0x3df, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x3e1, 0x3e3, 0x3e5, 0xffff, 0x3e7, 0x3e9, 0xffff, 0xffff, + 0xffff, 0x3eb, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x3ed, 0x3f0, 0xffff, 0x3f3, 0xffff, 0xffff, 0xffff, 0x3f6, + 0xffff, 0xffff, 0xffff, 0xffff, 0x3f9, 0x3fc, 0x3ff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0x402, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0x405, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x408, 0x40b, 0xffff, 0x40e, 0xffff, 0xffff, 0xffff, 0x411, + 0xffff, 0xffff, 0xffff, 0xffff, 0x414, 0x417, 0x41a, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x41d, 0x420, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0x423, 0x426, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x429, 0x42c, 0x42f, 0x432, 0xffff, 0xffff, 0x435, 0x438, + 0xffff, 0xffff, 0x43b, 0x43e, 0x441, 0x444, 0x447, 0x44a, + + 0xffff, 0xffff, 0x44d, 0x450, 0x453, 0x456, 0x459, 0x45c, + 0xffff, 0xffff, 0x45f, 0x462, 0x465, 0x468, 0x46b, 0x46e, + + 0x471, 0x474, 0x477, 0x47a, 0x47d, 0x480, 0xffff, 0xffff, + 0x483, 0x486, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x489, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0x48c, 0x48f, 0x492, 0x495, 0x498, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x49b, 0x49e, 0x4a1, + 0x4a4, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x4a7, 0xffff, 0x4aa, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0x4ad, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0x4b0, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0x4b3, 0xffff, 0xffff, 0x4b6, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x4b9, 0x4bc, 0x4bf, 0x4c2, 0x4c5, 0x4c8, 0x4cb, 0x4ce, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x4d1, 0x4d4, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x4d7, 0x4da, 0xffff, 0x4dd, + + 0xffff, 0xffff, 0xffff, 0x4e0, 0xffff, 0xffff, 0x4e3, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0x4e6, 0x4e9, 0x4ec, 0xffff, 0xffff, 0x4ef, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x4f2, 0xffff, 0xffff, 0x4f5, 0x4f8, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x4fb, 0x4fe, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0x501, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0x504, 0x507, 0x50a, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x50d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x510, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x513, + 0x516, 0xffff, 0x519, 0x51c, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0x51f, 0x522, 0x525, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0x528, 0xffff, 0x52b, 0x52e, 0x531, 0xffff, + + 0xffff, 0xffff, 0xffff, 0x534, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0x537, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x53a, 0x53d, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x540, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0x542, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x545, 0xffff, 0xffff, + + 0xffff, 0xffff, 0x548, 0xffff, 0xffff, 0xffff, 0xffff, 0x54b, + 0xffff, 0xffff, 0xffff, 0xffff, 0x54e, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0x551, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0x554, 0xffff, 0x557, 0x55a, 0x55d, + 0x560, 0x563, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0x566, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0x569, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x56c, 0xffff, 0xffff, + + 0xffff, 0xffff, 0x56f, 0xffff, 0xffff, 0xffff, 0xffff, 0x572, + 0xffff, 0xffff, 0xffff, 0xffff, 0x575, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0x578, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x57b, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x57e, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x580, 0xffff, + 0x583, 0xffff, 0x586, 0xffff, 0x589, 0xffff, 0x58c, 0xffff, + + 0xffff, 0xffff, 0x58f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x592, 0xffff, 0x595, 0xffff, 0xffff, + + 0x598, 0x59b, 0xffff, 0x59e, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x5a1, 0x5a3, 0x5a5, 0xffff, + + 0x5a7, 0x5a9, 0x5ab, 0x5ad, 0x5af, 0x5b1, 0x5b3, 0x5b5, + 0x5b7, 0x5b9, 0x5bb, 0xffff, 0x5bd, 0x5bf, 0x5c1, 0x5c3, + + 0x5c5, 0x5c7, 0x5c9, 0x5cb, 0x5cd, 0x5cf, 0x5d1, 0x5d3, + 0x5d5, 0x5d7, 0x5d9, 0x5db, 0x5dd, 0x5df, 0xffff, 0x5e1, + + 0x5e3, 0x5e5, 0x5e7, 0x5e9, 0x5eb, 0x5ed, 0x5ef, 0x5f1, + 0x5f3, 0x5f5, 0x5f7, 0x5f9, 0x5fb, 0x5fd, 0x5ff, 0x601, + + 0x603, 0x605, 0x607, 0x609, 0x60b, 0x60d, 0x60f, 0x611, + 0x613, 0x615, 0x617, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x619, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x61b, 0x61d, 0x61f, 0x621, 0x623, + + 0x625, 0x627, 0x629, 0x62b, 0x62d, 0x62f, 0x631, 0x633, + 0x635, 0x637, 0x639, 0x63b, 0x63d, 0x63f, 0x641, 0x643, + + 0x645, 0x647, 0x649, 0x64b, 0x64d, 0x64f, 0x651, 0x653, + 0x655, 0x657, 0x659, 0x65b, 0x65d, 0x65f, 0x661, 0x663, + + 0x665, 0x668, 0x66b, 0x66e, 0x671, 0x674, 0x677, 0x67a, + 0x67d, 0x680, 0x683, 0x686, 0x689, 0x68c, 0x68f, 0x692, + + 0x695, 0x698, 0x69b, 0x69e, 0x6a1, 0x6a4, 0x6a7, 0x6aa, + 0x6ad, 0x6b0, 0x6b3, 0x6b6, 0x6b9, 0x6bc, 0x6bf, 0x6c2, + + 0x6c5, 0x6c8, 0x6cb, 0x6ce, 0x6d1, 0x6d4, 0x6d7, 0x6da, + 0x6dd, 0x6e0, 0x6e3, 0x6e6, 0x6e9, 0x6ec, 0x6ef, 0x6f2, + + 0x6f5, 0x6f8, 0x6fb, 0x6fe, 0x701, 0x704, 0x707, 0x70a, + 0x70d, 0x710, 0x713, 0x716, 0x719, 0x71c, 0x71f, 0x722, + + 0x725, 0x728, 0x72b, 0x72e, 0x731, 0x734, 0x737, 0x73a, + 0x73d, 0x740, 0x743, 0x746, 0x749, 0x74c, 0x74f, 0x752, + + 0x755, 0x758, 0x75b, 0x75e, 0x761, 0x764, 0x767, 0x76a, + 0x76d, 0x770, 0x773, 0x776, 0x779, 0x77c, 0x77f, 0x782, + + 0x785, 0x788, 0x78b, 0x78e, 0x791, 0x794, 0x797, 0x79a, + 0x79d, 0x7a0, 0x7a3, 0x7a6, 0x7a9, 0x7ac, 0x7af, 0x7b2, + + 0x7b5, 0x7b8, 0x7bb, 0x7be, 0x7c1, 0x7c4, 0x7c7, 0x7ca, + 0x7cd, 0x7d0, 0x7d3, 0x7d6, 0x7d9, 0x7dc, 0x7df, 0x7e2, + + 0x7e5, 0x7e8, 0x7eb, 0x7ee, 0x7f1, 0x7f4, 0x7f7, 0x7fa, + 0x7fd, 0x800, 0x803, 0x806, 0x809, 0x80c, 0x80f, 0x812, + + 0x815, 0x818, 0x81b, 0x81e, 0x821, 0x824, 0x827, 0x82a, + 0x82d, 0x830, 0x833, 0x836, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x839, 0x83c, 0x83f, 0x842, 0x845, 0x848, 0x84b, 0x84e, + 0x851, 0x854, 0x857, 0x85a, 0x85d, 0x860, 0x863, 0x866, + + 0x869, 0x86c, 0x86f, 0x872, 0x875, 0x878, 0x87b, 0x87e, + 0x881, 0x884, 0x887, 0x88a, 0x88d, 0x890, 0x893, 0x896, + + 0x899, 0x89c, 0x89f, 0x8a2, 0x8a5, 0x8a8, 0x8ab, 0x8ae, + 0x8b1, 0x8b4, 0x8b7, 0x8ba, 0x8bd, 0x8c0, 0x8c3, 0x8c6, + + 0x8c9, 0x8cc, 0x8cf, 0x8d2, 0x8d5, 0x8d8, 0x8db, 0x8de, + 0x8e1, 0x8e4, 0x8e7, 0x8ea, 0x8ed, 0x8f0, 0x8f3, 0x8f6, + + 0x8f9, 0x8fc, 0x8ff, 0x902, 0x905, 0x908, 0x90b, 0x90e, + 0x911, 0x914, 0x917, 0x91a, 0x91d, 0x920, 0x923, 0x926, + + 0x929, 0x92c, 0x92f, 0x932, 0x935, 0x938, 0x93b, 0x93e, + 0x941, 0x944, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x947, 0x94a, 0x94d, 0x950, 0x953, 0x956, 0x959, 0x95c, + 0x95f, 0x962, 0x965, 0x968, 0x96b, 0x96e, 0x971, 0x974, + + 0x977, 0x97a, 0x97d, 0x980, 0x983, 0x986, 0xffff, 0xffff, + 0x989, 0x98c, 0x98f, 0x992, 0x995, 0x998, 0xffff, 0xffff, + + 0x99b, 0x99e, 0x9a1, 0x9a4, 0x9a7, 0x9aa, 0x9ad, 0x9b0, + 0x9b3, 0x9b6, 0x9b9, 0x9bc, 0x9bf, 0x9c2, 0x9c5, 0x9c8, + + 0x9cb, 0x9ce, 0x9d1, 0x9d4, 0x9d7, 0x9da, 0x9dd, 0x9e0, + 0x9e3, 0x9e6, 0x9e9, 0x9ec, 0x9ef, 0x9f2, 0x9f5, 0x9f8, + + 0x9fb, 0x9fe, 0xa01, 0xa04, 0xa07, 0xa0a, 0xffff, 0xffff, + 0xa0d, 0xa10, 0xa13, 0xa16, 0xa19, 0xa1c, 0xffff, 0xffff, + + 0xa1f, 0xa22, 0xa25, 0xa28, 0xa2b, 0xa2e, 0xa31, 0xa34, + 0xffff, 0xa37, 0xffff, 0xa3a, 0xffff, 0xa3d, 0xffff, 0xa40, + + 0xa43, 0xa46, 0xa49, 0xa4c, 0xa4f, 0xa52, 0xa55, 0xa58, + 0xa5b, 0xa5e, 0xa61, 0xa64, 0xa67, 0xa6a, 0xa6d, 0xa70, + + 0xa73, 0xa76, 0xa78, 0xa7b, 0xa7d, 0xa80, 0xa82, 0xa85, + 0xa87, 0xa8a, 0xa8c, 0xa8f, 0xa91, 0xa94, 0xffff, 0xffff, + + 0xa96, 0xa99, 0xa9c, 0xa9f, 0xaa2, 0xaa5, 0xaa8, 0xaab, + 0xaae, 0xab1, 0xab4, 0xab7, 0xaba, 0xabd, 0xac0, 0xac3, + + 0xac6, 0xac9, 0xacc, 0xacf, 0xad2, 0xad5, 0xad8, 0xadb, + 0xade, 0xae1, 0xae4, 0xae7, 0xaea, 0xaed, 0xaf0, 0xaf3, + + 0xaf6, 0xaf9, 0xafc, 0xaff, 0xb02, 0xb05, 0xb08, 0xb0b, + 0xb0e, 0xb11, 0xb14, 0xb17, 0xb1a, 0xb1d, 0xb20, 0xb23, + + 0xb26, 0xb29, 0xb2c, 0xb2f, 0xb32, 0xffff, 0xb35, 0xb38, + 0xb3b, 0xb3e, 0xb41, 0xb44, 0xb46, 0xb49, 0xb4c, 0xb4e, + + 0xb51, 0xb54, 0xb57, 0xb5a, 0xb5d, 0xffff, 0xb60, 0xb63, + 0xb66, 0xb69, 0xb6b, 0xb6e, 0xb70, 0xb73, 0xb76, 0xb79, + + 0xb7c, 0xb7f, 0xb82, 0xb85, 0xffff, 0xffff, 0xb87, 0xb8a, + 0xb8d, 0xb90, 0xb93, 0xb96, 0xffff, 0xb98, 0xb9b, 0xb9e, + + 0xba1, 0xba4, 0xba7, 0xbaa, 0xbac, 0xbaf, 0xbb2, 0xbb5, + 0xbb8, 0xbbb, 0xbbe, 0xbc1, 0xbc3, 0xbc6, 0xbc9, 0xbcb, + + 0xffff, 0xffff, 0xbcd, 0xbd0, 0xbd3, 0xffff, 0xbd6, 0xbd9, + 0xbdc, 0xbdf, 0xbe1, 0xbe4, 0xbe6, 0xbe9, 0xbeb, 0xffff, + + 0xbee, 0xbf0, 0xbf2, 0xbf4, 0xbf6, 0xbf8, 0xbfa, 0xbfc, + 0xbfe, 0xc00, 0xc02, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xc04, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xc06, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xc09, 0xc0b, 0xc0e, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xc12, + + 0xffff, 0xffff, 0xffff, 0xc14, 0xc17, 0xffff, 0xc1b, 0xc1e, + 0xffff, 0xffff, 0xffff, 0xffff, 0xc22, 0xffff, 0xc25, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xc28, + 0xc2b, 0xc2e, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xc31, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xc36, + + 0xc38, 0xc3a, 0xffff, 0xffff, 0xc3c, 0xc3e, 0xc40, 0xc42, + 0xc44, 0xc46, 0xc48, 0xc4a, 0xc4c, 0xc4e, 0xc50, 0xc52, + + 0xc54, 0xc56, 0xc58, 0xc5a, 0xc5c, 0xc5e, 0xc60, 0xc62, + 0xc64, 0xc66, 0xc68, 0xc6a, 0xc6c, 0xc6e, 0xc70, 0xffff, + + 0xc72, 0xc74, 0xc76, 0xc78, 0xc7a, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xc7c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xc7f, 0xc83, 0xc87, 0xc89, 0xffff, 0xc8c, 0xc90, 0xc94, + 0xffff, 0xc96, 0xc99, 0xc9b, 0xc9d, 0xc9f, 0xca1, 0xca3, + + 0xca5, 0xca7, 0xca9, 0xcab, 0xffff, 0xcad, 0xcaf, 0xffff, + 0xffff, 0xcb2, 0xcb4, 0xcb6, 0xcb8, 0xcba, 0xffff, 0xffff, + + 0xcbc, 0xcbf, 0xcc3, 0xffff, 0xcc6, 0xffff, 0xcc8, 0xffff, + 0xcca, 0xffff, 0xccc, 0xcce, 0xcd0, 0xcd2, 0xffff, 0xcd4, + + 0xcd6, 0xcd8, 0xffff, 0xcda, 0xcdc, 0xcde, 0xce0, 0xce2, + 0xce4, 0xce6, 0xffff, 0xce8, 0xcec, 0xcee, 0xcf0, 0xcf2, + + 0xcf4, 0xffff, 0xffff, 0xffff, 0xffff, 0xcf6, 0xcf8, 0xcfa, + 0xcfc, 0xcfe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xd00, 0xd04, 0xd08, 0xd0c, 0xd10, + 0xd14, 0xd18, 0xd1c, 0xd20, 0xd24, 0xd28, 0xd2c, 0xd30, + + 0xd33, 0xd35, 0xd38, 0xd3c, 0xd3f, 0xd41, 0xd44, 0xd48, + 0xd4d, 0xd50, 0xd52, 0xd55, 0xd59, 0xd5b, 0xd5d, 0xd5f, + + 0xd61, 0xd63, 0xd66, 0xd6a, 0xd6d, 0xd6f, 0xd72, 0xd76, + 0xd7b, 0xd7e, 0xd80, 0xd83, 0xd87, 0xd89, 0xd8b, 0xd8d, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xd8f, 0xd92, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xd95, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xd98, 0xd9b, 0xd9e, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xda1, 0xffff, 0xffff, 0xffff, + 0xffff, 0xda4, 0xffff, 0xffff, 0xda7, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xdaa, 0xffff, 0xdad, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xdb0, 0xdb3, 0xffff, 0xdb7, + + 0xdba, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xdbe, 0xffff, 0xffff, 0xdc1, 0xffff, 0xffff, 0xdc4, + 0xffff, 0xdc7, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xdca, 0xffff, 0xdcd, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xdd0, 0xdd3, 0xdd6, + + 0xdd9, 0xddc, 0xffff, 0xffff, 0xddf, 0xde2, 0xffff, 0xffff, + 0xde5, 0xde8, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xdeb, 0xdee, 0xffff, 0xffff, 0xdf1, 0xdf4, 0xffff, 0xffff, + 0xdf7, 0xdfa, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xdfd, 0xe00, 0xe03, 0xe06, + + 0xe09, 0xe0c, 0xe0f, 0xe12, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xe15, 0xe18, 0xe1b, 0xe1e, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xe21, 0xe23, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xe25, 0xe27, 0xe29, 0xe2b, 0xe2d, 0xe2f, 0xe31, 0xe33, + 0xe35, 0xe37, 0xe3a, 0xe3d, 0xe40, 0xe43, 0xe46, 0xe49, + + 0xe4c, 0xe4f, 0xe52, 0xe55, 0xe58, 0xe5c, 0xe60, 0xe64, + 0xe68, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe81, 0xe86, + + 0xe8b, 0xe90, 0xe95, 0xe9a, 0xe9f, 0xea4, 0xea9, 0xeae, + 0xeb3, 0xeb6, 0xeb9, 0xebc, 0xebf, 0xec2, 0xec5, 0xec8, + + 0xecb, 0xece, 0xed2, 0xed6, 0xeda, 0xede, 0xee2, 0xee6, + 0xeea, 0xeee, 0xef2, 0xef6, 0xefa, 0xefe, 0xf02, 0xf06, + + 0xf0a, 0xf0e, 0xf12, 0xf16, 0xf1a, 0xf1e, 0xf22, 0xf26, + 0xf2a, 0xf2e, 0xf32, 0xf36, 0xf3a, 0xf3e, 0xf42, 0xf46, + + 0xf4a, 0xf4e, 0xf52, 0xf56, 0xf5a, 0xf5e, 0xf62, 0xf64, + 0xf66, 0xf68, 0xf6a, 0xf6c, 0xf6e, 0xf70, 0xf72, 0xf74, + + 0xf76, 0xf78, 0xf7a, 0xf7c, 0xf7e, 0xf80, 0xf82, 0xf84, + 0xf86, 0xf88, 0xf8a, 0xf8c, 0xf8e, 0xf90, 0xf92, 0xf94, + + 0xf96, 0xf98, 0xf9a, 0xf9c, 0xf9e, 0xfa0, 0xfa2, 0xfa4, + 0xfa6, 0xfa8, 0xfaa, 0xfac, 0xfae, 0xfb0, 0xfb2, 0xfb4, + + 0xfb6, 0xfb8, 0xfba, 0xfbc, 0xfbe, 0xfc0, 0xfc2, 0xfc4, + 0xfc6, 0xfc8, 0xfca, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xfcc, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xfd1, 0xfd5, 0xfd8, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xfdc, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfdf, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xfe1, + + 0xffff, 0xffff, 0xffff, 0xfe3, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xfe5, 0xfe7, 0xfe9, 0xfeb, 0xfed, 0xfef, 0xff1, 0xff3, + 0xff5, 0xff7, 0xff9, 0xffb, 0xffd, 0xfff, 0x1001, 0x1003, + + 0x1005, 0x1007, 0x1009, 0x100b, 0x100d, 0x100f, 0x1011, 0x1013, + 0x1015, 0x1017, 0x1019, 0x101b, 0x101d, 0x101f, 0x1021, 0x1023, + + 0x1025, 0x1027, 0x1029, 0x102b, 0x102d, 0x102f, 0x1031, 0x1033, + 0x1035, 0x1037, 0x1039, 0x103b, 0x103d, 0x103f, 0x1041, 0x1043, + + 0x1045, 0x1047, 0x1049, 0x104b, 0x104d, 0x104f, 0x1051, 0x1053, + 0x1055, 0x1057, 0x1059, 0x105b, 0x105d, 0x105f, 0x1061, 0x1063, + + 0x1065, 0x1067, 0x1069, 0x106b, 0x106d, 0x106f, 0x1071, 0x1073, + 0x1075, 0x1077, 0x1079, 0x107b, 0x107d, 0x107f, 0x1081, 0x1083, + + 0x1085, 0x1087, 0x1089, 0x108b, 0x108d, 0x108f, 0x1091, 0x1093, + 0x1095, 0x1097, 0x1099, 0x109b, 0x109d, 0x109f, 0x10a1, 0x10a3, + + 0x10a5, 0x10a7, 0x10a9, 0x10ab, 0x10ad, 0x10af, 0x10b1, 0x10b3, + 0x10b5, 0x10b7, 0x10b9, 0x10bb, 0x10bd, 0x10bf, 0x10c1, 0x10c3, + + 0x10c5, 0x10c7, 0x10c9, 0x10cb, 0x10cd, 0x10cf, 0x10d1, 0x10d3, + 0x10d5, 0x10d7, 0x10d9, 0x10db, 0x10dd, 0x10df, 0x10e1, 0x10e3, + + 0x10e5, 0x10e7, 0x10e9, 0x10eb, 0x10ed, 0x10ef, 0x10f1, 0x10f3, + 0x10f5, 0x10f7, 0x10f9, 0x10fb, 0x10fd, 0x10ff, 0x1101, 0x1103, + + 0x1105, 0x1107, 0x1109, 0x110b, 0x110d, 0x110f, 0x1111, 0x1113, + 0x1115, 0x1117, 0x1119, 0x111b, 0x111d, 0x111f, 0x1121, 0x1123, + + 0x1125, 0x1127, 0x1129, 0x112b, 0x112d, 0x112f, 0x1131, 0x1133, + 0x1135, 0x1137, 0x1139, 0x113b, 0x113d, 0x113f, 0x1141, 0x1143, + + 0x1145, 0x1147, 0x1149, 0x114b, 0x114d, 0x114f, 0x1151, 0x1153, + 0x1155, 0x1157, 0x1159, 0x115b, 0x115d, 0x115f, 0x1161, 0x1163, + + 0x1165, 0x1167, 0x1169, 0x116b, 0x116d, 0x116f, 0x1171, 0x1173, + 0x1175, 0x1177, 0x1179, 0x117b, 0x117d, 0x117f, 0x1181, 0x1183, + + 0x1185, 0x1187, 0x1189, 0x118b, 0x118d, 0x118f, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x1191, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x1193, 0xffff, + 0x1195, 0x1197, 0x1199, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x119b, 0xffff, 0x119e, 0xffff, + + 0x11a1, 0xffff, 0x11a4, 0xffff, 0x11a7, 0xffff, 0x11aa, 0xffff, + 0x11ad, 0xffff, 0x11b0, 0xffff, 0x11b3, 0xffff, 0x11b6, 0xffff, + + 0x11b9, 0xffff, 0x11bc, 0xffff, 0xffff, 0x11bf, 0xffff, 0x11c2, + 0xffff, 0x11c5, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x11c8, 0x11cb, 0xffff, 0x11ce, 0x11d1, 0xffff, 0x11d4, 0x11d7, + 0xffff, 0x11da, 0x11dd, 0xffff, 0x11e0, 0x11e3, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0x11e6, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x11e9, 0x11ec, 0xffff, 0x11ef, 0x11f2, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x11f5, 0xffff, 0x11f8, 0xffff, + + 0x11fb, 0xffff, 0x11fe, 0xffff, 0x1201, 0xffff, 0x1204, 0xffff, + 0x1207, 0xffff, 0x120a, 0xffff, 0x120d, 0xffff, 0x1210, 0xffff, + + 0x1213, 0xffff, 0x1216, 0xffff, 0xffff, 0x1219, 0xffff, 0x121c, + 0xffff, 0x121f, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x1222, 0x1225, 0xffff, 0x1228, 0x122b, 0xffff, 0x122e, 0x1231, + 0xffff, 0x1234, 0x1237, 0xffff, 0x123a, 0x123d, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0x1240, 0xffff, 0xffff, 0x1243, + 0x1246, 0x1249, 0x124c, 0xffff, 0xffff, 0xffff, 0x124f, 0x1252, + + 0xffff, 0x1255, 0x1257, 0x1259, 0x125b, 0x125d, 0x125f, 0x1261, + 0x1263, 0x1265, 0x1267, 0x1269, 0x126b, 0x126d, 0x126f, 0x1271, + + 0x1273, 0x1275, 0x1277, 0x1279, 0x127b, 0x127d, 0x127f, 0x1281, + 0x1283, 0x1285, 0x1287, 0x1289, 0x128b, 0x128d, 0x128f, 0x1291, + + 0x1293, 0x1295, 0x1297, 0x1299, 0x129b, 0x129d, 0x129f, 0x12a1, + 0x12a3, 0x12a5, 0x12a7, 0x12a9, 0x12ab, 0x12ad, 0x12af, 0x12b1, + + 0x12b3, 0x12b5, 0x12b7, 0x12b9, 0x12bb, 0x12bd, 0x12bf, 0x12c1, + 0x12c3, 0x12c5, 0x12c7, 0x12c9, 0x12cb, 0x12cd, 0x12cf, 0x12d1, + + 0x12d3, 0x12d5, 0x12d7, 0x12d9, 0x12db, 0x12dd, 0x12df, 0x12e1, + 0x12e3, 0x12e5, 0x12e7, 0x12e9, 0x12eb, 0x12ed, 0x12ef, 0x12f1, + + 0x12f3, 0x12f5, 0x12f7, 0x12f9, 0x12fb, 0x12fd, 0x12ff, 0x1301, + 0x1303, 0x1305, 0x1307, 0x1309, 0x130b, 0x130d, 0x130f, 0xffff, + + 0xffff, 0xffff, 0x1311, 0x1313, 0x1315, 0x1317, 0x1319, 0x131b, + 0x131d, 0x131f, 0x1321, 0x1323, 0x1325, 0x1327, 0x1329, 0x132b, + + 0x132d, 0x1331, 0x1335, 0x1339, 0x133d, 0x1341, 0x1345, 0x1349, + 0x134d, 0x1351, 0x1355, 0x1359, 0x135d, 0x1361, 0x1365, 0x136a, + + 0x136f, 0x1374, 0x1379, 0x137e, 0x1383, 0x1388, 0x138d, 0x1392, + 0x1397, 0x139c, 0x13a1, 0x13a6, 0x13ab, 0x13b0, 0x13b8, 0xffff, + + 0x13bf, 0x13c3, 0x13c7, 0x13cb, 0x13cf, 0x13d3, 0x13d7, 0x13db, + 0x13df, 0x13e3, 0x13e7, 0x13eb, 0x13ef, 0x13f3, 0x13f7, 0x13fb, + + 0x13ff, 0x1403, 0x1407, 0x140b, 0x140f, 0x1413, 0x1417, 0x141b, + 0x141f, 0x1423, 0x1427, 0x142b, 0x142f, 0x1433, 0x1437, 0x143b, + + 0x143f, 0x1443, 0x1447, 0x144b, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x144f, 0x1453, 0x1456, 0x1459, 0x145c, 0x145f, 0x1462, 0x1465, + 0x1468, 0x146b, 0x146e, 0x1471, 0x1474, 0x1477, 0x147a, 0x147d, + + 0x1480, 0x1482, 0x1484, 0x1486, 0x1488, 0x148a, 0x148c, 0x148e, + 0x1490, 0x1492, 0x1494, 0x1496, 0x1498, 0x149a, 0x149c, 0x149f, + + 0x14a2, 0x14a5, 0x14a8, 0x14ab, 0x14ae, 0x14b1, 0x14b4, 0x14b7, + 0x14ba, 0x14bd, 0x14c0, 0x14c3, 0x14c6, 0x14cc, 0x14d1, 0xffff, + + 0x14d4, 0x14d6, 0x14d8, 0x14da, 0x14dc, 0x14de, 0x14e0, 0x14e2, + 0x14e4, 0x14e6, 0x14e8, 0x14ea, 0x14ec, 0x14ee, 0x14f0, 0x14f2, + + 0x14f4, 0x14f6, 0x14f8, 0x14fa, 0x14fc, 0x14fe, 0x1500, 0x1502, + 0x1504, 0x1506, 0x1508, 0x150a, 0x150c, 0x150e, 0x1510, 0x1512, + + 0x1514, 0x1516, 0x1518, 0x151a, 0x151c, 0x151e, 0x1520, 0x1522, + 0x1524, 0x1526, 0x1528, 0x152a, 0x152c, 0x152e, 0x1530, 0x1532, + + 0x1534, 0x1536, 0x1539, 0x153c, 0x153f, 0x1542, 0x1545, 0x1548, + 0x154b, 0x154e, 0x1551, 0x1554, 0x1557, 0x155a, 0x155d, 0x1560, + + 0x1563, 0x1566, 0x1569, 0x156c, 0x156f, 0x1572, 0x1575, 0x1578, + 0x157b, 0x157e, 0x1582, 0x1586, 0x158a, 0x158d, 0x1591, 0x1594, + + 0x1598, 0x159a, 0x159c, 0x159e, 0x15a0, 0x15a2, 0x15a4, 0x15a6, + 0x15a8, 0x15aa, 0x15ac, 0x15ae, 0x15b0, 0x15b2, 0x15b4, 0x15b6, + + 0x15b8, 0x15ba, 0x15bc, 0x15be, 0x15c0, 0x15c2, 0x15c4, 0x15c6, + 0x15c8, 0x15ca, 0x15cc, 0x15ce, 0x15d0, 0x15d2, 0x15d4, 0x15d6, + + 0x15d8, 0x15da, 0x15dc, 0x15de, 0x15e0, 0x15e2, 0x15e4, 0x15e6, + 0x15e8, 0x15ea, 0x15ec, 0x15ee, 0x15f0, 0x15f2, 0x15f4, 0xffff, + + 0x15f6, 0x15fb, 0x1600, 0x1605, 0x1609, 0x160e, 0x1612, 0x1616, + 0x161c, 0x1621, 0x1625, 0x1629, 0x162d, 0x1632, 0x1637, 0x163b, + + 0x163f, 0x1642, 0x1646, 0x164b, 0x1650, 0x1653, 0x1659, 0x1660, + 0x1666, 0x166a, 0x1670, 0x1676, 0x167b, 0x167f, 0x1683, 0x1687, + + 0x168c, 0x1692, 0x1697, 0x169b, 0x169f, 0x16a3, 0x16a6, 0x16a9, + 0x16ac, 0x16af, 0x16b3, 0x16b7, 0x16bd, 0x16c1, 0x16c6, 0x16cc, + + 0x16d0, 0x16d3, 0x16d6, 0x16dc, 0x16e1, 0x16e7, 0x16eb, 0x16f1, + 0x16f4, 0x16f8, 0x16fc, 0x1700, 0x1704, 0x1708, 0x170d, 0x1711, + + 0x1714, 0x1718, 0x171c, 0x1720, 0x1725, 0x1729, 0x172d, 0x1731, + 0x1737, 0x173c, 0x173f, 0x1745, 0x1748, 0x174d, 0x1752, 0x1756, + + 0x175a, 0x175e, 0x1763, 0x1766, 0x176a, 0x176f, 0x1772, 0x1778, + 0x177c, 0x177f, 0x1782, 0x1785, 0x1788, 0x178b, 0x178e, 0x1791, + + 0x1794, 0x1797, 0x179a, 0x179e, 0x17a2, 0x17a6, 0x17aa, 0x17ae, + 0x17b2, 0x17b6, 0x17ba, 0x17be, 0x17c2, 0x17c6, 0x17ca, 0x17ce, + + 0x17d2, 0x17d6, 0x17da, 0x17dd, 0x17e0, 0x17e4, 0x17e7, 0x17ea, + 0x17ed, 0x17f1, 0x17f5, 0x17f8, 0x17fb, 0x17fe, 0x1801, 0x1804, + + 0x1809, 0x180c, 0x180f, 0x1812, 0x1815, 0x1818, 0x181b, 0x181e, + 0x1821, 0x1825, 0x182a, 0x182d, 0x1830, 0x1833, 0x1836, 0x1839, + + 0x183c, 0x183f, 0x1843, 0x1847, 0x184b, 0x184f, 0x1852, 0x1855, + 0x1858, 0x185b, 0x185e, 0x1861, 0x1864, 0x1867, 0x186a, 0x186d, + + 0x1871, 0x1875, 0x1878, 0x187c, 0x1880, 0x1884, 0x1887, 0x188b, + 0x188f, 0x1894, 0x1897, 0x189b, 0x189f, 0x18a3, 0x18a7, 0x18ad, + + 0x18b4, 0x18b7, 0x18ba, 0x18bd, 0x18c0, 0x18c3, 0x18c6, 0x18c9, + 0x18cc, 0x18cf, 0x18d2, 0x18d5, 0x18d8, 0x18db, 0x18de, 0x18e1, + + 0x18e4, 0x18e7, 0x18ea, 0x18ef, 0x18f2, 0x18f5, 0x18f8, 0x18fd, + 0x1901, 0x1904, 0x1907, 0x190a, 0x190d, 0x1910, 0x1913, 0x1916, + + 0x1919, 0x191c, 0x191f, 0x1923, 0x1926, 0x1929, 0x192d, 0x1931, + 0x1934, 0x1939, 0x193d, 0x1940, 0x1943, 0x1946, 0x1949, 0x194d, + + 0x1951, 0x1954, 0x1957, 0x195a, 0x195d, 0x1960, 0x1963, 0x1966, + 0x1969, 0x196c, 0x1970, 0x1974, 0x1978, 0x197c, 0x1980, 0x1984, + + 0x1988, 0x198c, 0x1990, 0x1994, 0x1998, 0x199c, 0x19a0, 0x19a4, + 0x19a8, 0x19ac, 0x19b0, 0x19b4, 0x19b8, 0x19bc, 0x19c0, 0x19c4, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x19c8, 0x19ca, 0x19cc, 0x19ce, 0x19d0, 0x19d2, 0x19d4, 0x19d6, + 0x19d8, 0x19da, 0x19dc, 0x19de, 0x19e0, 0x19e2, 0x19e4, 0x19e6, + 0x19e8, 0x19ea, 0x19ec, 0x19ee, 0x19f0, 0x19f2, 0x19f4, 0x19f6, + 0x19f8, 0x19fa, 0x19fc, 0x19fe, 0x1a00, 0x1a02, 0x1a04, 0x1a06, + 0x1a08, 0x1a0a, 0x1a0c, 0x1a0e, 0x1a10, 0x1a12, 0x1a14, 0x1a16, + 0x1a18, 0x1a1a, 0x1a1c, 0x1a1e, 0x1a20, 0x1a22, 0x1a24, 0x1a26, + 0x1a28, 0x1a2a, 0x1a2c, 0x1a2e, 0x1a30, 0x1a32, 0x1a34, 0x1a36, + 0x1a38, 0x1a3a, 0x1a3c, 0x1a3e, 0x1a40, 0x1a42, 0x1a44, 0x1a46, + 0x1a48, 0x1a4a, 0x1a4c, 0x1a4e, 0x1a50, 0x1a52, 0x1a54, 0x1a56, + 0x1a58, 0x1a5a, 0x1a5c, 0x1a5e, 0x1a60, 0x1a62, 0x1a64, 0x1a66, + 0x1a68, 0x1a6a, 0x1a6c, 0x1a6e, 0x1a70, 0x1a72, 0x1a74, 0x1a76, + 0x1a78, 0x1a7a, 0x1a7c, 0x1a7e, 0x1a80, 0x1a82, 0x1a84, 0x1a86, + 0x1a88, 0x1a8a, 0x1a8c, 0x1a8e, 0x1a90, 0x1a92, 0x1a94, 0x1a96, + 0x1a98, 0x1a9a, 0x1a9c, 0x1a9e, 0x1aa0, 0x1aa2, 0x1aa4, 0x1aa6, + 0x1aa8, 0x1aaa, 0x1aac, 0x1aae, 0x1ab0, 0x1ab2, 0x1ab4, 0x1ab6, + 0x1ab8, 0x1aba, 0x1abc, 0x1abe, 0x1ac0, 0x1ac2, 0x1ac4, 0x1ac6, + 0x1ac8, 0x1aca, 0x1acc, 0x1ace, 0x1ad0, 0x1ad2, 0x1ad4, 0x1ad6, + 0x1ad8, 0x1ada, 0x1adc, 0x1ade, 0x1ae0, 0x1ae2, 0x1ae4, 0x1ae6, + 0x1ae8, 0x1aea, 0x1aec, 0x1aee, 0x1af0, 0x1af2, 0x1af4, 0x1af6, + 0x1af8, 0x1afa, 0x1afc, 0x1afe, 0x1b00, 0x1b02, 0x1b04, 0x1b06, + 0x1b08, 0x1b0a, 0x1b0c, 0x1b0e, 0x1b10, 0x1b12, 0x1b14, 0x1b16, + 0x1b18, 0x1b1a, 0x1b1c, 0x1b1e, 0x1b20, 0x1b22, 0x1b24, 0x1b26, + 0x1b28, 0x1b2a, 0x1b2c, 0x1b2e, 0x1b30, 0x1b32, 0x1b34, 0x1b36, + 0x1b38, 0x1b3a, 0x1b3c, 0x1b3e, 0x1b40, 0x1b42, 0x1b44, 0x1b46, + 0x1b48, 0x1b4a, 0x1b4c, 0x1b4e, 0x1b50, 0x1b52, 0x1b54, 0x1b56, + 0x1b58, 0x1b5a, 0x1b5c, 0x1b5e, 0x1b60, 0x1b62, 0x1b64, 0x1b66, + 0x1b68, 0x1b6a, 0x1b6c, 0x1b6e, 0x1b70, 0x1b72, 0x1b74, 0x1b76, + 0x1b78, 0x1b7a, 0x1b7c, 0x1b7e, 0x1b80, 0x1b82, 0x1b84, 0x1b86, + 0x1b88, 0x1b8a, 0x1b8c, 0x1b8e, 0x1b90, 0x1b92, 0x1b94, 0x1b96, + 0x1b98, 0x1b9a, 0x1b9c, 0x1b9e, 0x1ba0, 0x1ba2, 0x1ba4, 0x1ba6, + 0x1ba8, 0x1baa, 0x1bac, 0x1bae, 0x1bb0, 0x1bb2, 0x1bb4, 0x1bb6, + 0x1bb8, 0x1bba, 0x1bbc, 0x1bbe, 0x1bc0, 0x1bc2, 0x1bc4, 0x1bc6, + + 0x1bc8, 0x1bca, 0x1bcc, 0x1bce, 0x1bd0, 0x1bd2, 0x1bd4, 0x1bd6, + 0x1bd8, 0x1bda, 0x1bdc, 0x1bde, 0x1be0, 0x1be2, 0xffff, 0xffff, + 0x1be4, 0xffff, 0x1be6, 0xffff, 0xffff, 0x1be8, 0x1bea, 0x1bec, + 0x1bee, 0x1bf0, 0x1bf2, 0x1bf4, 0x1bf6, 0x1bf8, 0x1bfa, 0xffff, + 0x1bfc, 0xffff, 0x1bfe, 0xffff, 0xffff, 0x1c00, 0x1c02, 0xffff, + 0xffff, 0xffff, 0x1c04, 0x1c06, 0x1c08, 0x1c0a, 0xffff, 0xffff, + 0x1c0c, 0x1c0e, 0x1c10, 0x1c12, 0x1c14, 0x1c16, 0x1c18, 0x1c1a, + 0x1c1c, 0x1c1e, 0x1c20, 0x1c22, 0x1c24, 0x1c26, 0x1c28, 0x1c2a, + 0x1c2c, 0x1c2e, 0x1c30, 0x1c32, 0x1c34, 0x1c36, 0x1c38, 0x1c3a, + 0x1c3c, 0x1c3e, 0x1c40, 0x1c42, 0x1c44, 0x1c46, 0x1c48, 0x1c4a, + 0x1c4c, 0x1c4e, 0x1c50, 0x1c52, 0x1c54, 0x1c56, 0x1c58, 0x1c5a, + 0x1c5c, 0x1c5e, 0x1c60, 0x1c62, 0x1c64, 0x1c66, 0x1c68, 0x1c6a, + 0x1c6c, 0x1c6e, 0x1c70, 0x1c72, 0x1c74, 0x1c76, 0x1c78, 0x1c7a, + 0x1c7c, 0x1c7e, 0x1c80, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x1c82, 0x1c84, 0x1c86, 0x1c88, 0x1c8a, 0x1c8c, 0x1c8e, 0x1c90, + 0x1c92, 0x1c94, 0x1c96, 0x1c98, 0x1c9a, 0x1c9c, 0x1c9e, 0x1ca0, + 0x1ca2, 0x1ca4, 0x1ca6, 0x1ca8, 0x1caa, 0x1cac, 0x1cae, 0x1cb0, + 0x1cb2, 0x1cb4, 0x1cb6, 0x1cb8, 0x1cba, 0x1cbc, 0x1cbe, 0x1cc0, + 0x1cc2, 0x1cc4, 0x1cc6, 0x1cc8, 0x1cca, 0x1ccc, 0x1cce, 0x1cd0, + 0x1cd2, 0x1cd4, 0x1cd6, 0x1cd8, 0x1cda, 0x1cdc, 0x1cde, 0x1ce0, + 0x1ce2, 0x1ce4, 0x1ce6, 0x1ce8, 0x1cea, 0x1cec, 0x1cee, 0x1cf0, + 0x1cf2, 0x1cf4, 0x1cf6, 0x1cf8, 0x1cfa, 0x1cfc, 0x1cfe, 0x1d00, + 0x1d02, 0x1d04, 0x1d06, 0x1d08, 0x1d0a, 0x1d0c, 0x1d0e, 0x1d10, + 0x1d12, 0x1d14, 0x1d16, 0x1d18, 0x1d1a, 0x1d1c, 0x1d1e, 0x1d20, + 0x1d22, 0x1d24, 0x1d26, 0x1d28, 0x1d2a, 0x1d2c, 0x1d2e, 0x1d30, + 0x1d32, 0x1d34, 0x1d36, 0x1d38, 0x1d3a, 0x1d3c, 0x1d3e, 0x1d40, + 0x1d43, 0x1d46, 0x1d49, 0x1d4b, 0x1d4d, 0x1d4f, 0x1d52, 0x1d55, + 0x1d58, 0x1d5a, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x1d5c, 0x1d5f, 0x1d62, 0x1d65, 0x1d69, 0x1d6d, 0x1d70, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x1d73, 0x1d76, 0x1d79, 0x1d7c, 0x1d7f, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x1d82, 0xffff, 0x1d85, + 0x1d88, 0x1d8a, 0x1d8c, 0x1d8e, 0x1d90, 0x1d92, 0x1d94, 0x1d96, + 0x1d98, 0x1d9a, 0x1d9c, 0x1d9f, 0x1da2, 0x1da5, 0x1da8, 0x1dab, + 0x1dae, 0x1db1, 0x1db4, 0x1db7, 0x1dba, 0x1dbd, 0x1dc0, 0xffff, + 0x1dc3, 0x1dc6, 0x1dc9, 0x1dcc, 0x1dcf, 0xffff, 0x1dd2, 0xffff, + 0x1dd5, 0x1dd8, 0xffff, 0x1ddb, 0x1dde, 0xffff, 0x1de1, 0x1de4, + 0x1de7, 0x1dea, 0x1ded, 0x1df0, 0x1df3, 0x1df6, 0x1df9, 0x1dfc, + 0x1dff, 0x1e01, 0x1e03, 0x1e05, 0x1e07, 0x1e09, 0x1e0b, 0x1e0d, + 0x1e0f, 0x1e11, 0x1e13, 0x1e15, 0x1e17, 0x1e19, 0x1e1b, 0x1e1d, + 0x1e1f, 0x1e21, 0x1e23, 0x1e25, 0x1e27, 0x1e29, 0x1e2b, 0x1e2d, + 0x1e2f, 0x1e31, 0x1e33, 0x1e35, 0x1e37, 0x1e39, 0x1e3b, 0x1e3d, + 0x1e3f, 0x1e41, 0x1e43, 0x1e45, 0x1e47, 0x1e49, 0x1e4b, 0x1e4d, + 0x1e4f, 0x1e51, 0x1e53, 0x1e55, 0x1e57, 0x1e59, 0x1e5b, 0x1e5d, + 0x1e5f, 0x1e61, 0x1e63, 0x1e65, 0x1e67, 0x1e69, 0x1e6b, 0x1e6d, + 0x1e6f, 0x1e71, 0x1e73, 0x1e75, 0x1e77, 0x1e79, 0x1e7b, 0x1e7d, + 0x1e7f, 0x1e81, 0x1e83, 0x1e85, 0x1e87, 0x1e89, 0x1e8b, 0x1e8d, + 0x1e8f, 0x1e91, 0x1e93, 0x1e95, 0x1e97, 0x1e99, 0x1e9b, 0x1e9d, + 0x1e9f, 0x1ea1, 0x1ea3, 0x1ea5, 0x1ea7, 0x1ea9, 0x1eab, 0x1ead, + 0x1eaf, 0x1eb1, 0x1eb3, 0x1eb5, 0x1eb7, 0x1eb9, 0x1ebb, 0x1ebd, + 0x1ebf, 0x1ec1, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x1ec3, 0x1ec5, 0x1ec7, 0x1ec9, 0x1ecb, + 0x1ecd, 0x1ecf, 0x1ed1, 0x1ed3, 0x1ed5, 0x1ed7, 0x1ed9, 0x1edb, + 0x1edd, 0x1edf, 0x1ee1, 0x1ee3, 0x1ee5, 0x1ee7, 0x1ee9, 0x1eeb, + 0x1eed, 0x1eef, 0x1ef1, 0x1ef4, 0x1ef7, 0x1efa, 0x1efd, 0x1f00, + 0x1f03, 0x1f06, 0x1f09, 0x1f0c, 0x1f0f, 0x1f12, 0x1f15, 0x1f18, + 0x1f1b, 0x1f1e, 0x1f21, 0x1f24, 0x1f27, 0x1f29, 0x1f2b, 0x1f2d, + + 0x1f2f, 0x1f32, 0x1f35, 0x1f38, 0x1f3b, 0x1f3e, 0x1f41, 0x1f44, + 0x1f47, 0x1f4a, 0x1f4d, 0x1f50, 0x1f53, 0x1f56, 0x1f59, 0x1f5c, + 0x1f5f, 0x1f62, 0x1f65, 0x1f68, 0x1f6b, 0x1f6e, 0x1f71, 0x1f74, + 0x1f77, 0x1f7a, 0x1f7d, 0x1f80, 0x1f83, 0x1f86, 0x1f89, 0x1f8c, + 0x1f8f, 0x1f92, 0x1f95, 0x1f98, 0x1f9b, 0x1f9e, 0x1fa1, 0x1fa4, + 0x1fa7, 0x1faa, 0x1fad, 0x1fb0, 0x1fb3, 0x1fb6, 0x1fb9, 0x1fbc, + 0x1fbf, 0x1fc2, 0x1fc5, 0x1fc8, 0x1fcb, 0x1fce, 0x1fd1, 0x1fd4, + 0x1fd7, 0x1fda, 0x1fdd, 0x1fe0, 0x1fe3, 0x1fe6, 0x1fe9, 0x1fec, + 0x1fef, 0x1ff2, 0x1ff5, 0x1ff8, 0x1ffb, 0x1ffe, 0x2001, 0x2004, + 0x2007, 0x200a, 0x200d, 0x2010, 0x2013, 0x2016, 0x2019, 0x201c, + 0x201f, 0x2022, 0x2025, 0x2028, 0x202b, 0x202e, 0x2031, 0x2034, + 0x2037, 0x203a, 0x203d, 0x2040, 0x2043, 0x2046, 0x2049, 0x204d, + 0x2051, 0x2055, 0x2059, 0x205d, 0x2061, 0x2064, 0x2067, 0x206a, + 0x206d, 0x2070, 0x2073, 0x2076, 0x2079, 0x207c, 0x207f, 0x2082, + 0x2085, 0x2088, 0x208b, 0x208e, 0x2091, 0x2094, 0x2097, 0x209a, + 0x209d, 0x20a0, 0x20a3, 0x20a6, 0x20a9, 0x20ac, 0x20af, 0x20b2, + 0x20b5, 0x20b8, 0x20bb, 0x20be, 0x20c1, 0x20c4, 0x20c7, 0x20ca, + 0x20cd, 0x20d0, 0x20d3, 0x20d6, 0x20d9, 0x20dc, 0x20df, 0x20e2, + 0x20e5, 0x20e8, 0x20eb, 0x20ee, 0x20f1, 0x20f4, 0x20f7, 0x20fa, + 0x20fd, 0x2100, 0x2103, 0x2106, 0x2109, 0x210c, 0x210f, 0x2112, + 0x2115, 0x2118, 0x211b, 0x211e, 0x2121, 0x2124, 0x2127, 0x212a, + 0x212d, 0x2130, 0x2133, 0x2136, 0x2139, 0x213c, 0x213f, 0x2142, + 0x2145, 0x2148, 0x214b, 0x214e, 0x2151, 0x2154, 0x2157, 0x215a, + 0x215d, 0x2160, 0x2163, 0x2166, 0x2169, 0x216c, 0x216f, 0x2172, + 0x2175, 0x2178, 0x217b, 0x217e, 0x2181, 0x2184, 0x2187, 0x218a, + 0x218d, 0x2190, 0x2193, 0x2196, 0x2199, 0x219c, 0x219f, 0x21a2, + 0x21a5, 0x21a8, 0x21ab, 0x21ae, 0x21b1, 0x21b4, 0x21b7, 0x21ba, + 0x21bd, 0x21c0, 0x21c3, 0x21c6, 0x21c9, 0x21cc, 0x21cf, 0x21d2, + 0x21d5, 0x21d8, 0x21db, 0x21de, 0x21e1, 0x21e4, 0x21e7, 0x21ea, + 0x21ed, 0x21f0, 0x21f3, 0x21f6, 0x21f9, 0x21fc, 0x21ff, 0x2202, + 0x2205, 0x2208, 0x220b, 0x220f, 0x2213, 0x2217, 0x221a, 0x221d, + 0x2220, 0x2223, 0x2226, 0x2229, 0x222c, 0x222f, 0x2232, 0x2235, + + 0x2238, 0x223b, 0x223e, 0x2241, 0x2244, 0x2247, 0x224a, 0x224d, + 0x2250, 0x2253, 0x2256, 0x2259, 0x225c, 0x225f, 0x2262, 0x2265, + 0x2268, 0x226b, 0x226e, 0x2271, 0x2274, 0x2277, 0x227a, 0x227d, + 0x2280, 0x2283, 0x2286, 0x2289, 0x228c, 0x228f, 0x2292, 0x2295, + 0x2298, 0x229b, 0x229e, 0x22a1, 0x22a4, 0x22a7, 0x22aa, 0x22ad, + 0x22b0, 0x22b3, 0x22b6, 0x22b9, 0x22bc, 0x22bf, 0x22c2, 0x22c5, + 0x22c8, 0x22cb, 0x22ce, 0x22d1, 0x22d4, 0x22d7, 0x22da, 0x22dd, + 0x22e0, 0x22e3, 0x22e6, 0x22e9, 0x22ec, 0x22ef, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x22f2, 0x22f6, 0x22fa, 0x22fe, 0x2302, 0x2306, 0x230a, 0x230e, + 0x2312, 0x2316, 0x231a, 0x231e, 0x2322, 0x2326, 0x232a, 0x232e, + 0x2332, 0x2336, 0x233a, 0x233e, 0x2342, 0x2346, 0x234a, 0x234e, + 0x2352, 0x2356, 0x235a, 0x235e, 0x2362, 0x2366, 0x236a, 0x236e, + 0x2372, 0x2376, 0x237a, 0x237e, 0x2382, 0x2386, 0x238a, 0x238e, + 0x2392, 0x2396, 0x239a, 0x239e, 0x23a2, 0x23a6, 0x23aa, 0x23ae, + 0x23b2, 0x23b6, 0x23ba, 0x23be, 0x23c2, 0x23c6, 0x23ca, 0x23ce, + 0x23d2, 0x23d6, 0x23da, 0x23de, 0x23e2, 0x23e6, 0x23ea, 0x23ee, + 0xffff, 0xffff, 0x23f2, 0x23f6, 0x23fa, 0x23fe, 0x2402, 0x2406, + 0x240a, 0x240e, 0x2412, 0x2416, 0x241a, 0x241e, 0x2422, 0x2426, + 0x242a, 0x242e, 0x2432, 0x2436, 0x243a, 0x243e, 0x2442, 0x2446, + 0x244a, 0x244e, 0x2452, 0x2456, 0x245a, 0x245e, 0x2462, 0x2466, + 0x246a, 0x246e, 0x2472, 0x2476, 0x247a, 0x247e, 0x2482, 0x2486, + 0x248a, 0x248e, 0x2492, 0x2496, 0x249a, 0x249e, 0x24a2, 0x24a6, + 0x24aa, 0x24ae, 0x24b2, 0x24b6, 0x24ba, 0x24be, 0x24c2, 0x24c6, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x24ca, 0x24ce, 0x24d2, 0x24d7, 0x24dc, 0x24e1, 0x24e6, 0x24eb, + 0x24f0, 0x24f5, 0x24f9, 0x250c, 0x2515, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x251a, 0x251c, 0x251e, 0x2520, 0x2522, 0x2524, 0x2526, 0x2528, + 0x252a, 0x252c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x252e, 0x2530, 0x2532, 0x2534, 0x2536, 0x2538, 0x253a, 0x253c, + 0x253e, 0x2540, 0x2542, 0x2544, 0x2546, 0x2548, 0x254a, 0x254c, + 0x254e, 0x2550, 0x2552, 0x2554, 0x2556, 0xffff, 0xffff, 0x2558, + 0x255a, 0x255c, 0x255e, 0x2560, 0x2562, 0x2564, 0x2566, 0x2568, + 0x256a, 0x256c, 0x256e, 0xffff, 0x2570, 0x2572, 0x2574, 0x2576, + 0x2578, 0x257a, 0x257c, 0x257e, 0x2580, 0x2582, 0x2584, 0x2586, + 0x2588, 0x258a, 0x258c, 0x258e, 0x2590, 0x2592, 0x2594, 0xffff, + 0x2596, 0x2598, 0x259a, 0x259c, 0xffff, 0xffff, 0xffff, 0xffff, + 0x259e, 0x25a1, 0x25a4, 0xffff, 0x25a7, 0xffff, 0x25aa, 0x25ad, + 0x25b0, 0x25b3, 0x25b6, 0x25b9, 0x25bc, 0x25bf, 0x25c2, 0x25c5, + 0x25c8, 0x25ca, 0x25cc, 0x25ce, 0x25d0, 0x25d2, 0x25d4, 0x25d6, + 0x25d8, 0x25da, 0x25dc, 0x25de, 0x25e0, 0x25e2, 0x25e4, 0x25e6, + 0x25e8, 0x25ea, 0x25ec, 0x25ee, 0x25f0, 0x25f2, 0x25f4, 0x25f6, + 0x25f8, 0x25fa, 0x25fc, 0x25fe, 0x2600, 0x2602, 0x2604, 0x2606, + 0x2608, 0x260a, 0x260c, 0x260e, 0x2610, 0x2612, 0x2614, 0x2616, + 0x2618, 0x261a, 0x261c, 0x261e, 0x2620, 0x2622, 0x2624, 0x2626, + 0x2628, 0x262a, 0x262c, 0x262e, 0x2630, 0x2632, 0x2634, 0x2636, + 0x2638, 0x263a, 0x263c, 0x263e, 0x2640, 0x2642, 0x2644, 0x2646, + 0x2648, 0x264a, 0x264c, 0x264e, 0x2650, 0x2652, 0x2654, 0x2656, + 0x2658, 0x265a, 0x265c, 0x265e, 0x2660, 0x2662, 0x2664, 0x2666, + 0x2668, 0x266a, 0x266c, 0x266e, 0x2670, 0x2672, 0x2674, 0x2676, + 0x2678, 0x267a, 0x267c, 0x267e, 0x2680, 0x2682, 0x2684, 0x2686, + 0x2688, 0x268a, 0x268c, 0x268e, 0x2690, 0x2692, 0x2694, 0x2696, + 0x2698, 0x269a, 0x269c, 0x269e, 0x26a0, 0x26a2, 0x26a4, 0x26a6, + 0x26a8, 0x26aa, 0x26ac, 0x26ae, 0x26b0, 0x26b2, 0x26b5, 0x26b8, + 0x26bb, 0x26be, 0x26c1, 0x26c4, 0x26c7, 0xffff, 0xffff, 0xffff, + + 0xffff, 0x26ca, 0x26cc, 0x26ce, 0x26d0, 0x26d2, 0x26d4, 0x26d6, + 0x26d8, 0x26da, 0x26dc, 0x26de, 0x26e0, 0x26e2, 0x26e4, 0x26e6, + 0x26e8, 0x26ea, 0x26ec, 0x26ee, 0x26f0, 0x26f2, 0x26f4, 0x26f6, + 0x26f8, 0x26fa, 0x26fc, 0x26fe, 0x2700, 0x2702, 0x2704, 0x2706, + 0x2708, 0x270a, 0x270c, 0x270e, 0x2710, 0x2712, 0x2714, 0x2716, + 0x2718, 0x271a, 0x271c, 0x271e, 0x2720, 0x2722, 0x2724, 0x2726, + 0x2728, 0x272a, 0x272c, 0x272e, 0x2730, 0x2732, 0x2734, 0x2736, + 0x2738, 0x273a, 0x273c, 0x273e, 0x2740, 0x2742, 0x2744, 0x2746, + 0x2748, 0x274a, 0x274c, 0x274e, 0x2750, 0x2752, 0x2754, 0x2756, + 0x2758, 0x275a, 0x275c, 0x275e, 0x2760, 0x2762, 0x2764, 0x2766, + 0x2768, 0x276a, 0x276c, 0x276e, 0x2770, 0x2772, 0x2774, 0x2776, + 0x2778, 0x277a, 0x277c, 0x277e, 0x2780, 0x2782, 0x2784, 0x2786, + 0x2788, 0x278a, 0x278c, 0x278e, 0x2790, 0x2792, 0x2794, 0x2796, + 0x2798, 0x279a, 0x279c, 0x279e, 0x27a0, 0x27a2, 0x27a4, 0x27a6, + 0x27a8, 0x27aa, 0x27ac, 0x27ae, 0x27b0, 0x27b2, 0x27b4, 0x27b6, + 0x27b8, 0x27ba, 0x27bc, 0x27be, 0x27c0, 0x27c2, 0x27c4, 0x27c6, + 0x27c8, 0x27ca, 0x27cc, 0x27ce, 0x27d0, 0x27d2, 0x27d4, 0x27d6, + 0x27d8, 0x27da, 0x27dc, 0x27de, 0x27e0, 0x27e2, 0x27e4, 0x27e6, + 0x27e8, 0x27ea, 0x27ec, 0x27ee, 0x27f0, 0x27f2, 0x27f4, 0x27f6, + 0x27f8, 0x27fa, 0x27fc, 0x27fe, 0x2800, 0x2802, 0x2804, 0x2806, + 0x2808, 0x280a, 0x280c, 0x280e, 0x2810, 0x2812, 0x2814, 0x2816, + 0x2818, 0x281a, 0x281c, 0x281e, 0x2820, 0x2822, 0x2824, 0x2826, + 0x2828, 0x282a, 0x282c, 0x282e, 0x2830, 0x2832, 0x2834, 0x2836, + 0x2838, 0x283a, 0x283c, 0x283e, 0x2840, 0x2842, 0x2844, 0xffff, + 0xffff, 0xffff, 0x2846, 0x2848, 0x284a, 0x284c, 0x284e, 0x2850, + 0xffff, 0xffff, 0x2852, 0x2854, 0x2856, 0x2858, 0x285a, 0x285c, + 0xffff, 0xffff, 0x285e, 0x2860, 0x2862, 0x2864, 0x2866, 0x2868, + 0xffff, 0xffff, 0x286a, 0x286c, 0x286e, 0xffff, 0xffff, 0xffff, + 0x2870, 0x2872, 0x2874, 0x2876, 0x2878, 0x287a, 0x287c, 0xffff, + 0x287e, 0x2880, 0x2882, 0x2884, 0x2886, 0x2888, 0x288a, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x288c, 0x2891, + 0x2896, 0x289b, 0x28a0, 0x28a5, 0x28aa, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x28af, 0x28b4, 0x28b9, 0x28be, 0x28c3, + 0x28c8, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x28cd, 0x28cf, 0x28d1, 0x28d3, 0x28d5, 0x28d7, 0x28d9, 0x28db, + 0x28dd, 0x28df, 0x28e1, 0x28e3, 0x28e5, 0x28e7, 0x28e9, 0x28eb, + 0x28ed, 0x28ef, 0x28f1, 0x28f3, 0x28f5, 0x28f7, 0x28f9, 0x28fb, + 0x28fd, 0x28ff, 0x2901, 0x2903, 0x2905, 0x2907, 0x2909, 0x290b, + 0x290d, 0x290f, 0x2911, 0x2913, 0x2915, 0x2917, 0x2919, 0x291b, + 0x291d, 0x291f, 0x2921, 0x2923, 0x2925, 0x2927, 0x2929, 0x292b, + 0x292d, 0x292f, 0x2931, 0x2933, 0x2935, 0x2937, 0x2939, 0x293b, + 0x293d, 0x293f, 0x2941, 0x2943, 0x2945, 0x2947, 0x2949, 0x294b, + 0x294d, 0x294f, 0x2951, 0x2953, 0x2955, 0x2957, 0x2959, 0x295b, + 0x295d, 0x295f, 0x2961, 0x2963, 0x2965, 0x2967, 0x2969, 0x296b, + 0x296d, 0x296f, 0x2971, 0x2973, 0x2975, 0xffff, 0x2977, 0x2979, + 0x297b, 0x297d, 0x297f, 0x2981, 0x2983, 0x2985, 0x2987, 0x2989, + 0x298b, 0x298d, 0x298f, 0x2991, 0x2993, 0x2995, 0x2997, 0x2999, + 0x299b, 0x299d, 0x299f, 0x29a1, 0x29a3, 0x29a5, 0x29a7, 0x29a9, + 0x29ab, 0x29ad, 0x29af, 0x29b1, 0x29b3, 0x29b5, 0x29b7, 0x29b9, + 0x29bb, 0x29bd, 0x29bf, 0x29c1, 0x29c3, 0x29c5, 0x29c7, 0x29c9, + 0x29cb, 0x29cd, 0x29cf, 0x29d1, 0x29d3, 0x29d5, 0x29d7, 0x29d9, + 0x29db, 0x29dd, 0x29df, 0x29e1, 0x29e3, 0x29e5, 0x29e7, 0x29e9, + 0x29eb, 0x29ed, 0x29ef, 0x29f1, 0x29f3, 0x29f5, 0x29f7, 0x29f9, + 0x29fb, 0x29fd, 0x29ff, 0x2a01, 0x2a03, 0xffff, 0x2a05, 0x2a07, + 0xffff, 0xffff, 0x2a09, 0xffff, 0xffff, 0x2a0b, 0x2a0d, 0xffff, + 0xffff, 0x2a0f, 0x2a11, 0x2a13, 0x2a15, 0xffff, 0x2a17, 0x2a19, + 0x2a1b, 0x2a1d, 0x2a1f, 0x2a21, 0x2a23, 0x2a25, 0x2a27, 0x2a29, + 0x2a2b, 0x2a2d, 0xffff, 0x2a2f, 0xffff, 0x2a31, 0x2a33, 0x2a35, + 0x2a37, 0x2a39, 0x2a3b, 0x2a3d, 0xffff, 0x2a3f, 0x2a41, 0x2a43, + 0x2a45, 0x2a47, 0x2a49, 0x2a4b, 0x2a4d, 0x2a4f, 0x2a51, 0x2a53, + 0x2a55, 0x2a57, 0x2a59, 0x2a5b, 0x2a5d, 0x2a5f, 0x2a61, 0x2a63, + 0x2a65, 0x2a67, 0x2a69, 0x2a6b, 0x2a6d, 0x2a6f, 0x2a71, 0x2a73, + 0x2a75, 0x2a77, 0x2a79, 0x2a7b, 0x2a7d, 0x2a7f, 0x2a81, 0x2a83, + 0x2a85, 0x2a87, 0x2a89, 0x2a8b, 0x2a8d, 0x2a8f, 0x2a91, 0x2a93, + 0x2a95, 0x2a97, 0x2a99, 0x2a9b, 0x2a9d, 0x2a9f, 0x2aa1, 0x2aa3, + 0x2aa5, 0x2aa7, 0x2aa9, 0x2aab, 0x2aad, 0x2aaf, 0x2ab1, 0x2ab3, + + 0x2ab5, 0x2ab7, 0x2ab9, 0x2abb, 0x2abd, 0x2abf, 0xffff, 0x2ac1, + 0x2ac3, 0x2ac5, 0x2ac7, 0xffff, 0xffff, 0x2ac9, 0x2acb, 0x2acd, + 0x2acf, 0x2ad1, 0x2ad3, 0x2ad5, 0x2ad7, 0xffff, 0x2ad9, 0x2adb, + 0x2add, 0x2adf, 0x2ae1, 0x2ae3, 0x2ae5, 0xffff, 0x2ae7, 0x2ae9, + 0x2aeb, 0x2aed, 0x2aef, 0x2af1, 0x2af3, 0x2af5, 0x2af7, 0x2af9, + 0x2afb, 0x2afd, 0x2aff, 0x2b01, 0x2b03, 0x2b05, 0x2b07, 0x2b09, + 0x2b0b, 0x2b0d, 0x2b0f, 0x2b11, 0x2b13, 0x2b15, 0x2b17, 0x2b19, + 0x2b1b, 0x2b1d, 0xffff, 0x2b1f, 0x2b21, 0x2b23, 0x2b25, 0xffff, + 0x2b27, 0x2b29, 0x2b2b, 0x2b2d, 0x2b2f, 0xffff, 0x2b31, 0xffff, + 0xffff, 0xffff, 0x2b33, 0x2b35, 0x2b37, 0x2b39, 0x2b3b, 0x2b3d, + 0x2b3f, 0xffff, 0x2b41, 0x2b43, 0x2b45, 0x2b47, 0x2b49, 0x2b4b, + 0x2b4d, 0x2b4f, 0x2b51, 0x2b53, 0x2b55, 0x2b57, 0x2b59, 0x2b5b, + 0x2b5d, 0x2b5f, 0x2b61, 0x2b63, 0x2b65, 0x2b67, 0x2b69, 0x2b6b, + 0x2b6d, 0x2b6f, 0x2b71, 0x2b73, 0x2b75, 0x2b77, 0x2b79, 0x2b7b, + 0x2b7d, 0x2b7f, 0x2b81, 0x2b83, 0x2b85, 0x2b87, 0x2b89, 0x2b8b, + 0x2b8d, 0x2b8f, 0x2b91, 0x2b93, 0x2b95, 0x2b97, 0x2b99, 0x2b9b, + 0x2b9d, 0x2b9f, 0x2ba1, 0x2ba3, 0x2ba5, 0x2ba7, 0x2ba9, 0x2bab, + 0x2bad, 0x2baf, 0x2bb1, 0x2bb3, 0x2bb5, 0x2bb7, 0x2bb9, 0x2bbb, + 0x2bbd, 0x2bbf, 0x2bc1, 0x2bc3, 0x2bc5, 0x2bc7, 0x2bc9, 0x2bcb, + 0x2bcd, 0x2bcf, 0x2bd1, 0x2bd3, 0x2bd5, 0x2bd7, 0x2bd9, 0x2bdb, + 0x2bdd, 0x2bdf, 0x2be1, 0x2be3, 0x2be5, 0x2be7, 0x2be9, 0x2beb, + 0x2bed, 0x2bef, 0x2bf1, 0x2bf3, 0x2bf5, 0x2bf7, 0x2bf9, 0x2bfb, + 0x2bfd, 0x2bff, 0x2c01, 0x2c03, 0x2c05, 0x2c07, 0x2c09, 0x2c0b, + 0x2c0d, 0x2c0f, 0x2c11, 0x2c13, 0x2c15, 0x2c17, 0x2c19, 0x2c1b, + 0x2c1d, 0x2c1f, 0x2c21, 0x2c23, 0x2c25, 0x2c27, 0x2c29, 0x2c2b, + 0x2c2d, 0x2c2f, 0x2c31, 0x2c33, 0x2c35, 0x2c37, 0x2c39, 0x2c3b, + 0x2c3d, 0x2c3f, 0x2c41, 0x2c43, 0x2c45, 0x2c47, 0x2c49, 0x2c4b, + 0x2c4d, 0x2c4f, 0x2c51, 0x2c53, 0x2c55, 0x2c57, 0x2c59, 0x2c5b, + 0x2c5d, 0x2c5f, 0x2c61, 0x2c63, 0x2c65, 0x2c67, 0x2c69, 0x2c6b, + 0x2c6d, 0x2c6f, 0x2c71, 0x2c73, 0x2c75, 0x2c77, 0x2c79, 0x2c7b, + 0x2c7d, 0x2c7f, 0x2c81, 0x2c83, 0x2c85, 0x2c87, 0x2c89, 0x2c8b, + 0x2c8d, 0x2c8f, 0x2c91, 0x2c93, 0x2c95, 0x2c97, 0x2c99, 0x2c9b, + + 0x2c9d, 0x2c9f, 0x2ca1, 0x2ca3, 0x2ca5, 0x2ca7, 0x2ca9, 0x2cab, + 0x2cad, 0x2caf, 0x2cb1, 0x2cb3, 0x2cb5, 0x2cb7, 0x2cb9, 0x2cbb, + 0x2cbd, 0x2cbf, 0x2cc1, 0x2cc3, 0x2cc5, 0x2cc7, 0x2cc9, 0x2ccb, + 0x2ccd, 0x2ccf, 0x2cd1, 0x2cd3, 0x2cd5, 0x2cd7, 0x2cd9, 0x2cdb, + 0x2cdd, 0x2cdf, 0x2ce1, 0x2ce3, 0x2ce5, 0x2ce7, 0x2ce9, 0x2ceb, + 0x2ced, 0x2cef, 0x2cf1, 0x2cf3, 0x2cf5, 0x2cf7, 0x2cf9, 0x2cfb, + 0x2cfd, 0x2cff, 0x2d01, 0x2d03, 0x2d05, 0x2d07, 0x2d09, 0x2d0b, + 0x2d0d, 0x2d0f, 0x2d11, 0x2d13, 0x2d15, 0x2d17, 0x2d19, 0x2d1b, + 0x2d1d, 0x2d1f, 0x2d21, 0x2d23, 0x2d25, 0x2d27, 0x2d29, 0x2d2b, + 0x2d2d, 0x2d2f, 0x2d31, 0x2d33, 0x2d35, 0x2d37, 0x2d39, 0x2d3b, + 0x2d3d, 0x2d3f, 0x2d41, 0x2d43, 0x2d45, 0x2d47, 0x2d49, 0x2d4b, + 0x2d4d, 0x2d4f, 0x2d51, 0x2d53, 0x2d55, 0x2d57, 0x2d59, 0x2d5b, + 0x2d5d, 0x2d5f, 0x2d61, 0x2d63, 0x2d65, 0x2d67, 0x2d69, 0x2d6b, + 0x2d6d, 0x2d6f, 0x2d71, 0x2d73, 0x2d75, 0x2d77, 0x2d79, 0x2d7b, + 0x2d7d, 0x2d7f, 0x2d81, 0x2d83, 0x2d85, 0x2d87, 0x2d89, 0x2d8b, + 0x2d8d, 0x2d8f, 0x2d91, 0x2d93, 0x2d95, 0x2d97, 0x2d99, 0x2d9b, + 0x2d9d, 0x2d9f, 0x2da1, 0x2da3, 0x2da5, 0x2da7, 0x2da9, 0x2dab, + 0x2dad, 0x2daf, 0x2db1, 0x2db3, 0x2db5, 0x2db7, 0x2db9, 0x2dbb, + 0x2dbd, 0x2dbf, 0x2dc1, 0x2dc3, 0x2dc5, 0x2dc7, 0x2dc9, 0x2dcb, + 0x2dcd, 0x2dcf, 0x2dd1, 0x2dd3, 0x2dd5, 0x2dd7, 0x2dd9, 0x2ddb, + 0x2ddd, 0x2ddf, 0x2de1, 0x2de3, 0x2de5, 0x2de7, 0xffff, 0xffff, + 0x2de9, 0x2deb, 0x2ded, 0x2def, 0x2df1, 0x2df3, 0x2df5, 0x2df7, + 0x2df9, 0x2dfb, 0x2dfd, 0x2dff, 0x2e01, 0x2e03, 0x2e05, 0x2e07, + 0x2e09, 0x2e0b, 0x2e0d, 0x2e0f, 0x2e11, 0x2e13, 0x2e15, 0x2e17, + 0x2e19, 0x2e1b, 0x2e1d, 0x2e1f, 0x2e21, 0x2e23, 0x2e25, 0x2e27, + 0x2e29, 0x2e2b, 0x2e2d, 0x2e2f, 0x2e31, 0x2e33, 0x2e35, 0x2e37, + 0x2e39, 0x2e3b, 0x2e3d, 0x2e3f, 0x2e41, 0x2e43, 0x2e45, 0x2e47, + 0x2e49, 0x2e4b, 0x2e4d, 0x2e4f, 0x2e51, 0x2e53, 0x2e55, 0x2e57, + 0x2e59, 0x2e5b, 0x2e5d, 0x2e5f, 0x2e61, 0x2e63, 0x2e65, 0x2e67, + 0x2e69, 0x2e6b, 0x2e6d, 0x2e6f, 0x2e71, 0x2e73, 0x2e75, 0x2e77, + 0x2e79, 0x2e7b, 0x2e7d, 0x2e7f, 0x2e81, 0x2e83, 0x2e85, 0x2e87, + 0x2e89, 0x2e8b, 0x2e8d, 0x2e8f, 0x2e91, 0x2e93, 0x2e95, 0x2e97, + + 0x2e99, 0x2e9b, 0x2e9d, 0x2e9f, 0x2ea1, 0x2ea3, 0x2ea5, 0x2ea7, + 0x2ea9, 0x2eab, 0x2ead, 0x2eaf, 0x2eb1, 0x2eb3, 0x2eb5, 0x2eb7, + 0x2eb9, 0x2ebb, 0x2ebd, 0x2ebf, 0x2ec1, 0x2ec3, 0x2ec5, 0x2ec7, + 0x2ec9, 0x2ecb, 0x2ecd, 0x2ecf, 0x2ed1, 0x2ed3, 0x2ed5, 0x2ed7, + 0x2ed9, 0x2edb, 0x2edd, 0x2edf, 0x2ee1, 0x2ee3, 0x2ee5, 0x2ee7, + 0x2ee9, 0x2eeb, 0x2eed, 0x2eef, 0x2ef1, 0x2ef3, 0x2ef5, 0x2ef7, + 0x2ef9, 0x2efb, 0x2efd, 0x2eff, 0x2f01, 0x2f03, 0x2f05, 0x2f07, + 0x2f09, 0x2f0b, 0x2f0d, 0x2f0f, 0x2f11, 0x2f13, 0x2f15, 0x2f17, + 0x2f19, 0x2f1b, 0x2f1d, 0x2f1f, 0x2f21, 0x2f23, 0x2f25, 0x2f27, + 0x2f29, 0x2f2b, 0x2f2d, 0x2f2f, 0x2f31, 0x2f33, 0x2f35, 0x2f37, + 0x2f39, 0x2f3b, 0x2f3d, 0x2f3f, 0x2f41, 0x2f43, 0x2f45, 0x2f47, + 0x2f49, 0x2f4b, 0x2f4d, 0x2f4f, 0x2f51, 0x2f53, 0x2f55, 0x2f57, + 0x2f59, 0x2f5b, 0x2f5d, 0x2f5f, 0x2f61, 0x2f63, 0x2f65, 0x2f67, + 0x2f69, 0x2f6b, 0x2f6d, 0x2f6f, 0x2f71, 0x2f73, 0x2f75, 0x2f77, + 0x2f79, 0x2f7b, 0x2f7d, 0x2f7f, 0x2f81, 0x2f83, 0x2f85, 0x2f87, + 0x2f89, 0x2f8b, 0x2f8d, 0x2f8f, 0x2f91, 0x2f93, 0x2f95, 0x2f97, + 0x2f99, 0x2f9b, 0x2f9d, 0x2f9f, 0x2fa1, 0x2fa3, 0x2fa5, 0x2fa7, + 0x2fa9, 0x2fab, 0x2fad, 0x2faf, 0x2fb1, 0x2fb3, 0x2fb5, 0x2fb7, + 0x2fb9, 0x2fbb, 0x2fbd, 0x2fbf, 0x2fc1, 0x2fc3, 0x2fc5, 0x2fc7, + 0x2fc9, 0x2fcb, 0x2fcd, 0x2fcf, 0x2fd1, 0x2fd3, 0x2fd5, 0x2fd7, + 0x2fd9, 0x2fdb, 0x2fdd, 0x2fdf, 0x2fe1, 0x2fe3, 0x2fe5, 0x2fe7, + 0x2fe9, 0x2feb, 0x2fed, 0x2fef, 0x2ff1, 0x2ff3, 0x2ff5, 0x2ff7, + 0x2ff9, 0x2ffb, 0x2ffd, 0x2fff, 0x3001, 0x3003, 0x3005, 0x3007, + 0x3009, 0x300b, 0x300d, 0x300f, 0x3011, 0x3013, 0x3015, 0x3017, + 0x3019, 0x301b, 0x301d, 0x301f, 0x3021, 0x3023, 0x3025, 0x3027, + 0x3029, 0x302b, 0x302d, 0x302f, 0xffff, 0xffff, 0x3031, 0x3033, + 0x3035, 0x3037, 0x3039, 0x303b, 0x303d, 0x303f, 0x3041, 0x3043, + 0x3045, 0x3047, 0x3049, 0x304b, 0x304d, 0x304f, 0x3051, 0x3053, + 0x3055, 0x3057, 0x3059, 0x305b, 0x305d, 0x305f, 0x3061, 0x3063, + 0x3065, 0x3067, 0x3069, 0x306b, 0x306d, 0x306f, 0x3071, 0x3073, + 0x3075, 0x3077, 0x3079, 0x307b, 0x307d, 0x307f, 0x3081, 0x3083, + 0x3085, 0x3087, 0x3089, 0x308b, 0x308d, 0x308f, 0x3091, 0x3093, + + 0x3095, 0x3097, 0x3099, 0x309b, 0x309e, 0x30a0, 0x30a2, 0x30a4, + 0x30a6, 0x30a8, 0x30aa, 0x30ac, 0x30ae, 0x30b0, 0x30b3, 0x30b5, + 0x30b7, 0x30b9, 0x30bb, 0x30be, 0x30c0, 0x30c2, 0x30c4, 0x30c7, + 0x30c9, 0x30cb, 0x30cd, 0x30cf, 0x30d1, 0x30d4, 0x30d6, 0x30d8, + 0x30da, 0x30dc, 0x30de, 0x30e0, 0x30e2, 0x30e4, 0x30e6, 0x30e8, + 0x30ea, 0x30ec, 0x30ee, 0x30f0, 0x30f2, 0x30f4, 0x30f6, 0x30f8, + 0x30fa, 0x30fc, 0x30fe, 0x3100, 0x3102, 0x3105, 0x3107, 0x3109, + 0x310b, 0x310e, 0x3110, 0x3112, 0x3114, 0x3116, 0x3118, 0x311a, + 0x311c, 0x311e, 0x3120, 0x3122, 0x3124, 0x3126, 0x3128, 0x312a, + 0x312c, 0x312e, 0x3130, 0x3132, 0x3134, 0x3136, 0x3138, 0x313a, + 0x313c, 0x313e, 0x3140, 0x3142, 0x3144, 0x3146, 0x3148, 0x314a, + 0x314c, 0x314e, 0x3151, 0x3153, 0x3155, 0x3157, 0x3159, 0x315b, + 0x315d, 0x3160, 0x3163, 0x3165, 0x3167, 0x3169, 0x316b, 0x316d, + 0x316f, 0x3171, 0x3173, 0x3175, 0x3177, 0x317a, 0x317c, 0x317e, + 0x3180, 0x3182, 0x3185, 0x3187, 0x3189, 0x318b, 0x318d, 0x318f, + 0x3191, 0x3193, 0x3195, 0x3197, 0x319a, 0x319c, 0x319f, 0x31a1, + 0x31a3, 0x31a5, 0x31a7, 0x31a9, 0x31ab, 0x31ad, 0x31af, 0x31b1, + 0x31b3, 0x31b5, 0x31b8, 0x31ba, 0x31bc, 0x31be, 0x31c0, 0x31c2, + 0x31c5, 0x31c7, 0x31ca, 0x31cd, 0x31cf, 0x31d1, 0x31d3, 0x31d5, + 0x31d8, 0x31db, 0x31dd, 0x31df, 0x31e1, 0x31e3, 0x31e5, 0x31e7, + 0x31e9, 0x31eb, 0x31ed, 0x31ef, 0x31f1, 0x31f4, 0x31f6, 0x31f8, + 0x31fa, 0x31fc, 0x31fe, 0x3200, 0x3202, 0x3204, 0x3206, 0x3208, + 0x320a, 0x320c, 0x320e, 0x3210, 0x3212, 0x3214, 0x3216, 0x3218, + 0x321a, 0x321d, 0x321f, 0x3221, 0x3223, 0x3225, 0x3227, 0x322a, + 0x322c, 0x322e, 0x3230, 0x3232, 0x3234, 0x3236, 0x3238, 0x323a, + 0x323c, 0x323e, 0x3240, 0x3243, 0x3245, 0x3247, 0x3249, 0x324b, + 0x324d, 0x324f, 0x3251, 0x3253, 0x3255, 0x3257, 0x3259, 0x325b, + 0x325d, 0x325f, 0x3261, 0x3263, 0x3265, 0x3267, 0x326a, 0x326c, + 0x326e, 0x3270, 0x3272, 0x3274, 0x3277, 0x3279, 0x327b, 0x327d, + 0x327f, 0x3281, 0x3283, 0x3285, 0x3287, 0x328a, 0x328c, 0x328e, + 0x3290, 0x3293, 0x3295, 0x3297, 0x3299, 0x329b, 0x329d, 0x329f, + 0x32a2, 0x32a5, 0x32a8, 0x32aa, 0x32ad, 0x32af, 0x32b1, 0x32b3, + + 0x32b5, 0x32b7, 0x32b9, 0x32bb, 0x32bd, 0x32bf, 0x32c1, 0x32c4, + 0x32c6, 0x32c8, 0x32ca, 0x32cc, 0x32ce, 0x32d0, 0x32d3, 0x32d5, + 0x32d7, 0x32da, 0x32dd, 0x32df, 0x32e1, 0x32e3, 0x32e5, 0x32e7, + 0x32e9, 0x32eb, 0x32ed, 0x32ef, 0x32f2, 0x32f4, 0x32f7, 0x32f9, + 0x32fc, 0x32fe, 0x3300, 0x3302, 0x3305, 0x3307, 0x3309, 0x330c, + 0x330f, 0x3311, 0x3313, 0x3315, 0x3317, 0x3319, 0x331b, 0x331d, + 0x331f, 0x3321, 0x3323, 0x3325, 0x3327, 0x3329, 0x332c, 0x332e, + 0x3331, 0x3333, 0x3336, 0x3338, 0x333b, 0x333e, 0x3341, 0x3343, + 0x3345, 0x3347, 0x334a, 0x334d, 0x3350, 0x3353, 0x3355, 0x3357, + 0x3359, 0x335b, 0x335d, 0x335f, 0x3361, 0x3363, 0x3366, 0x3368, + 0x336a, 0x336c, 0x336e, 0x3371, 0x3373, 0x3376, 0x3379, 0x337b, + 0x337d, 0x337f, 0x3381, 0x3383, 0x3385, 0x3388, 0x338b, 0x338e, + 0x3390, 0x3392, 0x3395, 0x3397, 0x3399, 0x339b, 0x339e, 0x33a0, + 0x33a2, 0x33a4, 0x33a6, 0x33a8, 0x33ab, 0x33ad, 0x33af, 0x33b1, + 0x33b3, 0x33b5, 0x33b7, 0x33ba, 0x33bd, 0x33bf, 0x33c2, 0x33c4, + 0x33c7, 0x33c9, 0x33cb, 0x33cd, 0x33d0, 0x33d3, 0x33d5, 0x33d8, + 0x33da, 0x33dd, 0x33df, 0x33e1, 0x33e3, 0x33e5, 0x33e7, 0x33e9, + 0x33ec, 0x33ef, 0x33f2, 0x33f5, 0x33f7, 0x33f9, 0x33fb, 0x33fd, + 0x33ff, 0x3401, 0x3403, 0x3405, 0x3407, 0x3409, 0x340b, 0x340d, + 0x3410, 0x3412, 0x3414, 0x3416, 0x3418, 0x341a, 0x341c, 0x341e, + 0x3420, 0x3422, 0x3424, 0x3426, 0x3428, 0x342b, 0x342e, 0x3431, + 0x3433, 0x3435, 0x3437, 0x3439, 0x343c, 0x343e, 0x3441, 0x3443, + 0x3445, 0x3448, 0x344b, 0x344d, 0x344f, 0x3451, 0x3453, 0x3455, + 0x3457, 0x3459, 0x345b, 0x345d, 0x345f, 0x3461, 0x3463, 0x3465, + 0x3467, 0x3469, 0x346b, 0x346d, 0x346f, 0x3471, 0x3474, 0x3476, + 0x3478, 0x347a, 0x347c, 0x347e, 0x3481, 0x3484, 0x3486, 0x3488, + 0x348a, 0x348c, 0x348e, 0x3490, 0x3493, 0x3495, 0x3497, 0x3499, + 0x349b, 0x349e, 0x34a1, 0x34a3, 0x34a5, 0x34a7, 0x34aa, 0x34ac, + 0x34ae, 0x34b1, 0x34b4, 0x34b6, 0x34b8, 0x34ba, 0x34bd, 0x34bf, + 0x34c1, 0x34c3, 0x34c5, 0x34c7, 0x34c9, 0x34cb, 0x34ce, 0x34d0, + 0x34d2, 0x34d4, 0x34d7, 0x34d9, 0x34db, 0x34dd, 0x34df, 0x34e2, + 0x34e5, 0x34e7, 0x34e9, 0x34eb, 0x34ee, 0x34f0, 0x34f3, 0x34f5, + + 0x34f7, 0x34f9, 0x34fc, 0x34fe, 0x3500, 0x3502, 0x3504, 0x3506, + 0x3508, 0x350a, 0x350d, 0x350f, 0x3511, 0x3513, 0x3515, 0x3517, + 0x3519, 0x351c, 0x351e, 0x3521, 0x3524, 0x3527, 0x3529, 0x352b, + 0x352d, 0x352f, 0x3531, 0x3533, 0x3535, 0x3537, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +}; + +#define GET_DECOMPOSITION_INDEX(ucs4) \ + (ucs4 < 0x3400 \ + ? (uc_decomposition_trie[uc_decomposition_trie[ucs4>>4] + (ucs4 & 0xf)]) \ + : (ucs4 < 0x30000\ + ? uc_decomposition_trie[uc_decomposition_trie[((ucs4 - 0x3400)>>8) + 0x340] + (ucs4 & 0xff)]\ + : 0xffff)) + +static const unsigned short uc_decomposition_map[] = { + + 0x103, 0x20, 0x210, 0x20, 0x308, 0x109, 0x61, 0x210, + 0x20, 0x304, 0x109, 0x32, 0x109, 0x33, 0x210, 0x20, + 0x301, 0x110, 0x3bc, 0x210, 0x20, 0x327, 0x109, 0x31, + 0x109, 0x6f, 0x311, 0x31, 0x2044, 0x34, 0x311, 0x31, + 0x2044, 0x32, 0x311, 0x33, 0x2044, 0x34, 0x201, 0x41, + 0x300, 0x201, 0x41, 0x301, 0x201, 0x41, 0x302, 0x201, + 0x41, 0x303, 0x201, 0x41, 0x308, 0x201, 0x41, 0x30a, + 0x201, 0x43, 0x327, 0x201, 0x45, 0x300, 0x201, 0x45, + 0x301, 0x201, 0x45, 0x302, 0x201, 0x45, 0x308, 0x201, + 0x49, 0x300, 0x201, 0x49, 0x301, 0x201, 0x49, 0x302, + 0x201, 0x49, 0x308, 0x201, 0x4e, 0x303, 0x201, 0x4f, + 0x300, 0x201, 0x4f, 0x301, 0x201, 0x4f, 0x302, 0x201, + 0x4f, 0x303, 0x201, 0x4f, 0x308, 0x201, 0x55, 0x300, + 0x201, 0x55, 0x301, 0x201, 0x55, 0x302, 0x201, 0x55, + 0x308, 0x201, 0x59, 0x301, 0x201, 0x61, 0x300, 0x201, + 0x61, 0x301, 0x201, 0x61, 0x302, 0x201, 0x61, 0x303, + 0x201, 0x61, 0x308, 0x201, 0x61, 0x30a, 0x201, 0x63, + 0x327, 0x201, 0x65, 0x300, 0x201, 0x65, 0x301, 0x201, + 0x65, 0x302, 0x201, 0x65, 0x308, 0x201, 0x69, 0x300, + 0x201, 0x69, 0x301, 0x201, 0x69, 0x302, 0x201, 0x69, + 0x308, 0x201, 0x6e, 0x303, 0x201, 0x6f, 0x300, 0x201, + 0x6f, 0x301, 0x201, 0x6f, 0x302, 0x201, 0x6f, 0x303, + 0x201, 0x6f, 0x308, 0x201, 0x75, 0x300, 0x201, 0x75, + 0x301, 0x201, 0x75, 0x302, 0x201, 0x75, 0x308, 0x201, + 0x79, 0x301, 0x201, 0x79, 0x308, 0x201, 0x41, 0x304, + 0x201, 0x61, 0x304, 0x201, 0x41, 0x306, 0x201, 0x61, + 0x306, 0x201, 0x41, 0x328, 0x201, 0x61, 0x328, 0x201, + 0x43, 0x301, 0x201, 0x63, 0x301, 0x201, 0x43, 0x302, + 0x201, 0x63, 0x302, 0x201, 0x43, 0x307, 0x201, 0x63, + 0x307, 0x201, 0x43, 0x30c, 0x201, 0x63, 0x30c, 0x201, + 0x44, 0x30c, 0x201, 0x64, 0x30c, 0x201, 0x45, 0x304, + 0x201, 0x65, 0x304, 0x201, 0x45, 0x306, 0x201, 0x65, + 0x306, 0x201, 0x45, 0x307, 0x201, 0x65, 0x307, 0x201, + 0x45, 0x328, 0x201, 0x65, 0x328, 0x201, 0x45, 0x30c, + 0x201, 0x65, 0x30c, 0x201, 0x47, 0x302, 0x201, 0x67, + 0x302, 0x201, 0x47, 0x306, 0x201, 0x67, 0x306, 0x201, + 0x47, 0x307, 0x201, 0x67, 0x307, 0x201, 0x47, 0x327, + 0x201, 0x67, 0x327, 0x201, 0x48, 0x302, 0x201, 0x68, + 0x302, 0x201, 0x49, 0x303, 0x201, 0x69, 0x303, 0x201, + 0x49, 0x304, 0x201, 0x69, 0x304, 0x201, 0x49, 0x306, + 0x201, 0x69, 0x306, 0x201, 0x49, 0x328, 0x201, 0x69, + 0x328, 0x201, 0x49, 0x307, 0x210, 0x49, 0x4a, 0x210, + 0x69, 0x6a, 0x201, 0x4a, 0x302, 0x201, 0x6a, 0x302, + 0x201, 0x4b, 0x327, 0x201, 0x6b, 0x327, 0x201, 0x4c, + 0x301, 0x201, 0x6c, 0x301, 0x201, 0x4c, 0x327, 0x201, + 0x6c, 0x327, 0x201, 0x4c, 0x30c, 0x201, 0x6c, 0x30c, + 0x210, 0x4c, 0xb7, 0x210, 0x6c, 0xb7, 0x201, 0x4e, + 0x301, 0x201, 0x6e, 0x301, 0x201, 0x4e, 0x327, 0x201, + 0x6e, 0x327, 0x201, 0x4e, 0x30c, 0x201, 0x6e, 0x30c, + 0x210, 0x2bc, 0x6e, 0x201, 0x4f, 0x304, 0x201, 0x6f, + 0x304, 0x201, 0x4f, 0x306, 0x201, 0x6f, 0x306, 0x201, + 0x4f, 0x30b, 0x201, 0x6f, 0x30b, 0x201, 0x52, 0x301, + 0x201, 0x72, 0x301, 0x201, 0x52, 0x327, 0x201, 0x72, + 0x327, 0x201, 0x52, 0x30c, 0x201, 0x72, 0x30c, 0x201, + 0x53, 0x301, 0x201, 0x73, 0x301, 0x201, 0x53, 0x302, + 0x201, 0x73, 0x302, 0x201, 0x53, 0x327, 0x201, 0x73, + 0x327, 0x201, 0x53, 0x30c, 0x201, 0x73, 0x30c, 0x201, + 0x54, 0x327, 0x201, 0x74, 0x327, 0x201, 0x54, 0x30c, + 0x201, 0x74, 0x30c, 0x201, 0x55, 0x303, 0x201, 0x75, + 0x303, 0x201, 0x55, 0x304, 0x201, 0x75, 0x304, 0x201, + 0x55, 0x306, 0x201, 0x75, 0x306, 0x201, 0x55, 0x30a, + 0x201, 0x75, 0x30a, 0x201, 0x55, 0x30b, 0x201, 0x75, + 0x30b, 0x201, 0x55, 0x328, 0x201, 0x75, 0x328, 0x201, + 0x57, 0x302, 0x201, 0x77, 0x302, 0x201, 0x59, 0x302, + 0x201, 0x79, 0x302, 0x201, 0x59, 0x308, 0x201, 0x5a, + 0x301, 0x201, 0x7a, 0x301, 0x201, 0x5a, 0x307, 0x201, + 0x7a, 0x307, 0x201, 0x5a, 0x30c, 0x201, 0x7a, 0x30c, + 0x110, 0x73, 0x201, 0x4f, 0x31b, 0x201, 0x6f, 0x31b, + 0x201, 0x55, 0x31b, 0x201, 0x75, 0x31b, 0x210, 0x44, + 0x17d, 0x210, 0x44, 0x17e, 0x210, 0x64, 0x17e, 0x210, + 0x4c, 0x4a, 0x210, 0x4c, 0x6a, 0x210, 0x6c, 0x6a, + 0x210, 0x4e, 0x4a, 0x210, 0x4e, 0x6a, 0x210, 0x6e, + 0x6a, 0x201, 0x41, 0x30c, 0x201, 0x61, 0x30c, 0x201, + 0x49, 0x30c, 0x201, 0x69, 0x30c, 0x201, 0x4f, 0x30c, + 0x201, 0x6f, 0x30c, 0x201, 0x55, 0x30c, 0x201, 0x75, + 0x30c, 0x201, 0xdc, 0x304, 0x201, 0xfc, 0x304, 0x201, + 0xdc, 0x301, 0x201, 0xfc, 0x301, 0x201, 0xdc, 0x30c, + 0x201, 0xfc, 0x30c, 0x201, 0xdc, 0x300, 0x201, 0xfc, + 0x300, 0x201, 0xc4, 0x304, 0x201, 0xe4, 0x304, 0x201, + 0x226, 0x304, 0x201, 0x227, 0x304, 0x201, 0xc6, 0x304, + 0x201, 0xe6, 0x304, 0x201, 0x47, 0x30c, 0x201, 0x67, + 0x30c, 0x201, 0x4b, 0x30c, 0x201, 0x6b, 0x30c, 0x201, + 0x4f, 0x328, 0x201, 0x6f, 0x328, 0x201, 0x1ea, 0x304, + 0x201, 0x1eb, 0x304, 0x201, 0x1b7, 0x30c, 0x201, 0x292, + 0x30c, 0x201, 0x6a, 0x30c, 0x210, 0x44, 0x5a, 0x210, + 0x44, 0x7a, 0x210, 0x64, 0x7a, 0x201, 0x47, 0x301, + 0x201, 0x67, 0x301, 0x201, 0x4e, 0x300, 0x201, 0x6e, + 0x300, 0x201, 0xc5, 0x301, 0x201, 0xe5, 0x301, 0x201, + 0xc6, 0x301, 0x201, 0xe6, 0x301, 0x201, 0xd8, 0x301, + 0x201, 0xf8, 0x301, 0x201, 0x41, 0x30f, 0x201, 0x61, + 0x30f, 0x201, 0x41, 0x311, 0x201, 0x61, 0x311, 0x201, + 0x45, 0x30f, 0x201, 0x65, 0x30f, 0x201, 0x45, 0x311, + 0x201, 0x65, 0x311, 0x201, 0x49, 0x30f, 0x201, 0x69, + 0x30f, 0x201, 0x49, 0x311, 0x201, 0x69, 0x311, 0x201, + 0x4f, 0x30f, 0x201, 0x6f, 0x30f, 0x201, 0x4f, 0x311, + 0x201, 0x6f, 0x311, 0x201, 0x52, 0x30f, 0x201, 0x72, + 0x30f, 0x201, 0x52, 0x311, 0x201, 0x72, 0x311, 0x201, + 0x55, 0x30f, 0x201, 0x75, 0x30f, 0x201, 0x55, 0x311, + 0x201, 0x75, 0x311, 0x201, 0x53, 0x326, 0x201, 0x73, + 0x326, 0x201, 0x54, 0x326, 0x201, 0x74, 0x326, 0x201, + 0x48, 0x30c, 0x201, 0x68, 0x30c, 0x201, 0x41, 0x307, + 0x201, 0x61, 0x307, 0x201, 0x45, 0x327, 0x201, 0x65, + 0x327, 0x201, 0xd6, 0x304, 0x201, 0xf6, 0x304, 0x201, + 0xd5, 0x304, 0x201, 0xf5, 0x304, 0x201, 0x4f, 0x307, + 0x201, 0x6f, 0x307, 0x201, 0x22e, 0x304, 0x201, 0x22f, + 0x304, 0x201, 0x59, 0x304, 0x201, 0x79, 0x304, 0x109, + 0x68, 0x109, 0x266, 0x109, 0x6a, 0x109, 0x72, 0x109, + 0x279, 0x109, 0x27b, 0x109, 0x281, 0x109, 0x77, 0x109, + 0x79, 0x210, 0x20, 0x306, 0x210, 0x20, 0x307, 0x210, + 0x20, 0x30a, 0x210, 0x20, 0x328, 0x210, 0x20, 0x303, + 0x210, 0x20, 0x30b, 0x109, 0x263, 0x109, 0x6c, 0x109, + 0x73, 0x109, 0x78, 0x109, 0x295, 0x101, 0x300, 0x101, + 0x301, 0x101, 0x313, 0x201, 0x308, 0x301, 0x101, 0x2b9, + 0x210, 0x20, 0x345, 0x101, 0x3b, 0x210, 0x20, 0x301, + 0x201, 0xa8, 0x301, 0x201, 0x391, 0x301, 0x101, 0xb7, + 0x201, 0x395, 0x301, 0x201, 0x397, 0x301, 0x201, 0x399, + 0x301, 0x201, 0x39f, 0x301, 0x201, 0x3a5, 0x301, 0x201, + 0x3a9, 0x301, 0x201, 0x3ca, 0x301, 0x201, 0x399, 0x308, + 0x201, 0x3a5, 0x308, 0x201, 0x3b1, 0x301, 0x201, 0x3b5, + 0x301, 0x201, 0x3b7, 0x301, 0x201, 0x3b9, 0x301, 0x201, + 0x3cb, 0x301, 0x201, 0x3b9, 0x308, 0x201, 0x3c5, 0x308, + 0x201, 0x3bf, 0x301, 0x201, 0x3c5, 0x301, 0x201, 0x3c9, + 0x301, 0x110, 0x3b2, 0x110, 0x3b8, 0x110, 0x3a5, 0x201, + 0x3d2, 0x301, 0x201, 0x3d2, 0x308, 0x110, 0x3c6, 0x110, + 0x3c0, 0x110, 0x3ba, 0x110, 0x3c1, 0x110, 0x3c2, 0x110, + 0x398, 0x110, 0x3b5, 0x110, 0x3a3, 0x201, 0x415, 0x300, + 0x201, 0x415, 0x308, 0x201, 0x413, 0x301, 0x201, 0x406, + 0x308, 0x201, 0x41a, 0x301, 0x201, 0x418, 0x300, 0x201, + 0x423, 0x306, 0x201, 0x418, 0x306, 0x201, 0x438, 0x306, + 0x201, 0x435, 0x300, 0x201, 0x435, 0x308, 0x201, 0x433, + 0x301, 0x201, 0x456, 0x308, 0x201, 0x43a, 0x301, 0x201, + 0x438, 0x300, 0x201, 0x443, 0x306, 0x201, 0x474, 0x30f, + 0x201, 0x475, 0x30f, 0x201, 0x416, 0x306, 0x201, 0x436, + 0x306, 0x201, 0x410, 0x306, 0x201, 0x430, 0x306, 0x201, + 0x410, 0x308, 0x201, 0x430, 0x308, 0x201, 0x415, 0x306, + 0x201, 0x435, 0x306, 0x201, 0x4d8, 0x308, 0x201, 0x4d9, + 0x308, 0x201, 0x416, 0x308, 0x201, 0x436, 0x308, 0x201, + 0x417, 0x308, 0x201, 0x437, 0x308, 0x201, 0x418, 0x304, + 0x201, 0x438, 0x304, 0x201, 0x418, 0x308, 0x201, 0x438, + 0x308, 0x201, 0x41e, 0x308, 0x201, 0x43e, 0x308, 0x201, + 0x4e8, 0x308, 0x201, 0x4e9, 0x308, 0x201, 0x42d, 0x308, + 0x201, 0x44d, 0x308, 0x201, 0x423, 0x304, 0x201, 0x443, + 0x304, 0x201, 0x423, 0x308, 0x201, 0x443, 0x308, 0x201, + 0x423, 0x30b, 0x201, 0x443, 0x30b, 0x201, 0x427, 0x308, + 0x201, 0x447, 0x308, 0x201, 0x42b, 0x308, 0x201, 0x44b, + 0x308, 0x210, 0x565, 0x582, 0x201, 0x627, 0x653, 0x201, + 0x627, 0x654, 0x201, 0x648, 0x654, 0x201, 0x627, 0x655, + 0x201, 0x64a, 0x654, 0x210, 0x627, 0x674, 0x210, 0x648, + 0x674, 0x210, 0x6c7, 0x674, 0x210, 0x64a, 0x674, 0x201, + 0x6d5, 0x654, 0x201, 0x6c1, 0x654, 0x201, 0x6d2, 0x654, + 0x201, 0x928, 0x93c, 0x201, 0x930, 0x93c, 0x201, 0x933, + 0x93c, 0x201, 0x915, 0x93c, 0x201, 0x916, 0x93c, 0x201, + 0x917, 0x93c, 0x201, 0x91c, 0x93c, 0x201, 0x921, 0x93c, + 0x201, 0x922, 0x93c, 0x201, 0x92b, 0x93c, 0x201, 0x92f, + 0x93c, 0x201, 0x9c7, 0x9be, 0x201, 0x9c7, 0x9d7, 0x201, + 0x9a1, 0x9bc, 0x201, 0x9a2, 0x9bc, 0x201, 0x9af, 0x9bc, + 0x201, 0xa32, 0xa3c, 0x201, 0xa38, 0xa3c, 0x201, 0xa16, + 0xa3c, 0x201, 0xa17, 0xa3c, 0x201, 0xa1c, 0xa3c, 0x201, + 0xa2b, 0xa3c, 0x201, 0xb47, 0xb56, 0x201, 0xb47, 0xb3e, + 0x201, 0xb47, 0xb57, 0x201, 0xb21, 0xb3c, 0x201, 0xb22, + 0xb3c, 0x201, 0xb92, 0xbd7, 0x201, 0xbc6, 0xbbe, 0x201, + 0xbc7, 0xbbe, 0x201, 0xbc6, 0xbd7, 0x201, 0xc46, 0xc56, + 0x201, 0xcbf, 0xcd5, 0x201, 0xcc6, 0xcd5, 0x201, 0xcc6, + 0xcd6, 0x201, 0xcc6, 0xcc2, 0x201, 0xcca, 0xcd5, 0x201, + 0xd46, 0xd3e, 0x201, 0xd47, 0xd3e, 0x201, 0xd46, 0xd57, + 0x201, 0xdd9, 0xdca, 0x201, 0xdd9, 0xdcf, 0x201, 0xddc, + 0xdca, 0x201, 0xdd9, 0xddf, 0x210, 0xe4d, 0xe32, 0x210, + 0xecd, 0xeb2, 0x210, 0xeab, 0xe99, 0x210, 0xeab, 0xea1, + 0x103, 0xf0b, 0x201, 0xf42, 0xfb7, 0x201, 0xf4c, 0xfb7, + 0x201, 0xf51, 0xfb7, 0x201, 0xf56, 0xfb7, 0x201, 0xf5b, + 0xfb7, 0x201, 0xf40, 0xfb5, 0x201, 0xf71, 0xf72, 0x201, + 0xf71, 0xf74, 0x201, 0xfb2, 0xf80, 0x210, 0xfb2, 0xf81, + 0x201, 0xfb3, 0xf80, 0x210, 0xfb3, 0xf81, 0x201, 0xf71, + 0xf80, 0x201, 0xf92, 0xfb7, 0x201, 0xf9c, 0xfb7, 0x201, + 0xfa1, 0xfb7, 0x201, 0xfa6, 0xfb7, 0x201, 0xfab, 0xfb7, + 0x201, 0xf90, 0xfb5, 0x201, 0x1025, 0x102e, 0x109, 0x10dc, + 0x201, 0x1b05, 0x1b35, 0x201, 0x1b07, 0x1b35, 0x201, 0x1b09, + 0x1b35, 0x201, 0x1b0b, 0x1b35, 0x201, 0x1b0d, 0x1b35, 0x201, + 0x1b11, 0x1b35, 0x201, 0x1b3a, 0x1b35, 0x201, 0x1b3c, 0x1b35, + 0x201, 0x1b3e, 0x1b35, 0x201, 0x1b3f, 0x1b35, 0x201, 0x1b42, + 0x1b35, 0x109, 0x41, 0x109, 0xc6, 0x109, 0x42, 0x109, + 0x44, 0x109, 0x45, 0x109, 0x18e, 0x109, 0x47, 0x109, + 0x48, 0x109, 0x49, 0x109, 0x4a, 0x109, 0x4b, 0x109, + 0x4c, 0x109, 0x4d, 0x109, 0x4e, 0x109, 0x4f, 0x109, + 0x222, 0x109, 0x50, 0x109, 0x52, 0x109, 0x54, 0x109, + 0x55, 0x109, 0x57, 0x109, 0x61, 0x109, 0x250, 0x109, + 0x251, 0x109, 0x1d02, 0x109, 0x62, 0x109, 0x64, 0x109, + 0x65, 0x109, 0x259, 0x109, 0x25b, 0x109, 0x25c, 0x109, + 0x67, 0x109, 0x6b, 0x109, 0x6d, 0x109, 0x14b, 0x109, + 0x6f, 0x109, 0x254, 0x109, 0x1d16, 0x109, 0x1d17, 0x109, + 0x70, 0x109, 0x74, 0x109, 0x75, 0x109, 0x1d1d, 0x109, + 0x26f, 0x109, 0x76, 0x109, 0x1d25, 0x109, 0x3b2, 0x109, + 0x3b3, 0x109, 0x3b4, 0x109, 0x3c6, 0x109, 0x3c7, 0x10a, + 0x69, 0x10a, 0x72, 0x10a, 0x75, 0x10a, 0x76, 0x10a, + 0x3b2, 0x10a, 0x3b3, 0x10a, 0x3c1, 0x10a, 0x3c6, 0x10a, + 0x3c7, 0x109, 0x43d, 0x109, 0x252, 0x109, 0x63, 0x109, + 0x255, 0x109, 0xf0, 0x109, 0x25c, 0x109, 0x66, 0x109, + 0x25f, 0x109, 0x261, 0x109, 0x265, 0x109, 0x268, 0x109, + 0x269, 0x109, 0x26a, 0x109, 0x1d7b, 0x109, 0x29d, 0x109, + 0x26d, 0x109, 0x1d85, 0x109, 0x29f, 0x109, 0x271, 0x109, + 0x270, 0x109, 0x272, 0x109, 0x273, 0x109, 0x274, 0x109, + 0x275, 0x109, 0x278, 0x109, 0x282, 0x109, 0x283, 0x109, + 0x1ab, 0x109, 0x289, 0x109, 0x28a, 0x109, 0x1d1c, 0x109, + 0x28b, 0x109, 0x28c, 0x109, 0x7a, 0x109, 0x290, 0x109, + 0x291, 0x109, 0x292, 0x109, 0x3b8, 0x201, 0x41, 0x325, + 0x201, 0x61, 0x325, 0x201, 0x42, 0x307, 0x201, 0x62, + 0x307, 0x201, 0x42, 0x323, 0x201, 0x62, 0x323, 0x201, + 0x42, 0x331, 0x201, 0x62, 0x331, 0x201, 0xc7, 0x301, + 0x201, 0xe7, 0x301, 0x201, 0x44, 0x307, 0x201, 0x64, + 0x307, 0x201, 0x44, 0x323, 0x201, 0x64, 0x323, 0x201, + 0x44, 0x331, 0x201, 0x64, 0x331, 0x201, 0x44, 0x327, + 0x201, 0x64, 0x327, 0x201, 0x44, 0x32d, 0x201, 0x64, + 0x32d, 0x201, 0x112, 0x300, 0x201, 0x113, 0x300, 0x201, + 0x112, 0x301, 0x201, 0x113, 0x301, 0x201, 0x45, 0x32d, + 0x201, 0x65, 0x32d, 0x201, 0x45, 0x330, 0x201, 0x65, + 0x330, 0x201, 0x228, 0x306, 0x201, 0x229, 0x306, 0x201, + 0x46, 0x307, 0x201, 0x66, 0x307, 0x201, 0x47, 0x304, + 0x201, 0x67, 0x304, 0x201, 0x48, 0x307, 0x201, 0x68, + 0x307, 0x201, 0x48, 0x323, 0x201, 0x68, 0x323, 0x201, + 0x48, 0x308, 0x201, 0x68, 0x308, 0x201, 0x48, 0x327, + 0x201, 0x68, 0x327, 0x201, 0x48, 0x32e, 0x201, 0x68, + 0x32e, 0x201, 0x49, 0x330, 0x201, 0x69, 0x330, 0x201, + 0xcf, 0x301, 0x201, 0xef, 0x301, 0x201, 0x4b, 0x301, + 0x201, 0x6b, 0x301, 0x201, 0x4b, 0x323, 0x201, 0x6b, + 0x323, 0x201, 0x4b, 0x331, 0x201, 0x6b, 0x331, 0x201, + 0x4c, 0x323, 0x201, 0x6c, 0x323, 0x201, 0x1e36, 0x304, + 0x201, 0x1e37, 0x304, 0x201, 0x4c, 0x331, 0x201, 0x6c, + 0x331, 0x201, 0x4c, 0x32d, 0x201, 0x6c, 0x32d, 0x201, + 0x4d, 0x301, 0x201, 0x6d, 0x301, 0x201, 0x4d, 0x307, + 0x201, 0x6d, 0x307, 0x201, 0x4d, 0x323, 0x201, 0x6d, + 0x323, 0x201, 0x4e, 0x307, 0x201, 0x6e, 0x307, 0x201, + 0x4e, 0x323, 0x201, 0x6e, 0x323, 0x201, 0x4e, 0x331, + 0x201, 0x6e, 0x331, 0x201, 0x4e, 0x32d, 0x201, 0x6e, + 0x32d, 0x201, 0xd5, 0x301, 0x201, 0xf5, 0x301, 0x201, + 0xd5, 0x308, 0x201, 0xf5, 0x308, 0x201, 0x14c, 0x300, + 0x201, 0x14d, 0x300, 0x201, 0x14c, 0x301, 0x201, 0x14d, + 0x301, 0x201, 0x50, 0x301, 0x201, 0x70, 0x301, 0x201, + 0x50, 0x307, 0x201, 0x70, 0x307, 0x201, 0x52, 0x307, + 0x201, 0x72, 0x307, 0x201, 0x52, 0x323, 0x201, 0x72, + 0x323, 0x201, 0x1e5a, 0x304, 0x201, 0x1e5b, 0x304, 0x201, + 0x52, 0x331, 0x201, 0x72, 0x331, 0x201, 0x53, 0x307, + 0x201, 0x73, 0x307, 0x201, 0x53, 0x323, 0x201, 0x73, + 0x323, 0x201, 0x15a, 0x307, 0x201, 0x15b, 0x307, 0x201, + 0x160, 0x307, 0x201, 0x161, 0x307, 0x201, 0x1e62, 0x307, + 0x201, 0x1e63, 0x307, 0x201, 0x54, 0x307, 0x201, 0x74, + 0x307, 0x201, 0x54, 0x323, 0x201, 0x74, 0x323, 0x201, + 0x54, 0x331, 0x201, 0x74, 0x331, 0x201, 0x54, 0x32d, + 0x201, 0x74, 0x32d, 0x201, 0x55, 0x324, 0x201, 0x75, + 0x324, 0x201, 0x55, 0x330, 0x201, 0x75, 0x330, 0x201, + 0x55, 0x32d, 0x201, 0x75, 0x32d, 0x201, 0x168, 0x301, + 0x201, 0x169, 0x301, 0x201, 0x16a, 0x308, 0x201, 0x16b, + 0x308, 0x201, 0x56, 0x303, 0x201, 0x76, 0x303, 0x201, + 0x56, 0x323, 0x201, 0x76, 0x323, 0x201, 0x57, 0x300, + 0x201, 0x77, 0x300, 0x201, 0x57, 0x301, 0x201, 0x77, + 0x301, 0x201, 0x57, 0x308, 0x201, 0x77, 0x308, 0x201, + 0x57, 0x307, 0x201, 0x77, 0x307, 0x201, 0x57, 0x323, + 0x201, 0x77, 0x323, 0x201, 0x58, 0x307, 0x201, 0x78, + 0x307, 0x201, 0x58, 0x308, 0x201, 0x78, 0x308, 0x201, + 0x59, 0x307, 0x201, 0x79, 0x307, 0x201, 0x5a, 0x302, + 0x201, 0x7a, 0x302, 0x201, 0x5a, 0x323, 0x201, 0x7a, + 0x323, 0x201, 0x5a, 0x331, 0x201, 0x7a, 0x331, 0x201, + 0x68, 0x331, 0x201, 0x74, 0x308, 0x201, 0x77, 0x30a, + 0x201, 0x79, 0x30a, 0x210, 0x61, 0x2be, 0x201, 0x17f, + 0x307, 0x201, 0x41, 0x323, 0x201, 0x61, 0x323, 0x201, + 0x41, 0x309, 0x201, 0x61, 0x309, 0x201, 0xc2, 0x301, + 0x201, 0xe2, 0x301, 0x201, 0xc2, 0x300, 0x201, 0xe2, + 0x300, 0x201, 0xc2, 0x309, 0x201, 0xe2, 0x309, 0x201, + 0xc2, 0x303, 0x201, 0xe2, 0x303, 0x201, 0x1ea0, 0x302, + 0x201, 0x1ea1, 0x302, 0x201, 0x102, 0x301, 0x201, 0x103, + 0x301, 0x201, 0x102, 0x300, 0x201, 0x103, 0x300, 0x201, + 0x102, 0x309, 0x201, 0x103, 0x309, 0x201, 0x102, 0x303, + 0x201, 0x103, 0x303, 0x201, 0x1ea0, 0x306, 0x201, 0x1ea1, + 0x306, 0x201, 0x45, 0x323, 0x201, 0x65, 0x323, 0x201, + 0x45, 0x309, 0x201, 0x65, 0x309, 0x201, 0x45, 0x303, + 0x201, 0x65, 0x303, 0x201, 0xca, 0x301, 0x201, 0xea, + 0x301, 0x201, 0xca, 0x300, 0x201, 0xea, 0x300, 0x201, + 0xca, 0x309, 0x201, 0xea, 0x309, 0x201, 0xca, 0x303, + 0x201, 0xea, 0x303, 0x201, 0x1eb8, 0x302, 0x201, 0x1eb9, + 0x302, 0x201, 0x49, 0x309, 0x201, 0x69, 0x309, 0x201, + 0x49, 0x323, 0x201, 0x69, 0x323, 0x201, 0x4f, 0x323, + 0x201, 0x6f, 0x323, 0x201, 0x4f, 0x309, 0x201, 0x6f, + 0x309, 0x201, 0xd4, 0x301, 0x201, 0xf4, 0x301, 0x201, + 0xd4, 0x300, 0x201, 0xf4, 0x300, 0x201, 0xd4, 0x309, + 0x201, 0xf4, 0x309, 0x201, 0xd4, 0x303, 0x201, 0xf4, + 0x303, 0x201, 0x1ecc, 0x302, 0x201, 0x1ecd, 0x302, 0x201, + 0x1a0, 0x301, 0x201, 0x1a1, 0x301, 0x201, 0x1a0, 0x300, + 0x201, 0x1a1, 0x300, 0x201, 0x1a0, 0x309, 0x201, 0x1a1, + 0x309, 0x201, 0x1a0, 0x303, 0x201, 0x1a1, 0x303, 0x201, + 0x1a0, 0x323, 0x201, 0x1a1, 0x323, 0x201, 0x55, 0x323, + 0x201, 0x75, 0x323, 0x201, 0x55, 0x309, 0x201, 0x75, + 0x309, 0x201, 0x1af, 0x301, 0x201, 0x1b0, 0x301, 0x201, + 0x1af, 0x300, 0x201, 0x1b0, 0x300, 0x201, 0x1af, 0x309, + 0x201, 0x1b0, 0x309, 0x201, 0x1af, 0x303, 0x201, 0x1b0, + 0x303, 0x201, 0x1af, 0x323, 0x201, 0x1b0, 0x323, 0x201, + 0x59, 0x300, 0x201, 0x79, 0x300, 0x201, 0x59, 0x323, + 0x201, 0x79, 0x323, 0x201, 0x59, 0x309, 0x201, 0x79, + 0x309, 0x201, 0x59, 0x303, 0x201, 0x79, 0x303, 0x201, + 0x3b1, 0x313, 0x201, 0x3b1, 0x314, 0x201, 0x1f00, 0x300, + 0x201, 0x1f01, 0x300, 0x201, 0x1f00, 0x301, 0x201, 0x1f01, + 0x301, 0x201, 0x1f00, 0x342, 0x201, 0x1f01, 0x342, 0x201, + 0x391, 0x313, 0x201, 0x391, 0x314, 0x201, 0x1f08, 0x300, + 0x201, 0x1f09, 0x300, 0x201, 0x1f08, 0x301, 0x201, 0x1f09, + 0x301, 0x201, 0x1f08, 0x342, 0x201, 0x1f09, 0x342, 0x201, + 0x3b5, 0x313, 0x201, 0x3b5, 0x314, 0x201, 0x1f10, 0x300, + 0x201, 0x1f11, 0x300, 0x201, 0x1f10, 0x301, 0x201, 0x1f11, + 0x301, 0x201, 0x395, 0x313, 0x201, 0x395, 0x314, 0x201, + 0x1f18, 0x300, 0x201, 0x1f19, 0x300, 0x201, 0x1f18, 0x301, + 0x201, 0x1f19, 0x301, 0x201, 0x3b7, 0x313, 0x201, 0x3b7, + 0x314, 0x201, 0x1f20, 0x300, 0x201, 0x1f21, 0x300, 0x201, + 0x1f20, 0x301, 0x201, 0x1f21, 0x301, 0x201, 0x1f20, 0x342, + 0x201, 0x1f21, 0x342, 0x201, 0x397, 0x313, 0x201, 0x397, + 0x314, 0x201, 0x1f28, 0x300, 0x201, 0x1f29, 0x300, 0x201, + 0x1f28, 0x301, 0x201, 0x1f29, 0x301, 0x201, 0x1f28, 0x342, + 0x201, 0x1f29, 0x342, 0x201, 0x3b9, 0x313, 0x201, 0x3b9, + 0x314, 0x201, 0x1f30, 0x300, 0x201, 0x1f31, 0x300, 0x201, + 0x1f30, 0x301, 0x201, 0x1f31, 0x301, 0x201, 0x1f30, 0x342, + 0x201, 0x1f31, 0x342, 0x201, 0x399, 0x313, 0x201, 0x399, + 0x314, 0x201, 0x1f38, 0x300, 0x201, 0x1f39, 0x300, 0x201, + 0x1f38, 0x301, 0x201, 0x1f39, 0x301, 0x201, 0x1f38, 0x342, + 0x201, 0x1f39, 0x342, 0x201, 0x3bf, 0x313, 0x201, 0x3bf, + 0x314, 0x201, 0x1f40, 0x300, 0x201, 0x1f41, 0x300, 0x201, + 0x1f40, 0x301, 0x201, 0x1f41, 0x301, 0x201, 0x39f, 0x313, + 0x201, 0x39f, 0x314, 0x201, 0x1f48, 0x300, 0x201, 0x1f49, + 0x300, 0x201, 0x1f48, 0x301, 0x201, 0x1f49, 0x301, 0x201, + 0x3c5, 0x313, 0x201, 0x3c5, 0x314, 0x201, 0x1f50, 0x300, + 0x201, 0x1f51, 0x300, 0x201, 0x1f50, 0x301, 0x201, 0x1f51, + 0x301, 0x201, 0x1f50, 0x342, 0x201, 0x1f51, 0x342, 0x201, + 0x3a5, 0x314, 0x201, 0x1f59, 0x300, 0x201, 0x1f59, 0x301, + 0x201, 0x1f59, 0x342, 0x201, 0x3c9, 0x313, 0x201, 0x3c9, + 0x314, 0x201, 0x1f60, 0x300, 0x201, 0x1f61, 0x300, 0x201, + 0x1f60, 0x301, 0x201, 0x1f61, 0x301, 0x201, 0x1f60, 0x342, + 0x201, 0x1f61, 0x342, 0x201, 0x3a9, 0x313, 0x201, 0x3a9, + 0x314, 0x201, 0x1f68, 0x300, 0x201, 0x1f69, 0x300, 0x201, + 0x1f68, 0x301, 0x201, 0x1f69, 0x301, 0x201, 0x1f68, 0x342, + 0x201, 0x1f69, 0x342, 0x201, 0x3b1, 0x300, 0x101, 0x3ac, + 0x201, 0x3b5, 0x300, 0x101, 0x3ad, 0x201, 0x3b7, 0x300, + 0x101, 0x3ae, 0x201, 0x3b9, 0x300, 0x101, 0x3af, 0x201, + 0x3bf, 0x300, 0x101, 0x3cc, 0x201, 0x3c5, 0x300, 0x101, + 0x3cd, 0x201, 0x3c9, 0x300, 0x101, 0x3ce, 0x201, 0x1f00, + 0x345, 0x201, 0x1f01, 0x345, 0x201, 0x1f02, 0x345, 0x201, + 0x1f03, 0x345, 0x201, 0x1f04, 0x345, 0x201, 0x1f05, 0x345, + 0x201, 0x1f06, 0x345, 0x201, 0x1f07, 0x345, 0x201, 0x1f08, + 0x345, 0x201, 0x1f09, 0x345, 0x201, 0x1f0a, 0x345, 0x201, + 0x1f0b, 0x345, 0x201, 0x1f0c, 0x345, 0x201, 0x1f0d, 0x345, + 0x201, 0x1f0e, 0x345, 0x201, 0x1f0f, 0x345, 0x201, 0x1f20, + 0x345, 0x201, 0x1f21, 0x345, 0x201, 0x1f22, 0x345, 0x201, + 0x1f23, 0x345, 0x201, 0x1f24, 0x345, 0x201, 0x1f25, 0x345, + 0x201, 0x1f26, 0x345, 0x201, 0x1f27, 0x345, 0x201, 0x1f28, + 0x345, 0x201, 0x1f29, 0x345, 0x201, 0x1f2a, 0x345, 0x201, + 0x1f2b, 0x345, 0x201, 0x1f2c, 0x345, 0x201, 0x1f2d, 0x345, + 0x201, 0x1f2e, 0x345, 0x201, 0x1f2f, 0x345, 0x201, 0x1f60, + 0x345, 0x201, 0x1f61, 0x345, 0x201, 0x1f62, 0x345, 0x201, + 0x1f63, 0x345, 0x201, 0x1f64, 0x345, 0x201, 0x1f65, 0x345, + 0x201, 0x1f66, 0x345, 0x201, 0x1f67, 0x345, 0x201, 0x1f68, + 0x345, 0x201, 0x1f69, 0x345, 0x201, 0x1f6a, 0x345, 0x201, + 0x1f6b, 0x345, 0x201, 0x1f6c, 0x345, 0x201, 0x1f6d, 0x345, + 0x201, 0x1f6e, 0x345, 0x201, 0x1f6f, 0x345, 0x201, 0x3b1, + 0x306, 0x201, 0x3b1, 0x304, 0x201, 0x1f70, 0x345, 0x201, + 0x3b1, 0x345, 0x201, 0x3ac, 0x345, 0x201, 0x3b1, 0x342, + 0x201, 0x1fb6, 0x345, 0x201, 0x391, 0x306, 0x201, 0x391, + 0x304, 0x201, 0x391, 0x300, 0x101, 0x386, 0x201, 0x391, + 0x345, 0x210, 0x20, 0x313, 0x101, 0x3b9, 0x210, 0x20, + 0x313, 0x210, 0x20, 0x342, 0x201, 0xa8, 0x342, 0x201, + 0x1f74, 0x345, 0x201, 0x3b7, 0x345, 0x201, 0x3ae, 0x345, + 0x201, 0x3b7, 0x342, 0x201, 0x1fc6, 0x345, 0x201, 0x395, + 0x300, 0x101, 0x388, 0x201, 0x397, 0x300, 0x101, 0x389, + 0x201, 0x397, 0x345, 0x201, 0x1fbf, 0x300, 0x201, 0x1fbf, + 0x301, 0x201, 0x1fbf, 0x342, 0x201, 0x3b9, 0x306, 0x201, + 0x3b9, 0x304, 0x201, 0x3ca, 0x300, 0x101, 0x390, 0x201, + 0x3b9, 0x342, 0x201, 0x3ca, 0x342, 0x201, 0x399, 0x306, + 0x201, 0x399, 0x304, 0x201, 0x399, 0x300, 0x101, 0x38a, + 0x201, 0x1ffe, 0x300, 0x201, 0x1ffe, 0x301, 0x201, 0x1ffe, + 0x342, 0x201, 0x3c5, 0x306, 0x201, 0x3c5, 0x304, 0x201, + 0x3cb, 0x300, 0x101, 0x3b0, 0x201, 0x3c1, 0x313, 0x201, + 0x3c1, 0x314, 0x201, 0x3c5, 0x342, 0x201, 0x3cb, 0x342, + 0x201, 0x3a5, 0x306, 0x201, 0x3a5, 0x304, 0x201, 0x3a5, + 0x300, 0x101, 0x38e, 0x201, 0x3a1, 0x314, 0x201, 0xa8, + 0x300, 0x101, 0x385, 0x101, 0x60, 0x201, 0x1f7c, 0x345, + 0x201, 0x3c9, 0x345, 0x201, 0x3ce, 0x345, 0x201, 0x3c9, + 0x342, 0x201, 0x1ff6, 0x345, 0x201, 0x39f, 0x300, 0x101, + 0x38c, 0x201, 0x3a9, 0x300, 0x101, 0x38f, 0x201, 0x3a9, + 0x345, 0x101, 0xb4, 0x210, 0x20, 0x314, 0x101, 0x2002, + 0x101, 0x2003, 0x110, 0x20, 0x110, 0x20, 0x110, 0x20, + 0x110, 0x20, 0x110, 0x20, 0x103, 0x20, 0x110, 0x20, + 0x110, 0x20, 0x110, 0x20, 0x103, 0x2010, 0x210, 0x20, + 0x333, 0x110, 0x2e, 0x210, 0x2e, 0x2e, 0x310, 0x2e, + 0x2e, 0x2e, 0x103, 0x20, 0x210, 0x2032, 0x2032, 0x310, + 0x2032, 0x2032, 0x2032, 0x210, 0x2035, 0x2035, 0x310, 0x2035, + 0x2035, 0x2035, 0x210, 0x21, 0x21, 0x210, 0x20, 0x305, + 0x210, 0x3f, 0x3f, 0x210, 0x3f, 0x21, 0x210, 0x21, + 0x3f, 0x410, 0x2032, 0x2032, 0x2032, 0x2032, 0x110, 0x20, + 0x109, 0x30, 0x109, 0x69, 0x109, 0x34, 0x109, 0x35, + 0x109, 0x36, 0x109, 0x37, 0x109, 0x38, 0x109, 0x39, + 0x109, 0x2b, 0x109, 0x2212, 0x109, 0x3d, 0x109, 0x28, + 0x109, 0x29, 0x109, 0x6e, 0x10a, 0x30, 0x10a, 0x31, + 0x10a, 0x32, 0x10a, 0x33, 0x10a, 0x34, 0x10a, 0x35, + 0x10a, 0x36, 0x10a, 0x37, 0x10a, 0x38, 0x10a, 0x39, + 0x10a, 0x2b, 0x10a, 0x2212, 0x10a, 0x3d, 0x10a, 0x28, + 0x10a, 0x29, 0x10a, 0x61, 0x10a, 0x65, 0x10a, 0x6f, + 0x10a, 0x78, 0x10a, 0x259, 0x210, 0x52, 0x73, 0x310, + 0x61, 0x2f, 0x63, 0x310, 0x61, 0x2f, 0x73, 0x102, + 0x43, 0x210, 0xb0, 0x43, 0x310, 0x63, 0x2f, 0x6f, + 0x310, 0x63, 0x2f, 0x75, 0x110, 0x190, 0x210, 0xb0, + 0x46, 0x102, 0x67, 0x102, 0x48, 0x102, 0x48, 0x102, + 0x48, 0x102, 0x68, 0x102, 0x127, 0x102, 0x49, 0x102, + 0x49, 0x102, 0x4c, 0x102, 0x6c, 0x102, 0x4e, 0x210, + 0x4e, 0x6f, 0x102, 0x50, 0x102, 0x51, 0x102, 0x52, + 0x102, 0x52, 0x102, 0x52, 0x209, 0x53, 0x4d, 0x310, + 0x54, 0x45, 0x4c, 0x209, 0x54, 0x4d, 0x102, 0x5a, + 0x101, 0x3a9, 0x102, 0x5a, 0x101, 0x4b, 0x101, 0xc5, + 0x102, 0x42, 0x102, 0x43, 0x102, 0x65, 0x102, 0x45, + 0x102, 0x46, 0x102, 0x4d, 0x102, 0x6f, 0x110, 0x5d0, + 0x110, 0x5d1, 0x110, 0x5d2, 0x110, 0x5d3, 0x102, 0x69, + 0x310, 0x46, 0x41, 0x58, 0x102, 0x3c0, 0x102, 0x3b3, + 0x102, 0x393, 0x102, 0x3a0, 0x102, 0x2211, 0x102, 0x44, + 0x102, 0x64, 0x102, 0x65, 0x102, 0x69, 0x102, 0x6a, + 0x311, 0x31, 0x2044, 0x33, 0x311, 0x32, 0x2044, 0x33, + 0x311, 0x31, 0x2044, 0x35, 0x311, 0x32, 0x2044, 0x35, + 0x311, 0x33, 0x2044, 0x35, 0x311, 0x34, 0x2044, 0x35, + 0x311, 0x31, 0x2044, 0x36, 0x311, 0x35, 0x2044, 0x36, + 0x311, 0x31, 0x2044, 0x38, 0x311, 0x33, 0x2044, 0x38, + 0x311, 0x35, 0x2044, 0x38, 0x311, 0x37, 0x2044, 0x38, + 0x211, 0x31, 0x2044, 0x110, 0x49, 0x210, 0x49, 0x49, + 0x310, 0x49, 0x49, 0x49, 0x210, 0x49, 0x56, 0x110, + 0x56, 0x210, 0x56, 0x49, 0x310, 0x56, 0x49, 0x49, + 0x410, 0x56, 0x49, 0x49, 0x49, 0x210, 0x49, 0x58, + 0x110, 0x58, 0x210, 0x58, 0x49, 0x310, 0x58, 0x49, + 0x49, 0x110, 0x4c, 0x110, 0x43, 0x110, 0x44, 0x110, + 0x4d, 0x110, 0x69, 0x210, 0x69, 0x69, 0x310, 0x69, + 0x69, 0x69, 0x210, 0x69, 0x76, 0x110, 0x76, 0x210, + 0x76, 0x69, 0x310, 0x76, 0x69, 0x69, 0x410, 0x76, + 0x69, 0x69, 0x69, 0x210, 0x69, 0x78, 0x110, 0x78, + 0x210, 0x78, 0x69, 0x310, 0x78, 0x69, 0x69, 0x110, + 0x6c, 0x110, 0x63, 0x110, 0x64, 0x110, 0x6d, 0x201, + 0x2190, 0x338, 0x201, 0x2192, 0x338, 0x201, 0x2194, 0x338, + 0x201, 0x21d0, 0x338, 0x201, 0x21d4, 0x338, 0x201, 0x21d2, + 0x338, 0x201, 0x2203, 0x338, 0x201, 0x2208, 0x338, 0x201, + 0x220b, 0x338, 0x201, 0x2223, 0x338, 0x201, 0x2225, 0x338, + 0x210, 0x222b, 0x222b, 0x310, 0x222b, 0x222b, 0x222b, 0x210, + 0x222e, 0x222e, 0x310, 0x222e, 0x222e, 0x222e, 0x201, 0x223c, + 0x338, 0x201, 0x2243, 0x338, 0x201, 0x2245, 0x338, 0x201, + 0x2248, 0x338, 0x201, 0x3d, 0x338, 0x201, 0x2261, 0x338, + 0x201, 0x224d, 0x338, 0x201, 0x3c, 0x338, 0x201, 0x3e, + 0x338, 0x201, 0x2264, 0x338, 0x201, 0x2265, 0x338, 0x201, + 0x2272, 0x338, 0x201, 0x2273, 0x338, 0x201, 0x2276, 0x338, + 0x201, 0x2277, 0x338, 0x201, 0x227a, 0x338, 0x201, 0x227b, + 0x338, 0x201, 0x2282, 0x338, 0x201, 0x2283, 0x338, 0x201, + 0x2286, 0x338, 0x201, 0x2287, 0x338, 0x201, 0x22a2, 0x338, + 0x201, 0x22a8, 0x338, 0x201, 0x22a9, 0x338, 0x201, 0x22ab, + 0x338, 0x201, 0x227c, 0x338, 0x201, 0x227d, 0x338, 0x201, + 0x2291, 0x338, 0x201, 0x2292, 0x338, 0x201, 0x22b2, 0x338, + 0x201, 0x22b3, 0x338, 0x201, 0x22b4, 0x338, 0x201, 0x22b5, + 0x338, 0x101, 0x3008, 0x101, 0x3009, 0x108, 0x31, 0x108, + 0x32, 0x108, 0x33, 0x108, 0x34, 0x108, 0x35, 0x108, + 0x36, 0x108, 0x37, 0x108, 0x38, 0x108, 0x39, 0x208, + 0x31, 0x30, 0x208, 0x31, 0x31, 0x208, 0x31, 0x32, + 0x208, 0x31, 0x33, 0x208, 0x31, 0x34, 0x208, 0x31, + 0x35, 0x208, 0x31, 0x36, 0x208, 0x31, 0x37, 0x208, + 0x31, 0x38, 0x208, 0x31, 0x39, 0x208, 0x32, 0x30, + 0x310, 0x28, 0x31, 0x29, 0x310, 0x28, 0x32, 0x29, + 0x310, 0x28, 0x33, 0x29, 0x310, 0x28, 0x34, 0x29, + 0x310, 0x28, 0x35, 0x29, 0x310, 0x28, 0x36, 0x29, + 0x310, 0x28, 0x37, 0x29, 0x310, 0x28, 0x38, 0x29, + 0x310, 0x28, 0x39, 0x29, 0x410, 0x28, 0x31, 0x30, + 0x29, 0x410, 0x28, 0x31, 0x31, 0x29, 0x410, 0x28, + 0x31, 0x32, 0x29, 0x410, 0x28, 0x31, 0x33, 0x29, + 0x410, 0x28, 0x31, 0x34, 0x29, 0x410, 0x28, 0x31, + 0x35, 0x29, 0x410, 0x28, 0x31, 0x36, 0x29, 0x410, + 0x28, 0x31, 0x37, 0x29, 0x410, 0x28, 0x31, 0x38, + 0x29, 0x410, 0x28, 0x31, 0x39, 0x29, 0x410, 0x28, + 0x32, 0x30, 0x29, 0x210, 0x31, 0x2e, 0x210, 0x32, + 0x2e, 0x210, 0x33, 0x2e, 0x210, 0x34, 0x2e, 0x210, + 0x35, 0x2e, 0x210, 0x36, 0x2e, 0x210, 0x37, 0x2e, + 0x210, 0x38, 0x2e, 0x210, 0x39, 0x2e, 0x310, 0x31, + 0x30, 0x2e, 0x310, 0x31, 0x31, 0x2e, 0x310, 0x31, + 0x32, 0x2e, 0x310, 0x31, 0x33, 0x2e, 0x310, 0x31, + 0x34, 0x2e, 0x310, 0x31, 0x35, 0x2e, 0x310, 0x31, + 0x36, 0x2e, 0x310, 0x31, 0x37, 0x2e, 0x310, 0x31, + 0x38, 0x2e, 0x310, 0x31, 0x39, 0x2e, 0x310, 0x32, + 0x30, 0x2e, 0x310, 0x28, 0x61, 0x29, 0x310, 0x28, + 0x62, 0x29, 0x310, 0x28, 0x63, 0x29, 0x310, 0x28, + 0x64, 0x29, 0x310, 0x28, 0x65, 0x29, 0x310, 0x28, + 0x66, 0x29, 0x310, 0x28, 0x67, 0x29, 0x310, 0x28, + 0x68, 0x29, 0x310, 0x28, 0x69, 0x29, 0x310, 0x28, + 0x6a, 0x29, 0x310, 0x28, 0x6b, 0x29, 0x310, 0x28, + 0x6c, 0x29, 0x310, 0x28, 0x6d, 0x29, 0x310, 0x28, + 0x6e, 0x29, 0x310, 0x28, 0x6f, 0x29, 0x310, 0x28, + 0x70, 0x29, 0x310, 0x28, 0x71, 0x29, 0x310, 0x28, + 0x72, 0x29, 0x310, 0x28, 0x73, 0x29, 0x310, 0x28, + 0x74, 0x29, 0x310, 0x28, 0x75, 0x29, 0x310, 0x28, + 0x76, 0x29, 0x310, 0x28, 0x77, 0x29, 0x310, 0x28, + 0x78, 0x29, 0x310, 0x28, 0x79, 0x29, 0x310, 0x28, + 0x7a, 0x29, 0x108, 0x41, 0x108, 0x42, 0x108, 0x43, + 0x108, 0x44, 0x108, 0x45, 0x108, 0x46, 0x108, 0x47, + 0x108, 0x48, 0x108, 0x49, 0x108, 0x4a, 0x108, 0x4b, + 0x108, 0x4c, 0x108, 0x4d, 0x108, 0x4e, 0x108, 0x4f, + 0x108, 0x50, 0x108, 0x51, 0x108, 0x52, 0x108, 0x53, + 0x108, 0x54, 0x108, 0x55, 0x108, 0x56, 0x108, 0x57, + 0x108, 0x58, 0x108, 0x59, 0x108, 0x5a, 0x108, 0x61, + 0x108, 0x62, 0x108, 0x63, 0x108, 0x64, 0x108, 0x65, + 0x108, 0x66, 0x108, 0x67, 0x108, 0x68, 0x108, 0x69, + 0x108, 0x6a, 0x108, 0x6b, 0x108, 0x6c, 0x108, 0x6d, + 0x108, 0x6e, 0x108, 0x6f, 0x108, 0x70, 0x108, 0x71, + 0x108, 0x72, 0x108, 0x73, 0x108, 0x74, 0x108, 0x75, + 0x108, 0x76, 0x108, 0x77, 0x108, 0x78, 0x108, 0x79, + 0x108, 0x7a, 0x108, 0x30, 0x410, 0x222b, 0x222b, 0x222b, + 0x222b, 0x310, 0x3a, 0x3a, 0x3d, 0x210, 0x3d, 0x3d, + 0x310, 0x3d, 0x3d, 0x3d, 0x201, 0x2add, 0x338, 0x109, + 0x2d61, 0x110, 0x6bcd, 0x110, 0x9f9f, 0x110, 0x4e00, 0x110, + 0x4e28, 0x110, 0x4e36, 0x110, 0x4e3f, 0x110, 0x4e59, 0x110, + 0x4e85, 0x110, 0x4e8c, 0x110, 0x4ea0, 0x110, 0x4eba, 0x110, + 0x513f, 0x110, 0x5165, 0x110, 0x516b, 0x110, 0x5182, 0x110, + 0x5196, 0x110, 0x51ab, 0x110, 0x51e0, 0x110, 0x51f5, 0x110, + 0x5200, 0x110, 0x529b, 0x110, 0x52f9, 0x110, 0x5315, 0x110, + 0x531a, 0x110, 0x5338, 0x110, 0x5341, 0x110, 0x535c, 0x110, + 0x5369, 0x110, 0x5382, 0x110, 0x53b6, 0x110, 0x53c8, 0x110, + 0x53e3, 0x110, 0x56d7, 0x110, 0x571f, 0x110, 0x58eb, 0x110, + 0x5902, 0x110, 0x590a, 0x110, 0x5915, 0x110, 0x5927, 0x110, + 0x5973, 0x110, 0x5b50, 0x110, 0x5b80, 0x110, 0x5bf8, 0x110, + 0x5c0f, 0x110, 0x5c22, 0x110, 0x5c38, 0x110, 0x5c6e, 0x110, + 0x5c71, 0x110, 0x5ddb, 0x110, 0x5de5, 0x110, 0x5df1, 0x110, + 0x5dfe, 0x110, 0x5e72, 0x110, 0x5e7a, 0x110, 0x5e7f, 0x110, + 0x5ef4, 0x110, 0x5efe, 0x110, 0x5f0b, 0x110, 0x5f13, 0x110, + 0x5f50, 0x110, 0x5f61, 0x110, 0x5f73, 0x110, 0x5fc3, 0x110, + 0x6208, 0x110, 0x6236, 0x110, 0x624b, 0x110, 0x652f, 0x110, + 0x6534, 0x110, 0x6587, 0x110, 0x6597, 0x110, 0x65a4, 0x110, + 0x65b9, 0x110, 0x65e0, 0x110, 0x65e5, 0x110, 0x66f0, 0x110, + 0x6708, 0x110, 0x6728, 0x110, 0x6b20, 0x110, 0x6b62, 0x110, + 0x6b79, 0x110, 0x6bb3, 0x110, 0x6bcb, 0x110, 0x6bd4, 0x110, + 0x6bdb, 0x110, 0x6c0f, 0x110, 0x6c14, 0x110, 0x6c34, 0x110, + 0x706b, 0x110, 0x722a, 0x110, 0x7236, 0x110, 0x723b, 0x110, + 0x723f, 0x110, 0x7247, 0x110, 0x7259, 0x110, 0x725b, 0x110, + 0x72ac, 0x110, 0x7384, 0x110, 0x7389, 0x110, 0x74dc, 0x110, + 0x74e6, 0x110, 0x7518, 0x110, 0x751f, 0x110, 0x7528, 0x110, + 0x7530, 0x110, 0x758b, 0x110, 0x7592, 0x110, 0x7676, 0x110, + 0x767d, 0x110, 0x76ae, 0x110, 0x76bf, 0x110, 0x76ee, 0x110, + 0x77db, 0x110, 0x77e2, 0x110, 0x77f3, 0x110, 0x793a, 0x110, + 0x79b8, 0x110, 0x79be, 0x110, 0x7a74, 0x110, 0x7acb, 0x110, + 0x7af9, 0x110, 0x7c73, 0x110, 0x7cf8, 0x110, 0x7f36, 0x110, + 0x7f51, 0x110, 0x7f8a, 0x110, 0x7fbd, 0x110, 0x8001, 0x110, + 0x800c, 0x110, 0x8012, 0x110, 0x8033, 0x110, 0x807f, 0x110, + 0x8089, 0x110, 0x81e3, 0x110, 0x81ea, 0x110, 0x81f3, 0x110, + 0x81fc, 0x110, 0x820c, 0x110, 0x821b, 0x110, 0x821f, 0x110, + 0x826e, 0x110, 0x8272, 0x110, 0x8278, 0x110, 0x864d, 0x110, + 0x866b, 0x110, 0x8840, 0x110, 0x884c, 0x110, 0x8863, 0x110, + 0x897e, 0x110, 0x898b, 0x110, 0x89d2, 0x110, 0x8a00, 0x110, + 0x8c37, 0x110, 0x8c46, 0x110, 0x8c55, 0x110, 0x8c78, 0x110, + 0x8c9d, 0x110, 0x8d64, 0x110, 0x8d70, 0x110, 0x8db3, 0x110, + 0x8eab, 0x110, 0x8eca, 0x110, 0x8f9b, 0x110, 0x8fb0, 0x110, + 0x8fb5, 0x110, 0x9091, 0x110, 0x9149, 0x110, 0x91c6, 0x110, + 0x91cc, 0x110, 0x91d1, 0x110, 0x9577, 0x110, 0x9580, 0x110, + 0x961c, 0x110, 0x96b6, 0x110, 0x96b9, 0x110, 0x96e8, 0x110, + 0x9751, 0x110, 0x975e, 0x110, 0x9762, 0x110, 0x9769, 0x110, + 0x97cb, 0x110, 0x97ed, 0x110, 0x97f3, 0x110, 0x9801, 0x110, + 0x98a8, 0x110, 0x98db, 0x110, 0x98df, 0x110, 0x9996, 0x110, + 0x9999, 0x110, 0x99ac, 0x110, 0x9aa8, 0x110, 0x9ad8, 0x110, + 0x9adf, 0x110, 0x9b25, 0x110, 0x9b2f, 0x110, 0x9b32, 0x110, + 0x9b3c, 0x110, 0x9b5a, 0x110, 0x9ce5, 0x110, 0x9e75, 0x110, + 0x9e7f, 0x110, 0x9ea5, 0x110, 0x9ebb, 0x110, 0x9ec3, 0x110, + 0x9ecd, 0x110, 0x9ed1, 0x110, 0x9ef9, 0x110, 0x9efd, 0x110, + 0x9f0e, 0x110, 0x9f13, 0x110, 0x9f20, 0x110, 0x9f3b, 0x110, + 0x9f4a, 0x110, 0x9f52, 0x110, 0x9f8d, 0x110, 0x9f9c, 0x110, + 0x9fa0, 0x10c, 0x20, 0x110, 0x3012, 0x110, 0x5341, 0x110, + 0x5344, 0x110, 0x5345, 0x201, 0x304b, 0x3099, 0x201, 0x304d, + 0x3099, 0x201, 0x304f, 0x3099, 0x201, 0x3051, 0x3099, 0x201, + 0x3053, 0x3099, 0x201, 0x3055, 0x3099, 0x201, 0x3057, 0x3099, + 0x201, 0x3059, 0x3099, 0x201, 0x305b, 0x3099, 0x201, 0x305d, + 0x3099, 0x201, 0x305f, 0x3099, 0x201, 0x3061, 0x3099, 0x201, + 0x3064, 0x3099, 0x201, 0x3066, 0x3099, 0x201, 0x3068, 0x3099, + 0x201, 0x306f, 0x3099, 0x201, 0x306f, 0x309a, 0x201, 0x3072, + 0x3099, 0x201, 0x3072, 0x309a, 0x201, 0x3075, 0x3099, 0x201, + 0x3075, 0x309a, 0x201, 0x3078, 0x3099, 0x201, 0x3078, 0x309a, + 0x201, 0x307b, 0x3099, 0x201, 0x307b, 0x309a, 0x201, 0x3046, + 0x3099, 0x210, 0x20, 0x3099, 0x210, 0x20, 0x309a, 0x201, + 0x309d, 0x3099, 0x20b, 0x3088, 0x308a, 0x201, 0x30ab, 0x3099, + 0x201, 0x30ad, 0x3099, 0x201, 0x30af, 0x3099, 0x201, 0x30b1, + 0x3099, 0x201, 0x30b3, 0x3099, 0x201, 0x30b5, 0x3099, 0x201, + 0x30b7, 0x3099, 0x201, 0x30b9, 0x3099, 0x201, 0x30bb, 0x3099, + 0x201, 0x30bd, 0x3099, 0x201, 0x30bf, 0x3099, 0x201, 0x30c1, + 0x3099, 0x201, 0x30c4, 0x3099, 0x201, 0x30c6, 0x3099, 0x201, + 0x30c8, 0x3099, 0x201, 0x30cf, 0x3099, 0x201, 0x30cf, 0x309a, + 0x201, 0x30d2, 0x3099, 0x201, 0x30d2, 0x309a, 0x201, 0x30d5, + 0x3099, 0x201, 0x30d5, 0x309a, 0x201, 0x30d8, 0x3099, 0x201, + 0x30d8, 0x309a, 0x201, 0x30db, 0x3099, 0x201, 0x30db, 0x309a, + 0x201, 0x30a6, 0x3099, 0x201, 0x30ef, 0x3099, 0x201, 0x30f0, + 0x3099, 0x201, 0x30f1, 0x3099, 0x201, 0x30f2, 0x3099, 0x201, + 0x30fd, 0x3099, 0x20b, 0x30b3, 0x30c8, 0x110, 0x1100, 0x110, + 0x1101, 0x110, 0x11aa, 0x110, 0x1102, 0x110, 0x11ac, 0x110, + 0x11ad, 0x110, 0x1103, 0x110, 0x1104, 0x110, 0x1105, 0x110, + 0x11b0, 0x110, 0x11b1, 0x110, 0x11b2, 0x110, 0x11b3, 0x110, + 0x11b4, 0x110, 0x11b5, 0x110, 0x111a, 0x110, 0x1106, 0x110, + 0x1107, 0x110, 0x1108, 0x110, 0x1121, 0x110, 0x1109, 0x110, + 0x110a, 0x110, 0x110b, 0x110, 0x110c, 0x110, 0x110d, 0x110, + 0x110e, 0x110, 0x110f, 0x110, 0x1110, 0x110, 0x1111, 0x110, + 0x1112, 0x110, 0x1161, 0x110, 0x1162, 0x110, 0x1163, 0x110, + 0x1164, 0x110, 0x1165, 0x110, 0x1166, 0x110, 0x1167, 0x110, + 0x1168, 0x110, 0x1169, 0x110, 0x116a, 0x110, 0x116b, 0x110, + 0x116c, 0x110, 0x116d, 0x110, 0x116e, 0x110, 0x116f, 0x110, + 0x1170, 0x110, 0x1171, 0x110, 0x1172, 0x110, 0x1173, 0x110, + 0x1174, 0x110, 0x1175, 0x110, 0x1160, 0x110, 0x1114, 0x110, + 0x1115, 0x110, 0x11c7, 0x110, 0x11c8, 0x110, 0x11cc, 0x110, + 0x11ce, 0x110, 0x11d3, 0x110, 0x11d7, 0x110, 0x11d9, 0x110, + 0x111c, 0x110, 0x11dd, 0x110, 0x11df, 0x110, 0x111d, 0x110, + 0x111e, 0x110, 0x1120, 0x110, 0x1122, 0x110, 0x1123, 0x110, + 0x1127, 0x110, 0x1129, 0x110, 0x112b, 0x110, 0x112c, 0x110, + 0x112d, 0x110, 0x112e, 0x110, 0x112f, 0x110, 0x1132, 0x110, + 0x1136, 0x110, 0x1140, 0x110, 0x1147, 0x110, 0x114c, 0x110, + 0x11f1, 0x110, 0x11f2, 0x110, 0x1157, 0x110, 0x1158, 0x110, + 0x1159, 0x110, 0x1184, 0x110, 0x1185, 0x110, 0x1188, 0x110, + 0x1191, 0x110, 0x1192, 0x110, 0x1194, 0x110, 0x119e, 0x110, + 0x11a1, 0x109, 0x4e00, 0x109, 0x4e8c, 0x109, 0x4e09, 0x109, + 0x56db, 0x109, 0x4e0a, 0x109, 0x4e2d, 0x109, 0x4e0b, 0x109, + 0x7532, 0x109, 0x4e59, 0x109, 0x4e19, 0x109, 0x4e01, 0x109, + 0x5929, 0x109, 0x5730, 0x109, 0x4eba, 0x310, 0x28, 0x1100, + 0x29, 0x310, 0x28, 0x1102, 0x29, 0x310, 0x28, 0x1103, + 0x29, 0x310, 0x28, 0x1105, 0x29, 0x310, 0x28, 0x1106, + 0x29, 0x310, 0x28, 0x1107, 0x29, 0x310, 0x28, 0x1109, + 0x29, 0x310, 0x28, 0x110b, 0x29, 0x310, 0x28, 0x110c, + 0x29, 0x310, 0x28, 0x110e, 0x29, 0x310, 0x28, 0x110f, + 0x29, 0x310, 0x28, 0x1110, 0x29, 0x310, 0x28, 0x1111, + 0x29, 0x310, 0x28, 0x1112, 0x29, 0x410, 0x28, 0x1100, + 0x1161, 0x29, 0x410, 0x28, 0x1102, 0x1161, 0x29, 0x410, + 0x28, 0x1103, 0x1161, 0x29, 0x410, 0x28, 0x1105, 0x1161, + 0x29, 0x410, 0x28, 0x1106, 0x1161, 0x29, 0x410, 0x28, + 0x1107, 0x1161, 0x29, 0x410, 0x28, 0x1109, 0x1161, 0x29, + 0x410, 0x28, 0x110b, 0x1161, 0x29, 0x410, 0x28, 0x110c, + 0x1161, 0x29, 0x410, 0x28, 0x110e, 0x1161, 0x29, 0x410, + 0x28, 0x110f, 0x1161, 0x29, 0x410, 0x28, 0x1110, 0x1161, + 0x29, 0x410, 0x28, 0x1111, 0x1161, 0x29, 0x410, 0x28, + 0x1112, 0x1161, 0x29, 0x410, 0x28, 0x110c, 0x116e, 0x29, + 0x710, 0x28, 0x110b, 0x1169, 0x110c, 0x1165, 0x11ab, 0x29, + 0x610, 0x28, 0x110b, 0x1169, 0x1112, 0x116e, 0x29, 0x310, + 0x28, 0x4e00, 0x29, 0x310, 0x28, 0x4e8c, 0x29, 0x310, + 0x28, 0x4e09, 0x29, 0x310, 0x28, 0x56db, 0x29, 0x310, + 0x28, 0x4e94, 0x29, 0x310, 0x28, 0x516d, 0x29, 0x310, + 0x28, 0x4e03, 0x29, 0x310, 0x28, 0x516b, 0x29, 0x310, + 0x28, 0x4e5d, 0x29, 0x310, 0x28, 0x5341, 0x29, 0x310, + 0x28, 0x6708, 0x29, 0x310, 0x28, 0x706b, 0x29, 0x310, + 0x28, 0x6c34, 0x29, 0x310, 0x28, 0x6728, 0x29, 0x310, + 0x28, 0x91d1, 0x29, 0x310, 0x28, 0x571f, 0x29, 0x310, + 0x28, 0x65e5, 0x29, 0x310, 0x28, 0x682a, 0x29, 0x310, + 0x28, 0x6709, 0x29, 0x310, 0x28, 0x793e, 0x29, 0x310, + 0x28, 0x540d, 0x29, 0x310, 0x28, 0x7279, 0x29, 0x310, + 0x28, 0x8ca1, 0x29, 0x310, 0x28, 0x795d, 0x29, 0x310, + 0x28, 0x52b4, 0x29, 0x310, 0x28, 0x4ee3, 0x29, 0x310, + 0x28, 0x547c, 0x29, 0x310, 0x28, 0x5b66, 0x29, 0x310, + 0x28, 0x76e3, 0x29, 0x310, 0x28, 0x4f01, 0x29, 0x310, + 0x28, 0x8cc7, 0x29, 0x310, 0x28, 0x5354, 0x29, 0x310, + 0x28, 0x796d, 0x29, 0x310, 0x28, 0x4f11, 0x29, 0x310, + 0x28, 0x81ea, 0x29, 0x310, 0x28, 0x81f3, 0x29, 0x30f, + 0x50, 0x54, 0x45, 0x208, 0x32, 0x31, 0x208, 0x32, + 0x32, 0x208, 0x32, 0x33, 0x208, 0x32, 0x34, 0x208, + 0x32, 0x35, 0x208, 0x32, 0x36, 0x208, 0x32, 0x37, + 0x208, 0x32, 0x38, 0x208, 0x32, 0x39, 0x208, 0x33, + 0x30, 0x208, 0x33, 0x31, 0x208, 0x33, 0x32, 0x208, + 0x33, 0x33, 0x208, 0x33, 0x34, 0x208, 0x33, 0x35, + 0x108, 0x1100, 0x108, 0x1102, 0x108, 0x1103, 0x108, 0x1105, + 0x108, 0x1106, 0x108, 0x1107, 0x108, 0x1109, 0x108, 0x110b, + 0x108, 0x110c, 0x108, 0x110e, 0x108, 0x110f, 0x108, 0x1110, + 0x108, 0x1111, 0x108, 0x1112, 0x208, 0x1100, 0x1161, 0x208, + 0x1102, 0x1161, 0x208, 0x1103, 0x1161, 0x208, 0x1105, 0x1161, + 0x208, 0x1106, 0x1161, 0x208, 0x1107, 0x1161, 0x208, 0x1109, + 0x1161, 0x208, 0x110b, 0x1161, 0x208, 0x110c, 0x1161, 0x208, + 0x110e, 0x1161, 0x208, 0x110f, 0x1161, 0x208, 0x1110, 0x1161, + 0x208, 0x1111, 0x1161, 0x208, 0x1112, 0x1161, 0x508, 0x110e, + 0x1161, 0x11b7, 0x1100, 0x1169, 0x408, 0x110c, 0x116e, 0x110b, + 0x1174, 0x208, 0x110b, 0x116e, 0x108, 0x4e00, 0x108, 0x4e8c, + 0x108, 0x4e09, 0x108, 0x56db, 0x108, 0x4e94, 0x108, 0x516d, + 0x108, 0x4e03, 0x108, 0x516b, 0x108, 0x4e5d, 0x108, 0x5341, + 0x108, 0x6708, 0x108, 0x706b, 0x108, 0x6c34, 0x108, 0x6728, + 0x108, 0x91d1, 0x108, 0x571f, 0x108, 0x65e5, 0x108, 0x682a, + 0x108, 0x6709, 0x108, 0x793e, 0x108, 0x540d, 0x108, 0x7279, + 0x108, 0x8ca1, 0x108, 0x795d, 0x108, 0x52b4, 0x108, 0x79d8, + 0x108, 0x7537, 0x108, 0x5973, 0x108, 0x9069, 0x108, 0x512a, + 0x108, 0x5370, 0x108, 0x6ce8, 0x108, 0x9805, 0x108, 0x4f11, + 0x108, 0x5199, 0x108, 0x6b63, 0x108, 0x4e0a, 0x108, 0x4e2d, + 0x108, 0x4e0b, 0x108, 0x5de6, 0x108, 0x53f3, 0x108, 0x533b, + 0x108, 0x5b97, 0x108, 0x5b66, 0x108, 0x76e3, 0x108, 0x4f01, + 0x108, 0x8cc7, 0x108, 0x5354, 0x108, 0x591c, 0x208, 0x33, + 0x36, 0x208, 0x33, 0x37, 0x208, 0x33, 0x38, 0x208, + 0x33, 0x39, 0x208, 0x34, 0x30, 0x208, 0x34, 0x31, + 0x208, 0x34, 0x32, 0x208, 0x34, 0x33, 0x208, 0x34, + 0x34, 0x208, 0x34, 0x35, 0x208, 0x34, 0x36, 0x208, + 0x34, 0x37, 0x208, 0x34, 0x38, 0x208, 0x34, 0x39, + 0x208, 0x35, 0x30, 0x210, 0x31, 0x6708, 0x210, 0x32, + 0x6708, 0x210, 0x33, 0x6708, 0x210, 0x34, 0x6708, 0x210, + 0x35, 0x6708, 0x210, 0x36, 0x6708, 0x210, 0x37, 0x6708, + 0x210, 0x38, 0x6708, 0x210, 0x39, 0x6708, 0x310, 0x31, + 0x30, 0x6708, 0x310, 0x31, 0x31, 0x6708, 0x310, 0x31, + 0x32, 0x6708, 0x20f, 0x48, 0x67, 0x30f, 0x65, 0x72, + 0x67, 0x20f, 0x65, 0x56, 0x30f, 0x4c, 0x54, 0x44, + 0x108, 0x30a2, 0x108, 0x30a4, 0x108, 0x30a6, 0x108, 0x30a8, + 0x108, 0x30aa, 0x108, 0x30ab, 0x108, 0x30ad, 0x108, 0x30af, + 0x108, 0x30b1, 0x108, 0x30b3, 0x108, 0x30b5, 0x108, 0x30b7, + 0x108, 0x30b9, 0x108, 0x30bb, 0x108, 0x30bd, 0x108, 0x30bf, + 0x108, 0x30c1, 0x108, 0x30c4, 0x108, 0x30c6, 0x108, 0x30c8, + 0x108, 0x30ca, 0x108, 0x30cb, 0x108, 0x30cc, 0x108, 0x30cd, + 0x108, 0x30ce, 0x108, 0x30cf, 0x108, 0x30d2, 0x108, 0x30d5, + 0x108, 0x30d8, 0x108, 0x30db, 0x108, 0x30de, 0x108, 0x30df, + 0x108, 0x30e0, 0x108, 0x30e1, 0x108, 0x30e2, 0x108, 0x30e4, + 0x108, 0x30e6, 0x108, 0x30e8, 0x108, 0x30e9, 0x108, 0x30ea, + 0x108, 0x30eb, 0x108, 0x30ec, 0x108, 0x30ed, 0x108, 0x30ef, + 0x108, 0x30f0, 0x108, 0x30f1, 0x108, 0x30f2, 0x40f, 0x30a2, + 0x30d1, 0x30fc, 0x30c8, 0x40f, 0x30a2, 0x30eb, 0x30d5, 0x30a1, + 0x40f, 0x30a2, 0x30f3, 0x30da, 0x30a2, 0x30f, 0x30a2, 0x30fc, + 0x30eb, 0x40f, 0x30a4, 0x30cb, 0x30f3, 0x30b0, 0x30f, 0x30a4, + 0x30f3, 0x30c1, 0x30f, 0x30a6, 0x30a9, 0x30f3, 0x50f, 0x30a8, + 0x30b9, 0x30af, 0x30fc, 0x30c9, 0x40f, 0x30a8, 0x30fc, 0x30ab, + 0x30fc, 0x30f, 0x30aa, 0x30f3, 0x30b9, 0x30f, 0x30aa, 0x30fc, + 0x30e0, 0x30f, 0x30ab, 0x30a4, 0x30ea, 0x40f, 0x30ab, 0x30e9, + 0x30c3, 0x30c8, 0x40f, 0x30ab, 0x30ed, 0x30ea, 0x30fc, 0x30f, + 0x30ac, 0x30ed, 0x30f3, 0x30f, 0x30ac, 0x30f3, 0x30de, 0x20f, + 0x30ae, 0x30ac, 0x30f, 0x30ae, 0x30cb, 0x30fc, 0x40f, 0x30ad, + 0x30e5, 0x30ea, 0x30fc, 0x40f, 0x30ae, 0x30eb, 0x30c0, 0x30fc, + 0x20f, 0x30ad, 0x30ed, 0x50f, 0x30ad, 0x30ed, 0x30b0, 0x30e9, + 0x30e0, 0x60f, 0x30ad, 0x30ed, 0x30e1, 0x30fc, 0x30c8, 0x30eb, + 0x50f, 0x30ad, 0x30ed, 0x30ef, 0x30c3, 0x30c8, 0x30f, 0x30b0, + 0x30e9, 0x30e0, 0x50f, 0x30b0, 0x30e9, 0x30e0, 0x30c8, 0x30f3, + 0x50f, 0x30af, 0x30eb, 0x30bc, 0x30a4, 0x30ed, 0x40f, 0x30af, + 0x30ed, 0x30fc, 0x30cd, 0x30f, 0x30b1, 0x30fc, 0x30b9, 0x30f, + 0x30b3, 0x30eb, 0x30ca, 0x30f, 0x30b3, 0x30fc, 0x30dd, 0x40f, + 0x30b5, 0x30a4, 0x30af, 0x30eb, 0x50f, 0x30b5, 0x30f3, 0x30c1, + 0x30fc, 0x30e0, 0x40f, 0x30b7, 0x30ea, 0x30f3, 0x30b0, 0x30f, + 0x30bb, 0x30f3, 0x30c1, 0x30f, 0x30bb, 0x30f3, 0x30c8, 0x30f, + 0x30c0, 0x30fc, 0x30b9, 0x20f, 0x30c7, 0x30b7, 0x20f, 0x30c9, + 0x30eb, 0x20f, 0x30c8, 0x30f3, 0x20f, 0x30ca, 0x30ce, 0x30f, + 0x30ce, 0x30c3, 0x30c8, 0x30f, 0x30cf, 0x30a4, 0x30c4, 0x50f, + 0x30d1, 0x30fc, 0x30bb, 0x30f3, 0x30c8, 0x30f, 0x30d1, 0x30fc, + 0x30c4, 0x40f, 0x30d0, 0x30fc, 0x30ec, 0x30eb, 0x50f, 0x30d4, + 0x30a2, 0x30b9, 0x30c8, 0x30eb, 0x30f, 0x30d4, 0x30af, 0x30eb, + 0x20f, 0x30d4, 0x30b3, 0x20f, 0x30d3, 0x30eb, 0x50f, 0x30d5, + 0x30a1, 0x30e9, 0x30c3, 0x30c9, 0x40f, 0x30d5, 0x30a3, 0x30fc, + 0x30c8, 0x50f, 0x30d6, 0x30c3, 0x30b7, 0x30a7, 0x30eb, 0x30f, + 0x30d5, 0x30e9, 0x30f3, 0x50f, 0x30d8, 0x30af, 0x30bf, 0x30fc, + 0x30eb, 0x20f, 0x30da, 0x30bd, 0x30f, 0x30da, 0x30cb, 0x30d2, + 0x30f, 0x30d8, 0x30eb, 0x30c4, 0x30f, 0x30da, 0x30f3, 0x30b9, + 0x30f, 0x30da, 0x30fc, 0x30b8, 0x30f, 0x30d9, 0x30fc, 0x30bf, + 0x40f, 0x30dd, 0x30a4, 0x30f3, 0x30c8, 0x30f, 0x30dc, 0x30eb, + 0x30c8, 0x20f, 0x30db, 0x30f3, 0x30f, 0x30dd, 0x30f3, 0x30c9, + 0x30f, 0x30db, 0x30fc, 0x30eb, 0x30f, 0x30db, 0x30fc, 0x30f3, + 0x40f, 0x30de, 0x30a4, 0x30af, 0x30ed, 0x30f, 0x30de, 0x30a4, + 0x30eb, 0x30f, 0x30de, 0x30c3, 0x30cf, 0x30f, 0x30de, 0x30eb, + 0x30af, 0x50f, 0x30de, 0x30f3, 0x30b7, 0x30e7, 0x30f3, 0x40f, + 0x30df, 0x30af, 0x30ed, 0x30f3, 0x20f, 0x30df, 0x30ea, 0x50f, + 0x30df, 0x30ea, 0x30d0, 0x30fc, 0x30eb, 0x20f, 0x30e1, 0x30ac, + 0x40f, 0x30e1, 0x30ac, 0x30c8, 0x30f3, 0x40f, 0x30e1, 0x30fc, + 0x30c8, 0x30eb, 0x30f, 0x30e4, 0x30fc, 0x30c9, 0x30f, 0x30e4, + 0x30fc, 0x30eb, 0x30f, 0x30e6, 0x30a2, 0x30f3, 0x40f, 0x30ea, + 0x30c3, 0x30c8, 0x30eb, 0x20f, 0x30ea, 0x30e9, 0x30f, 0x30eb, + 0x30d4, 0x30fc, 0x40f, 0x30eb, 0x30fc, 0x30d6, 0x30eb, 0x20f, + 0x30ec, 0x30e0, 0x50f, 0x30ec, 0x30f3, 0x30c8, 0x30b2, 0x30f3, + 0x30f, 0x30ef, 0x30c3, 0x30c8, 0x210, 0x30, 0x70b9, 0x210, + 0x31, 0x70b9, 0x210, 0x32, 0x70b9, 0x210, 0x33, 0x70b9, + 0x210, 0x34, 0x70b9, 0x210, 0x35, 0x70b9, 0x210, 0x36, + 0x70b9, 0x210, 0x37, 0x70b9, 0x210, 0x38, 0x70b9, 0x210, + 0x39, 0x70b9, 0x310, 0x31, 0x30, 0x70b9, 0x310, 0x31, + 0x31, 0x70b9, 0x310, 0x31, 0x32, 0x70b9, 0x310, 0x31, + 0x33, 0x70b9, 0x310, 0x31, 0x34, 0x70b9, 0x310, 0x31, + 0x35, 0x70b9, 0x310, 0x31, 0x36, 0x70b9, 0x310, 0x31, + 0x37, 0x70b9, 0x310, 0x31, 0x38, 0x70b9, 0x310, 0x31, + 0x39, 0x70b9, 0x310, 0x32, 0x30, 0x70b9, 0x310, 0x32, + 0x31, 0x70b9, 0x310, 0x32, 0x32, 0x70b9, 0x310, 0x32, + 0x33, 0x70b9, 0x310, 0x32, 0x34, 0x70b9, 0x30f, 0x68, + 0x50, 0x61, 0x20f, 0x64, 0x61, 0x20f, 0x41, 0x55, + 0x30f, 0x62, 0x61, 0x72, 0x20f, 0x6f, 0x56, 0x20f, + 0x70, 0x63, 0x20f, 0x64, 0x6d, 0x30f, 0x64, 0x6d, + 0xb2, 0x30f, 0x64, 0x6d, 0xb3, 0x20f, 0x49, 0x55, + 0x20f, 0x5e73, 0x6210, 0x20f, 0x662d, 0x548c, 0x20f, 0x5927, + 0x6b63, 0x20f, 0x660e, 0x6cbb, 0x40f, 0x682a, 0x5f0f, 0x4f1a, + 0x793e, 0x20f, 0x70, 0x41, 0x20f, 0x6e, 0x41, 0x20f, + 0x3bc, 0x41, 0x20f, 0x6d, 0x41, 0x20f, 0x6b, 0x41, + 0x20f, 0x4b, 0x42, 0x20f, 0x4d, 0x42, 0x20f, 0x47, + 0x42, 0x30f, 0x63, 0x61, 0x6c, 0x40f, 0x6b, 0x63, + 0x61, 0x6c, 0x20f, 0x70, 0x46, 0x20f, 0x6e, 0x46, + 0x20f, 0x3bc, 0x46, 0x20f, 0x3bc, 0x67, 0x20f, 0x6d, + 0x67, 0x20f, 0x6b, 0x67, 0x20f, 0x48, 0x7a, 0x30f, + 0x6b, 0x48, 0x7a, 0x30f, 0x4d, 0x48, 0x7a, 0x30f, + 0x47, 0x48, 0x7a, 0x30f, 0x54, 0x48, 0x7a, 0x20f, + 0x3bc, 0x2113, 0x20f, 0x6d, 0x2113, 0x20f, 0x64, 0x2113, + 0x20f, 0x6b, 0x2113, 0x20f, 0x66, 0x6d, 0x20f, 0x6e, + 0x6d, 0x20f, 0x3bc, 0x6d, 0x20f, 0x6d, 0x6d, 0x20f, + 0x63, 0x6d, 0x20f, 0x6b, 0x6d, 0x30f, 0x6d, 0x6d, + 0xb2, 0x30f, 0x63, 0x6d, 0xb2, 0x20f, 0x6d, 0xb2, + 0x30f, 0x6b, 0x6d, 0xb2, 0x30f, 0x6d, 0x6d, 0xb3, + 0x30f, 0x63, 0x6d, 0xb3, 0x20f, 0x6d, 0xb3, 0x30f, + 0x6b, 0x6d, 0xb3, 0x30f, 0x6d, 0x2215, 0x73, 0x40f, + 0x6d, 0x2215, 0x73, 0xb2, 0x20f, 0x50, 0x61, 0x30f, + 0x6b, 0x50, 0x61, 0x30f, 0x4d, 0x50, 0x61, 0x30f, + 0x47, 0x50, 0x61, 0x30f, 0x72, 0x61, 0x64, 0x50f, + 0x72, 0x61, 0x64, 0x2215, 0x73, 0x60f, 0x72, 0x61, + 0x64, 0x2215, 0x73, 0xb2, 0x20f, 0x70, 0x73, 0x20f, + 0x6e, 0x73, 0x20f, 0x3bc, 0x73, 0x20f, 0x6d, 0x73, + 0x20f, 0x70, 0x56, 0x20f, 0x6e, 0x56, 0x20f, 0x3bc, + 0x56, 0x20f, 0x6d, 0x56, 0x20f, 0x6b, 0x56, 0x20f, + 0x4d, 0x56, 0x20f, 0x70, 0x57, 0x20f, 0x6e, 0x57, + 0x20f, 0x3bc, 0x57, 0x20f, 0x6d, 0x57, 0x20f, 0x6b, + 0x57, 0x20f, 0x4d, 0x57, 0x20f, 0x6b, 0x3a9, 0x20f, + 0x4d, 0x3a9, 0x40f, 0x61, 0x2e, 0x6d, 0x2e, 0x20f, + 0x42, 0x71, 0x20f, 0x63, 0x63, 0x20f, 0x63, 0x64, + 0x40f, 0x43, 0x2215, 0x6b, 0x67, 0x30f, 0x43, 0x6f, + 0x2e, 0x20f, 0x64, 0x42, 0x20f, 0x47, 0x79, 0x20f, + 0x68, 0x61, 0x20f, 0x48, 0x50, 0x20f, 0x69, 0x6e, + 0x20f, 0x4b, 0x4b, 0x20f, 0x4b, 0x4d, 0x20f, 0x6b, + 0x74, 0x20f, 0x6c, 0x6d, 0x20f, 0x6c, 0x6e, 0x30f, + 0x6c, 0x6f, 0x67, 0x20f, 0x6c, 0x78, 0x20f, 0x6d, + 0x62, 0x30f, 0x6d, 0x69, 0x6c, 0x30f, 0x6d, 0x6f, + 0x6c, 0x20f, 0x50, 0x48, 0x40f, 0x70, 0x2e, 0x6d, + 0x2e, 0x30f, 0x50, 0x50, 0x4d, 0x20f, 0x50, 0x52, + 0x20f, 0x73, 0x72, 0x20f, 0x53, 0x76, 0x20f, 0x57, + 0x62, 0x30f, 0x56, 0x2215, 0x6d, 0x30f, 0x41, 0x2215, + 0x6d, 0x210, 0x31, 0x65e5, 0x210, 0x32, 0x65e5, 0x210, + 0x33, 0x65e5, 0x210, 0x34, 0x65e5, 0x210, 0x35, 0x65e5, + 0x210, 0x36, 0x65e5, 0x210, 0x37, 0x65e5, 0x210, 0x38, + 0x65e5, 0x210, 0x39, 0x65e5, 0x310, 0x31, 0x30, 0x65e5, + 0x310, 0x31, 0x31, 0x65e5, 0x310, 0x31, 0x32, 0x65e5, + 0x310, 0x31, 0x33, 0x65e5, 0x310, 0x31, 0x34, 0x65e5, + 0x310, 0x31, 0x35, 0x65e5, 0x310, 0x31, 0x36, 0x65e5, + 0x310, 0x31, 0x37, 0x65e5, 0x310, 0x31, 0x38, 0x65e5, + 0x310, 0x31, 0x39, 0x65e5, 0x310, 0x32, 0x30, 0x65e5, + 0x310, 0x32, 0x31, 0x65e5, 0x310, 0x32, 0x32, 0x65e5, + 0x310, 0x32, 0x33, 0x65e5, 0x310, 0x32, 0x34, 0x65e5, + 0x310, 0x32, 0x35, 0x65e5, 0x310, 0x32, 0x36, 0x65e5, + 0x310, 0x32, 0x37, 0x65e5, 0x310, 0x32, 0x38, 0x65e5, + 0x310, 0x32, 0x39, 0x65e5, 0x310, 0x33, 0x30, 0x65e5, + 0x310, 0x33, 0x31, 0x65e5, 0x30f, 0x67, 0x61, 0x6c, + 0x101, 0x8c48, 0x101, 0x66f4, 0x101, 0x8eca, 0x101, 0x8cc8, + 0x101, 0x6ed1, 0x101, 0x4e32, 0x101, 0x53e5, 0x101, 0x9f9c, + 0x101, 0x9f9c, 0x101, 0x5951, 0x101, 0x91d1, 0x101, 0x5587, + 0x101, 0x5948, 0x101, 0x61f6, 0x101, 0x7669, 0x101, 0x7f85, + 0x101, 0x863f, 0x101, 0x87ba, 0x101, 0x88f8, 0x101, 0x908f, + 0x101, 0x6a02, 0x101, 0x6d1b, 0x101, 0x70d9, 0x101, 0x73de, + 0x101, 0x843d, 0x101, 0x916a, 0x101, 0x99f1, 0x101, 0x4e82, + 0x101, 0x5375, 0x101, 0x6b04, 0x101, 0x721b, 0x101, 0x862d, + 0x101, 0x9e1e, 0x101, 0x5d50, 0x101, 0x6feb, 0x101, 0x85cd, + 0x101, 0x8964, 0x101, 0x62c9, 0x101, 0x81d8, 0x101, 0x881f, + 0x101, 0x5eca, 0x101, 0x6717, 0x101, 0x6d6a, 0x101, 0x72fc, + 0x101, 0x90ce, 0x101, 0x4f86, 0x101, 0x51b7, 0x101, 0x52de, + 0x101, 0x64c4, 0x101, 0x6ad3, 0x101, 0x7210, 0x101, 0x76e7, + 0x101, 0x8001, 0x101, 0x8606, 0x101, 0x865c, 0x101, 0x8def, + 0x101, 0x9732, 0x101, 0x9b6f, 0x101, 0x9dfa, 0x101, 0x788c, + 0x101, 0x797f, 0x101, 0x7da0, 0x101, 0x83c9, 0x101, 0x9304, + 0x101, 0x9e7f, 0x101, 0x8ad6, 0x101, 0x58df, 0x101, 0x5f04, + 0x101, 0x7c60, 0x101, 0x807e, 0x101, 0x7262, 0x101, 0x78ca, + 0x101, 0x8cc2, 0x101, 0x96f7, 0x101, 0x58d8, 0x101, 0x5c62, + 0x101, 0x6a13, 0x101, 0x6dda, 0x101, 0x6f0f, 0x101, 0x7d2f, + 0x101, 0x7e37, 0x101, 0x964b, 0x101, 0x52d2, 0x101, 0x808b, + 0x101, 0x51dc, 0x101, 0x51cc, 0x101, 0x7a1c, 0x101, 0x7dbe, + 0x101, 0x83f1, 0x101, 0x9675, 0x101, 0x8b80, 0x101, 0x62cf, + 0x101, 0x6a02, 0x101, 0x8afe, 0x101, 0x4e39, 0x101, 0x5be7, + 0x101, 0x6012, 0x101, 0x7387, 0x101, 0x7570, 0x101, 0x5317, + 0x101, 0x78fb, 0x101, 0x4fbf, 0x101, 0x5fa9, 0x101, 0x4e0d, + 0x101, 0x6ccc, 0x101, 0x6578, 0x101, 0x7d22, 0x101, 0x53c3, + 0x101, 0x585e, 0x101, 0x7701, 0x101, 0x8449, 0x101, 0x8aaa, + 0x101, 0x6bba, 0x101, 0x8fb0, 0x101, 0x6c88, 0x101, 0x62fe, + 0x101, 0x82e5, 0x101, 0x63a0, 0x101, 0x7565, 0x101, 0x4eae, + 0x101, 0x5169, 0x101, 0x51c9, 0x101, 0x6881, 0x101, 0x7ce7, + 0x101, 0x826f, 0x101, 0x8ad2, 0x101, 0x91cf, 0x101, 0x52f5, + 0x101, 0x5442, 0x101, 0x5973, 0x101, 0x5eec, 0x101, 0x65c5, + 0x101, 0x6ffe, 0x101, 0x792a, 0x101, 0x95ad, 0x101, 0x9a6a, + 0x101, 0x9e97, 0x101, 0x9ece, 0x101, 0x529b, 0x101, 0x66c6, + 0x101, 0x6b77, 0x101, 0x8f62, 0x101, 0x5e74, 0x101, 0x6190, + 0x101, 0x6200, 0x101, 0x649a, 0x101, 0x6f23, 0x101, 0x7149, + 0x101, 0x7489, 0x101, 0x79ca, 0x101, 0x7df4, 0x101, 0x806f, + 0x101, 0x8f26, 0x101, 0x84ee, 0x101, 0x9023, 0x101, 0x934a, + 0x101, 0x5217, 0x101, 0x52a3, 0x101, 0x54bd, 0x101, 0x70c8, + 0x101, 0x88c2, 0x101, 0x8aaa, 0x101, 0x5ec9, 0x101, 0x5ff5, + 0x101, 0x637b, 0x101, 0x6bae, 0x101, 0x7c3e, 0x101, 0x7375, + 0x101, 0x4ee4, 0x101, 0x56f9, 0x101, 0x5be7, 0x101, 0x5dba, + 0x101, 0x601c, 0x101, 0x73b2, 0x101, 0x7469, 0x101, 0x7f9a, + 0x101, 0x8046, 0x101, 0x9234, 0x101, 0x96f6, 0x101, 0x9748, + 0x101, 0x9818, 0x101, 0x4f8b, 0x101, 0x79ae, 0x101, 0x91b4, + 0x101, 0x96b8, 0x101, 0x60e1, 0x101, 0x4e86, 0x101, 0x50da, + 0x101, 0x5bee, 0x101, 0x5c3f, 0x101, 0x6599, 0x101, 0x6a02, + 0x101, 0x71ce, 0x101, 0x7642, 0x101, 0x84fc, 0x101, 0x907c, + 0x101, 0x9f8d, 0x101, 0x6688, 0x101, 0x962e, 0x101, 0x5289, + 0x101, 0x677b, 0x101, 0x67f3, 0x101, 0x6d41, 0x101, 0x6e9c, + 0x101, 0x7409, 0x101, 0x7559, 0x101, 0x786b, 0x101, 0x7d10, + 0x101, 0x985e, 0x101, 0x516d, 0x101, 0x622e, 0x101, 0x9678, + 0x101, 0x502b, 0x101, 0x5d19, 0x101, 0x6dea, 0x101, 0x8f2a, + 0x101, 0x5f8b, 0x101, 0x6144, 0x101, 0x6817, 0x101, 0x7387, + 0x101, 0x9686, 0x101, 0x5229, 0x101, 0x540f, 0x101, 0x5c65, + 0x101, 0x6613, 0x101, 0x674e, 0x101, 0x68a8, 0x101, 0x6ce5, + 0x101, 0x7406, 0x101, 0x75e2, 0x101, 0x7f79, 0x101, 0x88cf, + 0x101, 0x88e1, 0x101, 0x91cc, 0x101, 0x96e2, 0x101, 0x533f, + 0x101, 0x6eba, 0x101, 0x541d, 0x101, 0x71d0, 0x101, 0x7498, + 0x101, 0x85fa, 0x101, 0x96a3, 0x101, 0x9c57, 0x101, 0x9e9f, + 0x101, 0x6797, 0x101, 0x6dcb, 0x101, 0x81e8, 0x101, 0x7acb, + 0x101, 0x7b20, 0x101, 0x7c92, 0x101, 0x72c0, 0x101, 0x7099, + 0x101, 0x8b58, 0x101, 0x4ec0, 0x101, 0x8336, 0x101, 0x523a, + 0x101, 0x5207, 0x101, 0x5ea6, 0x101, 0x62d3, 0x101, 0x7cd6, + 0x101, 0x5b85, 0x101, 0x6d1e, 0x101, 0x66b4, 0x101, 0x8f3b, + 0x101, 0x884c, 0x101, 0x964d, 0x101, 0x898b, 0x101, 0x5ed3, + 0x101, 0x5140, 0x101, 0x55c0, 0x101, 0x585a, 0x101, 0x6674, + 0x101, 0x51de, 0x101, 0x732a, 0x101, 0x76ca, 0x101, 0x793c, + 0x101, 0x795e, 0x101, 0x7965, 0x101, 0x798f, 0x101, 0x9756, + 0x101, 0x7cbe, 0x101, 0x7fbd, 0x101, 0x8612, 0x101, 0x8af8, + 0x101, 0x9038, 0x101, 0x90fd, 0x101, 0x98ef, 0x101, 0x98fc, + 0x101, 0x9928, 0x101, 0x9db4, 0x101, 0x4fae, 0x101, 0x50e7, + 0x101, 0x514d, 0x101, 0x52c9, 0x101, 0x52e4, 0x101, 0x5351, + 0x101, 0x559d, 0x101, 0x5606, 0x101, 0x5668, 0x101, 0x5840, + 0x101, 0x58a8, 0x101, 0x5c64, 0x101, 0x5c6e, 0x101, 0x6094, + 0x101, 0x6168, 0x101, 0x618e, 0x101, 0x61f2, 0x101, 0x654f, + 0x101, 0x65e2, 0x101, 0x6691, 0x101, 0x6885, 0x101, 0x6d77, + 0x101, 0x6e1a, 0x101, 0x6f22, 0x101, 0x716e, 0x101, 0x722b, + 0x101, 0x7422, 0x101, 0x7891, 0x101, 0x793e, 0x101, 0x7949, + 0x101, 0x7948, 0x101, 0x7950, 0x101, 0x7956, 0x101, 0x795d, + 0x101, 0x798d, 0x101, 0x798e, 0x101, 0x7a40, 0x101, 0x7a81, + 0x101, 0x7bc0, 0x101, 0x7df4, 0x101, 0x7e09, 0x101, 0x7e41, + 0x101, 0x7f72, 0x101, 0x8005, 0x101, 0x81ed, 0x101, 0x8279, + 0x101, 0x8279, 0x101, 0x8457, 0x101, 0x8910, 0x101, 0x8996, + 0x101, 0x8b01, 0x101, 0x8b39, 0x101, 0x8cd3, 0x101, 0x8d08, + 0x101, 0x8fb6, 0x101, 0x9038, 0x101, 0x96e3, 0x101, 0x97ff, + 0x101, 0x983b, 0x101, 0x4e26, 0x101, 0x51b5, 0x101, 0x5168, + 0x101, 0x4f80, 0x101, 0x5145, 0x101, 0x5180, 0x101, 0x52c7, + 0x101, 0x52fa, 0x101, 0x559d, 0x101, 0x5555, 0x101, 0x5599, + 0x101, 0x55e2, 0x101, 0x585a, 0x101, 0x58b3, 0x101, 0x5944, + 0x101, 0x5954, 0x101, 0x5a62, 0x101, 0x5b28, 0x101, 0x5ed2, + 0x101, 0x5ed9, 0x101, 0x5f69, 0x101, 0x5fad, 0x101, 0x60d8, + 0x101, 0x614e, 0x101, 0x6108, 0x101, 0x618e, 0x101, 0x6160, + 0x101, 0x61f2, 0x101, 0x6234, 0x101, 0x63c4, 0x101, 0x641c, + 0x101, 0x6452, 0x101, 0x6556, 0x101, 0x6674, 0x101, 0x6717, + 0x101, 0x671b, 0x101, 0x6756, 0x101, 0x6b79, 0x101, 0x6bba, + 0x101, 0x6d41, 0x101, 0x6edb, 0x101, 0x6ecb, 0x101, 0x6f22, + 0x101, 0x701e, 0x101, 0x716e, 0x101, 0x77a7, 0x101, 0x7235, + 0x101, 0x72af, 0x101, 0x732a, 0x101, 0x7471, 0x101, 0x7506, + 0x101, 0x753b, 0x101, 0x761d, 0x101, 0x761f, 0x101, 0x76ca, + 0x101, 0x76db, 0x101, 0x76f4, 0x101, 0x774a, 0x101, 0x7740, + 0x101, 0x78cc, 0x101, 0x7ab1, 0x101, 0x7bc0, 0x101, 0x7c7b, + 0x101, 0x7d5b, 0x101, 0x7df4, 0x101, 0x7f3e, 0x101, 0x8005, + 0x101, 0x8352, 0x101, 0x83ef, 0x101, 0x8779, 0x101, 0x8941, + 0x101, 0x8986, 0x101, 0x8996, 0x101, 0x8abf, 0x101, 0x8af8, + 0x101, 0x8acb, 0x101, 0x8b01, 0x101, 0x8afe, 0x101, 0x8aed, + 0x101, 0x8b39, 0x101, 0x8b8a, 0x101, 0x8d08, 0x101, 0x8f38, + 0x101, 0x9072, 0x101, 0x9199, 0x101, 0x9276, 0x101, 0x967c, + 0x101, 0x96e3, 0x101, 0x9756, 0x101, 0x97db, 0x101, 0x97ff, + 0x101, 0x980b, 0x101, 0x983b, 0x101, 0x9b12, 0x101, 0x9f9c, + 0x201, 0xd84a, 0xdc4a, 0x201, 0xd84a, 0xdc44, 0x201, 0xd84c, + 0xdfd5, 0x101, 0x3b9d, 0x101, 0x4018, 0x101, 0x4039, 0x201, + 0xd854, 0xde49, 0x201, 0xd857, 0xdcd0, 0x201, 0xd85f, 0xded3, + 0x101, 0x9f43, 0x101, 0x9f8e, 0x210, 0x66, 0x66, 0x210, + 0x66, 0x69, 0x210, 0x66, 0x6c, 0x310, 0x66, 0x66, + 0x69, 0x310, 0x66, 0x66, 0x6c, 0x210, 0x17f, 0x74, + 0x210, 0x73, 0x74, 0x210, 0x574, 0x576, 0x210, 0x574, + 0x565, 0x210, 0x574, 0x56b, 0x210, 0x57e, 0x576, 0x210, + 0x574, 0x56d, 0x201, 0x5d9, 0x5b4, 0x201, 0x5f2, 0x5b7, + 0x102, 0x5e2, 0x102, 0x5d0, 0x102, 0x5d3, 0x102, 0x5d4, + 0x102, 0x5db, 0x102, 0x5dc, 0x102, 0x5dd, 0x102, 0x5e8, + 0x102, 0x5ea, 0x102, 0x2b, 0x201, 0x5e9, 0x5c1, 0x201, + 0x5e9, 0x5c2, 0x201, 0xfb49, 0x5c1, 0x201, 0xfb49, 0x5c2, + 0x201, 0x5d0, 0x5b7, 0x201, 0x5d0, 0x5b8, 0x201, 0x5d0, + 0x5bc, 0x201, 0x5d1, 0x5bc, 0x201, 0x5d2, 0x5bc, 0x201, + 0x5d3, 0x5bc, 0x201, 0x5d4, 0x5bc, 0x201, 0x5d5, 0x5bc, + 0x201, 0x5d6, 0x5bc, 0x201, 0x5d8, 0x5bc, 0x201, 0x5d9, + 0x5bc, 0x201, 0x5da, 0x5bc, 0x201, 0x5db, 0x5bc, 0x201, + 0x5dc, 0x5bc, 0x201, 0x5de, 0x5bc, 0x201, 0x5e0, 0x5bc, + 0x201, 0x5e1, 0x5bc, 0x201, 0x5e3, 0x5bc, 0x201, 0x5e4, + 0x5bc, 0x201, 0x5e6, 0x5bc, 0x201, 0x5e7, 0x5bc, 0x201, + 0x5e8, 0x5bc, 0x201, 0x5e9, 0x5bc, 0x201, 0x5ea, 0x5bc, + 0x201, 0x5d5, 0x5b9, 0x201, 0x5d1, 0x5bf, 0x201, 0x5db, + 0x5bf, 0x201, 0x5e4, 0x5bf, 0x210, 0x5d0, 0x5dc, 0x107, + 0x671, 0x106, 0x671, 0x107, 0x67b, 0x106, 0x67b, 0x104, + 0x67b, 0x105, 0x67b, 0x107, 0x67e, 0x106, 0x67e, 0x104, + 0x67e, 0x105, 0x67e, 0x107, 0x680, 0x106, 0x680, 0x104, + 0x680, 0x105, 0x680, 0x107, 0x67a, 0x106, 0x67a, 0x104, + 0x67a, 0x105, 0x67a, 0x107, 0x67f, 0x106, 0x67f, 0x104, + 0x67f, 0x105, 0x67f, 0x107, 0x679, 0x106, 0x679, 0x104, + 0x679, 0x105, 0x679, 0x107, 0x6a4, 0x106, 0x6a4, 0x104, + 0x6a4, 0x105, 0x6a4, 0x107, 0x6a6, 0x106, 0x6a6, 0x104, + 0x6a6, 0x105, 0x6a6, 0x107, 0x684, 0x106, 0x684, 0x104, + 0x684, 0x105, 0x684, 0x107, 0x683, 0x106, 0x683, 0x104, + 0x683, 0x105, 0x683, 0x107, 0x686, 0x106, 0x686, 0x104, + 0x686, 0x105, 0x686, 0x107, 0x687, 0x106, 0x687, 0x104, + 0x687, 0x105, 0x687, 0x107, 0x68d, 0x106, 0x68d, 0x107, + 0x68c, 0x106, 0x68c, 0x107, 0x68e, 0x106, 0x68e, 0x107, + 0x688, 0x106, 0x688, 0x107, 0x698, 0x106, 0x698, 0x107, + 0x691, 0x106, 0x691, 0x107, 0x6a9, 0x106, 0x6a9, 0x104, + 0x6a9, 0x105, 0x6a9, 0x107, 0x6af, 0x106, 0x6af, 0x104, + 0x6af, 0x105, 0x6af, 0x107, 0x6b3, 0x106, 0x6b3, 0x104, + 0x6b3, 0x105, 0x6b3, 0x107, 0x6b1, 0x106, 0x6b1, 0x104, + 0x6b1, 0x105, 0x6b1, 0x107, 0x6ba, 0x106, 0x6ba, 0x107, + 0x6bb, 0x106, 0x6bb, 0x104, 0x6bb, 0x105, 0x6bb, 0x107, + 0x6c0, 0x106, 0x6c0, 0x107, 0x6c1, 0x106, 0x6c1, 0x104, + 0x6c1, 0x105, 0x6c1, 0x107, 0x6be, 0x106, 0x6be, 0x104, + 0x6be, 0x105, 0x6be, 0x107, 0x6d2, 0x106, 0x6d2, 0x107, + 0x6d3, 0x106, 0x6d3, 0x107, 0x6ad, 0x106, 0x6ad, 0x104, + 0x6ad, 0x105, 0x6ad, 0x107, 0x6c7, 0x106, 0x6c7, 0x107, + 0x6c6, 0x106, 0x6c6, 0x107, 0x6c8, 0x106, 0x6c8, 0x107, + 0x677, 0x107, 0x6cb, 0x106, 0x6cb, 0x107, 0x6c5, 0x106, + 0x6c5, 0x107, 0x6c9, 0x106, 0x6c9, 0x107, 0x6d0, 0x106, + 0x6d0, 0x104, 0x6d0, 0x105, 0x6d0, 0x104, 0x649, 0x105, + 0x649, 0x207, 0x626, 0x627, 0x206, 0x626, 0x627, 0x207, + 0x626, 0x6d5, 0x206, 0x626, 0x6d5, 0x207, 0x626, 0x648, + 0x206, 0x626, 0x648, 0x207, 0x626, 0x6c7, 0x206, 0x626, + 0x6c7, 0x207, 0x626, 0x6c6, 0x206, 0x626, 0x6c6, 0x207, + 0x626, 0x6c8, 0x206, 0x626, 0x6c8, 0x207, 0x626, 0x6d0, + 0x206, 0x626, 0x6d0, 0x204, 0x626, 0x6d0, 0x207, 0x626, + 0x649, 0x206, 0x626, 0x649, 0x204, 0x626, 0x649, 0x107, + 0x6cc, 0x106, 0x6cc, 0x104, 0x6cc, 0x105, 0x6cc, 0x207, + 0x626, 0x62c, 0x207, 0x626, 0x62d, 0x207, 0x626, 0x645, + 0x207, 0x626, 0x649, 0x207, 0x626, 0x64a, 0x207, 0x628, + 0x62c, 0x207, 0x628, 0x62d, 0x207, 0x628, 0x62e, 0x207, + 0x628, 0x645, 0x207, 0x628, 0x649, 0x207, 0x628, 0x64a, + 0x207, 0x62a, 0x62c, 0x207, 0x62a, 0x62d, 0x207, 0x62a, + 0x62e, 0x207, 0x62a, 0x645, 0x207, 0x62a, 0x649, 0x207, + 0x62a, 0x64a, 0x207, 0x62b, 0x62c, 0x207, 0x62b, 0x645, + 0x207, 0x62b, 0x649, 0x207, 0x62b, 0x64a, 0x207, 0x62c, + 0x62d, 0x207, 0x62c, 0x645, 0x207, 0x62d, 0x62c, 0x207, + 0x62d, 0x645, 0x207, 0x62e, 0x62c, 0x207, 0x62e, 0x62d, + 0x207, 0x62e, 0x645, 0x207, 0x633, 0x62c, 0x207, 0x633, + 0x62d, 0x207, 0x633, 0x62e, 0x207, 0x633, 0x645, 0x207, + 0x635, 0x62d, 0x207, 0x635, 0x645, 0x207, 0x636, 0x62c, + 0x207, 0x636, 0x62d, 0x207, 0x636, 0x62e, 0x207, 0x636, + 0x645, 0x207, 0x637, 0x62d, 0x207, 0x637, 0x645, 0x207, + 0x638, 0x645, 0x207, 0x639, 0x62c, 0x207, 0x639, 0x645, + 0x207, 0x63a, 0x62c, 0x207, 0x63a, 0x645, 0x207, 0x641, + 0x62c, 0x207, 0x641, 0x62d, 0x207, 0x641, 0x62e, 0x207, + 0x641, 0x645, 0x207, 0x641, 0x649, 0x207, 0x641, 0x64a, + 0x207, 0x642, 0x62d, 0x207, 0x642, 0x645, 0x207, 0x642, + 0x649, 0x207, 0x642, 0x64a, 0x207, 0x643, 0x627, 0x207, + 0x643, 0x62c, 0x207, 0x643, 0x62d, 0x207, 0x643, 0x62e, + 0x207, 0x643, 0x644, 0x207, 0x643, 0x645, 0x207, 0x643, + 0x649, 0x207, 0x643, 0x64a, 0x207, 0x644, 0x62c, 0x207, + 0x644, 0x62d, 0x207, 0x644, 0x62e, 0x207, 0x644, 0x645, + 0x207, 0x644, 0x649, 0x207, 0x644, 0x64a, 0x207, 0x645, + 0x62c, 0x207, 0x645, 0x62d, 0x207, 0x645, 0x62e, 0x207, + 0x645, 0x645, 0x207, 0x645, 0x649, 0x207, 0x645, 0x64a, + 0x207, 0x646, 0x62c, 0x207, 0x646, 0x62d, 0x207, 0x646, + 0x62e, 0x207, 0x646, 0x645, 0x207, 0x646, 0x649, 0x207, + 0x646, 0x64a, 0x207, 0x647, 0x62c, 0x207, 0x647, 0x645, + 0x207, 0x647, 0x649, 0x207, 0x647, 0x64a, 0x207, 0x64a, + 0x62c, 0x207, 0x64a, 0x62d, 0x207, 0x64a, 0x62e, 0x207, + 0x64a, 0x645, 0x207, 0x64a, 0x649, 0x207, 0x64a, 0x64a, + 0x207, 0x630, 0x670, 0x207, 0x631, 0x670, 0x207, 0x649, + 0x670, 0x307, 0x20, 0x64c, 0x651, 0x307, 0x20, 0x64d, + 0x651, 0x307, 0x20, 0x64e, 0x651, 0x307, 0x20, 0x64f, + 0x651, 0x307, 0x20, 0x650, 0x651, 0x307, 0x20, 0x651, + 0x670, 0x206, 0x626, 0x631, 0x206, 0x626, 0x632, 0x206, + 0x626, 0x645, 0x206, 0x626, 0x646, 0x206, 0x626, 0x649, + 0x206, 0x626, 0x64a, 0x206, 0x628, 0x631, 0x206, 0x628, + 0x632, 0x206, 0x628, 0x645, 0x206, 0x628, 0x646, 0x206, + 0x628, 0x649, 0x206, 0x628, 0x64a, 0x206, 0x62a, 0x631, + 0x206, 0x62a, 0x632, 0x206, 0x62a, 0x645, 0x206, 0x62a, + 0x646, 0x206, 0x62a, 0x649, 0x206, 0x62a, 0x64a, 0x206, + 0x62b, 0x631, 0x206, 0x62b, 0x632, 0x206, 0x62b, 0x645, + 0x206, 0x62b, 0x646, 0x206, 0x62b, 0x649, 0x206, 0x62b, + 0x64a, 0x206, 0x641, 0x649, 0x206, 0x641, 0x64a, 0x206, + 0x642, 0x649, 0x206, 0x642, 0x64a, 0x206, 0x643, 0x627, + 0x206, 0x643, 0x644, 0x206, 0x643, 0x645, 0x206, 0x643, + 0x649, 0x206, 0x643, 0x64a, 0x206, 0x644, 0x645, 0x206, + 0x644, 0x649, 0x206, 0x644, 0x64a, 0x206, 0x645, 0x627, + 0x206, 0x645, 0x645, 0x206, 0x646, 0x631, 0x206, 0x646, + 0x632, 0x206, 0x646, 0x645, 0x206, 0x646, 0x646, 0x206, + 0x646, 0x649, 0x206, 0x646, 0x64a, 0x206, 0x649, 0x670, + 0x206, 0x64a, 0x631, 0x206, 0x64a, 0x632, 0x206, 0x64a, + 0x645, 0x206, 0x64a, 0x646, 0x206, 0x64a, 0x649, 0x206, + 0x64a, 0x64a, 0x204, 0x626, 0x62c, 0x204, 0x626, 0x62d, + 0x204, 0x626, 0x62e, 0x204, 0x626, 0x645, 0x204, 0x626, + 0x647, 0x204, 0x628, 0x62c, 0x204, 0x628, 0x62d, 0x204, + 0x628, 0x62e, 0x204, 0x628, 0x645, 0x204, 0x628, 0x647, + 0x204, 0x62a, 0x62c, 0x204, 0x62a, 0x62d, 0x204, 0x62a, + 0x62e, 0x204, 0x62a, 0x645, 0x204, 0x62a, 0x647, 0x204, + 0x62b, 0x645, 0x204, 0x62c, 0x62d, 0x204, 0x62c, 0x645, + 0x204, 0x62d, 0x62c, 0x204, 0x62d, 0x645, 0x204, 0x62e, + 0x62c, 0x204, 0x62e, 0x645, 0x204, 0x633, 0x62c, 0x204, + 0x633, 0x62d, 0x204, 0x633, 0x62e, 0x204, 0x633, 0x645, + 0x204, 0x635, 0x62d, 0x204, 0x635, 0x62e, 0x204, 0x635, + 0x645, 0x204, 0x636, 0x62c, 0x204, 0x636, 0x62d, 0x204, + 0x636, 0x62e, 0x204, 0x636, 0x645, 0x204, 0x637, 0x62d, + 0x204, 0x638, 0x645, 0x204, 0x639, 0x62c, 0x204, 0x639, + 0x645, 0x204, 0x63a, 0x62c, 0x204, 0x63a, 0x645, 0x204, + 0x641, 0x62c, 0x204, 0x641, 0x62d, 0x204, 0x641, 0x62e, + 0x204, 0x641, 0x645, 0x204, 0x642, 0x62d, 0x204, 0x642, + 0x645, 0x204, 0x643, 0x62c, 0x204, 0x643, 0x62d, 0x204, + 0x643, 0x62e, 0x204, 0x643, 0x644, 0x204, 0x643, 0x645, + 0x204, 0x644, 0x62c, 0x204, 0x644, 0x62d, 0x204, 0x644, + 0x62e, 0x204, 0x644, 0x645, 0x204, 0x644, 0x647, 0x204, + 0x645, 0x62c, 0x204, 0x645, 0x62d, 0x204, 0x645, 0x62e, + 0x204, 0x645, 0x645, 0x204, 0x646, 0x62c, 0x204, 0x646, + 0x62d, 0x204, 0x646, 0x62e, 0x204, 0x646, 0x645, 0x204, + 0x646, 0x647, 0x204, 0x647, 0x62c, 0x204, 0x647, 0x645, + 0x204, 0x647, 0x670, 0x204, 0x64a, 0x62c, 0x204, 0x64a, + 0x62d, 0x204, 0x64a, 0x62e, 0x204, 0x64a, 0x645, 0x204, + 0x64a, 0x647, 0x205, 0x626, 0x645, 0x205, 0x626, 0x647, + 0x205, 0x628, 0x645, 0x205, 0x628, 0x647, 0x205, 0x62a, + 0x645, 0x205, 0x62a, 0x647, 0x205, 0x62b, 0x645, 0x205, + 0x62b, 0x647, 0x205, 0x633, 0x645, 0x205, 0x633, 0x647, + 0x205, 0x634, 0x645, 0x205, 0x634, 0x647, 0x205, 0x643, + 0x644, 0x205, 0x643, 0x645, 0x205, 0x644, 0x645, 0x205, + 0x646, 0x645, 0x205, 0x646, 0x647, 0x205, 0x64a, 0x645, + 0x205, 0x64a, 0x647, 0x305, 0x640, 0x64e, 0x651, 0x305, + 0x640, 0x64f, 0x651, 0x305, 0x640, 0x650, 0x651, 0x207, + 0x637, 0x649, 0x207, 0x637, 0x64a, 0x207, 0x639, 0x649, + 0x207, 0x639, 0x64a, 0x207, 0x63a, 0x649, 0x207, 0x63a, + 0x64a, 0x207, 0x633, 0x649, 0x207, 0x633, 0x64a, 0x207, + 0x634, 0x649, 0x207, 0x634, 0x64a, 0x207, 0x62d, 0x649, + 0x207, 0x62d, 0x64a, 0x207, 0x62c, 0x649, 0x207, 0x62c, + 0x64a, 0x207, 0x62e, 0x649, 0x207, 0x62e, 0x64a, 0x207, + 0x635, 0x649, 0x207, 0x635, 0x64a, 0x207, 0x636, 0x649, + 0x207, 0x636, 0x64a, 0x207, 0x634, 0x62c, 0x207, 0x634, + 0x62d, 0x207, 0x634, 0x62e, 0x207, 0x634, 0x645, 0x207, + 0x634, 0x631, 0x207, 0x633, 0x631, 0x207, 0x635, 0x631, + 0x207, 0x636, 0x631, 0x206, 0x637, 0x649, 0x206, 0x637, + 0x64a, 0x206, 0x639, 0x649, 0x206, 0x639, 0x64a, 0x206, + 0x63a, 0x649, 0x206, 0x63a, 0x64a, 0x206, 0x633, 0x649, + 0x206, 0x633, 0x64a, 0x206, 0x634, 0x649, 0x206, 0x634, + 0x64a, 0x206, 0x62d, 0x649, 0x206, 0x62d, 0x64a, 0x206, + 0x62c, 0x649, 0x206, 0x62c, 0x64a, 0x206, 0x62e, 0x649, + 0x206, 0x62e, 0x64a, 0x206, 0x635, 0x649, 0x206, 0x635, + 0x64a, 0x206, 0x636, 0x649, 0x206, 0x636, 0x64a, 0x206, + 0x634, 0x62c, 0x206, 0x634, 0x62d, 0x206, 0x634, 0x62e, + 0x206, 0x634, 0x645, 0x206, 0x634, 0x631, 0x206, 0x633, + 0x631, 0x206, 0x635, 0x631, 0x206, 0x636, 0x631, 0x204, + 0x634, 0x62c, 0x204, 0x634, 0x62d, 0x204, 0x634, 0x62e, + 0x204, 0x634, 0x645, 0x204, 0x633, 0x647, 0x204, 0x634, + 0x647, 0x204, 0x637, 0x645, 0x205, 0x633, 0x62c, 0x205, + 0x633, 0x62d, 0x205, 0x633, 0x62e, 0x205, 0x634, 0x62c, + 0x205, 0x634, 0x62d, 0x205, 0x634, 0x62e, 0x205, 0x637, + 0x645, 0x205, 0x638, 0x645, 0x206, 0x627, 0x64b, 0x207, + 0x627, 0x64b, 0x304, 0x62a, 0x62c, 0x645, 0x306, 0x62a, + 0x62d, 0x62c, 0x304, 0x62a, 0x62d, 0x62c, 0x304, 0x62a, + 0x62d, 0x645, 0x304, 0x62a, 0x62e, 0x645, 0x304, 0x62a, + 0x645, 0x62c, 0x304, 0x62a, 0x645, 0x62d, 0x304, 0x62a, + 0x645, 0x62e, 0x306, 0x62c, 0x645, 0x62d, 0x304, 0x62c, + 0x645, 0x62d, 0x306, 0x62d, 0x645, 0x64a, 0x306, 0x62d, + 0x645, 0x649, 0x304, 0x633, 0x62d, 0x62c, 0x304, 0x633, + 0x62c, 0x62d, 0x306, 0x633, 0x62c, 0x649, 0x306, 0x633, + 0x645, 0x62d, 0x304, 0x633, 0x645, 0x62d, 0x304, 0x633, + 0x645, 0x62c, 0x306, 0x633, 0x645, 0x645, 0x304, 0x633, + 0x645, 0x645, 0x306, 0x635, 0x62d, 0x62d, 0x304, 0x635, + 0x62d, 0x62d, 0x306, 0x635, 0x645, 0x645, 0x306, 0x634, + 0x62d, 0x645, 0x304, 0x634, 0x62d, 0x645, 0x306, 0x634, + 0x62c, 0x64a, 0x306, 0x634, 0x645, 0x62e, 0x304, 0x634, + 0x645, 0x62e, 0x306, 0x634, 0x645, 0x645, 0x304, 0x634, + 0x645, 0x645, 0x306, 0x636, 0x62d, 0x649, 0x306, 0x636, + 0x62e, 0x645, 0x304, 0x636, 0x62e, 0x645, 0x306, 0x637, + 0x645, 0x62d, 0x304, 0x637, 0x645, 0x62d, 0x304, 0x637, + 0x645, 0x645, 0x306, 0x637, 0x645, 0x64a, 0x306, 0x639, + 0x62c, 0x645, 0x306, 0x639, 0x645, 0x645, 0x304, 0x639, + 0x645, 0x645, 0x306, 0x639, 0x645, 0x649, 0x306, 0x63a, + 0x645, 0x645, 0x306, 0x63a, 0x645, 0x64a, 0x306, 0x63a, + 0x645, 0x649, 0x306, 0x641, 0x62e, 0x645, 0x304, 0x641, + 0x62e, 0x645, 0x306, 0x642, 0x645, 0x62d, 0x306, 0x642, + 0x645, 0x645, 0x306, 0x644, 0x62d, 0x645, 0x306, 0x644, + 0x62d, 0x64a, 0x306, 0x644, 0x62d, 0x649, 0x304, 0x644, + 0x62c, 0x62c, 0x306, 0x644, 0x62c, 0x62c, 0x306, 0x644, + 0x62e, 0x645, 0x304, 0x644, 0x62e, 0x645, 0x306, 0x644, + 0x645, 0x62d, 0x304, 0x644, 0x645, 0x62d, 0x304, 0x645, + 0x62d, 0x62c, 0x304, 0x645, 0x62d, 0x645, 0x306, 0x645, + 0x62d, 0x64a, 0x304, 0x645, 0x62c, 0x62d, 0x304, 0x645, + 0x62c, 0x645, 0x304, 0x645, 0x62e, 0x62c, 0x304, 0x645, + 0x62e, 0x645, 0x304, 0x645, 0x62c, 0x62e, 0x304, 0x647, + 0x645, 0x62c, 0x304, 0x647, 0x645, 0x645, 0x304, 0x646, + 0x62d, 0x645, 0x306, 0x646, 0x62d, 0x649, 0x306, 0x646, + 0x62c, 0x645, 0x304, 0x646, 0x62c, 0x645, 0x306, 0x646, + 0x62c, 0x649, 0x306, 0x646, 0x645, 0x64a, 0x306, 0x646, + 0x645, 0x649, 0x306, 0x64a, 0x645, 0x645, 0x304, 0x64a, + 0x645, 0x645, 0x306, 0x628, 0x62e, 0x64a, 0x306, 0x62a, + 0x62c, 0x64a, 0x306, 0x62a, 0x62c, 0x649, 0x306, 0x62a, + 0x62e, 0x64a, 0x306, 0x62a, 0x62e, 0x649, 0x306, 0x62a, + 0x645, 0x64a, 0x306, 0x62a, 0x645, 0x649, 0x306, 0x62c, + 0x645, 0x64a, 0x306, 0x62c, 0x62d, 0x649, 0x306, 0x62c, + 0x645, 0x649, 0x306, 0x633, 0x62e, 0x649, 0x306, 0x635, + 0x62d, 0x64a, 0x306, 0x634, 0x62d, 0x64a, 0x306, 0x636, + 0x62d, 0x64a, 0x306, 0x644, 0x62c, 0x64a, 0x306, 0x644, + 0x645, 0x64a, 0x306, 0x64a, 0x62d, 0x64a, 0x306, 0x64a, + 0x62c, 0x64a, 0x306, 0x64a, 0x645, 0x64a, 0x306, 0x645, + 0x645, 0x64a, 0x306, 0x642, 0x645, 0x64a, 0x306, 0x646, + 0x62d, 0x64a, 0x304, 0x642, 0x645, 0x62d, 0x304, 0x644, + 0x62d, 0x645, 0x306, 0x639, 0x645, 0x64a, 0x306, 0x643, + 0x645, 0x64a, 0x304, 0x646, 0x62c, 0x62d, 0x306, 0x645, + 0x62e, 0x64a, 0x304, 0x644, 0x62c, 0x645, 0x306, 0x643, + 0x645, 0x645, 0x306, 0x644, 0x62c, 0x645, 0x306, 0x646, + 0x62c, 0x62d, 0x306, 0x62c, 0x62d, 0x64a, 0x306, 0x62d, + 0x62c, 0x64a, 0x306, 0x645, 0x62c, 0x64a, 0x306, 0x641, + 0x645, 0x64a, 0x306, 0x628, 0x62d, 0x64a, 0x304, 0x643, + 0x645, 0x645, 0x304, 0x639, 0x62c, 0x645, 0x304, 0x635, + 0x645, 0x645, 0x306, 0x633, 0x62e, 0x64a, 0x306, 0x646, + 0x62c, 0x64a, 0x307, 0x635, 0x644, 0x6d2, 0x307, 0x642, + 0x644, 0x6d2, 0x407, 0x627, 0x644, 0x644, 0x647, 0x407, + 0x627, 0x643, 0x628, 0x631, 0x407, 0x645, 0x62d, 0x645, + 0x62f, 0x407, 0x635, 0x644, 0x639, 0x645, 0x407, 0x631, + 0x633, 0x648, 0x644, 0x407, 0x639, 0x644, 0x64a, 0x647, + 0x407, 0x648, 0x633, 0x644, 0x645, 0x307, 0x635, 0x644, + 0x649, 0x1207, 0x635, 0x644, 0x649, 0x20, 0x627, 0x644, + 0x644, 0x647, 0x20, 0x639, 0x644, 0x64a, 0x647, 0x20, + 0x648, 0x633, 0x644, 0x645, 0x807, 0x62c, 0x644, 0x20, + 0x62c, 0x644, 0x627, 0x644, 0x647, 0x407, 0x631, 0x6cc, + 0x627, 0x644, 0x10b, 0x2c, 0x10b, 0x3001, 0x10b, 0x3002, + 0x10b, 0x3a, 0x10b, 0x3b, 0x10b, 0x21, 0x10b, 0x3f, + 0x10b, 0x3016, 0x10b, 0x3017, 0x10b, 0x2026, 0x10b, 0x2025, + 0x10b, 0x2014, 0x10b, 0x2013, 0x10b, 0x5f, 0x10b, 0x5f, + 0x10b, 0x28, 0x10b, 0x29, 0x10b, 0x7b, 0x10b, 0x7d, + 0x10b, 0x3014, 0x10b, 0x3015, 0x10b, 0x3010, 0x10b, 0x3011, + 0x10b, 0x300a, 0x10b, 0x300b, 0x10b, 0x3008, 0x10b, 0x3009, + 0x10b, 0x300c, 0x10b, 0x300d, 0x10b, 0x300e, 0x10b, 0x300f, + 0x10b, 0x5b, 0x10b, 0x5d, 0x110, 0x203e, 0x110, 0x203e, + 0x110, 0x203e, 0x110, 0x203e, 0x110, 0x5f, 0x110, 0x5f, + 0x110, 0x5f, 0x10e, 0x2c, 0x10e, 0x3001, 0x10e, 0x2e, + 0x10e, 0x3b, 0x10e, 0x3a, 0x10e, 0x3f, 0x10e, 0x21, + 0x10e, 0x2014, 0x10e, 0x28, 0x10e, 0x29, 0x10e, 0x7b, + 0x10e, 0x7d, 0x10e, 0x3014, 0x10e, 0x3015, 0x10e, 0x23, + 0x10e, 0x26, 0x10e, 0x2a, 0x10e, 0x2b, 0x10e, 0x2d, + 0x10e, 0x3c, 0x10e, 0x3e, 0x10e, 0x3d, 0x10e, 0x5c, + 0x10e, 0x24, 0x10e, 0x25, 0x10e, 0x40, 0x207, 0x20, + 0x64b, 0x205, 0x640, 0x64b, 0x207, 0x20, 0x64c, 0x207, + 0x20, 0x64d, 0x207, 0x20, 0x64e, 0x205, 0x640, 0x64e, + 0x207, 0x20, 0x64f, 0x205, 0x640, 0x64f, 0x207, 0x20, + 0x650, 0x205, 0x640, 0x650, 0x207, 0x20, 0x651, 0x205, + 0x640, 0x651, 0x207, 0x20, 0x652, 0x205, 0x640, 0x652, + 0x107, 0x621, 0x107, 0x622, 0x106, 0x622, 0x107, 0x623, + 0x106, 0x623, 0x107, 0x624, 0x106, 0x624, 0x107, 0x625, + 0x106, 0x625, 0x107, 0x626, 0x106, 0x626, 0x104, 0x626, + 0x105, 0x626, 0x107, 0x627, 0x106, 0x627, 0x107, 0x628, + 0x106, 0x628, 0x104, 0x628, 0x105, 0x628, 0x107, 0x629, + 0x106, 0x629, 0x107, 0x62a, 0x106, 0x62a, 0x104, 0x62a, + 0x105, 0x62a, 0x107, 0x62b, 0x106, 0x62b, 0x104, 0x62b, + 0x105, 0x62b, 0x107, 0x62c, 0x106, 0x62c, 0x104, 0x62c, + 0x105, 0x62c, 0x107, 0x62d, 0x106, 0x62d, 0x104, 0x62d, + 0x105, 0x62d, 0x107, 0x62e, 0x106, 0x62e, 0x104, 0x62e, + 0x105, 0x62e, 0x107, 0x62f, 0x106, 0x62f, 0x107, 0x630, + 0x106, 0x630, 0x107, 0x631, 0x106, 0x631, 0x107, 0x632, + 0x106, 0x632, 0x107, 0x633, 0x106, 0x633, 0x104, 0x633, + 0x105, 0x633, 0x107, 0x634, 0x106, 0x634, 0x104, 0x634, + 0x105, 0x634, 0x107, 0x635, 0x106, 0x635, 0x104, 0x635, + 0x105, 0x635, 0x107, 0x636, 0x106, 0x636, 0x104, 0x636, + 0x105, 0x636, 0x107, 0x637, 0x106, 0x637, 0x104, 0x637, + 0x105, 0x637, 0x107, 0x638, 0x106, 0x638, 0x104, 0x638, + 0x105, 0x638, 0x107, 0x639, 0x106, 0x639, 0x104, 0x639, + 0x105, 0x639, 0x107, 0x63a, 0x106, 0x63a, 0x104, 0x63a, + 0x105, 0x63a, 0x107, 0x641, 0x106, 0x641, 0x104, 0x641, + 0x105, 0x641, 0x107, 0x642, 0x106, 0x642, 0x104, 0x642, + 0x105, 0x642, 0x107, 0x643, 0x106, 0x643, 0x104, 0x643, + 0x105, 0x643, 0x107, 0x644, 0x106, 0x644, 0x104, 0x644, + 0x105, 0x644, 0x107, 0x645, 0x106, 0x645, 0x104, 0x645, + 0x105, 0x645, 0x107, 0x646, 0x106, 0x646, 0x104, 0x646, + 0x105, 0x646, 0x107, 0x647, 0x106, 0x647, 0x104, 0x647, + 0x105, 0x647, 0x107, 0x648, 0x106, 0x648, 0x107, 0x649, + 0x106, 0x649, 0x107, 0x64a, 0x106, 0x64a, 0x104, 0x64a, + 0x105, 0x64a, 0x207, 0x644, 0x622, 0x206, 0x644, 0x622, + 0x207, 0x644, 0x623, 0x206, 0x644, 0x623, 0x207, 0x644, + 0x625, 0x206, 0x644, 0x625, 0x207, 0x644, 0x627, 0x206, + 0x644, 0x627, 0x10c, 0x21, 0x10c, 0x22, 0x10c, 0x23, + 0x10c, 0x24, 0x10c, 0x25, 0x10c, 0x26, 0x10c, 0x27, + 0x10c, 0x28, 0x10c, 0x29, 0x10c, 0x2a, 0x10c, 0x2b, + 0x10c, 0x2c, 0x10c, 0x2d, 0x10c, 0x2e, 0x10c, 0x2f, + 0x10c, 0x30, 0x10c, 0x31, 0x10c, 0x32, 0x10c, 0x33, + 0x10c, 0x34, 0x10c, 0x35, 0x10c, 0x36, 0x10c, 0x37, + 0x10c, 0x38, 0x10c, 0x39, 0x10c, 0x3a, 0x10c, 0x3b, + 0x10c, 0x3c, 0x10c, 0x3d, 0x10c, 0x3e, 0x10c, 0x3f, + 0x10c, 0x40, 0x10c, 0x41, 0x10c, 0x42, 0x10c, 0x43, + 0x10c, 0x44, 0x10c, 0x45, 0x10c, 0x46, 0x10c, 0x47, + 0x10c, 0x48, 0x10c, 0x49, 0x10c, 0x4a, 0x10c, 0x4b, + 0x10c, 0x4c, 0x10c, 0x4d, 0x10c, 0x4e, 0x10c, 0x4f, + 0x10c, 0x50, 0x10c, 0x51, 0x10c, 0x52, 0x10c, 0x53, + 0x10c, 0x54, 0x10c, 0x55, 0x10c, 0x56, 0x10c, 0x57, + 0x10c, 0x58, 0x10c, 0x59, 0x10c, 0x5a, 0x10c, 0x5b, + 0x10c, 0x5c, 0x10c, 0x5d, 0x10c, 0x5e, 0x10c, 0x5f, + 0x10c, 0x60, 0x10c, 0x61, 0x10c, 0x62, 0x10c, 0x63, + 0x10c, 0x64, 0x10c, 0x65, 0x10c, 0x66, 0x10c, 0x67, + 0x10c, 0x68, 0x10c, 0x69, 0x10c, 0x6a, 0x10c, 0x6b, + 0x10c, 0x6c, 0x10c, 0x6d, 0x10c, 0x6e, 0x10c, 0x6f, + 0x10c, 0x70, 0x10c, 0x71, 0x10c, 0x72, 0x10c, 0x73, + 0x10c, 0x74, 0x10c, 0x75, 0x10c, 0x76, 0x10c, 0x77, + 0x10c, 0x78, 0x10c, 0x79, 0x10c, 0x7a, 0x10c, 0x7b, + 0x10c, 0x7c, 0x10c, 0x7d, 0x10c, 0x7e, 0x10c, 0x2985, + 0x10c, 0x2986, 0x10d, 0x3002, 0x10d, 0x300c, 0x10d, 0x300d, + 0x10d, 0x3001, 0x10d, 0x30fb, 0x10d, 0x30f2, 0x10d, 0x30a1, + 0x10d, 0x30a3, 0x10d, 0x30a5, 0x10d, 0x30a7, 0x10d, 0x30a9, + 0x10d, 0x30e3, 0x10d, 0x30e5, 0x10d, 0x30e7, 0x10d, 0x30c3, + 0x10d, 0x30fc, 0x10d, 0x30a2, 0x10d, 0x30a4, 0x10d, 0x30a6, + 0x10d, 0x30a8, 0x10d, 0x30aa, 0x10d, 0x30ab, 0x10d, 0x30ad, + 0x10d, 0x30af, 0x10d, 0x30b1, 0x10d, 0x30b3, 0x10d, 0x30b5, + 0x10d, 0x30b7, 0x10d, 0x30b9, 0x10d, 0x30bb, 0x10d, 0x30bd, + 0x10d, 0x30bf, 0x10d, 0x30c1, 0x10d, 0x30c4, 0x10d, 0x30c6, + 0x10d, 0x30c8, 0x10d, 0x30ca, 0x10d, 0x30cb, 0x10d, 0x30cc, + 0x10d, 0x30cd, 0x10d, 0x30ce, 0x10d, 0x30cf, 0x10d, 0x30d2, + 0x10d, 0x30d5, 0x10d, 0x30d8, 0x10d, 0x30db, 0x10d, 0x30de, + 0x10d, 0x30df, 0x10d, 0x30e0, 0x10d, 0x30e1, 0x10d, 0x30e2, + 0x10d, 0x30e4, 0x10d, 0x30e6, 0x10d, 0x30e8, 0x10d, 0x30e9, + 0x10d, 0x30ea, 0x10d, 0x30eb, 0x10d, 0x30ec, 0x10d, 0x30ed, + 0x10d, 0x30ef, 0x10d, 0x30f3, 0x10d, 0x3099, 0x10d, 0x309a, + 0x10d, 0x3164, 0x10d, 0x3131, 0x10d, 0x3132, 0x10d, 0x3133, + 0x10d, 0x3134, 0x10d, 0x3135, 0x10d, 0x3136, 0x10d, 0x3137, + 0x10d, 0x3138, 0x10d, 0x3139, 0x10d, 0x313a, 0x10d, 0x313b, + 0x10d, 0x313c, 0x10d, 0x313d, 0x10d, 0x313e, 0x10d, 0x313f, + 0x10d, 0x3140, 0x10d, 0x3141, 0x10d, 0x3142, 0x10d, 0x3143, + 0x10d, 0x3144, 0x10d, 0x3145, 0x10d, 0x3146, 0x10d, 0x3147, + 0x10d, 0x3148, 0x10d, 0x3149, 0x10d, 0x314a, 0x10d, 0x314b, + 0x10d, 0x314c, 0x10d, 0x314d, 0x10d, 0x314e, 0x10d, 0x314f, + 0x10d, 0x3150, 0x10d, 0x3151, 0x10d, 0x3152, 0x10d, 0x3153, + 0x10d, 0x3154, 0x10d, 0x3155, 0x10d, 0x3156, 0x10d, 0x3157, + 0x10d, 0x3158, 0x10d, 0x3159, 0x10d, 0x315a, 0x10d, 0x315b, + 0x10d, 0x315c, 0x10d, 0x315d, 0x10d, 0x315e, 0x10d, 0x315f, + 0x10d, 0x3160, 0x10d, 0x3161, 0x10d, 0x3162, 0x10d, 0x3163, + 0x10c, 0xa2, 0x10c, 0xa3, 0x10c, 0xac, 0x10c, 0xaf, + 0x10c, 0xa6, 0x10c, 0xa5, 0x10c, 0x20a9, 0x10d, 0x2502, + 0x10d, 0x2190, 0x10d, 0x2191, 0x10d, 0x2192, 0x10d, 0x2193, + 0x10d, 0x25a0, 0x10d, 0x25cb, 0x401, 0xd834, 0xdd57, 0xd834, + 0xdd65, 0x401, 0xd834, 0xdd58, 0xd834, 0xdd65, 0x401, 0xd834, + 0xdd5f, 0xd834, 0xdd6e, 0x401, 0xd834, 0xdd5f, 0xd834, 0xdd6f, + 0x401, 0xd834, 0xdd5f, 0xd834, 0xdd70, 0x401, 0xd834, 0xdd5f, + 0xd834, 0xdd71, 0x401, 0xd834, 0xdd5f, 0xd834, 0xdd72, 0x401, + 0xd834, 0xddb9, 0xd834, 0xdd65, 0x401, 0xd834, 0xddba, 0xd834, + 0xdd65, 0x401, 0xd834, 0xddbb, 0xd834, 0xdd6e, 0x401, 0xd834, + 0xddbc, 0xd834, 0xdd6e, 0x401, 0xd834, 0xddbb, 0xd834, 0xdd6f, + 0x401, 0xd834, 0xddbc, 0xd834, 0xdd6f, 0x102, 0x41, 0x102, + 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102, + 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102, + 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102, + 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102, + 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, + 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, + 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, + 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102, + 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, + 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, + 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, + 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, + 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, + 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102, + 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102, + 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102, + 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102, + 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, + 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, + 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, + 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102, + 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102, + 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102, + 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, 0x74, 0x102, + 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, 0x78, 0x102, + 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, 0x42, 0x102, + 0x43, 0x102, 0x44, 0x102, 0x45, 0x102, 0x46, 0x102, + 0x47, 0x102, 0x48, 0x102, 0x49, 0x102, 0x4a, 0x102, + 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102, 0x4e, 0x102, + 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102, 0x52, 0x102, + 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, 0x56, 0x102, + 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, 0x5a, 0x102, + 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, 0x64, 0x102, + 0x65, 0x102, 0x66, 0x102, 0x67, 0x102, 0x68, 0x102, + 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102, + 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102, + 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, 0x74, 0x102, + 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, 0x78, 0x102, + 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, 0x43, 0x102, + 0x44, 0x102, 0x47, 0x102, 0x4a, 0x102, 0x4b, 0x102, + 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102, + 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, 0x56, 0x102, + 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, 0x5a, 0x102, + 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, 0x64, 0x102, + 0x66, 0x102, 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, + 0x6b, 0x102, 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, + 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, + 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, + 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, + 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102, + 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102, + 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102, + 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102, + 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, + 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, + 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, + 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102, + 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, + 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, + 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, + 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, + 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, + 0x42, 0x102, 0x44, 0x102, 0x45, 0x102, 0x46, 0x102, + 0x47, 0x102, 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, + 0x4d, 0x102, 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, + 0x51, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, + 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, + 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, 0x64, 0x102, + 0x65, 0x102, 0x66, 0x102, 0x67, 0x102, 0x68, 0x102, + 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, 0x6c, 0x102, + 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, 0x70, 0x102, + 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, 0x74, 0x102, + 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, 0x78, 0x102, + 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, 0x42, 0x102, + 0x44, 0x102, 0x45, 0x102, 0x46, 0x102, 0x47, 0x102, + 0x49, 0x102, 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, + 0x4d, 0x102, 0x4f, 0x102, 0x53, 0x102, 0x54, 0x102, + 0x55, 0x102, 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, + 0x59, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, + 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102, + 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, + 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, + 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, + 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, + 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, + 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102, + 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102, + 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102, + 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102, + 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, + 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, + 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, + 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102, + 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, + 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, + 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, + 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, + 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, + 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102, + 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102, + 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102, + 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102, + 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, + 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, + 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, + 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102, + 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, + 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, + 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, + 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, + 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, + 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102, + 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102, + 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102, + 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102, + 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, + 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, + 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, + 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102, + 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, + 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, + 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, + 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, + 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, + 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102, + 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102, + 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102, + 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102, + 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, + 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, + 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, + 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102, + 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, + 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, + 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, + 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, + 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, + 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102, + 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102, + 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102, + 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102, + 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, + 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, + 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, + 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102, + 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, + 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, + 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, + 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, + 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x41, 0x102, + 0x42, 0x102, 0x43, 0x102, 0x44, 0x102, 0x45, 0x102, + 0x46, 0x102, 0x47, 0x102, 0x48, 0x102, 0x49, 0x102, + 0x4a, 0x102, 0x4b, 0x102, 0x4c, 0x102, 0x4d, 0x102, + 0x4e, 0x102, 0x4f, 0x102, 0x50, 0x102, 0x51, 0x102, + 0x52, 0x102, 0x53, 0x102, 0x54, 0x102, 0x55, 0x102, + 0x56, 0x102, 0x57, 0x102, 0x58, 0x102, 0x59, 0x102, + 0x5a, 0x102, 0x61, 0x102, 0x62, 0x102, 0x63, 0x102, + 0x64, 0x102, 0x65, 0x102, 0x66, 0x102, 0x67, 0x102, + 0x68, 0x102, 0x69, 0x102, 0x6a, 0x102, 0x6b, 0x102, + 0x6c, 0x102, 0x6d, 0x102, 0x6e, 0x102, 0x6f, 0x102, + 0x70, 0x102, 0x71, 0x102, 0x72, 0x102, 0x73, 0x102, + 0x74, 0x102, 0x75, 0x102, 0x76, 0x102, 0x77, 0x102, + 0x78, 0x102, 0x79, 0x102, 0x7a, 0x102, 0x131, 0x102, + 0x237, 0x102, 0x391, 0x102, 0x392, 0x102, 0x393, 0x102, + 0x394, 0x102, 0x395, 0x102, 0x396, 0x102, 0x397, 0x102, + 0x398, 0x102, 0x399, 0x102, 0x39a, 0x102, 0x39b, 0x102, + 0x39c, 0x102, 0x39d, 0x102, 0x39e, 0x102, 0x39f, 0x102, + 0x3a0, 0x102, 0x3a1, 0x102, 0x3f4, 0x102, 0x3a3, 0x102, + 0x3a4, 0x102, 0x3a5, 0x102, 0x3a6, 0x102, 0x3a7, 0x102, + 0x3a8, 0x102, 0x3a9, 0x102, 0x2207, 0x102, 0x3b1, 0x102, + 0x3b2, 0x102, 0x3b3, 0x102, 0x3b4, 0x102, 0x3b5, 0x102, + 0x3b6, 0x102, 0x3b7, 0x102, 0x3b8, 0x102, 0x3b9, 0x102, + 0x3ba, 0x102, 0x3bb, 0x102, 0x3bc, 0x102, 0x3bd, 0x102, + 0x3be, 0x102, 0x3bf, 0x102, 0x3c0, 0x102, 0x3c1, 0x102, + 0x3c2, 0x102, 0x3c3, 0x102, 0x3c4, 0x102, 0x3c5, 0x102, + 0x3c6, 0x102, 0x3c7, 0x102, 0x3c8, 0x102, 0x3c9, 0x102, + 0x2202, 0x102, 0x3f5, 0x102, 0x3d1, 0x102, 0x3f0, 0x102, + 0x3d5, 0x102, 0x3f1, 0x102, 0x3d6, 0x102, 0x391, 0x102, + 0x392, 0x102, 0x393, 0x102, 0x394, 0x102, 0x395, 0x102, + 0x396, 0x102, 0x397, 0x102, 0x398, 0x102, 0x399, 0x102, + 0x39a, 0x102, 0x39b, 0x102, 0x39c, 0x102, 0x39d, 0x102, + 0x39e, 0x102, 0x39f, 0x102, 0x3a0, 0x102, 0x3a1, 0x102, + 0x3f4, 0x102, 0x3a3, 0x102, 0x3a4, 0x102, 0x3a5, 0x102, + 0x3a6, 0x102, 0x3a7, 0x102, 0x3a8, 0x102, 0x3a9, 0x102, + 0x2207, 0x102, 0x3b1, 0x102, 0x3b2, 0x102, 0x3b3, 0x102, + 0x3b4, 0x102, 0x3b5, 0x102, 0x3b6, 0x102, 0x3b7, 0x102, + 0x3b8, 0x102, 0x3b9, 0x102, 0x3ba, 0x102, 0x3bb, 0x102, + 0x3bc, 0x102, 0x3bd, 0x102, 0x3be, 0x102, 0x3bf, 0x102, + 0x3c0, 0x102, 0x3c1, 0x102, 0x3c2, 0x102, 0x3c3, 0x102, + 0x3c4, 0x102, 0x3c5, 0x102, 0x3c6, 0x102, 0x3c7, 0x102, + 0x3c8, 0x102, 0x3c9, 0x102, 0x2202, 0x102, 0x3f5, 0x102, + 0x3d1, 0x102, 0x3f0, 0x102, 0x3d5, 0x102, 0x3f1, 0x102, + 0x3d6, 0x102, 0x391, 0x102, 0x392, 0x102, 0x393, 0x102, + 0x394, 0x102, 0x395, 0x102, 0x396, 0x102, 0x397, 0x102, + 0x398, 0x102, 0x399, 0x102, 0x39a, 0x102, 0x39b, 0x102, + 0x39c, 0x102, 0x39d, 0x102, 0x39e, 0x102, 0x39f, 0x102, + 0x3a0, 0x102, 0x3a1, 0x102, 0x3f4, 0x102, 0x3a3, 0x102, + 0x3a4, 0x102, 0x3a5, 0x102, 0x3a6, 0x102, 0x3a7, 0x102, + 0x3a8, 0x102, 0x3a9, 0x102, 0x2207, 0x102, 0x3b1, 0x102, + 0x3b2, 0x102, 0x3b3, 0x102, 0x3b4, 0x102, 0x3b5, 0x102, + 0x3b6, 0x102, 0x3b7, 0x102, 0x3b8, 0x102, 0x3b9, 0x102, + 0x3ba, 0x102, 0x3bb, 0x102, 0x3bc, 0x102, 0x3bd, 0x102, + 0x3be, 0x102, 0x3bf, 0x102, 0x3c0, 0x102, 0x3c1, 0x102, + 0x3c2, 0x102, 0x3c3, 0x102, 0x3c4, 0x102, 0x3c5, 0x102, + 0x3c6, 0x102, 0x3c7, 0x102, 0x3c8, 0x102, 0x3c9, 0x102, + 0x2202, 0x102, 0x3f5, 0x102, 0x3d1, 0x102, 0x3f0, 0x102, + 0x3d5, 0x102, 0x3f1, 0x102, 0x3d6, 0x102, 0x391, 0x102, + 0x392, 0x102, 0x393, 0x102, 0x394, 0x102, 0x395, 0x102, + 0x396, 0x102, 0x397, 0x102, 0x398, 0x102, 0x399, 0x102, + 0x39a, 0x102, 0x39b, 0x102, 0x39c, 0x102, 0x39d, 0x102, + 0x39e, 0x102, 0x39f, 0x102, 0x3a0, 0x102, 0x3a1, 0x102, + 0x3f4, 0x102, 0x3a3, 0x102, 0x3a4, 0x102, 0x3a5, 0x102, + 0x3a6, 0x102, 0x3a7, 0x102, 0x3a8, 0x102, 0x3a9, 0x102, + 0x2207, 0x102, 0x3b1, 0x102, 0x3b2, 0x102, 0x3b3, 0x102, + 0x3b4, 0x102, 0x3b5, 0x102, 0x3b6, 0x102, 0x3b7, 0x102, + 0x3b8, 0x102, 0x3b9, 0x102, 0x3ba, 0x102, 0x3bb, 0x102, + 0x3bc, 0x102, 0x3bd, 0x102, 0x3be, 0x102, 0x3bf, 0x102, + 0x3c0, 0x102, 0x3c1, 0x102, 0x3c2, 0x102, 0x3c3, 0x102, + 0x3c4, 0x102, 0x3c5, 0x102, 0x3c6, 0x102, 0x3c7, 0x102, + 0x3c8, 0x102, 0x3c9, 0x102, 0x2202, 0x102, 0x3f5, 0x102, + 0x3d1, 0x102, 0x3f0, 0x102, 0x3d5, 0x102, 0x3f1, 0x102, + 0x3d6, 0x102, 0x391, 0x102, 0x392, 0x102, 0x393, 0x102, + 0x394, 0x102, 0x395, 0x102, 0x396, 0x102, 0x397, 0x102, + 0x398, 0x102, 0x399, 0x102, 0x39a, 0x102, 0x39b, 0x102, + 0x39c, 0x102, 0x39d, 0x102, 0x39e, 0x102, 0x39f, 0x102, + 0x3a0, 0x102, 0x3a1, 0x102, 0x3f4, 0x102, 0x3a3, 0x102, + 0x3a4, 0x102, 0x3a5, 0x102, 0x3a6, 0x102, 0x3a7, 0x102, + 0x3a8, 0x102, 0x3a9, 0x102, 0x2207, 0x102, 0x3b1, 0x102, + 0x3b2, 0x102, 0x3b3, 0x102, 0x3b4, 0x102, 0x3b5, 0x102, + 0x3b6, 0x102, 0x3b7, 0x102, 0x3b8, 0x102, 0x3b9, 0x102, + 0x3ba, 0x102, 0x3bb, 0x102, 0x3bc, 0x102, 0x3bd, 0x102, + 0x3be, 0x102, 0x3bf, 0x102, 0x3c0, 0x102, 0x3c1, 0x102, + 0x3c2, 0x102, 0x3c3, 0x102, 0x3c4, 0x102, 0x3c5, 0x102, + 0x3c6, 0x102, 0x3c7, 0x102, 0x3c8, 0x102, 0x3c9, 0x102, + 0x2202, 0x102, 0x3f5, 0x102, 0x3d1, 0x102, 0x3f0, 0x102, + 0x3d5, 0x102, 0x3f1, 0x102, 0x3d6, 0x102, 0x3dc, 0x102, + 0x3dd, 0x102, 0x30, 0x102, 0x31, 0x102, 0x32, 0x102, + 0x33, 0x102, 0x34, 0x102, 0x35, 0x102, 0x36, 0x102, + 0x37, 0x102, 0x38, 0x102, 0x39, 0x102, 0x30, 0x102, + 0x31, 0x102, 0x32, 0x102, 0x33, 0x102, 0x34, 0x102, + 0x35, 0x102, 0x36, 0x102, 0x37, 0x102, 0x38, 0x102, + 0x39, 0x102, 0x30, 0x102, 0x31, 0x102, 0x32, 0x102, + 0x33, 0x102, 0x34, 0x102, 0x35, 0x102, 0x36, 0x102, + 0x37, 0x102, 0x38, 0x102, 0x39, 0x102, 0x30, 0x102, + 0x31, 0x102, 0x32, 0x102, 0x33, 0x102, 0x34, 0x102, + 0x35, 0x102, 0x36, 0x102, 0x37, 0x102, 0x38, 0x102, + 0x39, 0x102, 0x30, 0x102, 0x31, 0x102, 0x32, 0x102, + 0x33, 0x102, 0x34, 0x102, 0x35, 0x102, 0x36, 0x102, + 0x37, 0x102, 0x38, 0x102, 0x39, 0x101, 0x4e3d, 0x101, + 0x4e38, 0x101, 0x4e41, 0x201, 0xd840, 0xdd22, 0x101, 0x4f60, + 0x101, 0x4fae, 0x101, 0x4fbb, 0x101, 0x5002, 0x101, 0x507a, + 0x101, 0x5099, 0x101, 0x50e7, 0x101, 0x50cf, 0x101, 0x349e, + 0x201, 0xd841, 0xde3a, 0x101, 0x514d, 0x101, 0x5154, 0x101, + 0x5164, 0x101, 0x5177, 0x201, 0xd841, 0xdd1c, 0x101, 0x34b9, + 0x101, 0x5167, 0x101, 0x518d, 0x201, 0xd841, 0xdd4b, 0x101, + 0x5197, 0x101, 0x51a4, 0x101, 0x4ecc, 0x101, 0x51ac, 0x101, + 0x51b5, 0x201, 0xd864, 0xdddf, 0x101, 0x51f5, 0x101, 0x5203, + 0x101, 0x34df, 0x101, 0x523b, 0x101, 0x5246, 0x101, 0x5272, + 0x101, 0x5277, 0x101, 0x3515, 0x101, 0x52c7, 0x101, 0x52c9, + 0x101, 0x52e4, 0x101, 0x52fa, 0x101, 0x5305, 0x101, 0x5306, + 0x101, 0x5317, 0x101, 0x5349, 0x101, 0x5351, 0x101, 0x535a, + 0x101, 0x5373, 0x101, 0x537d, 0x101, 0x537f, 0x101, 0x537f, + 0x101, 0x537f, 0x201, 0xd842, 0xde2c, 0x101, 0x7070, 0x101, + 0x53ca, 0x101, 0x53df, 0x201, 0xd842, 0xdf63, 0x101, 0x53eb, + 0x101, 0x53f1, 0x101, 0x5406, 0x101, 0x549e, 0x101, 0x5438, + 0x101, 0x5448, 0x101, 0x5468, 0x101, 0x54a2, 0x101, 0x54f6, + 0x101, 0x5510, 0x101, 0x5553, 0x101, 0x5563, 0x101, 0x5584, + 0x101, 0x5584, 0x101, 0x5599, 0x101, 0x55ab, 0x101, 0x55b3, + 0x101, 0x55c2, 0x101, 0x5716, 0x101, 0x5606, 0x101, 0x5717, + 0x101, 0x5651, 0x101, 0x5674, 0x101, 0x5207, 0x101, 0x58ee, + 0x101, 0x57ce, 0x101, 0x57f4, 0x101, 0x580d, 0x101, 0x578b, + 0x101, 0x5832, 0x101, 0x5831, 0x101, 0x58ac, 0x201, 0xd845, + 0xdce4, 0x101, 0x58f2, 0x101, 0x58f7, 0x101, 0x5906, 0x101, + 0x591a, 0x101, 0x5922, 0x101, 0x5962, 0x201, 0xd845, 0xdea8, + 0x201, 0xd845, 0xdeea, 0x101, 0x59ec, 0x101, 0x5a1b, 0x101, + 0x5a27, 0x101, 0x59d8, 0x101, 0x5a66, 0x101, 0x36ee, 0x101, + 0x36fc, 0x101, 0x5b08, 0x101, 0x5b3e, 0x101, 0x5b3e, 0x201, + 0xd846, 0xddc8, 0x101, 0x5bc3, 0x101, 0x5bd8, 0x101, 0x5be7, + 0x101, 0x5bf3, 0x201, 0xd846, 0xdf18, 0x101, 0x5bff, 0x101, + 0x5c06, 0x101, 0x5f53, 0x101, 0x5c22, 0x101, 0x3781, 0x101, + 0x5c60, 0x101, 0x5c6e, 0x101, 0x5cc0, 0x101, 0x5c8d, 0x201, + 0xd847, 0xdde4, 0x101, 0x5d43, 0x201, 0xd847, 0xdde6, 0x101, + 0x5d6e, 0x101, 0x5d6b, 0x101, 0x5d7c, 0x101, 0x5de1, 0x101, + 0x5de2, 0x101, 0x382f, 0x101, 0x5dfd, 0x101, 0x5e28, 0x101, + 0x5e3d, 0x101, 0x5e69, 0x101, 0x3862, 0x201, 0xd848, 0xdd83, + 0x101, 0x387c, 0x101, 0x5eb0, 0x101, 0x5eb3, 0x101, 0x5eb6, + 0x101, 0x5eca, 0x201, 0xd868, 0xdf92, 0x101, 0x5efe, 0x201, + 0xd848, 0xdf31, 0x201, 0xd848, 0xdf31, 0x101, 0x8201, 0x101, + 0x5f22, 0x101, 0x5f22, 0x101, 0x38c7, 0x201, 0xd84c, 0xdeb8, + 0x201, 0xd858, 0xddda, 0x101, 0x5f62, 0x101, 0x5f6b, 0x101, + 0x38e3, 0x101, 0x5f9a, 0x101, 0x5fcd, 0x101, 0x5fd7, 0x101, + 0x5ff9, 0x101, 0x6081, 0x101, 0x393a, 0x101, 0x391c, 0x101, + 0x6094, 0x201, 0xd849, 0xded4, 0x101, 0x60c7, 0x101, 0x6148, + 0x101, 0x614c, 0x101, 0x614e, 0x101, 0x614c, 0x101, 0x617a, + 0x101, 0x618e, 0x101, 0x61b2, 0x101, 0x61a4, 0x101, 0x61af, + 0x101, 0x61de, 0x101, 0x61f2, 0x101, 0x61f6, 0x101, 0x6210, + 0x101, 0x621b, 0x101, 0x625d, 0x101, 0x62b1, 0x101, 0x62d4, + 0x101, 0x6350, 0x201, 0xd84a, 0xdf0c, 0x101, 0x633d, 0x101, + 0x62fc, 0x101, 0x6368, 0x101, 0x6383, 0x101, 0x63e4, 0x201, + 0xd84a, 0xdff1, 0x101, 0x6422, 0x101, 0x63c5, 0x101, 0x63a9, + 0x101, 0x3a2e, 0x101, 0x6469, 0x101, 0x647e, 0x101, 0x649d, + 0x101, 0x6477, 0x101, 0x3a6c, 0x101, 0x654f, 0x101, 0x656c, + 0x201, 0xd84c, 0xdc0a, 0x101, 0x65e3, 0x101, 0x66f8, 0x101, + 0x6649, 0x101, 0x3b19, 0x101, 0x6691, 0x101, 0x3b08, 0x101, + 0x3ae4, 0x101, 0x5192, 0x101, 0x5195, 0x101, 0x6700, 0x101, + 0x669c, 0x101, 0x80ad, 0x101, 0x43d9, 0x101, 0x6717, 0x101, + 0x671b, 0x101, 0x6721, 0x101, 0x675e, 0x101, 0x6753, 0x201, + 0xd84c, 0xdfc3, 0x101, 0x3b49, 0x101, 0x67fa, 0x101, 0x6785, + 0x101, 0x6852, 0x101, 0x6885, 0x201, 0xd84d, 0xdc6d, 0x101, + 0x688e, 0x101, 0x681f, 0x101, 0x6914, 0x101, 0x3b9d, 0x101, + 0x6942, 0x101, 0x69a3, 0x101, 0x69ea, 0x101, 0x6aa8, 0x201, + 0xd84d, 0xdea3, 0x101, 0x6adb, 0x101, 0x3c18, 0x101, 0x6b21, + 0x201, 0xd84e, 0xdca7, 0x101, 0x6b54, 0x101, 0x3c4e, 0x101, + 0x6b72, 0x101, 0x6b9f, 0x101, 0x6bba, 0x101, 0x6bbb, 0x201, + 0xd84e, 0xde8d, 0x201, 0xd847, 0xdd0b, 0x201, 0xd84e, 0xdefa, + 0x101, 0x6c4e, 0x201, 0xd84f, 0xdcbc, 0x101, 0x6cbf, 0x101, + 0x6ccd, 0x101, 0x6c67, 0x101, 0x6d16, 0x101, 0x6d3e, 0x101, + 0x6d77, 0x101, 0x6d41, 0x101, 0x6d69, 0x101, 0x6d78, 0x101, + 0x6d85, 0x201, 0xd84f, 0xdd1e, 0x101, 0x6d34, 0x101, 0x6e2f, + 0x101, 0x6e6e, 0x101, 0x3d33, 0x101, 0x6ecb, 0x101, 0x6ec7, + 0x201, 0xd84f, 0xded1, 0x101, 0x6df9, 0x101, 0x6f6e, 0x201, + 0xd84f, 0xdf5e, 0x201, 0xd84f, 0xdf8e, 0x101, 0x6fc6, 0x101, + 0x7039, 0x101, 0x701e, 0x101, 0x701b, 0x101, 0x3d96, 0x101, + 0x704a, 0x101, 0x707d, 0x101, 0x7077, 0x101, 0x70ad, 0x201, + 0xd841, 0xdd25, 0x101, 0x7145, 0x201, 0xd850, 0xde63, 0x101, + 0x719c, 0x201, 0xd850, 0xdfab, 0x101, 0x7228, 0x101, 0x7235, + 0x101, 0x7250, 0x201, 0xd851, 0xde08, 0x101, 0x7280, 0x101, + 0x7295, 0x201, 0xd851, 0xdf35, 0x201, 0xd852, 0xdc14, 0x101, + 0x737a, 0x101, 0x738b, 0x101, 0x3eac, 0x101, 0x73a5, 0x101, + 0x3eb8, 0x101, 0x3eb8, 0x101, 0x7447, 0x101, 0x745c, 0x101, + 0x7471, 0x101, 0x7485, 0x101, 0x74ca, 0x101, 0x3f1b, 0x101, + 0x7524, 0x201, 0xd853, 0xdc36, 0x101, 0x753e, 0x201, 0xd853, + 0xdc92, 0x101, 0x7570, 0x201, 0xd848, 0xdd9f, 0x101, 0x7610, + 0x201, 0xd853, 0xdfa1, 0x201, 0xd853, 0xdfb8, 0x201, 0xd854, + 0xdc44, 0x101, 0x3ffc, 0x101, 0x4008, 0x101, 0x76f4, 0x201, + 0xd854, 0xdcf3, 0x201, 0xd854, 0xdcf2, 0x201, 0xd854, 0xdd19, + 0x201, 0xd854, 0xdd33, 0x101, 0x771e, 0x101, 0x771f, 0x101, + 0x771f, 0x101, 0x774a, 0x101, 0x4039, 0x101, 0x778b, 0x101, + 0x4046, 0x101, 0x4096, 0x201, 0xd855, 0xdc1d, 0x101, 0x784e, + 0x101, 0x788c, 0x101, 0x78cc, 0x101, 0x40e3, 0x201, 0xd855, + 0xde26, 0x101, 0x7956, 0x201, 0xd855, 0xde9a, 0x201, 0xd855, + 0xdec5, 0x101, 0x798f, 0x101, 0x79eb, 0x101, 0x412f, 0x101, + 0x7a40, 0x101, 0x7a4a, 0x101, 0x7a4f, 0x201, 0xd856, 0xdd7c, + 0x201, 0xd856, 0xdea7, 0x201, 0xd856, 0xdea7, 0x101, 0x7aee, + 0x101, 0x4202, 0x201, 0xd856, 0xdfab, 0x101, 0x7bc6, 0x101, + 0x7bc9, 0x101, 0x4227, 0x201, 0xd857, 0xdc80, 0x101, 0x7cd2, + 0x101, 0x42a0, 0x101, 0x7ce8, 0x101, 0x7ce3, 0x101, 0x7d00, + 0x201, 0xd857, 0xdf86, 0x101, 0x7d63, 0x101, 0x4301, 0x101, + 0x7dc7, 0x101, 0x7e02, 0x101, 0x7e45, 0x101, 0x4334, 0x201, + 0xd858, 0xde28, 0x201, 0xd858, 0xde47, 0x101, 0x4359, 0x201, + 0xd858, 0xded9, 0x101, 0x7f7a, 0x201, 0xd858, 0xdf3e, 0x101, + 0x7f95, 0x101, 0x7ffa, 0x101, 0x8005, 0x201, 0xd859, 0xdcda, + 0x201, 0xd859, 0xdd23, 0x101, 0x8060, 0x201, 0xd859, 0xdda8, + 0x101, 0x8070, 0x201, 0xd84c, 0xdf5f, 0x101, 0x43d5, 0x101, + 0x80b2, 0x101, 0x8103, 0x101, 0x440b, 0x101, 0x813e, 0x101, + 0x5ab5, 0x201, 0xd859, 0xdfa7, 0x201, 0xd859, 0xdfb5, 0x201, + 0xd84c, 0xdf93, 0x201, 0xd84c, 0xdf9c, 0x101, 0x8201, 0x101, + 0x8204, 0x101, 0x8f9e, 0x101, 0x446b, 0x101, 0x8291, 0x101, + 0x828b, 0x101, 0x829d, 0x101, 0x52b3, 0x101, 0x82b1, 0x101, + 0x82b3, 0x101, 0x82bd, 0x101, 0x82e6, 0x201, 0xd85a, 0xdf3c, + 0x101, 0x82e5, 0x101, 0x831d, 0x101, 0x8363, 0x101, 0x83ad, + 0x101, 0x8323, 0x101, 0x83bd, 0x101, 0x83e7, 0x101, 0x8457, + 0x101, 0x8353, 0x101, 0x83ca, 0x101, 0x83cc, 0x101, 0x83dc, + 0x201, 0xd85b, 0xdc36, 0x201, 0xd85b, 0xdd6b, 0x201, 0xd85b, + 0xdcd5, 0x101, 0x452b, 0x101, 0x84f1, 0x101, 0x84f3, 0x101, + 0x8516, 0x201, 0xd85c, 0xdfca, 0x101, 0x8564, 0x201, 0xd85b, + 0xdf2c, 0x101, 0x455d, 0x101, 0x4561, 0x201, 0xd85b, 0xdfb1, + 0x201, 0xd85c, 0xdcd2, 0x101, 0x456b, 0x101, 0x8650, 0x101, + 0x865c, 0x101, 0x8667, 0x101, 0x8669, 0x101, 0x86a9, 0x101, + 0x8688, 0x101, 0x870e, 0x101, 0x86e2, 0x101, 0x8779, 0x101, + 0x8728, 0x101, 0x876b, 0x101, 0x8786, 0x101, 0x45d7, 0x101, + 0x87e1, 0x101, 0x8801, 0x101, 0x45f9, 0x101, 0x8860, 0x101, + 0x8863, 0x201, 0xd85d, 0xde67, 0x101, 0x88d7, 0x101, 0x88de, + 0x101, 0x4635, 0x101, 0x88fa, 0x101, 0x34bb, 0x201, 0xd85e, + 0xdcae, 0x201, 0xd85e, 0xdd66, 0x101, 0x46be, 0x101, 0x46c7, + 0x101, 0x8aa0, 0x101, 0x8aed, 0x101, 0x8b8a, 0x101, 0x8c55, + 0x201, 0xd85f, 0xdca8, 0x101, 0x8cab, 0x101, 0x8cc1, 0x101, + 0x8d1b, 0x101, 0x8d77, 0x201, 0xd85f, 0xdf2f, 0x201, 0xd842, + 0xdc04, 0x101, 0x8dcb, 0x101, 0x8dbc, 0x101, 0x8df0, 0x201, + 0xd842, 0xdcde, 0x101, 0x8ed4, 0x101, 0x8f38, 0x201, 0xd861, + 0xddd2, 0x201, 0xd861, 0xdded, 0x101, 0x9094, 0x101, 0x90f1, + 0x101, 0x9111, 0x201, 0xd861, 0xdf2e, 0x101, 0x911b, 0x101, + 0x9238, 0x101, 0x92d7, 0x101, 0x92d8, 0x101, 0x927c, 0x101, + 0x93f9, 0x101, 0x9415, 0x201, 0xd862, 0xdffa, 0x101, 0x958b, + 0x101, 0x4995, 0x101, 0x95b7, 0x201, 0xd863, 0xdd77, 0x101, + 0x49e6, 0x101, 0x96c3, 0x101, 0x5db2, 0x101, 0x9723, 0x201, + 0xd864, 0xdd45, 0x201, 0xd864, 0xde1a, 0x101, 0x4a6e, 0x101, + 0x4a76, 0x101, 0x97e0, 0x201, 0xd865, 0xdc0a, 0x101, 0x4ab2, + 0x201, 0xd865, 0xdc96, 0x101, 0x980b, 0x101, 0x980b, 0x101, + 0x9829, 0x201, 0xd865, 0xddb6, 0x101, 0x98e2, 0x101, 0x4b33, + 0x101, 0x9929, 0x101, 0x99a7, 0x101, 0x99c2, 0x101, 0x99fe, + 0x101, 0x4bce, 0x201, 0xd866, 0xdf30, 0x101, 0x9b12, 0x101, + 0x9c40, 0x101, 0x9cfd, 0x101, 0x4cce, 0x101, 0x4ced, 0x101, + 0x9d67, 0x201, 0xd868, 0xdcce, 0x101, 0x4cf8, 0x201, 0xd868, + 0xdd05, 0x201, 0xd868, 0xde0e, 0x201, 0xd868, 0xde91, 0x101, + 0x9ebb, 0x101, 0x4d56, 0x101, 0x9ef9, 0x101, 0x9efe, 0x101, + 0x9f05, 0x101, 0x9f0f, 0x101, 0x9f16, 0x101, 0x9f3b, 0x201, + 0xd869, 0xde00, +}; + +static const unsigned short uc_ligature_trie[] = { + // 0 - 0x3100 + + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 424, 456, 488, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 520, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 552, 392, 392, 392, 584, 616, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 648, 680, 392, 392, 712, 744, 392, + 392, 392, 776, 392, 392, 392, 808, 392, + 392, 840, 872, 392, 392, 392, 904, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + + 392, 936, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 968, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, + + 392, 392, 392, 392, 1000, 392, 392, 392, + + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0x0, 0xa9, 0x194, 0x1d5, 0x20e, 0xffff, 0x267, 0x2a8, + 0x305, 0x372, 0x3a3, 0x3b0, 0x3bd, 0xffff, 0xffff, 0x408, + 0xffff, 0x425, 0xffff, 0x43e, 0x45b, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x47c, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0x485, 0x4da, 0x4df, 0x4e4, 0x4ed, + 0x51a, 0xffff, 0xffff, 0xffff, 0xffff, 0x52f, 0x548, 0xffff, + 0x54d, 0x55a, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0x57d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0x5d6, 0xffff, 0xffff, 0x611, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0x690, 0x693, 0x6a0, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0x6a3, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6aa, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6ad, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6b0, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6b3, 0x6b6, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6b9, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6be, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6c3, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0x6c6, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6c9, 0x6d0, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6d3, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6d8, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0x6db, 0xffff, 0xffff, 0xffff, 0xffff, 0x6e0, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6e3, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6e6, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6e9, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0x700, 0x761, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, +}; + +#define GET_LIGATURE_INDEX(u2) (u2 < 0x3100 ? uc_ligature_trie[uc_ligature_trie[u2>>5] + (u2 & 0x1f)] : 0xffff); + +static const unsigned short uc_ligature_map [] = { + + 0x54, 0x41, 0xc0, 0x45, 0xc8, 0x49, 0xcc, 0x4e, + 0x1f8, 0x4f, 0xd2, 0x55, 0xd9, 0x57, 0x1e80, 0x59, + 0x1ef2, 0x61, 0xe0, 0x65, 0xe8, 0x69, 0xec, 0x6e, + 0x1f9, 0x6f, 0xf2, 0x75, 0xf9, 0x77, 0x1e81, 0x79, + 0x1ef3, 0xa8, 0x1fed, 0xc2, 0x1ea6, 0xca, 0x1ec0, 0xd4, + 0x1ed2, 0xdc, 0x1db, 0xe2, 0x1ea7, 0xea, 0x1ec1, 0xf4, + 0x1ed3, 0xfc, 0x1dc, 0x102, 0x1eb0, 0x103, 0x1eb1, 0x112, + 0x1e14, 0x113, 0x1e15, 0x14c, 0x1e50, 0x14d, 0x1e51, 0x1a0, + 0x1edc, 0x1a1, 0x1edd, 0x1af, 0x1eea, 0x1b0, 0x1eeb, 0x391, + 0x1fba, 0x395, 0x1fc8, 0x397, 0x1fca, 0x399, 0x1fda, 0x39f, + 0x1ff8, 0x3a5, 0x1fea, 0x3a9, 0x1ffa, 0x3b1, 0x1f70, 0x3b5, + 0x1f72, 0x3b7, 0x1f74, 0x3b9, 0x1f76, 0x3bf, 0x1f78, 0x3c5, + 0x1f7a, 0x3c9, 0x1f7c, 0x3ca, 0x1fd2, 0x3cb, 0x1fe2, 0x415, + 0x400, 0x418, 0x40d, 0x435, 0x450, 0x438, 0x45d, 0x1f00, + 0x1f02, 0x1f01, 0x1f03, 0x1f08, 0x1f0a, 0x1f09, 0x1f0b, 0x1f10, + 0x1f12, 0x1f11, 0x1f13, 0x1f18, 0x1f1a, 0x1f19, 0x1f1b, 0x1f20, + 0x1f22, 0x1f21, 0x1f23, 0x1f28, 0x1f2a, 0x1f29, 0x1f2b, 0x1f30, + 0x1f32, 0x1f31, 0x1f33, 0x1f38, 0x1f3a, 0x1f39, 0x1f3b, 0x1f40, + 0x1f42, 0x1f41, 0x1f43, 0x1f48, 0x1f4a, 0x1f49, 0x1f4b, 0x1f50, + 0x1f52, 0x1f51, 0x1f53, 0x1f59, 0x1f5b, 0x1f60, 0x1f62, 0x1f61, + 0x1f63, 0x1f68, 0x1f6a, 0x1f69, 0x1f6b, 0x1fbf, 0x1fcd, 0x1ffe, + 0x1fdd, 0x75, 0x41, 0xc1, 0x43, 0x106, 0x45, 0xc9, + 0x47, 0x1f4, 0x49, 0xcd, 0x4b, 0x1e30, 0x4c, 0x139, + 0x4d, 0x1e3e, 0x4e, 0x143, 0x4f, 0xd3, 0x50, 0x1e54, + 0x52, 0x154, 0x53, 0x15a, 0x55, 0xda, 0x57, 0x1e82, + 0x59, 0xdd, 0x5a, 0x179, 0x61, 0xe1, 0x63, 0x107, + 0x65, 0xe9, 0x67, 0x1f5, 0x69, 0xed, 0x6b, 0x1e31, + 0x6c, 0x13a, 0x6d, 0x1e3f, 0x6e, 0x144, 0x6f, 0xf3, + 0x70, 0x1e55, 0x72, 0x155, 0x73, 0x15b, 0x75, 0xfa, + 0x77, 0x1e83, 0x79, 0xfd, 0x7a, 0x17a, 0xa8, 0x385, + 0xc2, 0x1ea4, 0xc5, 0x1fa, 0xc6, 0x1fc, 0xc7, 0x1e08, + 0xca, 0x1ebe, 0xcf, 0x1e2e, 0xd4, 0x1ed0, 0xd5, 0x1e4c, + 0xd8, 0x1fe, 0xdc, 0x1d7, 0xe2, 0x1ea5, 0xe5, 0x1fb, + 0xe6, 0x1fd, 0xe7, 0x1e09, 0xea, 0x1ebf, 0xef, 0x1e2f, + 0xf4, 0x1ed1, 0xf5, 0x1e4d, 0xf8, 0x1ff, 0xfc, 0x1d8, + 0x102, 0x1eae, 0x103, 0x1eaf, 0x112, 0x1e16, 0x113, 0x1e17, + 0x14c, 0x1e52, 0x14d, 0x1e53, 0x168, 0x1e78, 0x169, 0x1e79, + 0x1a0, 0x1eda, 0x1a1, 0x1edb, 0x1af, 0x1ee8, 0x1b0, 0x1ee9, + 0x391, 0x386, 0x395, 0x388, 0x397, 0x389, 0x399, 0x38a, + 0x39f, 0x38c, 0x3a5, 0x38e, 0x3a9, 0x38f, 0x3b1, 0x3ac, + 0x3b5, 0x3ad, 0x3b7, 0x3ae, 0x3b9, 0x3af, 0x3bf, 0x3cc, + 0x3c5, 0x3cd, 0x3c9, 0x3ce, 0x3ca, 0x390, 0x3cb, 0x3b0, + 0x3d2, 0x3d3, 0x413, 0x403, 0x41a, 0x40c, 0x433, 0x453, + 0x43a, 0x45c, 0x1f00, 0x1f04, 0x1f01, 0x1f05, 0x1f08, 0x1f0c, + 0x1f09, 0x1f0d, 0x1f10, 0x1f14, 0x1f11, 0x1f15, 0x1f18, 0x1f1c, + 0x1f19, 0x1f1d, 0x1f20, 0x1f24, 0x1f21, 0x1f25, 0x1f28, 0x1f2c, + 0x1f29, 0x1f2d, 0x1f30, 0x1f34, 0x1f31, 0x1f35, 0x1f38, 0x1f3c, + 0x1f39, 0x1f3d, 0x1f40, 0x1f44, 0x1f41, 0x1f45, 0x1f48, 0x1f4c, + 0x1f49, 0x1f4d, 0x1f50, 0x1f54, 0x1f51, 0x1f55, 0x1f59, 0x1f5d, + 0x1f60, 0x1f64, 0x1f61, 0x1f65, 0x1f68, 0x1f6c, 0x1f69, 0x1f6d, + 0x1fbf, 0x1fce, 0x1ffe, 0x1fde, 0x20, 0x41, 0xc2, 0x43, + 0x108, 0x45, 0xca, 0x47, 0x11c, 0x48, 0x124, 0x49, + 0xce, 0x4a, 0x134, 0x4f, 0xd4, 0x53, 0x15c, 0x55, + 0xdb, 0x57, 0x174, 0x59, 0x176, 0x5a, 0x1e90, 0x61, + 0xe2, 0x63, 0x109, 0x65, 0xea, 0x67, 0x11d, 0x68, + 0x125, 0x69, 0xee, 0x6a, 0x135, 0x6f, 0xf4, 0x73, + 0x15d, 0x75, 0xfb, 0x77, 0x175, 0x79, 0x177, 0x7a, + 0x1e91, 0x1ea0, 0x1eac, 0x1ea1, 0x1ead, 0x1eb8, 0x1ec6, 0x1eb9, + 0x1ec7, 0x1ecc, 0x1ed8, 0x1ecd, 0x1ed9, 0x1c, 0x41, 0xc3, + 0x45, 0x1ebc, 0x49, 0x128, 0x4e, 0xd1, 0x4f, 0xd5, + 0x55, 0x168, 0x56, 0x1e7c, 0x59, 0x1ef8, 0x61, 0xe3, + 0x65, 0x1ebd, 0x69, 0x129, 0x6e, 0xf1, 0x6f, 0xf5, + 0x75, 0x169, 0x76, 0x1e7d, 0x79, 0x1ef9, 0xc2, 0x1eaa, + 0xca, 0x1ec4, 0xd4, 0x1ed6, 0xe2, 0x1eab, 0xea, 0x1ec5, + 0xf4, 0x1ed7, 0x102, 0x1eb4, 0x103, 0x1eb5, 0x1a0, 0x1ee0, + 0x1a1, 0x1ee1, 0x1af, 0x1eee, 0x1b0, 0x1eef, 0x2c, 0x41, + 0x100, 0x45, 0x112, 0x47, 0x1e20, 0x49, 0x12a, 0x4f, + 0x14c, 0x55, 0x16a, 0x59, 0x232, 0x61, 0x101, 0x65, + 0x113, 0x67, 0x1e21, 0x69, 0x12b, 0x6f, 0x14d, 0x75, + 0x16b, 0x79, 0x233, 0xc4, 0x1de, 0xc6, 0x1e2, 0xd5, + 0x22c, 0xd6, 0x22a, 0xdc, 0x1d5, 0xe4, 0x1df, 0xe6, + 0x1e3, 0xf5, 0x22d, 0xf6, 0x22b, 0xfc, 0x1d6, 0x1ea, + 0x1ec, 0x1eb, 0x1ed, 0x226, 0x1e0, 0x227, 0x1e1, 0x22e, + 0x230, 0x22f, 0x231, 0x391, 0x1fb9, 0x399, 0x1fd9, 0x3a5, + 0x1fe9, 0x3b1, 0x1fb1, 0x3b9, 0x1fd1, 0x3c5, 0x1fe1, 0x418, + 0x4e2, 0x423, 0x4ee, 0x438, 0x4e3, 0x443, 0x4ef, 0x1e36, + 0x1e38, 0x1e37, 0x1e39, 0x1e5a, 0x1e5c, 0x1e5b, 0x1e5d, 0x20, + 0x41, 0x102, 0x45, 0x114, 0x47, 0x11e, 0x49, 0x12c, + 0x4f, 0x14e, 0x55, 0x16c, 0x61, 0x103, 0x65, 0x115, + 0x67, 0x11f, 0x69, 0x12d, 0x6f, 0x14f, 0x75, 0x16d, + 0x228, 0x1e1c, 0x229, 0x1e1d, 0x391, 0x1fb8, 0x399, 0x1fd8, + 0x3a5, 0x1fe8, 0x3b1, 0x1fb0, 0x3b9, 0x1fd0, 0x3c5, 0x1fe0, + 0x410, 0x4d0, 0x415, 0x4d6, 0x416, 0x4c1, 0x418, 0x419, + 0x423, 0x40e, 0x430, 0x4d1, 0x435, 0x4d7, 0x436, 0x4c2, + 0x438, 0x439, 0x443, 0x45e, 0x1ea0, 0x1eb6, 0x1ea1, 0x1eb7, + 0x2e, 0x41, 0x226, 0x42, 0x1e02, 0x43, 0x10a, 0x44, + 0x1e0a, 0x45, 0x116, 0x46, 0x1e1e, 0x47, 0x120, 0x48, + 0x1e22, 0x49, 0x130, 0x4d, 0x1e40, 0x4e, 0x1e44, 0x4f, + 0x22e, 0x50, 0x1e56, 0x52, 0x1e58, 0x53, 0x1e60, 0x54, + 0x1e6a, 0x57, 0x1e86, 0x58, 0x1e8a, 0x59, 0x1e8e, 0x5a, + 0x17b, 0x61, 0x227, 0x62, 0x1e03, 0x63, 0x10b, 0x64, + 0x1e0b, 0x65, 0x117, 0x66, 0x1e1f, 0x67, 0x121, 0x68, + 0x1e23, 0x6d, 0x1e41, 0x6e, 0x1e45, 0x6f, 0x22f, 0x70, + 0x1e57, 0x72, 0x1e59, 0x73, 0x1e61, 0x74, 0x1e6b, 0x77, + 0x1e87, 0x78, 0x1e8b, 0x79, 0x1e8f, 0x7a, 0x17c, 0x15a, + 0x1e64, 0x15b, 0x1e65, 0x160, 0x1e66, 0x161, 0x1e67, 0x17f, + 0x1e9b, 0x1e62, 0x1e68, 0x1e63, 0x1e69, 0x36, 0x41, 0xc4, + 0x45, 0xcb, 0x48, 0x1e26, 0x49, 0xcf, 0x4f, 0xd6, + 0x55, 0xdc, 0x57, 0x1e84, 0x58, 0x1e8c, 0x59, 0x178, + 0x61, 0xe4, 0x65, 0xeb, 0x68, 0x1e27, 0x69, 0xef, + 0x6f, 0xf6, 0x74, 0x1e97, 0x75, 0xfc, 0x77, 0x1e85, + 0x78, 0x1e8d, 0x79, 0xff, 0xd5, 0x1e4e, 0xf5, 0x1e4f, + 0x16a, 0x1e7a, 0x16b, 0x1e7b, 0x399, 0x3aa, 0x3a5, 0x3ab, + 0x3b9, 0x3ca, 0x3c5, 0x3cb, 0x3d2, 0x3d4, 0x406, 0x407, + 0x410, 0x4d2, 0x415, 0x401, 0x416, 0x4dc, 0x417, 0x4de, + 0x418, 0x4e4, 0x41e, 0x4e6, 0x423, 0x4f0, 0x427, 0x4f4, + 0x42b, 0x4f8, 0x42d, 0x4ec, 0x430, 0x4d3, 0x435, 0x451, + 0x436, 0x4dd, 0x437, 0x4df, 0x438, 0x4e5, 0x43e, 0x4e7, + 0x443, 0x4f1, 0x447, 0x4f5, 0x44b, 0x4f9, 0x44d, 0x4ed, + 0x456, 0x457, 0x4d8, 0x4da, 0x4d9, 0x4db, 0x4e8, 0x4ea, + 0x4e9, 0x4eb, 0x18, 0x41, 0x1ea2, 0x45, 0x1eba, 0x49, + 0x1ec8, 0x4f, 0x1ece, 0x55, 0x1ee6, 0x59, 0x1ef6, 0x61, + 0x1ea3, 0x65, 0x1ebb, 0x69, 0x1ec9, 0x6f, 0x1ecf, 0x75, + 0x1ee7, 0x79, 0x1ef7, 0xc2, 0x1ea8, 0xca, 0x1ec2, 0xd4, + 0x1ed4, 0xe2, 0x1ea9, 0xea, 0x1ec3, 0xf4, 0x1ed5, 0x102, + 0x1eb2, 0x103, 0x1eb3, 0x1a0, 0x1ede, 0x1a1, 0x1edf, 0x1af, + 0x1eec, 0x1b0, 0x1eed, 0x6, 0x41, 0xc5, 0x55, 0x16e, + 0x61, 0xe5, 0x75, 0x16f, 0x77, 0x1e98, 0x79, 0x1e99, + 0x6, 0x4f, 0x150, 0x55, 0x170, 0x6f, 0x151, 0x75, + 0x171, 0x423, 0x4f2, 0x443, 0x4f3, 0x25, 0x41, 0x1cd, + 0x43, 0x10c, 0x44, 0x10e, 0x45, 0x11a, 0x47, 0x1e6, + 0x48, 0x21e, 0x49, 0x1cf, 0x4b, 0x1e8, 0x4c, 0x13d, + 0x4e, 0x147, 0x4f, 0x1d1, 0x52, 0x158, 0x53, 0x160, + 0x54, 0x164, 0x55, 0x1d3, 0x5a, 0x17d, 0x61, 0x1ce, + 0x63, 0x10d, 0x64, 0x10f, 0x65, 0x11b, 0x67, 0x1e7, + 0x68, 0x21f, 0x69, 0x1d0, 0x6a, 0x1f0, 0x6b, 0x1e9, + 0x6c, 0x13e, 0x6e, 0x148, 0x6f, 0x1d2, 0x72, 0x159, + 0x73, 0x161, 0x74, 0x165, 0x75, 0x1d4, 0x7a, 0x17e, + 0xdc, 0x1d9, 0xfc, 0x1da, 0x1b7, 0x1ee, 0x292, 0x1ef, + 0xe, 0x41, 0x200, 0x45, 0x204, 0x49, 0x208, 0x4f, + 0x20c, 0x52, 0x210, 0x55, 0x214, 0x61, 0x201, 0x65, + 0x205, 0x69, 0x209, 0x6f, 0x20d, 0x72, 0x211, 0x75, + 0x215, 0x474, 0x476, 0x475, 0x477, 0xc, 0x41, 0x202, + 0x45, 0x206, 0x49, 0x20a, 0x4f, 0x20e, 0x52, 0x212, + 0x55, 0x216, 0x61, 0x203, 0x65, 0x207, 0x69, 0x20b, + 0x6f, 0x20f, 0x72, 0x213, 0x75, 0x217, 0xe, 0x391, + 0x1f08, 0x395, 0x1f18, 0x397, 0x1f28, 0x399, 0x1f38, 0x39f, + 0x1f48, 0x3a9, 0x1f68, 0x3b1, 0x1f00, 0x3b5, 0x1f10, 0x3b7, + 0x1f20, 0x3b9, 0x1f30, 0x3bf, 0x1f40, 0x3c1, 0x1fe4, 0x3c5, + 0x1f50, 0x3c9, 0x1f60, 0x10, 0x391, 0x1f09, 0x395, 0x1f19, + 0x397, 0x1f29, 0x399, 0x1f39, 0x39f, 0x1f49, 0x3a1, 0x1fec, + 0x3a5, 0x1f59, 0x3a9, 0x1f69, 0x3b1, 0x1f01, 0x3b5, 0x1f11, + 0x3b7, 0x1f21, 0x3b9, 0x1f31, 0x3bf, 0x1f41, 0x3c1, 0x1fe5, + 0x3c5, 0x1f51, 0x3c9, 0x1f61, 0x4, 0x4f, 0x1a0, 0x55, + 0x1af, 0x6f, 0x1a1, 0x75, 0x1b0, 0x2a, 0x41, 0x1ea0, + 0x42, 0x1e04, 0x44, 0x1e0c, 0x45, 0x1eb8, 0x48, 0x1e24, + 0x49, 0x1eca, 0x4b, 0x1e32, 0x4c, 0x1e36, 0x4d, 0x1e42, + 0x4e, 0x1e46, 0x4f, 0x1ecc, 0x52, 0x1e5a, 0x53, 0x1e62, + 0x54, 0x1e6c, 0x55, 0x1ee4, 0x56, 0x1e7e, 0x57, 0x1e88, + 0x59, 0x1ef4, 0x5a, 0x1e92, 0x61, 0x1ea1, 0x62, 0x1e05, + 0x64, 0x1e0d, 0x65, 0x1eb9, 0x68, 0x1e25, 0x69, 0x1ecb, + 0x6b, 0x1e33, 0x6c, 0x1e37, 0x6d, 0x1e43, 0x6e, 0x1e47, + 0x6f, 0x1ecd, 0x72, 0x1e5b, 0x73, 0x1e63, 0x74, 0x1e6d, + 0x75, 0x1ee5, 0x76, 0x1e7f, 0x77, 0x1e89, 0x79, 0x1ef5, + 0x7a, 0x1e93, 0x1a0, 0x1ee2, 0x1a1, 0x1ee3, 0x1af, 0x1ef0, + 0x1b0, 0x1ef1, 0x2, 0x55, 0x1e72, 0x75, 0x1e73, 0x2, + 0x41, 0x1e00, 0x61, 0x1e01, 0x4, 0x53, 0x218, 0x54, + 0x21a, 0x73, 0x219, 0x74, 0x21b, 0x16, 0x43, 0xc7, + 0x44, 0x1e10, 0x45, 0x228, 0x47, 0x122, 0x48, 0x1e28, + 0x4b, 0x136, 0x4c, 0x13b, 0x4e, 0x145, 0x52, 0x156, + 0x53, 0x15e, 0x54, 0x162, 0x63, 0xe7, 0x64, 0x1e11, + 0x65, 0x229, 0x67, 0x123, 0x68, 0x1e29, 0x6b, 0x137, + 0x6c, 0x13c, 0x6e, 0x146, 0x72, 0x157, 0x73, 0x15f, + 0x74, 0x163, 0xa, 0x41, 0x104, 0x45, 0x118, 0x49, + 0x12e, 0x4f, 0x1ea, 0x55, 0x172, 0x61, 0x105, 0x65, + 0x119, 0x69, 0x12f, 0x6f, 0x1eb, 0x75, 0x173, 0xc, + 0x44, 0x1e12, 0x45, 0x1e18, 0x4c, 0x1e3c, 0x4e, 0x1e4a, + 0x54, 0x1e70, 0x55, 0x1e76, 0x64, 0x1e13, 0x65, 0x1e19, + 0x6c, 0x1e3d, 0x6e, 0x1e4b, 0x74, 0x1e71, 0x75, 0x1e77, + 0x2, 0x48, 0x1e2a, 0x68, 0x1e2b, 0x6, 0x45, 0x1e1a, + 0x49, 0x1e2c, 0x55, 0x1e74, 0x65, 0x1e1b, 0x69, 0x1e2d, + 0x75, 0x1e75, 0x11, 0x42, 0x1e06, 0x44, 0x1e0e, 0x4b, + 0x1e34, 0x4c, 0x1e3a, 0x4e, 0x1e48, 0x52, 0x1e5e, 0x54, + 0x1e6e, 0x5a, 0x1e94, 0x62, 0x1e07, 0x64, 0x1e0f, 0x68, + 0x1e96, 0x6b, 0x1e35, 0x6c, 0x1e3b, 0x6e, 0x1e49, 0x72, + 0x1e5f, 0x74, 0x1e6f, 0x7a, 0x1e95, 0x2c, 0x3c, 0x226e, + 0x3d, 0x2260, 0x3e, 0x226f, 0x2190, 0x219a, 0x2192, 0x219b, + 0x2194, 0x21ae, 0x21d0, 0x21cd, 0x21d2, 0x21cf, 0x21d4, 0x21ce, + 0x2203, 0x2204, 0x2208, 0x2209, 0x220b, 0x220c, 0x2223, 0x2224, + 0x2225, 0x2226, 0x223c, 0x2241, 0x2243, 0x2244, 0x2245, 0x2247, + 0x2248, 0x2249, 0x224d, 0x226d, 0x2261, 0x2262, 0x2264, 0x2270, + 0x2265, 0x2271, 0x2272, 0x2274, 0x2273, 0x2275, 0x2276, 0x2278, + 0x2277, 0x2279, 0x227a, 0x2280, 0x227b, 0x2281, 0x227c, 0x22e0, + 0x227d, 0x22e1, 0x2282, 0x2284, 0x2283, 0x2285, 0x2286, 0x2288, + 0x2287, 0x2289, 0x2291, 0x22e2, 0x2292, 0x22e3, 0x22a2, 0x22ac, + 0x22a8, 0x22ad, 0x22a9, 0x22ae, 0x22ab, 0x22af, 0x22b2, 0x22ea, + 0x22b3, 0x22eb, 0x22b4, 0x22ec, 0x22b5, 0x22ed, 0x1d, 0xa8, + 0x1fc1, 0x3b1, 0x1fb6, 0x3b7, 0x1fc6, 0x3b9, 0x1fd6, 0x3c5, + 0x1fe6, 0x3c9, 0x1ff6, 0x3ca, 0x1fd7, 0x3cb, 0x1fe7, 0x1f00, + 0x1f06, 0x1f01, 0x1f07, 0x1f08, 0x1f0e, 0x1f09, 0x1f0f, 0x1f20, + 0x1f26, 0x1f21, 0x1f27, 0x1f28, 0x1f2e, 0x1f29, 0x1f2f, 0x1f30, + 0x1f36, 0x1f31, 0x1f37, 0x1f38, 0x1f3e, 0x1f39, 0x1f3f, 0x1f50, + 0x1f56, 0x1f51, 0x1f57, 0x1f59, 0x1f5f, 0x1f60, 0x1f66, 0x1f61, + 0x1f67, 0x1f68, 0x1f6e, 0x1f69, 0x1f6f, 0x1fbf, 0x1fcf, 0x1ffe, + 0x1fdf, 0x3f, 0x391, 0x1fbc, 0x397, 0x1fcc, 0x3a9, 0x1ffc, + 0x3ac, 0x1fb4, 0x3ae, 0x1fc4, 0x3b1, 0x1fb3, 0x3b7, 0x1fc3, + 0x3c9, 0x1ff3, 0x3ce, 0x1ff4, 0x1f00, 0x1f80, 0x1f01, 0x1f81, + 0x1f02, 0x1f82, 0x1f03, 0x1f83, 0x1f04, 0x1f84, 0x1f05, 0x1f85, + 0x1f06, 0x1f86, 0x1f07, 0x1f87, 0x1f08, 0x1f88, 0x1f09, 0x1f89, + 0x1f0a, 0x1f8a, 0x1f0b, 0x1f8b, 0x1f0c, 0x1f8c, 0x1f0d, 0x1f8d, + 0x1f0e, 0x1f8e, 0x1f0f, 0x1f8f, 0x1f20, 0x1f90, 0x1f21, 0x1f91, + 0x1f22, 0x1f92, 0x1f23, 0x1f93, 0x1f24, 0x1f94, 0x1f25, 0x1f95, + 0x1f26, 0x1f96, 0x1f27, 0x1f97, 0x1f28, 0x1f98, 0x1f29, 0x1f99, + 0x1f2a, 0x1f9a, 0x1f2b, 0x1f9b, 0x1f2c, 0x1f9c, 0x1f2d, 0x1f9d, + 0x1f2e, 0x1f9e, 0x1f2f, 0x1f9f, 0x1f60, 0x1fa0, 0x1f61, 0x1fa1, + 0x1f62, 0x1fa2, 0x1f63, 0x1fa3, 0x1f64, 0x1fa4, 0x1f65, 0x1fa5, + 0x1f66, 0x1fa6, 0x1f67, 0x1fa7, 0x1f68, 0x1fa8, 0x1f69, 0x1fa9, + 0x1f6a, 0x1faa, 0x1f6b, 0x1fab, 0x1f6c, 0x1fac, 0x1f6d, 0x1fad, + 0x1f6e, 0x1fae, 0x1f6f, 0x1faf, 0x1f70, 0x1fb2, 0x1f74, 0x1fc2, + 0x1f7c, 0x1ff2, 0x1fb6, 0x1fb7, 0x1fc6, 0x1fc7, 0x1ff6, 0x1ff7, + 0x1, 0x627, 0x622, 0x6, 0x627, 0x623, 0x648, 0x624, + 0x64a, 0x626, 0x6c1, 0x6c2, 0x6d2, 0x6d3, 0x6d5, 0x6c0, + 0x1, 0x627, 0x625, 0x3, 0x928, 0x929, 0x930, 0x931, + 0x933, 0x934, 0x1, 0x9c7, 0x9cb, 0x1, 0x9c7, 0x9cc, + 0x1, 0xb47, 0xb4b, 0x1, 0xb47, 0xb48, 0x1, 0xb47, + 0xb4c, 0x2, 0xbc6, 0xbca, 0xbc7, 0xbcb, 0x2, 0xb92, + 0xb94, 0xbc6, 0xbcc, 0x1, 0xc46, 0xc48, 0x1, 0xcc6, + 0xcca, 0x3, 0xcbf, 0xcc0, 0xcc6, 0xcc7, 0xcca, 0xccb, + 0x1, 0xcc6, 0xcc8, 0x2, 0xd46, 0xd4a, 0xd47, 0xd4b, + 0x1, 0xd46, 0xd4c, 0x2, 0xdd9, 0xdda, 0xddc, 0xddd, + 0x1, 0xdd9, 0xddc, 0x1, 0xdd9, 0xdde, 0x1, 0x1025, + 0x1026, 0xb, 0x1b05, 0x1b06, 0x1b07, 0x1b08, 0x1b09, 0x1b0a, + 0x1b0b, 0x1b0c, 0x1b0d, 0x1b0e, 0x1b11, 0x1b12, 0x1b3a, 0x1b3b, + 0x1b3c, 0x1b3d, 0x1b3e, 0x1b40, 0x1b3f, 0x1b41, 0x1b42, 0x1b43, + 0x30, 0x3046, 0x3094, 0x304b, 0x304c, 0x304d, 0x304e, 0x304f, + 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, + 0x3058, 0x3059, 0x305a, 0x305b, 0x305c, 0x305d, 0x305e, 0x305f, + 0x3060, 0x3061, 0x3062, 0x3064, 0x3065, 0x3066, 0x3067, 0x3068, + 0x3069, 0x306f, 0x3070, 0x3072, 0x3073, 0x3075, 0x3076, 0x3078, + 0x3079, 0x307b, 0x307c, 0x309d, 0x309e, 0x30a6, 0x30f4, 0x30ab, + 0x30ac, 0x30ad, 0x30ae, 0x30af, 0x30b0, 0x30b1, 0x30b2, 0x30b3, + 0x30b4, 0x30b5, 0x30b6, 0x30b7, 0x30b8, 0x30b9, 0x30ba, 0x30bb, + 0x30bc, 0x30bd, 0x30be, 0x30bf, 0x30c0, 0x30c1, 0x30c2, 0x30c4, + 0x30c5, 0x30c6, 0x30c7, 0x30c8, 0x30c9, 0x30cf, 0x30d0, 0x30d2, + 0x30d3, 0x30d5, 0x30d6, 0x30d8, 0x30d9, 0x30db, 0x30dc, 0x30ef, + 0x30f7, 0x30f0, 0x30f8, 0x30f1, 0x30f9, 0x30f2, 0x30fa, 0x30fd, + 0x30fe, 0xa, 0x306f, 0x3071, 0x3072, 0x3074, 0x3075, 0x3077, + 0x3078, 0x307a, 0x307b, 0x307d, 0x30cf, 0x30d1, 0x30d2, 0x30d4, + 0x30d5, 0x30d7, 0x30d8, 0x30da, 0x30db, 0x30dd, +}; + +struct NormalizationCorrection { + uint ucs4; + uint old_mapping; + int version; +}; + +static const NormalizationCorrection uc_normalization_corrections[] = { + { 0xf951, 0x96fb, 6 }, + { 0x2f868, 0x2136a, 7 }, + { 0x2f874, 0x5f33, 7 }, + { 0x2f91f, 0x43ab, 7 }, + { 0x2f95f, 0x7aae, 7 }, + { 0x2f9bf, 0x4d57, 7 }, +}; + +enum { NumNormalizationCorrections = 6 }; + +enum { UnicodeBlockCount = 512 }; // number of unicode blocks +enum { UnicodeBlockSize = 128 }; // size of each block + +namespace QUnicodeTables { + +static const unsigned char uc_scripts[] = { + Common, /* U+0000-007f */ + Common, /* U+0080-00ff */ + Latin, /* U+0100-017f */ + Latin, /* U+0180-01ff */ + Latin, /* U+0200-027f */ + Latin, /* U+0280-02ff */ + 32, /* U+0300-037f at offset 512 */ + 33, /* U+0380-03ff at offset 640 */ + Cyrillic, /* U+0400-047f */ + 34, /* U+0480-04ff at offset 768 */ + 35, /* U+0500-057f at offset 896 */ + 36, /* U+0580-05ff at offset 1024 */ + 37, /* U+0600-067f at offset 1152 */ + 38, /* U+0680-06ff at offset 1280 */ + 39, /* U+0700-077f at offset 1408 */ + 40, /* U+0780-07ff at offset 1536 */ + Common, /* U+0800-087f */ + Common, /* U+0880-08ff */ + 41, /* U+0900-097f at offset 1664 */ + 42, /* U+0980-09ff at offset 1792 */ + 43, /* U+0a00-0a7f at offset 1920 */ + 44, /* U+0a80-0aff at offset 2048 */ + 45, /* U+0b00-0b7f at offset 2176 */ + 46, /* U+0b80-0bff at offset 2304 */ + 47, /* U+0c00-0c7f at offset 2432 */ + 48, /* U+0c80-0cff at offset 2560 */ + 49, /* U+0d00-0d7f at offset 2688 */ + 50, /* U+0d80-0dff at offset 2816 */ + 51, /* U+0e00-0e7f at offset 2944 */ + 52, /* U+0e80-0eff at offset 3072 */ + 53, /* U+0f00-0f7f at offset 3200 */ + 54, /* U+0f80-0fff at offset 3328 */ + 55, /* U+1000-107f at offset 3456 */ + 56, /* U+1080-10ff at offset 3584 */ + 57, /* U+1100-117f at offset 3712 */ + 58, /* U+1180-11ff at offset 3840 */ + Ethiopic, /* U+1200-127f */ + Ethiopic, /* U+1280-12ff */ + Ethiopic, /* U+1300-137f */ + Ethiopic, /* U+1380-13ff */ + Common, /* U+1400-147f */ + CanadianAboriginal, /* U+1480-14ff */ + CanadianAboriginal, /* U+1500-157f */ + CanadianAboriginal, /* U+1580-15ff */ + CanadianAboriginal, /* U+1600-167f */ + 59, /* U+1680-16ff at offset 3968 */ + Tagalog, /* U+1700-177f */ + 60, /* U+1780-17ff at offset 4096 */ + Mongolian, /* U+1800-187f */ + Mongolian, /* U+1880-18ff */ + Limbu, /* U+1900-197f */ + 61, /* U+1980-19ff at offset 4224 */ + Buginese, /* U+1a00-1a7f */ + Common, /* U+1a80-1aff */ + Balinese, /* U+1b00-1b7f */ + Common, /* U+1b80-1bff */ + Common, /* U+1c00-1c7f */ + Common, /* U+1c80-1cff */ + 62, /* U+1d00-1d7f at offset 4352 */ + 63, /* U+1d80-1dff at offset 4480 */ + Latin, /* U+1e00-1e7f */ + Latin, /* U+1e80-1eff */ + 64, /* U+1f00-1f7f at offset 4608 */ + 65, /* U+1f80-1fff at offset 4736 */ + 66, /* U+2000-207f at offset 4864 */ + 67, /* U+2080-20ff at offset 4992 */ + 68, /* U+2100-217f at offset 5120 */ + Common, /* U+2180-21ff */ + Common, /* U+2200-227f */ + Common, /* U+2280-22ff */ + Common, /* U+2300-237f */ + Common, /* U+2380-23ff */ + Common, /* U+2400-247f */ + Common, /* U+2480-24ff */ + Common, /* U+2500-257f */ + Common, /* U+2580-25ff */ + Common, /* U+2600-267f */ + Common, /* U+2680-26ff */ + Common, /* U+2700-277f */ + Common, /* U+2780-27ff */ + Braille, /* U+2800-287f */ + Braille, /* U+2880-28ff */ + Common, /* U+2900-297f */ + Common, /* U+2980-29ff */ + Common, /* U+2a00-2a7f */ + Common, /* U+2a80-2aff */ + Common, /* U+2b00-2b7f */ + Common, /* U+2b80-2bff */ + Glagolitic, /* U+2c00-2c7f */ + Coptic, /* U+2c80-2cff */ + 69, /* U+2d00-2d7f at offset 5248 */ + Ethiopic, /* U+2d80-2dff */ + Common, /* U+2e00-2e7f */ + Han, /* U+2e80-2eff */ + Han, /* U+2f00-2f7f */ + Han, /* U+2f80-2fff */ + 70, /* U+3000-307f at offset 5376 */ + 71, /* U+3080-30ff at offset 5504 */ + 72, /* U+3100-317f at offset 5632 */ + 73, /* U+3180-31ff at offset 5760 */ + 74, /* U+3200-327f at offset 5888 */ + Common, /* U+3280-32ff */ + Common, /* U+3300-337f */ + Common, /* U+3380-33ff */ + Han, /* U+3400-347f */ + Han, /* U+3480-34ff */ + Han, /* U+3500-357f */ + Han, /* U+3580-35ff */ + Han, /* U+3600-367f */ + Han, /* U+3680-36ff */ + Han, /* U+3700-377f */ + Han, /* U+3780-37ff */ + Han, /* U+3800-387f */ + Han, /* U+3880-38ff */ + Han, /* U+3900-397f */ + Han, /* U+3980-39ff */ + Han, /* U+3a00-3a7f */ + Han, /* U+3a80-3aff */ + Han, /* U+3b00-3b7f */ + Han, /* U+3b80-3bff */ + Han, /* U+3c00-3c7f */ + Han, /* U+3c80-3cff */ + Han, /* U+3d00-3d7f */ + Han, /* U+3d80-3dff */ + Han, /* U+3e00-3e7f */ + Han, /* U+3e80-3eff */ + Han, /* U+3f00-3f7f */ + Han, /* U+3f80-3fff */ + Han, /* U+4000-407f */ + Han, /* U+4080-40ff */ + Han, /* U+4100-417f */ + Han, /* U+4180-41ff */ + Han, /* U+4200-427f */ + Han, /* U+4280-42ff */ + Han, /* U+4300-437f */ + Han, /* U+4380-43ff */ + Han, /* U+4400-447f */ + Han, /* U+4480-44ff */ + Han, /* U+4500-457f */ + Han, /* U+4580-45ff */ + Han, /* U+4600-467f */ + Han, /* U+4680-46ff */ + Han, /* U+4700-477f */ + Han, /* U+4780-47ff */ + Han, /* U+4800-487f */ + Han, /* U+4880-48ff */ + Han, /* U+4900-497f */ + Han, /* U+4980-49ff */ + Han, /* U+4a00-4a7f */ + Han, /* U+4a80-4aff */ + Han, /* U+4b00-4b7f */ + Han, /* U+4b80-4bff */ + Han, /* U+4c00-4c7f */ + Han, /* U+4c80-4cff */ + Han, /* U+4d00-4d7f */ + Han, /* U+4d80-4dff */ + Han, /* U+4e00-4e7f */ + Han, /* U+4e80-4eff */ + Han, /* U+4f00-4f7f */ + Han, /* U+4f80-4fff */ + Han, /* U+5000-507f */ + Han, /* U+5080-50ff */ + Han, /* U+5100-517f */ + Han, /* U+5180-51ff */ + Han, /* U+5200-527f */ + Han, /* U+5280-52ff */ + Han, /* U+5300-537f */ + Han, /* U+5380-53ff */ + Han, /* U+5400-547f */ + Han, /* U+5480-54ff */ + Han, /* U+5500-557f */ + Han, /* U+5580-55ff */ + Han, /* U+5600-567f */ + Han, /* U+5680-56ff */ + Han, /* U+5700-577f */ + Han, /* U+5780-57ff */ + Han, /* U+5800-587f */ + Han, /* U+5880-58ff */ + Han, /* U+5900-597f */ + Han, /* U+5980-59ff */ + Han, /* U+5a00-5a7f */ + Han, /* U+5a80-5aff */ + Han, /* U+5b00-5b7f */ + Han, /* U+5b80-5bff */ + Han, /* U+5c00-5c7f */ + Han, /* U+5c80-5cff */ + Han, /* U+5d00-5d7f */ + Han, /* U+5d80-5dff */ + Han, /* U+5e00-5e7f */ + Han, /* U+5e80-5eff */ + Han, /* U+5f00-5f7f */ + Han, /* U+5f80-5fff */ + Han, /* U+6000-607f */ + Han, /* U+6080-60ff */ + Han, /* U+6100-617f */ + Han, /* U+6180-61ff */ + Han, /* U+6200-627f */ + Han, /* U+6280-62ff */ + Han, /* U+6300-637f */ + Han, /* U+6380-63ff */ + Han, /* U+6400-647f */ + Han, /* U+6480-64ff */ + Han, /* U+6500-657f */ + Han, /* U+6580-65ff */ + Han, /* U+6600-667f */ + Han, /* U+6680-66ff */ + Han, /* U+6700-677f */ + Han, /* U+6780-67ff */ + Han, /* U+6800-687f */ + Han, /* U+6880-68ff */ + Han, /* U+6900-697f */ + Han, /* U+6980-69ff */ + Han, /* U+6a00-6a7f */ + Han, /* U+6a80-6aff */ + Han, /* U+6b00-6b7f */ + Han, /* U+6b80-6bff */ + Han, /* U+6c00-6c7f */ + Han, /* U+6c80-6cff */ + Han, /* U+6d00-6d7f */ + Han, /* U+6d80-6dff */ + Han, /* U+6e00-6e7f */ + Han, /* U+6e80-6eff */ + Han, /* U+6f00-6f7f */ + Han, /* U+6f80-6fff */ + Han, /* U+7000-707f */ + Han, /* U+7080-70ff */ + Han, /* U+7100-717f */ + Han, /* U+7180-71ff */ + Han, /* U+7200-727f */ + Han, /* U+7280-72ff */ + Han, /* U+7300-737f */ + Han, /* U+7380-73ff */ + Han, /* U+7400-747f */ + Han, /* U+7480-74ff */ + Han, /* U+7500-757f */ + Han, /* U+7580-75ff */ + Han, /* U+7600-767f */ + Han, /* U+7680-76ff */ + Han, /* U+7700-777f */ + Han, /* U+7780-77ff */ + Han, /* U+7800-787f */ + Han, /* U+7880-78ff */ + Han, /* U+7900-797f */ + Han, /* U+7980-79ff */ + Han, /* U+7a00-7a7f */ + Han, /* U+7a80-7aff */ + Han, /* U+7b00-7b7f */ + Han, /* U+7b80-7bff */ + Han, /* U+7c00-7c7f */ + Han, /* U+7c80-7cff */ + Han, /* U+7d00-7d7f */ + Han, /* U+7d80-7dff */ + Han, /* U+7e00-7e7f */ + Han, /* U+7e80-7eff */ + Han, /* U+7f00-7f7f */ + Han, /* U+7f80-7fff */ + Han, /* U+8000-807f */ + Han, /* U+8080-80ff */ + Han, /* U+8100-817f */ + Han, /* U+8180-81ff */ + Han, /* U+8200-827f */ + Han, /* U+8280-82ff */ + Han, /* U+8300-837f */ + Han, /* U+8380-83ff */ + Han, /* U+8400-847f */ + Han, /* U+8480-84ff */ + Han, /* U+8500-857f */ + Han, /* U+8580-85ff */ + Han, /* U+8600-867f */ + Han, /* U+8680-86ff */ + Han, /* U+8700-877f */ + Han, /* U+8780-87ff */ + Han, /* U+8800-887f */ + Han, /* U+8880-88ff */ + Han, /* U+8900-897f */ + Han, /* U+8980-89ff */ + Han, /* U+8a00-8a7f */ + Han, /* U+8a80-8aff */ + Han, /* U+8b00-8b7f */ + Han, /* U+8b80-8bff */ + Han, /* U+8c00-8c7f */ + Han, /* U+8c80-8cff */ + Han, /* U+8d00-8d7f */ + Han, /* U+8d80-8dff */ + Han, /* U+8e00-8e7f */ + Han, /* U+8e80-8eff */ + Han, /* U+8f00-8f7f */ + Han, /* U+8f80-8fff */ + Han, /* U+9000-907f */ + Han, /* U+9080-90ff */ + Han, /* U+9100-917f */ + Han, /* U+9180-91ff */ + Han, /* U+9200-927f */ + Han, /* U+9280-92ff */ + Han, /* U+9300-937f */ + Han, /* U+9380-93ff */ + Han, /* U+9400-947f */ + Han, /* U+9480-94ff */ + Han, /* U+9500-957f */ + Han, /* U+9580-95ff */ + Han, /* U+9600-967f */ + Han, /* U+9680-96ff */ + Han, /* U+9700-977f */ + Han, /* U+9780-97ff */ + Han, /* U+9800-987f */ + Han, /* U+9880-98ff */ + Han, /* U+9900-997f */ + Han, /* U+9980-99ff */ + Han, /* U+9a00-9a7f */ + Han, /* U+9a80-9aff */ + Han, /* U+9b00-9b7f */ + Han, /* U+9b80-9bff */ + Han, /* U+9c00-9c7f */ + Han, /* U+9c80-9cff */ + Han, /* U+9d00-9d7f */ + Han, /* U+9d80-9dff */ + Han, /* U+9e00-9e7f */ + Han, /* U+9e80-9eff */ + Han, /* U+9f00-9f7f */ + Han, /* U+9f80-9fff */ + Yi, /* U+a000-a07f */ + Yi, /* U+a080-a0ff */ + Yi, /* U+a100-a17f */ + Yi, /* U+a180-a1ff */ + Yi, /* U+a200-a27f */ + Yi, /* U+a280-a2ff */ + Yi, /* U+a300-a37f */ + Yi, /* U+a380-a3ff */ + Yi, /* U+a400-a47f */ + Yi, /* U+a480-a4ff */ + Common, /* U+a500-a57f */ + Common, /* U+a580-a5ff */ + Common, /* U+a600-a67f */ + Common, /* U+a680-a6ff */ + Common, /* U+a700-a77f */ + Common, /* U+a780-a7ff */ + SylotiNagri, /* U+a800-a87f */ + Common, /* U+a880-a8ff */ + Common, /* U+a900-a97f */ + Common, /* U+a980-a9ff */ + Common, /* U+aa00-aa7f */ + Common, /* U+aa80-aaff */ + Common, /* U+ab00-ab7f */ + Common, /* U+ab80-abff */ + Hangul, /* U+ac00-ac7f */ + Hangul, /* U+ac80-acff */ + Hangul, /* U+ad00-ad7f */ + Hangul, /* U+ad80-adff */ + Hangul, /* U+ae00-ae7f */ + Hangul, /* U+ae80-aeff */ + Hangul, /* U+af00-af7f */ + Hangul, /* U+af80-afff */ + Hangul, /* U+b000-b07f */ + Hangul, /* U+b080-b0ff */ + Hangul, /* U+b100-b17f */ + Hangul, /* U+b180-b1ff */ + Hangul, /* U+b200-b27f */ + Hangul, /* U+b280-b2ff */ + Hangul, /* U+b300-b37f */ + Hangul, /* U+b380-b3ff */ + Hangul, /* U+b400-b47f */ + Hangul, /* U+b480-b4ff */ + Hangul, /* U+b500-b57f */ + Hangul, /* U+b580-b5ff */ + Hangul, /* U+b600-b67f */ + Hangul, /* U+b680-b6ff */ + Hangul, /* U+b700-b77f */ + Hangul, /* U+b780-b7ff */ + Hangul, /* U+b800-b87f */ + Hangul, /* U+b880-b8ff */ + Hangul, /* U+b900-b97f */ + Hangul, /* U+b980-b9ff */ + Hangul, /* U+ba00-ba7f */ + Hangul, /* U+ba80-baff */ + Hangul, /* U+bb00-bb7f */ + Hangul, /* U+bb80-bbff */ + Hangul, /* U+bc00-bc7f */ + Hangul, /* U+bc80-bcff */ + Hangul, /* U+bd00-bd7f */ + Hangul, /* U+bd80-bdff */ + Hangul, /* U+be00-be7f */ + Hangul, /* U+be80-beff */ + Hangul, /* U+bf00-bf7f */ + Hangul, /* U+bf80-bfff */ + Hangul, /* U+c000-c07f */ + Hangul, /* U+c080-c0ff */ + Hangul, /* U+c100-c17f */ + Hangul, /* U+c180-c1ff */ + Hangul, /* U+c200-c27f */ + Hangul, /* U+c280-c2ff */ + Hangul, /* U+c300-c37f */ + Hangul, /* U+c380-c3ff */ + Hangul, /* U+c400-c47f */ + Hangul, /* U+c480-c4ff */ + Hangul, /* U+c500-c57f */ + Hangul, /* U+c580-c5ff */ + Hangul, /* U+c600-c67f */ + Hangul, /* U+c680-c6ff */ + Hangul, /* U+c700-c77f */ + Hangul, /* U+c780-c7ff */ + Hangul, /* U+c800-c87f */ + Hangul, /* U+c880-c8ff */ + Hangul, /* U+c900-c97f */ + Hangul, /* U+c980-c9ff */ + Hangul, /* U+ca00-ca7f */ + Hangul, /* U+ca80-caff */ + Hangul, /* U+cb00-cb7f */ + Hangul, /* U+cb80-cbff */ + Hangul, /* U+cc00-cc7f */ + Hangul, /* U+cc80-ccff */ + Hangul, /* U+cd00-cd7f */ + Hangul, /* U+cd80-cdff */ + Hangul, /* U+ce00-ce7f */ + Hangul, /* U+ce80-ceff */ + Hangul, /* U+cf00-cf7f */ + Hangul, /* U+cf80-cfff */ + Hangul, /* U+d000-d07f */ + Hangul, /* U+d080-d0ff */ + Hangul, /* U+d100-d17f */ + Hangul, /* U+d180-d1ff */ + Hangul, /* U+d200-d27f */ + Hangul, /* U+d280-d2ff */ + Hangul, /* U+d300-d37f */ + Hangul, /* U+d380-d3ff */ + Hangul, /* U+d400-d47f */ + Hangul, /* U+d480-d4ff */ + Hangul, /* U+d500-d57f */ + Hangul, /* U+d580-d5ff */ + Hangul, /* U+d600-d67f */ + Hangul, /* U+d680-d6ff */ + Hangul, /* U+d700-d77f */ + 75, /* U+d780-d7ff at offset 6016 */ + Common, /* U+d800-d87f */ + Common, /* U+d880-d8ff */ + Common, /* U+d900-d97f */ + Common, /* U+d980-d9ff */ + Common, /* U+da00-da7f */ + Common, /* U+da80-daff */ + Common, /* U+db00-db7f */ + Common, /* U+db80-dbff */ + Common, /* U+dc00-dc7f */ + Common, /* U+dc80-dcff */ + Common, /* U+dd00-dd7f */ + Common, /* U+dd80-ddff */ + Common, /* U+de00-de7f */ + Common, /* U+de80-deff */ + Common, /* U+df00-df7f */ + Common, /* U+df80-dfff */ + Common, /* U+e000-e07f */ + Common, /* U+e080-e0ff */ + Common, /* U+e100-e17f */ + Common, /* U+e180-e1ff */ + Common, /* U+e200-e27f */ + Common, /* U+e280-e2ff */ + Common, /* U+e300-e37f */ + Common, /* U+e380-e3ff */ + Common, /* U+e400-e47f */ + Common, /* U+e480-e4ff */ + Common, /* U+e500-e57f */ + Common, /* U+e580-e5ff */ + Common, /* U+e600-e67f */ + Common, /* U+e680-e6ff */ + Common, /* U+e700-e77f */ + Common, /* U+e780-e7ff */ + Common, /* U+e800-e87f */ + Common, /* U+e880-e8ff */ + Common, /* U+e900-e97f */ + Common, /* U+e980-e9ff */ + Common, /* U+ea00-ea7f */ + Common, /* U+ea80-eaff */ + Common, /* U+eb00-eb7f */ + Common, /* U+eb80-ebff */ + Common, /* U+ec00-ec7f */ + Common, /* U+ec80-ecff */ + Common, /* U+ed00-ed7f */ + Common, /* U+ed80-edff */ + Common, /* U+ee00-ee7f */ + Common, /* U+ee80-eeff */ + Common, /* U+ef00-ef7f */ + Common, /* U+ef80-efff */ + Common, /* U+f000-f07f */ + Common, /* U+f080-f0ff */ + Common, /* U+f100-f17f */ + Common, /* U+f180-f1ff */ + Common, /* U+f200-f27f */ + Common, /* U+f280-f2ff */ + Common, /* U+f300-f37f */ + Common, /* U+f380-f3ff */ + Common, /* U+f400-f47f */ + Common, /* U+f480-f4ff */ + Common, /* U+f500-f57f */ + Common, /* U+f580-f5ff */ + Common, /* U+f600-f67f */ + Common, /* U+f680-f6ff */ + Common, /* U+f700-f77f */ + Common, /* U+f780-f7ff */ + Common, /* U+f800-f87f */ + Common, /* U+f880-f8ff */ + Han, /* U+f900-f97f */ + Han, /* U+f980-f9ff */ + Han, /* U+fa00-fa7f */ + Han, /* U+fa80-faff */ + 76, /* U+fb00-fb7f at offset 6144 */ + 77, /* U+fb80-fbff at offset 6272 */ + Arabic, /* U+fc00-fc7f */ + Arabic, /* U+fc80-fcff */ + 78, /* U+fd00-fd7f at offset 6400 */ + 79, /* U+fd80-fdff at offset 6528 */ + 80, /* U+fe00-fe7f at offset 6656 */ + 81, /* U+fe80-feff at offset 6784 */ + Common, /* U+ff00-ff7f */ + 82, /* U+ff80-ffff at offset 6912 */ + + + /* U+0300-037f at offset 512 */ + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Common, Common, Common, Common, Greek, Greek, Common, Common, + Common, Common, Greek, Greek, Greek, Greek, Common, Common, + + /* U+0380-03ff at offset 640 */ + Common, Common, Common, Common, Greek, Greek, Greek, Common, + Greek, Greek, Greek, Common, Greek, Common, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Common, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Common, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, + Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, Coptic, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + + /* U+0480-04ff at offset 768 */ + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Common, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + + /* U+0500-057f at offset 896 */ + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, Cyrillic, + Cyrillic, Cyrillic, Cyrillic, Cyrillic, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, + Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, + Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, + Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, + Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Common, + Common, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, + Common, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, + Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, + Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, + Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, + + /* U+0580-05ff at offset 1024 */ + Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, Armenian, + Common, Common, Armenian, Common, Common, Common, Common, Common, + Common, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, + Common, Common, Common, Common, Common, Common, Common, Common, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, + Hebrew, Hebrew, Hebrew, Common, Common, Common, Common, Common, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+0600-067f at offset 1152 */ + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Arabic, Common, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common, + Common, Common, Common, Common, Common, Common, Arabic, Common, + Common, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Common, Common, Common, Common, Common, + Common, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Inherited, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + + /* U+0680-06ff at offset 1280 */ + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Common, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + + /* U+0700-077f at offset 1408 */ + Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, + Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Common, Syriac, + Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, + Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, + Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, + Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, + Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, + Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, + Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, Syriac, + Syriac, Syriac, Syriac, Common, Common, Syriac, Syriac, Syriac, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+0780-07ff at offset 1536 */ + Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, + Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, + Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, + Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, + Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, + Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, Thaana, + Thaana, Thaana, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, + Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, + Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, + Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, + Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, + Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, + Nko, Nko, Nko, Nko, Nko, Nko, Nko, Nko, + Nko, Nko, Nko, Common, Common, Common, Common, Common, + + /* U+0900-097f at offset 1664 */ + Common, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, + Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, + Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, + Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, + Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, + Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, + Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, + Devanagari, Devanagari, Common, Common, Devanagari, Devanagari, Devanagari, Devanagari, + Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, + Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Common, Common, + Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Common, Common, Common, + Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, + Devanagari, Devanagari, Devanagari, Devanagari, Common, Common, Devanagari, Devanagari, + Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Devanagari, Devanagari, Devanagari, Devanagari, Devanagari, + + /* U+0980-09ff at offset 1792 */ + Common, Bengali, Bengali, Bengali, Common, Bengali, Bengali, Bengali, + Bengali, Bengali, Bengali, Bengali, Bengali, Common, Common, Bengali, + Bengali, Common, Common, Bengali, Bengali, Bengali, Bengali, Bengali, + Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, + Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, + Bengali, Common, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, + Bengali, Common, Bengali, Common, Common, Common, Bengali, Bengali, + Bengali, Bengali, Common, Common, Bengali, Bengali, Bengali, Bengali, + Bengali, Bengali, Bengali, Bengali, Bengali, Common, Common, Bengali, + Bengali, Common, Common, Bengali, Bengali, Bengali, Bengali, Common, + Common, Common, Common, Common, Common, Common, Common, Bengali, + Common, Common, Common, Common, Bengali, Bengali, Common, Bengali, + Bengali, Bengali, Bengali, Bengali, Common, Common, Bengali, Bengali, + Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, + Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, Bengali, + Bengali, Bengali, Bengali, Common, Common, Common, Common, Common, + + /* U+0a00-0a7f at offset 1920 */ + Common, Gurmukhi, Gurmukhi, Gurmukhi, Common, Gurmukhi, Gurmukhi, Gurmukhi, + Gurmukhi, Gurmukhi, Gurmukhi, Common, Common, Common, Common, Gurmukhi, + Gurmukhi, Common, Common, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, + Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, + Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, + Gurmukhi, Common, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, + Gurmukhi, Common, Gurmukhi, Gurmukhi, Common, Gurmukhi, Gurmukhi, Common, + Gurmukhi, Gurmukhi, Common, Common, Gurmukhi, Common, Gurmukhi, Gurmukhi, + Gurmukhi, Gurmukhi, Gurmukhi, Common, Common, Common, Common, Gurmukhi, + Gurmukhi, Common, Common, Gurmukhi, Gurmukhi, Gurmukhi, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Common, Gurmukhi, Common, + Common, Common, Common, Common, Common, Common, Gurmukhi, Gurmukhi, + Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, + Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Gurmukhi, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+0a80-0aff at offset 2048 */ + Common, Gujarati, Gujarati, Gujarati, Common, Gujarati, Gujarati, Gujarati, + Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Common, Gujarati, + Gujarati, Gujarati, Common, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, + Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, + Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, + Gujarati, Common, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, + Gujarati, Common, Gujarati, Gujarati, Common, Gujarati, Gujarati, Gujarati, + Gujarati, Gujarati, Common, Common, Gujarati, Gujarati, Gujarati, Gujarati, + Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Common, Gujarati, + Gujarati, Gujarati, Common, Gujarati, Gujarati, Gujarati, Common, Common, + Gujarati, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Gujarati, Gujarati, Gujarati, Gujarati, Common, Common, Gujarati, Gujarati, + Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, Gujarati, + Common, Gujarati, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+0b00-0b7f at offset 2176 */ + Common, Oriya, Oriya, Oriya, Common, Oriya, Oriya, Oriya, + Oriya, Oriya, Oriya, Oriya, Oriya, Common, Common, Oriya, + Oriya, Common, Common, Oriya, Oriya, Oriya, Oriya, Oriya, + Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, + Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, + Oriya, Common, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, + Oriya, Common, Oriya, Oriya, Common, Oriya, Oriya, Oriya, + Oriya, Oriya, Common, Common, Oriya, Oriya, Oriya, Oriya, + Oriya, Oriya, Oriya, Oriya, Common, Common, Common, Oriya, + Oriya, Common, Common, Oriya, Oriya, Oriya, Common, Common, + Common, Common, Common, Common, Common, Common, Oriya, Oriya, + Common, Common, Common, Common, Oriya, Oriya, Common, Oriya, + Oriya, Oriya, Common, Common, Common, Common, Oriya, Oriya, + Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, Oriya, + Oriya, Oriya, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+0b80-0bff at offset 2304 */ + Common, Common, Tamil, Tamil, Common, Tamil, Tamil, Tamil, + Tamil, Tamil, Tamil, Common, Common, Common, Tamil, Tamil, + Tamil, Common, Tamil, Tamil, Tamil, Tamil, Common, Common, + Common, Tamil, Tamil, Common, Tamil, Common, Tamil, Tamil, + Common, Common, Common, Tamil, Tamil, Common, Common, Common, + Tamil, Tamil, Tamil, Common, Common, Common, Tamil, Tamil, + Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, + Tamil, Tamil, Common, Common, Common, Common, Tamil, Tamil, + Tamil, Tamil, Tamil, Common, Common, Common, Tamil, Tamil, + Tamil, Common, Tamil, Tamil, Tamil, Tamil, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Tamil, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Tamil, Tamil, + Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, + Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, Tamil, + Tamil, Tamil, Tamil, Common, Common, Common, Common, Common, + + /* U+0c00-0c7f at offset 2432 */ + Common, Telugu, Telugu, Telugu, Common, Telugu, Telugu, Telugu, + Telugu, Telugu, Telugu, Telugu, Telugu, Common, Telugu, Telugu, + Telugu, Common, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, + Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, + Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, + Telugu, Common, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, + Telugu, Telugu, Telugu, Telugu, Common, Telugu, Telugu, Telugu, + Telugu, Telugu, Common, Common, Common, Common, Telugu, Telugu, + Telugu, Telugu, Telugu, Telugu, Telugu, Common, Telugu, Telugu, + Telugu, Common, Telugu, Telugu, Telugu, Telugu, Common, Common, + Common, Common, Common, Common, Common, Telugu, Telugu, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Telugu, Telugu, Common, Common, Common, Common, Telugu, Telugu, + Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, Telugu, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+0c80-0cff at offset 2560 */ + Common, Common, Kannada, Kannada, Common, Kannada, Kannada, Kannada, + Kannada, Kannada, Kannada, Kannada, Kannada, Common, Kannada, Kannada, + Kannada, Common, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, + Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, + Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, + Kannada, Common, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, + Kannada, Kannada, Kannada, Kannada, Common, Kannada, Kannada, Kannada, + Kannada, Kannada, Common, Common, Kannada, Kannada, Kannada, Kannada, + Kannada, Kannada, Kannada, Kannada, Kannada, Common, Kannada, Kannada, + Kannada, Common, Kannada, Kannada, Kannada, Kannada, Common, Common, + Common, Common, Common, Common, Common, Kannada, Kannada, Common, + Common, Common, Common, Common, Common, Common, Kannada, Common, + Kannada, Kannada, Kannada, Kannada, Common, Common, Kannada, Kannada, + Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, Kannada, + Common, Kannada, Kannada, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+0d00-0d7f at offset 2688 */ + Common, Common, Malayalam, Malayalam, Common, Malayalam, Malayalam, Malayalam, + Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Common, Malayalam, Malayalam, + Malayalam, Common, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, + Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, + Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, + Malayalam, Common, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, + Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, + Malayalam, Malayalam, Common, Common, Common, Common, Malayalam, Malayalam, + Malayalam, Malayalam, Malayalam, Malayalam, Common, Common, Malayalam, Malayalam, + Malayalam, Common, Malayalam, Malayalam, Malayalam, Malayalam, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Malayalam, + Common, Common, Common, Common, Common, Common, Common, Common, + Malayalam, Malayalam, Common, Common, Common, Common, Malayalam, Malayalam, + Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, Malayalam, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+0d80-0dff at offset 2816 */ + Common, Common, Sinhala, Sinhala, Common, Sinhala, Sinhala, Sinhala, + Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, + Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Common, + Common, Common, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, + Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, + Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, + Sinhala, Sinhala, Common, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, + Sinhala, Sinhala, Sinhala, Sinhala, Common, Sinhala, Common, Common, + Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Common, + Common, Common, Sinhala, Common, Common, Common, Common, Sinhala, + Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Common, Sinhala, Common, + Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, Sinhala, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Sinhala, Sinhala, Sinhala, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+0e00-0e7f at offset 2944 */ + Common, Thai, Thai, Thai, Thai, Thai, Thai, Thai, + Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, + Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, + Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, + Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, + Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, + Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, + Thai, Thai, Thai, Common, Common, Common, Common, Common, + Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, + Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, + Thai, Thai, Thai, Thai, Thai, Thai, Thai, Thai, + Thai, Thai, Thai, Thai, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+0e80-0eff at offset 3072 */ + Common, Lao, Lao, Common, Lao, Common, Common, Lao, + Lao, Common, Lao, Common, Common, Lao, Common, Common, + Common, Common, Common, Common, Lao, Lao, Lao, Lao, + Common, Lao, Lao, Lao, Lao, Lao, Lao, Lao, + Common, Lao, Lao, Lao, Common, Lao, Common, Lao, + Common, Common, Lao, Lao, Common, Lao, Lao, Lao, + Lao, Lao, Lao, Lao, Lao, Lao, Lao, Lao, + Lao, Lao, Common, Lao, Lao, Lao, Common, Common, + Lao, Lao, Lao, Lao, Lao, Common, Lao, Common, + Lao, Lao, Lao, Lao, Lao, Lao, Common, Common, + Lao, Lao, Lao, Lao, Lao, Lao, Lao, Lao, + Lao, Lao, Common, Common, Lao, Lao, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+0f00-0f7f at offset 3200 */ + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Common, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Common, Common, Common, Common, Common, + Common, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + + /* U+0f80-0fff at offset 3328 */ + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Common, Common, Common, Common, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Common, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Common, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, + Tibetan, Tibetan, Tibetan, Tibetan, Tibetan, Common, Common, Tibetan, + Tibetan, Tibetan, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+1000-107f at offset 3456 */ + Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, + Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, + Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, + Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, + Myanmar, Myanmar, Common, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, + Common, Myanmar, Myanmar, Common, Myanmar, Myanmar, Myanmar, Myanmar, + Myanmar, Myanmar, Myanmar, Common, Common, Common, Myanmar, Myanmar, + Myanmar, Myanmar, Common, Common, Common, Common, Common, Common, + Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, + Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, + Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, Myanmar, + Myanmar, Myanmar, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+1080-10ff at offset 3584 */ + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, + Georgian, Georgian, Georgian, Common, Georgian, Common, Common, Common, + + /* U+1100-117f at offset 3712 */ + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Common, Common, Common, Common, Common, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + + /* U+1180-11ff at offset 3840 */ + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Common, Common, Common, Common, Common, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Common, Common, Common, Common, Common, Common, + + /* U+1680-16ff at offset 3968 */ + Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, + Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, + Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, Ogham, + Ogham, Ogham, Ogham, Ogham, Ogham, Common, Common, Common, + Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic, + Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic, + Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic, + Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic, + Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic, + Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic, + Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic, + Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic, + Runic, Runic, Runic, Runic, Runic, Runic, Runic, Runic, + Runic, Runic, Runic, Common, Common, Common, Runic, Runic, + Runic, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+1780-17ff at offset 4096 */ + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Common, Common, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Common, Common, Common, Common, Common, Common, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Common, Common, Common, Common, Common, Common, + + /* U+1980-19ff at offset 4224 */ + NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, + NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, + NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, + NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, + NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, + NewTaiLue, NewTaiLue, Common, Common, Common, Common, Common, Common, + NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, + NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, + NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, + NewTaiLue, NewTaiLue, Common, Common, Common, Common, Common, Common, + NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, NewTaiLue, + NewTaiLue, NewTaiLue, Common, Common, Common, Common, NewTaiLue, NewTaiLue, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, Khmer, + + /* U+1d00-1d7f at offset 4352 */ + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Greek, Greek, + Greek, Greek, Greek, Cyrillic, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Greek, Greek, Greek, + Greek, Greek, Latin, Latin, Latin, Latin, Greek, Greek, + Greek, Greek, Greek, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Cyrillic, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + + /* U+1d80-1dff at offset 4480 */ + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Latin, + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Greek, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Inherited, Inherited, + + /* U+1f00-1f7f at offset 4608 */ + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Common, Common, + Greek, Greek, Greek, Greek, Greek, Greek, Common, Common, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Common, Common, + Greek, Greek, Greek, Greek, Greek, Greek, Common, Common, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Common, Greek, Common, Greek, Common, Greek, Common, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Common, Common, + + /* U+1f80-1fff at offset 4736 */ + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Common, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Common, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Common, Common, Greek, Greek, + Greek, Greek, Greek, Greek, Common, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Greek, + Common, Common, Greek, Greek, Greek, Common, Greek, Greek, + Greek, Greek, Greek, Greek, Greek, Greek, Greek, Common, + + /* U+2000-207f at offset 4864 */ + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Inherited, Inherited, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Latin, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Latin, + + /* U+2080-20ff at offset 4992 */ + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Latin, Latin, Latin, Latin, Latin, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+2100-217f at offset 5120 */ + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Greek, Common, + Common, Common, Latin, Latin, Common, Common, Common, Common, + Common, Common, Latin, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Latin, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+2d00-2d7f at offset 5248 */ + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, + Georgian, Georgian, Georgian, Georgian, Georgian, Georgian, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, + Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, + Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, + Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, + Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, + Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, + Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Tifinagh, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Tifinagh, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+3000-307f at offset 5376 */ + Common, Common, Common, Common, Common, Han, Common, Han, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Han, Han, Han, Han, Han, Han, Han, + Han, Han, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Common, Common, Common, Common, Common, Common, Common, Common, + Han, Han, Han, Han, Common, Common, Common, Common, + Common, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, + Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, + Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, + Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, + Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, + Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, + Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, + Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, + + /* U+3080-30ff at offset 5504 */ + Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, + Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, + Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Hiragana, Common, + Common, Inherited, Inherited, Common, Common, Hiragana, Hiragana, Hiragana, + Common, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Common, Common, Katakana, Katakana, Katakana, + + /* U+3100-317f at offset 5632 */ + Common, Common, Common, Common, Common, Bopomofo, Bopomofo, Bopomofo, + Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, + Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, + Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, + Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, + Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Common, Common, Common, + Common, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + + /* U+3180-31ff at offset 5760 */ + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, + Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, + Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, Bopomofo, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + + /* U+3200-327f at offset 5888 */ + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Common, Common, + + /* U+d780-d7ff at offset 6016 */ + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + + /* U+fb00-fb7f at offset 6144 */ + Latin, Latin, Latin, Latin, Latin, Latin, Latin, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Armenian, Armenian, Armenian, Armenian, Armenian, + Common, Common, Common, Common, Common, Hebrew, Hebrew, Hebrew, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Common, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Common, Hebrew, Common, + Hebrew, Hebrew, Common, Hebrew, Hebrew, Common, Hebrew, Hebrew, + Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, Hebrew, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + + /* U+fb80-fbff at offset 6272 */ + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + + /* U+fd00-fd7f at offset 6400 */ + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + + /* U+fd80-fdff at offset 6528 */ + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Common, Common, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common, Common, + + /* U+fe00-fe7f at offset 6656 */ + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, Inherited, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Inherited, Inherited, Inherited, Inherited, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Arabic, Arabic, Arabic, Arabic, Arabic, Common, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + + /* U+fe80-feff at offset 6784 */ + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, Arabic, + Arabic, Arabic, Arabic, Arabic, Arabic, Common, Common, Common, + + /* U+ff80-ffff at offset 6912 */ + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, + Katakana, Katakana, Katakana, Katakana, Katakana, Katakana, Common, Common, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, Common, + Common, Common, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Common, Common, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Common, Common, Hangul, Hangul, Hangul, Hangul, Hangul, Hangul, + Common, Common, Hangul, Hangul, Hangul, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common, + Common, Common, Common, Common, Common, Common, Common, Common +}; + +} // namespace QUnicodeTables + + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qunicodetables_p.h b/src/corelib/tools/qunicodetables_p.h new file mode 100644 index 0000000..e588313 --- /dev/null +++ b/src/corelib/tools/qunicodetables_p.h @@ -0,0 +1,231 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* This file is autogenerated from the Unicode 5.0 database. Do not edit */ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#ifndef QUNICODETABLES_P_H +#define QUNICODETABLES_P_H + +#include <QtCore/qchar.h> + +QT_BEGIN_NAMESPACE + +namespace QUnicodeTables { + struct Properties { + ushort category : 8; + ushort line_break_class : 8; + ushort direction : 8; + ushort combiningClass :8; + ushort joining : 2; + signed short digitValue : 6; /* 5 needed */ + ushort unicodeVersion : 4; + ushort lowerCaseSpecial : 1; + ushort upperCaseSpecial : 1; + ushort titleCaseSpecial : 1; + ushort caseFoldSpecial : 1; /* currently unused */ + signed short mirrorDiff : 16; + signed short lowerCaseDiff : 16; + signed short upperCaseDiff : 16; + signed short titleCaseDiff : 16; + signed short caseFoldDiff : 16; + ushort graphemeBreak : 8; + ushort wordBreak : 8; + ushort sentenceBreak : 8; + }; + Q_CORE_EXPORT const Properties* QT_FASTCALL properties(uint ucs4); + Q_CORE_EXPORT const Properties* QT_FASTCALL properties(ushort ucs2); + + // See http://www.unicode.org/reports/tr24/tr24-5.html + + enum Script { + Common, + Greek, + Cyrillic, + Armenian, + Hebrew, + Arabic, + Syriac, + Thaana, + Devanagari, + Bengali, + Gurmukhi, + Gujarati, + Oriya, + Tamil, + Telugu, + Kannada, + Malayalam, + Sinhala, + Thai, + Lao, + Tibetan, + Myanmar, + Georgian, + Hangul, + Ogham, + Runic, + Khmer, + Inherited, + ScriptCount = Inherited, + Latin = Common, + Ethiopic = Common, + Cherokee = Common, + CanadianAboriginal = Common, + Mongolian = Common, + Hiragana = Common, + Katakana = Common, + Bopomofo = Common, + Han = Common, + Yi = Common, + OldItalic = Common, + Gothic = Common, + Deseret = Common, + Tagalog = Common, + Hanunoo = Common, + Buhid = Common, + Tagbanwa = Common, + Limbu = Common, + TaiLe = Common, + LinearB = Common, + Ugaritic = Common, + Shavian = Common, + Osmanya = Common, + Cypriot = Common, + Braille = Common, + Buginese = Common, + Coptic = Common, + NewTaiLue = Common, + Glagolitic = Common, + Tifinagh = Common, + SylotiNagri = Common, + OldPersian = Common, + Kharoshthi = Common, + Balinese = Common, + Cuneiform = Common, + Phoenician = Common, + PhagsPa = Common, + Nko = Common + }; + enum { ScriptSentinel = 32 }; + + + // see http://www.unicode.org/reports/tr14/tr14-19.html + // we don't use the XX, AI and CB properties and map them to AL instead. + // as we don't support any EBDIC based OS'es, NL is ignored and mapped to AL as well. + enum LineBreakClass { + LineBreak_OP, LineBreak_CL, LineBreak_QU, LineBreak_GL, LineBreak_NS, + LineBreak_EX, LineBreak_SY, LineBreak_IS, LineBreak_PR, LineBreak_PO, + LineBreak_NU, LineBreak_AL, LineBreak_ID, LineBreak_IN, LineBreak_HY, + LineBreak_BA, LineBreak_BB, LineBreak_B2, LineBreak_ZW, LineBreak_CM, + LineBreak_WJ, LineBreak_H2, LineBreak_H3, LineBreak_JL, LineBreak_JV, + LineBreak_JT, LineBreak_SA, LineBreak_SG, + LineBreak_SP, LineBreak_CR, LineBreak_LF, LineBreak_BK + }; + + + Q_CORE_EXPORT QUnicodeTables::LineBreakClass QT_FASTCALL lineBreakClass(uint ucs4); + inline int lineBreakClass(const QChar &ch) { + return QUnicodeTables::lineBreakClass(ch.unicode()); + } + + Q_CORE_EXPORT int QT_FASTCALL script(uint ucs4); + Q_CORE_EXPORT_INLINE int QT_FASTCALL script(const QChar &ch) { + return script(ch.unicode()); + } + + + enum GraphemeBreak { + GraphemeBreakOther, + GraphemeBreakCR, + GraphemeBreakLF, + GraphemeBreakControl, + GraphemeBreakExtend, + GraphemeBreakL, + GraphemeBreakV, + GraphemeBreakT, + GraphemeBreakLV, + GraphemeBreakLVT + }; + + + enum WordBreak { + WordBreakOther, + WordBreakFormat, + WordBreakKatakana, + WordBreakALetter, + WordBreakMidLetter, + WordBreakMidNum, + WordBreakNumeric, + WordBreakExtendNumLet + }; + + + enum SentenceBreak { + SentenceBreakOther, + SentenceBreakSep, + SentenceBreakFormat, + SentenceBreakSp, + SentenceBreakLower, + SentenceBreakUpper, + SentenceBreakOLetter, + SentenceBreakNumeric, + SentenceBreakATerm, + SentenceBreakSTerm, + SentenceBreakClose + }; + + +} + +QT_END_NAMESPACE + +#endif diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h new file mode 100644 index 0000000..e2f60ed --- /dev/null +++ b/src/corelib/tools/qvarlengtharray.h @@ -0,0 +1,238 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVARLENGTHARRAY_H +#define QVARLENGTHARRAY_H + +#include <QtCore/qcontainerfwd.h> +#include <QtCore/qglobal.h> +#include <new> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +// Prealloc = 256 by default, specified in qcontainerfwd.h +template<class T, int Prealloc> +class QVarLengthArray +{ +public: + inline explicit QVarLengthArray(int size = 0); + + inline QVarLengthArray(const QVarLengthArray<T, Prealloc> &other) + : a(Prealloc), s(0), ptr(reinterpret_cast<T *>(array)) + { + append(other.constData(), other.size()); + } + + inline ~QVarLengthArray() { + if (QTypeInfo<T>::isComplex) { + T *i = ptr + s; + while (i-- != ptr) + i->~T(); + } + if (ptr != reinterpret_cast<T *>(array)) + qFree(ptr); + } + inline QVarLengthArray<T, Prealloc> &operator=(const QVarLengthArray<T, Prealloc> &other) + { + if (this != &other) { + clear(); + append(other.constData(), other.size()); + } + return *this; + } + + inline void removeLast() { + Q_ASSERT(s > 0); + realloc(s - 1, a); + } + inline int size() const { return s; } + inline int count() const { return s; } + inline bool isEmpty() const { return (s == 0); } + inline void resize(int size); + inline void clear() { resize(0); } + + inline int capacity() const { return a; } + inline void reserve(int size); + + inline T &operator[](int idx) { + Q_ASSERT(idx >= 0 && idx < s); + return ptr[idx]; + } + inline const T &operator[](int idx) const { + Q_ASSERT(idx >= 0 && idx < s); + return ptr[idx]; + } + + inline void append(const T &t) { + if (s == a) // i.e. s != 0 + realloc(s, s<<1); + const int idx = s++; + if (QTypeInfo<T>::isComplex) { + new (ptr + idx) T(t); + } else { + ptr[idx] = t; + } + } + void append(const T *buf, int size); + + inline T *data() { return ptr; } + inline const T *data() const { return ptr; } + inline const T * constData() const { return ptr; } + +private: + void realloc(int size, int alloc); + + int a; + int s; + T *ptr; + union { + // ### Qt 5: Use 'Prealloc * sizeof(T)' as array size + char array[sizeof(qint64) * (((Prealloc * sizeof(T)) / sizeof(qint64)) + 1)]; + qint64 q_for_alignment_1; + double q_for_alignment_2; + }; +}; + +template <class T, int Prealloc> +Q_INLINE_TEMPLATE QVarLengthArray<T, Prealloc>::QVarLengthArray(int asize) + : s(asize) { + if (s > Prealloc) { + ptr = reinterpret_cast<T *>(qMalloc(s * sizeof(T))); + a = s; + } else { + ptr = reinterpret_cast<T *>(array); + a = Prealloc; + } + if (QTypeInfo<T>::isComplex) { + T *i = ptr + s; + while (i != ptr) + new (--i) T; + } +} + +template <class T, int Prealloc> +Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::resize(int asize) +{ realloc(asize, qMax(asize, a)); } + +template <class T, int Prealloc> +Q_INLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::reserve(int asize) +{ if (asize > a) realloc(s, asize); } + +template <class T, int Prealloc> +Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::append(const T *abuf, int asize) +{ + Q_ASSERT(abuf); + if (asize <= 0) + return; + + const int idx = s; + const int news = s + asize; + if (news >= a) + realloc(s, qMax(s<<1, news)); + s = news; + + if (QTypeInfo<T>::isComplex) { + T *i = ptr + idx; + T *j = i + asize; + while (i < j) + new (i++) T(*abuf++); + } else { + qMemCopy(&ptr[idx], abuf, asize * sizeof(T)); + } +} + +template <class T, int Prealloc> +Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::realloc(int asize, int aalloc) +{ + Q_ASSERT(aalloc >= asize); + T *oldPtr = ptr; + int osize = s; + s = asize; + + if (aalloc != a) { + ptr = reinterpret_cast<T *>(qMalloc(aalloc * sizeof(T))); + if (ptr) { + a = aalloc; + + if (QTypeInfo<T>::isStatic) { + T *i = ptr + osize; + T *j = oldPtr + osize; + while (i != ptr) { + new (--i) T(*--j); + j->~T(); + } + } else { + qMemCopy(ptr, oldPtr, osize * sizeof(T)); + } + } else { + ptr = oldPtr; + s = 0; + asize = 0; + } + } + + if (QTypeInfo<T>::isComplex) { + if (asize < osize) { + T *i = oldPtr + osize; + T *j = oldPtr + asize; + while (i-- != j) + i->~T(); + } else { + T *i = ptr + asize; + T *j = ptr + osize; + while (i != j) + new (--i) T; + } + } + + if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr) + qFree(oldPtr); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QVARLENGTHARRAY_H diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp new file mode 100644 index 0000000..6b26b2e --- /dev/null +++ b/src/corelib/tools/qvector.cpp @@ -0,0 +1,968 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qvector.h" +#include "qtools_p.h" +#include <string.h> + +QT_BEGIN_NAMESPACE + +QVectorData QVectorData::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0, true, false }; + +QVectorData *QVectorData::malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init) +{ + QVectorData* p = (QVectorData *)qMalloc(sizeofTypedData + (size - 1) * sizeofT); + ::memcpy(p, init, sizeofTypedData + (qMin(size, init->alloc) - 1) * sizeofT); + return p; +} + +int QVectorData::grow(int sizeofTypedData, int size, int sizeofT, bool excessive) +{ + if (excessive) + return size + size / 2; + return qAllocMore(size * sizeofT, sizeofTypedData - sizeofT) / sizeofT; +} + +/*! + \class QVector + \brief The QVector class is a template class that provides a dynamic array. + + \ingroup tools + \ingroup shared + \mainclass + \reentrant + + QVector\<T\> is one of Qt's generic \l{container classes}. It + stores its items in adjacent memory locations and provides fast + index-based access. + + QList\<T\>, QLinkedList\<T\>, and QVarLengthArray\<T\> provide + similar functionality. Here's an overview: + + \list + \i For most purposes, QList is the right class to use. Operations + like prepend() and insert() are usually faster than with + QVector because of the way QList stores its items in memory + (see \l{Algorithmic Complexity} for details), + and its index-based API is more convenient than QLinkedList's + iterator-based API. It also expands to less code in your + executable. + \i If you need a real linked list, with guarantees of \l{constant + time} insertions in the middle of the list and iterators to + items rather than indexes, use QLinkedList. + \i If you want the items to occupy adjacent memory positions, or + if your items are larger than a pointer and you want to avoid + the overhead of allocating them on the heap individually at + insertion time, then use QVector. + \i If you want a low-level variable-size array, QVarLengthArray + may be sufficient. + \endlist + + Here's an example of a QVector that stores integers and a QVector + that stores QString values: + + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 0 + + QVector stores a vector (or array) of items. Typically, vectors + are created with an initial size. For example, the following code + constructs a QVector with 200 elements: + + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 1 + + The elements are automatically initialized with a + \l{default-constructed value}. If you want to initialize the + vector with a different value, pass that value as the second + argument to the constructor: + + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 2 + + You can also call fill() at any time to fill the vector with a + value. + + QVector uses 0-based indexes, just like C++ arrays. To access the + item at a particular index position, you can use operator[](). On + non-const vectors, operator[]() returns a reference to the item + that can be used on the left side of an assignment: + + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 3 + + For read-only access, an alternative syntax is to use at(): + + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 4 + + at() can be faster than operator[](), because it never causes a + \l{deep copy} to occur. + + Another way to access the data stored in a QVector is to call + data(). The function returns a pointer to the first item in the + vector. You can use the pointer to directly access and modify the + elements stored in the vector. The pointer is also useful if you + need to pass a QVector to a function that accepts a plain C++ + array. + + If you want to find all occurrences of a particular value in a + vector, use indexOf() or lastIndexOf(). The former searches + forward starting from a given index position, the latter searches + backward. Both return the index of the matching item if they found + one; otherwise, they return -1. For example: + + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 5 + + If you simply want to check whether a vector contains a + particular value, use contains(). If you want to find out how + many times a particular value occurs in the vector, use count(). + + QVector provides these basic functions to add, move, and remove + items: insert(), replace(), remove(), prepend(), append(). With + the exception of append() and replace(), these functions can be slow + (\l{linear time}) for large vectors, because they require moving many + items in the vector by one position in memory. If you want a container + class that provides fast insertion/removal in the middle, use + QList or QLinkedList instead. + + Unlike plain C++ arrays, QVectors can be resized at any time by + calling resize(). If the new size is larger than the old size, + QVector might need to reallocate the whole vector. QVector tries + to reduce the number of reallocations by preallocating up to twice + as much memory as the actual data needs. + + If you know in advance approximately how many items the QVector + will contain, you can call reserve(), asking QVector to + preallocate a certain amount of memory. You can also call + capacity() to find out how much memory QVector actually + allocated. + + Note that using non-const operators and functions can cause + QVector to do a deep copy of the data. This is due to \l{implicit sharing}. + + QVector's value type must be an \l{assignable data type}. This + covers most data types that are commonly used, but the compiler + won't let you, for example, store a QWidget as a value; instead, + store a QWidget *. A few functions have additional requirements; + for example, indexOf() and lastIndexOf() expect the value type to + support \c operator==(). These requirements are documented on a + per-function basis. + + Like the other container classes, QVector provides \l{Java-style + iterators} (QVectorIterator and QMutableVectorIterator) and + \l{STL-style iterators} (QVector::const_iterator and + QVector::iterator). In practice, these are rarely used, because + you can use indexes into the QVector. + + In addition to QVector, Qt also provides QVarLengthArray, a very + low-level class with little functionality that is optimized for + speed. + + QVector does \e not support inserting, prepending, appending or replacing + with references to its own values. Doing so will cause your application to + abort with an error message. + + \sa QVectorIterator, QMutableVectorIterator, QList, QLinkedList +*/ + +/*! + \fn QVector<T> QVector::mid(int pos, int length = -1) const + + Returns a vector whose elements are copied from this vector, + starting at position \a pos. If \a length is -1 (the default), all + elements after \a pos are copied; otherwise \a length elements (or + all remaining elements if there are less than \a length elements) + are copied. +*/ + + +/*! \fn QVector::QVector() + + Constructs an empty vector. + + \sa resize() +*/ + +/*! \fn QVector::QVector(int size) + + Constructs a vector with an initial size of \a size elements. + + The elements are initialized with a \l{default-constructed + value}. + + \sa resize() +*/ + +/*! \fn QVector::QVector(int size, const T &value) + + Constructs a vector with an initial size of \a size elements. + Each element is initialized with \a value. + + \sa resize(), fill() +*/ + +/*! \fn QVector::QVector(const QVector<T> &other) + + Constructs a copy of \a other. + + This operation takes \l{constant time}, because QVector is + \l{implicitly shared}. This makes returning a QVector from a + function very fast. If a shared instance is modified, it will be + copied (copy-on-write), and that takes \l{linear time}. + + \sa operator=() +*/ + +/*! \fn QVector::~QVector() + + Destroys the vector. +*/ + +/*! \fn QVector<T> &QVector::operator=(const QVector<T> &other) + + Assigns \a other to this vector and returns a reference to this + vector. +*/ + +/*! \fn bool QVector::operator==(const QVector<T> &other) const + + Returns true if \a other is equal to this vector; otherwise + returns false. + + Two vectors are considered equal if they contain the same values + in the same order. + + This function requires the value type to have an implementation + of \c operator==(). + + \sa operator!=() +*/ + +/*! \fn bool QVector::operator!=(const QVector<T> &other) const + + Returns true if \a other is not equal to this vector; otherwise + returns false. + + Two vectors are considered equal if they contain the same values + in the same order. + + This function requires the value type to have an implementation + of \c operator==(). + + \sa operator==() +*/ + +/*! \fn int QVector::size() const + + Returns the number of items in the vector. + + \sa isEmpty(), resize() +*/ + +/*! \fn bool QVector::isEmpty() const + + Returns true if the vector has size 0; otherwise returns false. + + \sa size(), resize() +*/ + +/*! \fn void QVector::resize(int size) + + Sets the size of the vector to \a size. If \a size is greater than the + current size, elements are added to the end; the new elements are + initialized with a \l{default-constructed value}. If \a size is less + than the current size, elements are removed from the end. + + \sa size() +*/ + +/*! \fn int QVector::capacity() const + + Returns the maximum number of items that can be stored in the + vector without forcing a reallocation. + + The sole purpose of this function is to provide a means of fine + tuning QVector's memory usage. In general, you will rarely ever + need to call this function. If you want to know how many items are + in the vector, call size(). + + \sa reserve(), squeeze() +*/ + +/*! \fn void QVector::reserve(int size) + + Attempts to allocate memory for at least \a size elements. If you + know in advance how large the vector will be, you can call this + function, and if you call resize() often you are likely to get + better performance. If \a size is an underestimate, the worst + that will happen is that the QVector will be a bit slower. + + The sole purpose of this function is to provide a means of fine + tuning QVector's memory usage. In general, you will rarely ever + need to call this function. If you want to change the size of the + vector, call resize(). + + \sa squeeze(), capacity() +*/ + +/*! \fn void QVector::squeeze() + + Releases any memory not required to store the items. + + The sole purpose of this function is to provide a means of fine + tuning QVector's memory usage. In general, you will rarely ever + need to call this function. + + \sa reserve(), capacity() +*/ + +/*! \fn void QVector::detach() + + \internal +*/ + +/*! \fn bool QVector::isDetached() const + + \internal +*/ + +/*! \fn void QVector::setSharable(bool sharable) + + \internal +*/ + +/*! \fn T *QVector::data() + + Returns a pointer to the data stored in the vector. The pointer + can be used to access and modify the items in the vector. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 6 + + The pointer remains valid as long as the vector isn't + reallocated. + + This function is mostly useful to pass a vector to a function + that accepts a plain C++ array. + + \sa constData(), operator[]() +*/ + +/*! \fn const T *QVector::data() const + + \overload +*/ + +/*! \fn const T *QVector::constData() const + + Returns a const pointer to the data stored in the vector. The + pointer can be used to access the items in the vector. + The pointer remains valid as long as the vector isn't + reallocated. + + This function is mostly useful to pass a vector to a function + that accepts a plain C++ array. + + \sa data(), operator[]() +*/ + +/*! \fn void QVector::clear() + + Removes all the elements from the vector and releases the memory used by + the vector. +*/ + +/*! \fn const T &QVector::at(int i) const + + Returns the item at index position \a i in the vector. + + \a i must be a valid index position in the vector (i.e., 0 <= \a + i < size()). + + \sa value(), operator[]() +*/ + +/*! \fn T &QVector::operator[](int i) + + Returns the item at index position \a i as a modifiable reference. + + \a i must be a valid index position in the vector (i.e., 0 <= \a i + < size()). + + Note that using non-const operators can cause QVector to do a deep + copy. + + \sa at(), value() +*/ + +/*! \fn const T &QVector::operator[](int i) const + + \overload + + Same as at(\a i). +*/ + +/*! + \fn void QVector::append(const T &value) + + Inserts \a value at the end of the vector. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 7 + + This is the same as calling resize(size() + 1) and assigning \a + value to the new last element in the vector. + + This operation is relatively fast, because QVector typically + allocates more memory than necessary, so it can grow without + reallocating the entire vector each time. + + \sa operator<<(), prepend(), insert() +*/ + +/*! \fn void QVector::prepend(const T &value) + + Inserts \a value at the beginning of the vector. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 8 + + This is the same as vector.insert(0, \a value). + + For large vectors, this operation can be slow (\l{linear time}), + because it requires moving all the items in the vector by one + position further in memory. If you want a container class that + provides a fast prepend() function, use QList or QLinkedList + instead. + + \sa append(), insert() +*/ + +/*! \fn void QVector::insert(int i, const T &value) + + Inserts \a value at index position \a i in the vector. If \a i is + 0, the value is prepended to the vector. If \a i is size(), the + value is appended to the vector. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 9 + + For large vectors, this operation can be slow (\l{linear time}), + because it requires moving all the items at indexes \a i and + above by one position further in memory. If you want a container + class that provides a fast insert() function, use QLinkedList + instead. + + \sa append(), prepend(), remove() +*/ + +/*! \fn void QVector::insert(int i, int count, const T &value) + + \overload + + Inserts \a count copies of \a value at index position \a i in the + vector. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 10 +*/ + +/*! \fn QVector::iterator QVector::insert(iterator before, const T &value) + + \overload + + Inserts \a value in front of the item pointed to by the iterator + \a before. Returns an iterator pointing at the inserted item. +*/ + +/*! \fn QVector::iterator QVector::insert(iterator before, int count, const T &value) + + Inserts \a count copies of \a value in front of the item pointed to + by the iterator \a before. Returns an iterator pointing at the + first of the inserted items. +*/ + +/*! \fn void QVector::replace(int i, const T &value) + + Replaces the item at index position \a i with \a value. + + \a i must be a valid index position in the vector (i.e., 0 <= \a + i < size()). + + \sa operator[](), remove() +*/ + +/*! \fn void QVector::remove(int i) + + \overload + + Removes the element at index position \a i. + + \sa insert(), replace(), fill() +*/ + +/*! \fn void QVector::remove(int i, int count) + + \overload + + Removes \a count elements from the middle of the vector, starting at + index position \a i. + + \sa insert(), replace(), fill() +*/ + +/*! \fn QVector &QVector::fill(const T &value, int size = -1) + + Assigns \a value to all items in the vector. If \a size is + different from -1 (the default), the vector is resized to size \a + size beforehand. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 11 + + \sa resize() +*/ + +/*! \fn int QVector::indexOf(const T &value, int from = 0) const + + Returns the index position of the first occurrence of \a value in + the vector, searching forward from index position \a from. + Returns -1 if no item matched. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 12 + + This function requires the value type to have an implementation of + \c operator==(). + + \sa lastIndexOf(), contains() +*/ + +/*! \fn int QVector::lastIndexOf(const T &value, int from = -1) const + + Returns the index position of the last occurrence of the value \a + value in the vector, searching backward from index position \a + from. If \a from is -1 (the default), the search starts at the + last item. Returns -1 if no item matched. + + Example: + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 13 + + This function requires the value type to have an implementation of + \c operator==(). + + \sa indexOf() +*/ + +/*! \fn bool QVector::contains(const T &value) const + + Returns true if the vector contains an occurrence of \a value; + otherwise returns false. + + This function requires the value type to have an implementation of + \c operator==(). + + \sa indexOf(), count() +*/ + +/*! \fn bool QVector::startsWith(const T &value) const + \since 4.5 + + Returns true if this vector is not empty and its first + item is equal to \a value; otherwise returns false. + + \sa isEmpty(), first() +*/ + +/*! \fn bool QVector::endsWith(const T &value) const + \since 4.5 + + Returns true if this vector is not empty and its last + item is equal to \a value; otherwise returns false. + + \sa isEmpty(), last() +*/ + + +/*! \fn int QVector::count(const T &value) const + + Returns the number of occurrences of \a value in the vector. + + This function requires the value type to have an implementation of + \c operator==(). + + \sa contains(), indexOf() +*/ + +/*! \fn int QVector::count() const + + \overload + + Same as size(). +*/ + +/*! \fn QVector::iterator QVector::begin() + + Returns an \l{STL-style iterator} pointing to the first item in + the vector. + + \sa constBegin(), end() +*/ + +/*! \fn QVector::const_iterator QVector::begin() const + + \overload +*/ + +/*! \fn QVector::const_iterator QVector::constBegin() const + + Returns a const \l{STL-style iterator} pointing to the first item + in the vector. + + \sa begin(), constEnd() +*/ + +/*! \fn QVector::iterator QVector::end() + + Returns an \l{STL-style iterator} pointing to the imaginary item + after the last item in the vector. + + \sa begin(), constEnd() +*/ + +/*! \fn QVector::const_iterator QVector::end() const + + \overload +*/ + +/*! \fn QVector::const_iterator QVector::constEnd() const + + Returns a const \l{STL-style iterator} pointing to the imaginary + item after the last item in the vector. + + \sa constBegin(), end() +*/ + +/*! \fn QVector::iterator QVector::erase(iterator pos) + + Removes the item pointed to by the iterator \a pos from the + vector, and returns an iterator to the next item in the vector + (which may be end()). + + \sa insert(), remove() +*/ + +/*! \fn QVector::iterator QVector::erase(iterator begin, iterator end) + + \overload + + Removes all the items from \a begin up to (but not including) \a + end. Returns an iterator to the same item that \a end referred to + before the call. +*/ + +/*! \fn T& QVector::first() + + Returns a reference to the first item in the vector. This + function assumes that the vector isn't empty. + + \sa last(), isEmpty() +*/ + +/*! \fn const T& QVector::first() const + + \overload +*/ + +/*! \fn T& QVector::last() + + Returns a reference to the last item in the vector. This function + assumes that the vector isn't empty. + + \sa first(), isEmpty() +*/ + +/*! \fn const T& QVector::last() const + + \overload +*/ + +/*! \fn T QVector::value(int i) const + + Returns the value at index position \a i in the vector. + + If the index \a i is out of bounds, the function returns + a \l{default-constructed value}. If you are certain that + \a i is within bounds, you can use at() instead, which is slightly + faster. + + \sa at(), operator[]() +*/ + +/*! \fn T QVector::value(int i, const T &defaultValue) const + + \overload + + If the index \a i is out of bounds, the function returns + \a defaultValue. +*/ + +/*! \fn void QVector::push_back(const T &value) + + This function is provided for STL compatibility. It is equivalent + to append(\a value). +*/ + +/*! \fn void QVector::push_front(const T &value) + + This function is provided for STL compatibility. It is equivalent + to prepend(\a value). +*/ + +/*! \fn void QVector::pop_front() + + This function is provided for STL compatibility. It is equivalent + to erase(begin()). +*/ + +/*! \fn void QVector::pop_back() + + This function is provided for STL compatibility. It is equivalent + to erase(end() - 1). +*/ + +/*! \fn T& QVector::front() + + This function is provided for STL compatibility. It is equivalent + to first(). +*/ + +/*! \fn QVector::const_reference QVector::front() const + + \overload +*/ + +/*! \fn QVector::reference QVector::back() + + This function is provided for STL compatibility. It is equivalent + to last(). +*/ + +/*! \fn QVector::const_reference QVector::back() const + + \overload +*/ + +/*! \fn bool QVector::empty() const + + This function is provided for STL compatibility. It is equivalent + to isEmpty(), returning true if the vector is empty; otherwise + returns false. +*/ + +/*! \fn QVector<T> &QVector::operator+=(const QVector<T> &other) + + Appends the items of the \a other vector to this vector and + returns a reference to this vector. + + \sa operator+(), append() +*/ + +/*! \fn void QVector::operator+=(const T &value) + + \overload + + Appends \a value to the vector. + + \sa append(), operator<<() +*/ + +/*! \fn QVector<T> QVector::operator+(const QVector<T> &other) const + + Returns a vector that contains all the items in this vector + followed by all the items in the \a other vector. + + \sa operator+=() +*/ + +/*! \fn QVector<T> &QVector::operator<<(const T &value) + + Appends \a value to the vector and returns a reference to this + vector. + + \sa append(), operator+=() +*/ + +/*! \fn QVector<T> &QVector::operator<<(const QVector<T> &other) + + Appends \a other to the vector and returns a reference to the + vector. +*/ + +/*! \typedef QVector::iterator + + The QVector::iterator typedef provides an STL-style non-const + iterator for QVector and QStack. + + QVector provides both \l{STL-style iterators} and \l{Java-style + iterators}. The STL-style non-const iterator is simply a typedef + for "T *" (pointer to T). + + \sa QVector::begin(), QVector::end(), QVector::const_iterator, QMutableVectorIterator +*/ + +/*! \typedef QVector::const_iterator + + The QVector::const_iterator typedef provides an STL-style const + iterator for QVector and QStack. + + QVector provides both \l{STL-style iterators} and \l{Java-style + iterators}. The STL-style const iterator is simply a typedef for + "const T *" (pointer to const T). + + \sa QVector::constBegin(), QVector::constEnd(), QVector::iterator, QVectorIterator +*/ + +/*! \typedef QVector::Iterator + + Qt-style synonym for QVector::iterator. +*/ + +/*! \typedef QVector::ConstIterator + + Qt-style synonym for QVector::const_iterator. +*/ + +/*! \typedef QVector::const_pointer + + Typedef for const T *. Provided for STL compatibility. +*/ + +/*! \typedef QVector::const_reference + + Typedef for T &. Provided for STL compatibility. +*/ + +/*! \typedef QVector::difference_type + + Typedef for ptrdiff_t. Provided for STL compatibility. +*/ + +/*! \typedef QVector::pointer + + Typedef for T *. Provided for STL compatibility. +*/ + +/*! \typedef QVector::reference + + Typedef for T &. Provided for STL compatibility. +*/ + +/*! \typedef QVector::size_type + + Typedef for int. Provided for STL compatibility. +*/ + +/*! \typedef QVector::value_type + + Typedef for T. Provided for STL compatibility. +*/ + +/*! \fn QList<T> QVector<T>::toList() const + + Returns a QList object with the data contained in this QVector. + + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 14 + + \sa fromList(), QList::fromVector() +*/ + +/*! \fn QVector<T> QVector<T>::fromList(const QList<T> &list) + + Returns a QVector object with the data contained in \a list. + + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 15 + + \sa toList(), QList::toVector() +*/ + +/*! \fn QVector<T> QVector<T>::fromStdVector(const std::vector<T> &vector) + + Returns a QVector object with the data contained in \a vector. The + order of the elements in the QVector is the same as in \a vector. + + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 16 + + \sa toStdVector(), QList::fromStdList() +*/ + +/*! \fn std::vector<T> QVector<T>::toStdVector() const + + Returns a std::vector object with the data contained in this QVector. + Example: + + \snippet doc/src/snippets/code/src_corelib_tools_qvector.cpp 17 + + \sa fromStdVector(), QList::toStdList() +*/ + +/*! \fn QDataStream &operator<<(QDataStream &out, const QVector<T> &vector) + \relates QVector + + Writes the vector \a vector to stream \a out. + + This function requires the value type to implement \c operator<<(). + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +/*! \fn QDataStream &operator>>(QDataStream &in, QVector<T> &vector) + \relates QVector + + Reads a vector from stream \a in into \a vector. + + This function requires the value type to implement \c operator>>(). + + \sa \link datastreamformat.html Format of the QDataStream operators \endlink +*/ + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h new file mode 100644 index 0000000..6bea03b --- /dev/null +++ b/src/corelib/tools/qvector.h @@ -0,0 +1,776 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QVECTOR_H +#define QVECTOR_H + +#include <QtCore/qiterator.h> +#include <QtCore/qatomic.h> +#include <QtCore/qalgorithms.h> +#include <QtCore/qlist.h> + +#ifndef QT_NO_STL +#include <iterator> +#include <vector> +#endif +#include <stdlib.h> +#include <string.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +struct Q_CORE_EXPORT QVectorData +{ + QBasicAtomicInt ref; + int alloc; + int size; +#if defined(QT_ARCH_SPARC) && defined(Q_CC_GNU) && defined(__LP64__) && defined(QT_BOOTSTRAPPED) + // workaround for bug in gcc 3.4.2 + uint sharable; + uint capacity; +#else + uint sharable : 1; + uint capacity : 1; +#endif + + static QVectorData shared_null; + // ### Qt 5: rename to 'allocate()'. The current name causes problems for + // some debugges when the QVector is member of a class within an unnamed namespace. + static QVectorData *malloc(int sizeofTypedData, int size, int sizeofT, QVectorData *init); + static int grow(int sizeofTypedData, int size, int sizeofT, bool excessive); +}; + +template <typename T> +struct QVectorTypedData +{ + QBasicAtomicInt ref; + int alloc; + int size; +#if defined(QT_ARCH_SPARC) && defined(Q_CC_GNU) && defined(__LP64__) && defined(QT_BOOTSTRAPPED) + // workaround for bug in gcc 3.4.2 + uint sharable; + uint capacity; +#else + uint sharable : 1; + uint capacity : 1; +#endif + T array[1]; +}; + +template <typename T> +class QVector +{ + typedef QVectorTypedData<T> Data; + union { QVectorData *p; QVectorTypedData<T> *d; }; + +public: + inline QVector() : p(&QVectorData::shared_null) { d->ref.ref(); } + explicit QVector(int size); + QVector(int size, const T &t); + inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); } + inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(d); } + QVector<T> &operator=(const QVector<T> &v); + bool operator==(const QVector<T> &v) const; + inline bool operator!=(const QVector<T> &v) const { return !(*this == v); } + + inline int size() const { return d->size; } + + inline bool isEmpty() const { return d->size == 0; } + + void resize(int size); + + inline int capacity() const { return d->alloc; } + void reserve(int size); + inline void squeeze() { realloc(d->size, d->size); d->capacity = 0; } + + inline void detach() { if (d->ref != 1) detach_helper(); } + inline bool isDetached() const { return d->ref == 1; } + inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } + + inline T *data() { detach(); return d->array; } + inline const T *data() const { return d->array; } + inline const T *constData() const { return d->array; } + void clear(); + + const T &at(int i) const; + T &operator[](int i); + const T &operator[](int i) const; + void append(const T &t); + void prepend(const T &t); + void insert(int i, const T &t); + void insert(int i, int n, const T &t); + void replace(int i, const T &t); + void remove(int i); + void remove(int i, int n); + + QVector<T> &fill(const T &t, int size = -1); + + int indexOf(const T &t, int from = 0) const; + int lastIndexOf(const T &t, int from = -1) const; + bool contains(const T &t) const; + int count(const T &t) const; + +#ifdef QT_STRICT_ITERATORS + class iterator { + public: + T *i; + typedef std::random_access_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T *pointer; + typedef T &reference; + + inline iterator() : i(0) {} + inline iterator(T *n) : i(n) {} + inline iterator(const iterator &o): i(o.i){} + inline T &operator*() const { return *i; } + inline T *operator->() const { return i; } + inline T &operator[](int j) const { return *(i + j); } + inline bool operator==(const iterator &o) const { return i == o.i; } + inline bool operator!=(const iterator &o) const { return i != o.i; } + inline bool operator<(const iterator& other) const { return i < other.i; } + inline bool operator<=(const iterator& other) const { return i <= other.i; } + inline bool operator>(const iterator& other) const { return i > other.i; } + inline bool operator>=(const iterator& other) const { return i >= other.i; } + inline iterator &operator++() { ++i; return *this; } + inline iterator operator++(int) { T *n = i; ++i; return n; } + inline iterator &operator--() { i--; return *this; } + inline iterator operator--(int) { T *n = i; i--; return n; } + inline iterator &operator+=(int j) { i+=j; return *this; } + inline iterator &operator-=(int j) { i-=j; return *this; } + inline iterator operator+(int j) const { return iterator(i+j); } + inline iterator operator-(int j) const { return iterator(i-j); } + inline int operator-(iterator j) const { return i - j.i; } + }; + friend class iterator; + + class const_iterator { + public: + T *i; + typedef std::random_access_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef const T *pointer; + typedef const T &reference; + + inline const_iterator() : i(0) {} + inline const_iterator(T *n) : i(n) {} + inline const_iterator(const const_iterator &o): i(o.i) {} + inline explicit const_iterator(const iterator &o): i(o.i) {} + inline const T &operator*() const { return *i; } + inline const T *operator->() const { return i; } + inline const T &operator[](int j) const { return *(i + j); } + inline bool operator==(const const_iterator &o) const { return i == o.i; } + inline bool operator!=(const const_iterator &o) const { return i != o.i; } + inline bool operator<(const const_iterator& other) const { return i < other.i; } + inline bool operator<=(const const_iterator& other) const { return i <= other.i; } + inline bool operator>(const const_iterator& other) const { return i > other.i; } + inline bool operator>=(const const_iterator& other) const { return i >= other.i; } + inline const_iterator &operator++() { ++i; return *this; } + inline const_iterator operator++(int) { T *n = i; ++i; return n; } + inline const_iterator &operator--() { i--; return *this; } + inline const_iterator operator--(int) { T *n = i; i--; return n; } + inline const_iterator &operator+=(int j) { i+=j; return *this; } + inline const_iterator &operator-=(int j) { i+=j; return *this; } + inline const_iterator operator+(int j) const { return const_iterator(i+j); } + inline const_iterator operator-(int j) const { return const_iterator(i-j); } + inline int operator-(const_iterator j) const { return i - j.i; } + }; + friend class const_iterator; +#else + // STL-style + typedef T* iterator; + typedef const T* const_iterator; +#endif + inline iterator begin() { detach(); return d->array; } + inline const_iterator begin() const { return d->array; } + inline const_iterator constBegin() const { return d->array; } + inline iterator end() { detach(); return d->array + d->size; } + inline const_iterator end() const { return d->array + d->size; } + inline const_iterator constEnd() const { return d->array + d->size; } + iterator insert(iterator before, int n, const T &x); + inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); } + iterator erase(iterator begin, iterator end); + inline iterator erase(iterator pos) { return erase(pos, pos+1); } + + // more Qt + inline int count() const { return d->size; } + inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); } + inline const T &first() const { Q_ASSERT(!isEmpty()); return *begin(); } + inline T& last() { Q_ASSERT(!isEmpty()); return *(end()-1); } + inline const T &last() const { Q_ASSERT(!isEmpty()); return *(end()-1); } + inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; } + inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; } + QVector<T> mid(int pos, int length = -1) const; + + T value(int i) const; + T value(int i, const T &defaultValue) const; + + // STL compatibility + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; +#ifndef QT_NO_STL + typedef ptrdiff_t difference_type; +#else + typedef int difference_type; +#endif + typedef iterator Iterator; + typedef const_iterator ConstIterator; + typedef int size_type; + inline void push_back(const T &t) { append(t); } + inline void push_front(const T &t) { prepend(t); } + void pop_back() { Q_ASSERT(!isEmpty()); erase(end()-1); } + void pop_front() { Q_ASSERT(!isEmpty()); erase(begin()); } + inline bool empty() const + { return d->size == 0; } + inline T& front() { return first(); } + inline const_reference front() const { return first(); } + inline reference back() { return last(); } + inline const_reference back() const { return last(); } + + // comfort + QVector<T> &operator+=(const QVector<T> &l); + inline QVector<T> operator+(const QVector<T> &l) const + { QVector n = *this; n += l; return n; } + inline QVector<T> &operator+=(const T &t) + { append(t); return *this; } + inline QVector<T> &operator<< (const T &t) + { append(t); return *this; } + inline QVector<T> &operator<<(const QVector<T> &l) + { *this += l; return *this; } + + QList<T> toList() const; + + static QVector<T> fromList(const QList<T> &list); + +#ifndef QT_NO_STL + static inline QVector<T> fromStdVector(const std::vector<T> &vector) + { QVector<T> tmp; qCopy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; } + inline std::vector<T> toStdVector() const + { std::vector<T> tmp; qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; } +#endif + +private: + friend class QRegion; // Optimization for QRegion::rects() + + void detach_helper(); + QVectorData *malloc(int alloc); + void realloc(int size, int alloc); + void free(Data *d); + int sizeOfTypedData() { + // this is more or less the same as sizeof(Data), except that it doesn't + // count the padding at the end + return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this); + } +}; + +template <typename T> +void QVector<T>::detach_helper() +{ realloc(d->size, d->alloc); } +template <typename T> +void QVector<T>::reserve(int asize) +{ if (asize > d->alloc) realloc(d->size, asize); d->capacity = 1; } +template <typename T> +void QVector<T>::resize(int asize) +{ realloc(asize, (asize > d->alloc || (!d->capacity && asize < d->size && asize < (d->alloc >> 1))) ? + QVectorData::grow(sizeOfTypedData(), asize, sizeof(T), QTypeInfo<T>::isStatic) + : d->alloc); } +template <typename T> +inline void QVector<T>::clear() +{ *this = QVector<T>(); } +template <typename T> +inline const T &QVector<T>::at(int i) const +{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::at", "index out of range"); + return d->array[i]; } +template <typename T> +inline const T &QVector<T>::operator[](int i) const +{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range"); + return d->array[i]; } +template <typename T> +inline T &QVector<T>::operator[](int i) +{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range"); + return data()[i]; } +template <typename T> +inline void QVector<T>::insert(int i, const T &t) +{ Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range"); + insert(begin() + i, 1, t); } +template <typename T> +inline void QVector<T>::insert(int i, int n, const T &t) +{ Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range"); + insert(begin() + i, n, t); } +template <typename T> +inline void QVector<T>::remove(int i, int n) +{ Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= d->size, "QVector<T>::remove", "index out of range"); + erase(begin() + i, begin() + i + n); } +template <typename T> +inline void QVector<T>::remove(int i) +{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::remove", "index out of range"); + erase(begin() + i, begin() + i + 1); } +template <typename T> +inline void QVector<T>::prepend(const T &t) +{ insert(begin(), 1, t); } + +template <typename T> +inline void QVector<T>::replace(int i, const T &t) +{ + Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::replace", "index out of range"); + const T copy(t); + data()[i] = copy; +} + +template <typename T> +QVector<T> &QVector<T>::operator=(const QVector<T> &v) +{ + v.d->ref.ref(); + if (!d->ref.deref()) + free(d); + d = v.d; + if (!d->sharable) + detach_helper(); + return *this; +} + +template <typename T> +inline QVectorData *QVector<T>::malloc(int aalloc) +{ + return static_cast<QVectorData *>(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T))); +} + +template <typename T> +QVector<T>::QVector(int asize) +{ + p = malloc(asize); + d->ref = 1; + d->alloc = d->size = asize; + d->sharable = true; + d->capacity = false; + if (QTypeInfo<T>::isComplex) { + T* b = d->array; + T* i = d->array + d->size; + while (i != b) + new (--i) T; + } else { + qMemSet(d->array, 0, asize * sizeof(T)); + } +} + +template <typename T> +QVector<T>::QVector(int asize, const T &t) +{ + p = malloc(asize); + d->ref = 1; + d->alloc = d->size = asize; + d->sharable = true; + d->capacity = false; + T* i = d->array + d->size; + while (i != d->array) + new (--i) T(t); +} + +template <typename T> +void QVector<T>::free(Data *x) +{ + if (QTypeInfo<T>::isComplex) { + T* b = x->array; + T* i = b + x->size; + while (i-- != b) + i->~T(); + } + qFree(x); +} + +template <typename T> +void QVector<T>::realloc(int asize, int aalloc) +{ + T *j, *i, *b; + union { QVectorData *p; Data *d; } x; + x.d = d; + + if (QTypeInfo<T>::isComplex && aalloc == d->alloc && d->ref == 1) { + // pure resize + i = d->array + d->size; + j = d->array + asize; + if (i > j) { + while (i-- != j) + i->~T(); + } else { + while (j-- != i) + new (j) T; + } + d->size = asize; + return; + } + + if (aalloc != d->alloc || d->ref != 1) { + // (re)allocate memory + if (QTypeInfo<T>::isStatic) { + x.p = malloc(aalloc); + } else if (d->ref != 1) { + x.p = QVectorData::malloc(sizeOfTypedData(), aalloc, sizeof(T), p); + } else { + if (QTypeInfo<T>::isComplex) { + // call the destructor on all objects that need to be + // destroyed when shrinking + if (asize < d->size) { + j = d->array + asize; + i = d->array + d->size; + while (i-- != j) + i->~T(); + i = d->array + asize; + } + } + x.p = p = static_cast<QVectorData *>(qRealloc(p, sizeOfTypedData() + (aalloc - 1) * sizeof(T))); + } + x.d->ref = 1; + x.d->sharable = true; + x.d->capacity = d->capacity; + + } + if (QTypeInfo<T>::isComplex) { + if (asize < d->size) { + j = d->array + asize; + i = x.d->array + asize; + } else { + // construct all new objects when growing + i = x.d->array + asize; + j = x.d->array + d->size; + while (i != j) + new (--i) T; + j = d->array + d->size; + } + if (i != j) { + // copy objects from the old array into the new array + b = x.d->array; + while (i != b) + new (--i) T(*--j); + } + } else if (asize > d->size) { + // initialize newly allocated memory to 0 + qMemSet(x.d->array + d->size, 0, (asize - d->size) * sizeof(T)); + } + x.d->size = asize; + x.d->alloc = aalloc; + if (d != x.d) { + if (!d->ref.deref()) + free(d); + d = x.d; + } +} + +template<typename T> +Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i) const +{ + if (i < 0 || i >= p->size) { + return T(); + } + return d->array[i]; +} +template<typename T> +Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i, const T &defaultValue) const +{ + return ((i < 0 || i >= p->size) ? defaultValue : d->array[i]); +} + +template <typename T> +void QVector<T>::append(const T &t) +{ + if (d->ref != 1 || d->size + 1 > d->alloc) { + const T copy(t); + realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + 1, sizeof(T), + QTypeInfo<T>::isStatic)); + if (QTypeInfo<T>::isComplex) + new (d->array + d->size) T(copy); + else + d->array[d->size] = copy; + } else { + if (QTypeInfo<T>::isComplex) + new (d->array + d->size) T(t); + else + d->array[d->size] = t; + } + ++d->size; +} + +template <typename T> +Q_TYPENAME QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, const T &t) +{ + int offset = before - d->array; + if (n != 0) { + const T copy(t); + if (d->ref != 1 || d->size + n > d->alloc) + realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + n, sizeof(T), + QTypeInfo<T>::isStatic)); + if (QTypeInfo<T>::isStatic) { + T *b = d->array + d->size; + T *i = d->array + d->size + n; + while (i != b) + new (--i) T; + i = d->array + d->size; + T *j = i + n; + b = d->array + offset; + while (i != b) + *--j = *--i; + i = b+n; + while (i != b) + *--i = copy; + } else { + T *b = d->array + offset; + T *i = b + n; + memmove(i, b, (d->size - offset) * sizeof(T)); + while (i != b) + new (--i) T(copy); + } + d->size += n; + } + return d->array + offset; +} + +template <typename T> +Q_TYPENAME QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend) +{ + int f = abegin - d->array; + int l = aend - d->array; + int n = l - f; + detach(); + if (QTypeInfo<T>::isComplex) { + qCopy(d->array+l, d->array+d->size, d->array+f); + T *i = d->array+d->size; + T* b = d->array+d->size-n; + while (i != b) { + --i; + i->~T(); + } + } else { + memmove(d->array + f, d->array + l, (d->size-l)*sizeof(T)); + } + d->size -= n; + return d->array + f; +} + +template <typename T> +bool QVector<T>::operator==(const QVector<T> &v) const +{ + if (d->size != v.d->size) + return false; + if (d == v.d) + return true; + T* b = d->array; + T* i = b + d->size; + T* j = v.d->array + d->size; + while (i != b) + if (!(*--i == *--j)) + return false; + return true; +} + +template <typename T> +QVector<T> &QVector<T>::fill(const T &from, int asize) +{ + const T copy(from); + resize(asize < 0 ? d->size : asize); + if (d->size) { + T *i = d->array + d->size; + T *b = d->array; + while (i != b) + *--i = copy; + } + return *this; +} + +template <typename T> +QVector<T> &QVector<T>::operator+=(const QVector &l) +{ + int newSize = d->size + l.d->size; + realloc(d->size, newSize); + + T *w = d->array + newSize; + T *i = l.d->array + l.d->size; + T *b = l.d->array; + while (i != b) { + if (QTypeInfo<T>::isComplex) + new (--w) T(*--i); + else + *--w = *--i; + } + d->size = newSize; + return *this; +} + +template <typename T> +int QVector<T>::indexOf(const T &t, int from) const +{ + if (from < 0) + from = qMax(from + d->size, 0); + if (from < d->size) { + T* n = d->array + from - 1; + T* e = d->array + d->size; + while (++n != e) + if (*n == t) + return n - d->array; + } + return -1; +} + +template <typename T> +int QVector<T>::lastIndexOf(const T &t, int from) const +{ + if (from < 0) + from += d->size; + else if (from >= d->size) + from = d->size-1; + if (from >= 0) { + T* b = d->array; + T* n = d->array + from + 1; + while (n != b) { + if (*--n == t) + return n - b; + } + } + return -1; +} + +template <typename T> +bool QVector<T>::contains(const T &t) const +{ + T* b = d->array; + T* i = d->array + d->size; + while (i != b) + if (*--i == t) + return true; + return false; +} + +template <typename T> +int QVector<T>::count(const T &t) const +{ + int c = 0; + T* b = d->array; + T* i = d->array + d->size; + while (i != b) + if (*--i == t) + ++c; + return c; +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE QVector<T> QVector<T>::mid(int pos, int length) const +{ + if (length < 0) + length = size() - pos; + if (pos == 0 && length == size()) + return *this; + QVector<T> copy; + if (pos + length > size()) + length = size() - pos; + for (int i = pos; i < pos + length; ++i) + copy += at(i); + return copy; +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE QList<T> QVector<T>::toList() const +{ + QList<T> result; + for (int i = 0; i < size(); ++i) + result.append(at(i)); + return result; +} + +template <typename T> +Q_OUTOFLINE_TEMPLATE QVector<T> QList<T>::toVector() const +{ + QVector<T> result(size()); + for (int i = 0; i < size(); ++i) + result[i] = at(i); + return result; +} + +template <typename T> +QVector<T> QVector<T>::fromList(const QList<T> &list) +{ + return list.toVector(); +} + +template <typename T> +QList<T> QList<T>::fromVector(const QVector<T> &vector) +{ + return vector.toList(); +} + +Q_DECLARE_SEQUENTIAL_ITERATOR(Vector) +Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(Vector) + +/* + ### Qt 5: + ### This needs to be removed for next releases of Qt. It is a workaround for vc++ because + ### Qt exports QPolygon and QPolygonF that inherit QVector<QPoint> and + ### QVector<QPointF> respectively. +*/ + +#ifdef Q_CC_MSVC +QT_BEGIN_INCLUDE_NAMESPACE +#include <QtCore/QPointF> +#include <QtCore/QPoint> +QT_END_INCLUDE_NAMESPACE + +#if defined(QT_BUILD_CORE_LIB) +#define Q_TEMPLATE_EXTERN +#else +#define Q_TEMPLATE_EXTERN extern +#endif +# pragma warning(push) /* MSVC 6.0 doesn't care about the disabling in qglobal.h (why?), so do it here */ +# pragma warning(disable: 4231) /* nonstandard extension used : 'extern' before template explicit instantiation */ +Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPointF>; +Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPoint>; +# pragma warning(pop) +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QVECTOR_H diff --git a/src/corelib/tools/qvsnprintf.cpp b/src/corelib/tools/qvsnprintf.cpp new file mode 100644 index 0000000..31b8632 --- /dev/null +++ b/src/corelib/tools/qvsnprintf.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformdefs.h" + +#include "qbytearray.h" +#include "qstring.h" + +#include "string.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_VSNPRINTF + +/*! + \relates QByteArray + + A portable \c vsnprintf() function. Will call \c ::vsnprintf(), \c + ::_vsnprintf(), or \c ::vsnprintf_s depending on the system, or + fall back to an internal version. + + \a fmt is the \c printf() format string. The result is put into + \a str, which is a buffer of at least \a n bytes. + + The caller is responsible to call \c va_end() on \a ap. + + \warning Since vsnprintf() shows different behavior on certain + platforms, you should not rely on the return value or on the fact + that you will always get a 0 terminated string back. + + Ideally, you should never call this function but use QString::sprintf() + instead. + + \sa qsnprintf(), QString::sprintf() +*/ + +int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap) +{ + if (!str || !fmt) + return -1; + + QString buf; + buf.vsprintf(fmt, ap); + + QByteArray ba = buf.toLocal8Bit(); + + if (n > 0) { + size_t blen = qMin(size_t(ba.length()), size_t(n - 1)); + memcpy(str, ba.constData(), blen); + str[blen] = '\0'; // make sure str is always 0 terminated + } + + return ba.length(); +} + +#else + +QT_BEGIN_INCLUDE_NAMESPACE +#include <stdio.h> +QT_END_INCLUDE_NAMESPACE + +int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap) +{ + return QT_VSNPRINTF(str, n, fmt, ap); +} + +#endif + +/*! + \relates QByteArray + + A portable snprintf() function, calls qvsnprintf. + + \a fmt is the \c printf() format string. The result is put into + \a str, which is a buffer of at least \a n bytes. + + \warning Call this function only when you know what you are doing + since it shows different behavior on certain platforms. + Use QString::sprintf() to format a string instead. + + \sa qvsnprintf(), QString::sprintf() +*/ + +int qsnprintf(char *str, size_t n, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + int ret = qvsnprintf(str, n, fmt, ap); + va_end(ap); + + return ret; +} + +QT_END_NAMESPACE diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri new file mode 100644 index 0000000..e5bf7e4 --- /dev/null +++ b/src/corelib/tools/tools.pri @@ -0,0 +1,104 @@ +# Qt tools module + +HEADERS += \ + tools/qalgorithms.h \ + tools/qbitarray.h \ + tools/qbytearray.h \ + tools/qbytearraymatcher.h \ + tools/qcache.h \ + tools/qchar.h \ + tools/qcontainerfwd.h \ + tools/qcryptographichash.h \ + tools/qdatetime.h \ + tools/qdatetime_p.h \ + tools/qhash.h \ + tools/qline.h \ + tools/qlinkedlist.h \ + tools/qlist.h \ + tools/qlocale.h \ + tools/qlocale_p.h \ + tools/qlocale_data_p.h \ + tools/qmap.h \ + tools/qpodlist_p.h \ + tools/qpoint.h \ + tools/qqueue.h \ + tools/qrect.h \ + tools/qregexp.h \ + tools/qringbuffer_p.h \ + tools/qshareddata.h \ + tools/qset.h \ + tools/qsize.h \ + tools/qstack.h \ + tools/qstring.h \ + tools/qstringlist.h \ + tools/qstringmatcher.h \ + tools/qtextboundaryfinder.h \ + tools/qtimeline.h \ + tools/qunicodetables_p.h \ + tools/qvarlengtharray.h \ + tools/qvector.h + + +SOURCES += \ + tools/qbitarray.cpp \ + tools/qbytearray.cpp \ + tools/qbytearraymatcher.cpp \ + tools/qcryptographichash.cpp \ + tools/qdatetime.cpp \ + tools/qdumper.cpp \ + tools/qhash.cpp \ + tools/qline.cpp \ + tools/qlinkedlist.cpp \ + tools/qlistdata.cpp \ + tools/qlocale.cpp \ + tools/qpoint.cpp \ + tools/qmap.cpp \ + tools/qrect.cpp \ + tools/qregexp.cpp \ + tools/qshareddata.cpp \ + tools/qsharedpointer.cpp \ + tools/qsize.cpp \ + tools/qstring.cpp \ + tools/qstringlist.cpp \ + tools/qtextboundaryfinder.cpp \ + tools/qtimeline.cpp \ + tools/qvector.cpp \ + tools/qvsnprintf.cpp + + +#zlib support +contains(QT_CONFIG, zlib) { + wince*: DEFINES += NO_ERRNO_H + INCLUDEPATH += ../3rdparty/zlib + SOURCES+= \ + ../3rdparty/zlib/adler32.c \ + ../3rdparty/zlib/compress.c \ + ../3rdparty/zlib/crc32.c \ + ../3rdparty/zlib/deflate.c \ + ../3rdparty/zlib/gzio.c \ + ../3rdparty/zlib/inffast.c \ + ../3rdparty/zlib/inflate.c \ + ../3rdparty/zlib/inftrees.c \ + ../3rdparty/zlib/trees.c \ + ../3rdparty/zlib/uncompr.c \ + ../3rdparty/zlib/zutil.c +} else:!contains(QT_CONFIG, no-zlib) { + unix:LIBS += -lz +# win32:LIBS += libz.lib +} + +DEFINES += HB_EXPORT=Q_CORE_EXPORT +INCLUDEPATH += ../3rdparty/harfbuzz/src +HEADERS += ../3rdparty/harfbuzz/src/harfbuzz.h +SOURCES += ../3rdparty/harfbuzz/src/harfbuzz-buffer.c \ + ../3rdparty/harfbuzz/src/harfbuzz-gdef.c \ + ../3rdparty/harfbuzz/src/harfbuzz-gsub.c \ + ../3rdparty/harfbuzz/src/harfbuzz-gpos.c \ + ../3rdparty/harfbuzz/src/harfbuzz-impl.c \ + ../3rdparty/harfbuzz/src/harfbuzz-open.c \ + ../3rdparty/harfbuzz/src/harfbuzz-stream.c \ + ../3rdparty/harfbuzz/src/harfbuzz-shaper-all.cpp \ + tools/qharfbuzz.cpp +HEADERS += tools/qharfbuzz_p.h + +!macx-icc:unix:LIBS += -lm |