?? qtranslator.cpp
字號:
int k = fname.lastIndexOf(delims[i]); if (k > rightmost) rightmost = k; } // no truncations? fail if (rightmost == 0) return false; fname.truncate(rightmost); } // realname is now the fully qualified name of a readable file. bool ok = false;#ifdef QT_USE_MMAP#ifndef MAP_FILE#define MAP_FILE 0#endif#ifndef MAP_FAILED#define MAP_FAILED -1#endif int fd = -1; if (!realname.startsWith(QLatin1Char(':'))) fd = QT_OPEN(QFile::encodeName(realname), O_RDONLY,#if defined(Q_OS_WIN) _S_IREAD | _S_IWRITE#else 0666#endif ); if (fd >= 0) { struct stat st; if (!fstat(fd, &st)) { char *ptr; ptr = reinterpret_cast<char *>( mmap(0, st.st_size, // any address, whole file PROT_READ, // read-only memory MAP_FILE | MAP_PRIVATE, // swap-backed map from file fd, 0)); // from offset 0 of fd if (ptr && ptr != reinterpret_cast<char *>(MAP_FAILED)) { d->used_mmap = true; d->unmapPointer = ptr; d->unmapLength = st.st_size; ok = true; } } ::close(fd); }#endif // QT_USE_MMAP if (!ok) { QFile file(realname); d->unmapLength = file.size(); if (!d->unmapLength) return false; d->unmapPointer = new char[d->unmapLength]; if (file.open(QIODevice::ReadOnly)) ok = (d->unmapLength == (uint)file.read(d->unmapPointer, d->unmapLength)); if (!ok) { delete [] d->unmapPointer; d->unmapPointer = 0; d->unmapLength = 0; return false; } } return d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength);}/*! \overload \fn bool QTranslator::load(const uchar *data, int len) Loads the .qm file data \a data of length \a len into the translator. The data is not copied. The caller must be able to guarantee that \a data will not be deleted or modified.*/bool QTranslator::load(const uchar *data, int len){ Q_D(QTranslator); d->clear(); return d->do_load(data, len);}static quint8 read8(const uchar *data){ return *data;}static quint16 read16(const uchar *data){ return (data[0] << 8) | (data[1]);}static quint32 read32(const uchar *data){ return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3]);}bool QTranslatorPrivate::do_load(const uchar *data, int len){ if (!data || len < MagicLength || memcmp(data, magic, MagicLength) != 0) return false; bool ok = true; const uchar *end = data + len; data += MagicLength; while (data < end - 4) { quint8 tag = read8(data++); quint32 blockLen = read32(data); data += 4; if (!tag || !blockLen) break; if (data + blockLen > end) { ok = false; break; } if (tag == QTranslatorPrivate::Contexts) { contextArray = data; contextLength = blockLen; } else if (tag == QTranslatorPrivate::Hashes) { offsetArray = data; offsetLength = blockLen; } else if (tag == QTranslatorPrivate::Messages) { messageArray = data; messageLength = blockLen; } else if (tag == QTranslatorPrivate::NumerusRules) { numerusRulesArray = data; numerusRulesLength = blockLen; } data += blockLen; } return ok;}static QString getMessage(const uchar *m, const uchar *end, const char *context, const char *sourceText, const char *comment, int numerus){ const uchar *tn = 0; uint tn_length = 0; int currentNumerus = -1; for (;;) { uchar tag = 0; if (m < end) tag = read8(m++); switch((Tag)tag) { case Tag_End: goto end; case Tag_Translation: { int len = read32(m); if (len % 1) return QString(); m += 4; if (++currentNumerus == numerus) { tn_length = len; tn = m; } m += len; break; } case Tag_Obsolete1: m += 4; break; case Tag_SourceText: { quint32 len = read32(m); m += 4; if (!match(m, sourceText, len)) return QString(); m += len; } break; case Tag_Context: { quint32 len = read32(m); m += 4; if (*m && !match(m, context, len)) return QString(); m += len; } break; case Tag_Comment: { quint32 len = read32(m); m += 4; if (*m && !match(m, comment, len)) return QString(); m += len; } break; default: return QString(); } }end: if (!tn) return QString(); QString str = QString::fromUtf16((const ushort *)tn, tn_length/2); if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) { for (int i = 0; i < str.length(); ++i) str[i] = QChar((str.at(i).unicode() >> 8) + ((str.at(i).unicode() << 8) & 0xff00)); } return str;}QString QTranslatorPrivate::do_translate(const char *context, const char *sourceText, const char *comment, int n) const{ if (context == 0) context = ""; if (sourceText == 0) sourceText = ""; if (comment == 0) comment = ""; if (!offsetLength) return QString(); /* Check if the context belongs to this QTranslator. If many translators are installed, this step is necessary. */ if (contextLength) { quint16 hTableSize = read16(contextArray); uint g = elfHash(context) % hTableSize; const uchar *c = contextArray + 2 + (g << 1); quint16 off = read16(c); c += 2; if (off == 0) return QString(); c = contextArray + (2 + (hTableSize << 1) + (off << 1)); for (;;) { quint8 len = read8(c++); if (len == 0) return QString(); if (match(c, context, len)) break; c += len; } } size_t numItems = offsetLength / (2 * sizeof(quint32)); if (!numItems) return QString(); int numerus = 0; if (n >= 0) numerus = ::numerus(n, numerusRulesArray, numerusRulesLength); for (;;) { quint32 h = elfHash(QByteArray(sourceText) + comment); const uchar *start = offsetArray; const uchar *end = start + ((numItems-1) << 3); while (start <= end) { const uchar *middle = start + (((end - start) >> 4) << 3); uint hash = read32(middle); if (h == hash) { start = middle; break; } else if (hash < h) { start = middle + 8; } else { end = middle - 8; } } if (start <= end) { // go back on equal key while (start != offsetArray && read32(start) == read32(start-8)) start -= 8; while (start < offsetArray + offsetLength) { quint32 rh = read32(start); start += 4; if (rh != h) break; quint32 ro = read32(start); start += 4; QString tn = getMessage(messageArray + ro, messageArray + messageLength, context, sourceText, comment, numerus); if (!tn.isNull()) return tn; } } if (!comment[0]) break; comment = ""; } return QString();}/*! Empties this translator of all contents. This function works with stripped translator files.*/void QTranslatorPrivate::clear(){ Q_Q(QTranslator); if (unmapPointer && unmapLength) {#if defined(QT_USE_MMAP) if (used_mmap) munmap(unmapPointer, unmapLength); else#endif delete [] unmapPointer; } unmapPointer = 0; unmapLength = 0; messageArray = 0; contextArray = 0; offsetArray = 0; numerusRulesArray = 0; messageLength = 0; contextLength = 0; offsetLength = 0; numerusRulesLength = 0; if (QCoreApplicationPrivate::isTranslatorInstalled(q)) QCoreApplication::postEvent(QCoreApplication::instance(), new QEvent(QEvent::LanguageChange));}/*! Returns the translation for the key (\a context, \a sourceText, \a comment). If none is found, also tries (\a context, \a sourceText, ""). If that still fails, returns an empty string. \sa load()*/QString QTranslator::translate(const char *context, const char *sourceText, const char *comment) const{ Q_D(const QTranslator); return d->do_translate(context, sourceText, comment, -1);}/*! \overload Returns the translation for the key (\a context, \a sourceText, \a comment). If none is found, also tries (\a context, \a sourceText, ""). If that still fails, returns an empty string. If \a n is not -1, it is used to choose an appropriate form for the translation (e.g. "%n file found" vs. "%n files found"). \sa load()*/QString QTranslator::translate(const char *context, const char *sourceText, const char *comment, int n) const{ Q_D(const QTranslator); // this step is necessary because the 3-parameter translate() overload is virtual if (n == -1) return translate(context, sourceText, comment); return d->do_translate(context, sourceText, comment, n);}/*! Returns true if this translator is empty, otherwise returns false. This function works with stripped and unstripped translation files.*/bool QTranslator::isEmpty() const{ Q_D(const QTranslator); return !d->unmapPointer && !d->unmapLength && !d->messageArray && !d->offsetArray && !d->contextArray;}/*! \fn QString QTranslator::find(const char *context, const char *sourceText, const char * comment = 0) const Use translate(\a context, \a sourceText, \a comment) instead.*/#endif // QT_NO_TRANSLATION
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -