⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 translator.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
                ok = true;            }        }        ::close(fd);    }#endif // QT_USE_MMAP    if (!ok) {        QFile file(realname);        if (!file.exists())            return false;        d->unmapLength = file.size();        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 Translator::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 Translator::load(const uchar *data, int len){    clear();    return d->do_load(data, len);}bool TranslatorPrivate::do_load(const uchar *data, int len){    if (len < MagicLength || memcmp(data, magic, MagicLength) != 0) {        q->clear();        return false;    }    QByteArray array = QByteArray::fromRawData((const char *) data, len);    QDataStream s(&array, QIODevice::ReadOnly);    bool ok = true;    s.device()->seek(MagicLength);    quint8 tag = 0;    quint32 blockLen = 0;    s >> tag >> blockLen;    while (tag && blockLen) {        if ((quint32) s.device()->pos() + blockLen > (quint32) len) {            ok = false;            break;        }        if (tag == TranslatorPrivate::Contexts) {            contextArray = QByteArray(array.constData() + s.device()->pos(), blockLen);        } else if (tag == TranslatorPrivate::Hashes) {            offsetArray = QByteArray(array.constData() + s.device()->pos(), blockLen);        } else if (tag == TranslatorPrivate::Messages) {            messageArray = QByteArray(array.constData() + s.device()->pos(), blockLen);        }        if (!s.device()->seek(s.device()->pos() + blockLen)) {            ok = false;            break;        }        tag = 0;        blockLen = 0;        if (!s.atEnd())            s >> tag >> blockLen;    }    return ok;}#ifndef QT_NO_TRANSLATION_BUILDER/*!    Saves this message file to \a filename, overwriting the previous    contents of \a filename. If \a mode is \c Everything (the    default), all the information is preserved. If \a mode is \c    Stripped, any information that is not necessary for findMessage()    is stripped away.    \sa load()*/bool Translator::save(const QString & filename, SaveMode mode){    QFile file(filename);    if (file.open(QIODevice::WriteOnly)) {        squeeze(mode);        QDataStream s(&file);        s.writeRawData((const char *)magic, MagicLength);        quint8 tag;        if (!d->offsetArray.isEmpty()) {            tag = (quint8)TranslatorPrivate::Hashes;            quint32 oas = (quint32)d->offsetArray.size();            s << tag << oas;            s.writeRawData(d->offsetArray, oas);        }        if (!d->messageArray.isEmpty()) {            tag = (quint8)TranslatorPrivate::Messages;            quint32 mas = (quint32)d->messageArray.size();            s << tag << mas;            s.writeRawData(d->messageArray, mas);        }        if (!d->contextArray.isEmpty()) {            tag = (quint8)TranslatorPrivate::Contexts;            quint32 cas = (quint32)d->contextArray.size();            s << tag << cas;            s.writeRawData(d->contextArray, cas);        }        return true;    }    return false;}#endif/*!    Empties this translator of all contents.    This function works with stripped translator files.*/void Translator::clear(){    if (d->unmapPointer && d->unmapLength) {#if defined(QT_USE_MMAP)        munmap(d->unmapPointer, d->unmapLength);#else        delete [] d->unmapPointer;#endif        d->unmapPointer = 0;        d->unmapLength = 0;    }    d->messageArray.clear();    d->offsetArray.clear();    d->contextArray.clear();#ifndef QT_NO_TRANSLATION_BUILDER    d->messages.clear();#endif    QEvent ev(QEvent::LanguageChange);    QCoreApplication::sendEvent(QCoreApplication::instance(), &ev);}#ifndef QT_NO_TRANSLATION_BUILDER/*!    Converts this message file to the compact format used to store    message files on disk.    You should never need to call this directly; save() and other    functions call it as necessary. \a mode is for internal use.    \sa save() unsqueeze()*/void Translator::squeeze(SaveMode mode){    if (d->messages.isEmpty()) {        if (mode == Stripped)            unsqueeze();        else            return;    }    QMap<TranslatorMessage, void *> messages = d->messages;    clear();    QMap<TranslatorPrivate::Offset, void *> offsets;    QDataStream ms(&d->messageArray, QIODevice::WriteOnly);    QMap<TranslatorMessage, void *>::const_iterator it, next;    int cpPrev = 0, cpNext = 0;    for (it = messages.constBegin(); it != messages.constEnd(); ++it) {        cpPrev = cpNext;        next = it;        ++next;        if (next == messages.constEnd())            cpNext = 0;        else            cpNext = (int) it.key().commonPrefix(next.key());        offsets.insert(TranslatorPrivate::Offset(it.key(), ms.device()->pos()), (void *)0);        it.key().write(ms, mode == Stripped, (TranslatorMessage::Prefix)qMax(cpPrev, cpNext + 1));    }    QMap<TranslatorPrivate::Offset, void *>::Iterator offset;    offset = offsets.begin();    QDataStream ds(&d->offsetArray, QIODevice::WriteOnly);    while (offset != offsets.end()) {        TranslatorPrivate::Offset k = offset.key();        ++offset;        ds << (quint32)k.h << (quint32)k.o;    }    if (mode == Stripped) {        QMap<QByteArray, int> contextSet;        for (it = messages.constBegin(); it != messages.constEnd(); ++it)            ++contextSet[it.key().context()];        quint16 hTableSize;        if (contextSet.size() < 200)            hTableSize = (contextSet.size() < 60) ? 151 : 503;        else if (contextSet.size() < 2500)            hTableSize = (contextSet.size() < 750) ? 1511 : 5003;        else            hTableSize = (contextSet.size() < 10000) ? 15013 : 3 * contextSet.size() / 2;        QMultiMap<int, const char *> hashMap;        QMap<QByteArray, int>::const_iterator c;        for (c = contextSet.constBegin(); c != contextSet.constEnd(); ++c)            hashMap.insert(elfHash(c.key()) % hTableSize, c.key());        /*          The contexts found in this translator are stored in a hash          table to provide fast lookup. The context array has the          following format:              quint16 hTableSize;              quint16 hTable[hTableSize];              quint8  contextPool[...];          The context pool stores the contexts as Pascal strings:              quint8  len;              quint8  data[len];          Let's consider the look-up of context "FunnyDialog".  A          hash value between 0 and hTableSize - 1 is computed, say h.          If hTable[h] is 0, "FunnyDialog" is not covered by this          translator. Else, we check in the contextPool at offset          2 * hTable[h] to see if "FunnyDialog" is one of the          contexts stored there, until we find it or we meet the          empty string.        */        d->contextArray.resize(2 + (hTableSize << 1));        QDataStream t(&d->contextArray, QIODevice::WriteOnly);        quint16 *hTable = new quint16[hTableSize];        memset(hTable, 0, hTableSize * sizeof(quint16));        t << hTableSize;        t.device()->seek(2 + (hTableSize << 1));        t << (quint16)0; // the entry at offset 0 cannot be used        uint upto = 2;        QMap<int, const char *>::const_iterator entry = hashMap.constBegin();        while (entry != hashMap.constEnd()) {            int i = entry.key();            hTable[i] = (quint16)(upto >> 1);            do {	            const char *con = entry.value();                uint len = (uint)qstrlen(con);                len = qMin(len, 255u);                t << (quint8)len;                t.writeRawData(con, len);                upto += 1 + len;                ++entry;            } while (entry != hashMap.constEnd() && entry.key() == i);            do {                t << (quint8) 0; // empty string                ++upto;            } while ((upto & 0x1) != 0); // offsets have to be even        }        t.device()->seek(2);        for (int j = 0; j < hTableSize; j++)            t << hTable[j];        delete [] hTable;        if (upto > 131072) {            qWarning("Translator::squeeze: Too many contexts");            d->contextArray.clear();        }    }}/*!    Converts this message file into an easily modifiable data    structure, less compact than the format used in the files.    You should never need to call this function; it is called by    insert() and friends as necessary.    \sa squeeze()*/void Translator::unsqueeze(){    if (!d->messages.isEmpty() || d->messageArray.isEmpty())        return;    QDataStream s(&d->messageArray, QIODevice::ReadOnly);    for (;;) {        TranslatorMessage m(s);        if (m.hash() == 0)            break;        d->messages.insert(m, (void *)0);    }}/*!    Returns true if this message file contains a message with the key    (\a context, \a sourceText, \a comment); otherwise returns false.    This function works with stripped translator files.    (This is is a one-liner that calls findMessage().)*/bool Translator::contains(const char* context, const char* sourceText,                            const char* comment) const{    return !findMessage(context, sourceText, comment).translation().isNull();}/*!    Inserts \a message into this message file.    This function does \e not work with stripped translator files. It    may appear to, but that is not dependable.    \sa remove()*/void Translator::insert(const TranslatorMessage& message){    unsqueeze();    d->messages.remove(message); // safer    d->messages.insert(message, (void *) 0);}/*!  \fn void Translator::insert(const char *context, const char *sourceText, const QString &translation)  \overload  \obsolete  Inserts the \a sourceText and \a translation into the translator  with the given \a context.*//*!    Removes \a message from this translator.    This function works with stripped translator files.    \sa insert()*/void Translator::remove(const TranslatorMessage& message){    unsqueeze();    d->messages.remove(message);}/*!  \fn void Translator::remove(const char *, const char *)  \overload  \obsolete  Removes the translation associated to the key (\a context, \a sourceText,  "") from this translator.*/#endif/*!  Returns the TranslatorMessage for the key     (\a context, \a sourceText, \a comment). If none is found,     also tries (\a context, \a sourceText, "").*/TranslatorMessage Translator::findMessage(const char *context, const char *sourceText,                                          const char *comment) const{    if (context == 0)        context = "";    if (sourceText == 0)        sourceText = "";    if (comment == 0)        comment = "";#ifndef QT_NO_TRANSLATION_BUILDER    if (!d->messages.isEmpty()) {        QMap<TranslatorMessage, void *>::const_iterator it;        it = d->messages.find(TranslatorMessage(context, sourceText, comment));        if (it != d->messages.constEnd())            return it.key();        if (comment[0]) {            it = d->messages.find(TranslatorMessage(context, sourceText, ""));            if (it != d->messages.constEnd())                return it.key();        }        return TranslatorMessage();    }#endif    if (d->offsetArray.isEmpty())        return TranslatorMessage();    /*        Check if the context belongs to this Translator. If many        translators are installed, this step is necessary.    */    if (!d->contextArray.isEmpty()) {        quint16 hTableSize = 0;        QDataStream t(d->contextArray);        t >> hTableSize;        uint g = elfHash(context) % hTableSize;        t.device()->seek(2 + (g << 1));        quint16 off;        t >> off;        if (off == 0)            return TranslatorMessage();        t.device()->seek(2 + (hTableSize << 1) + (off << 1));        quint8 len;        char con[256];        for (;;) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -