qtranslator.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/corelib/kernel/qtranslator.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtCore module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qplatformdefs.h"-
41-
42#include "qtranslator.h"-
43-
44#ifndef QT_NO_TRANSLATION-
45-
46#include "qfileinfo.h"-
47#include "qstring.h"-
48#include "qstringlist.h"-
49#include "qcoreapplication.h"-
50#include "qcoreapplication_p.h"-
51#include "qdatastream.h"-
52#include "qfile.h"-
53#include "qmap.h"-
54#include "qalgorithms.h"-
55#include "qtranslator_p.h"-
56#include "qlocale.h"-
57#include "qendian.h"-
58#include "qresource.h"-
59-
60#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY)-
61#define QT_USE_MMAP-
62#include "private/qcore_unix_p.h"-
63#endif-
64-
65// most of the headers below are already included in qplatformdefs.h-
66// also this lacks Large File support but that's probably irrelevant-
67#if defined(QT_USE_MMAP)-
68// for mmap-
69#include <sys/mman.h>-
70#include <errno.h>-
71#endif-
72-
73#include <stdlib.h>-
74-
75#include "qobject_p.h"-
76-
77QT_BEGIN_NAMESPACE-
78-
79enum Tag { Tag_End = 1, Tag_SourceText16, Tag_Translation, Tag_Context16, Tag_Obsolete1,-
80 Tag_SourceText, Tag_Context, Tag_Comment, Tag_Obsolete2 };-
81/*-
82$ mcookie-
833cb86418caef9c95cd211cbf60a1bddd-
84$-
85*/-
86-
87// magic number for the file-
88static const int MagicLength = 16;-
89static const uchar magic[MagicLength] = {-
90 0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95,-
91 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd-
92};-
93-
94static
executed 18 times by 2 tests: return ([]() -> QString { enum { Size = sizeof(u"" ".qm")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" ".qm" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }());
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
executed 18 times by 2 tests: return qstring_literal_temp;
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
executed 18 times by 2 tests: return ([]() -> QString { enum { Size = sizeof(u"" ".qm")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" ".qm" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }());
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
executed 18 times by 2 tests: return qstring_literal_temp;
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
inline QString dotQmLiteral() { return QStringLiteral(".qm"); }
executed 18 times by 2 tests: return ([]() -> QString { enum { Size = sizeof(u"" ".qm")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" ".qm" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }());
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
executed 18 times by 2 tests: return qstring_literal_temp;
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
18
95-
96static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)-
97{-
98 // catch the case if \a found has a zero-terminating symbol and \a len includes it.-
99 // (normalize it to be without the zero-terminating symbol)-
100 if (foundLen > 0 && found[foundLen-1] == '\0')-
101 --foundLen;-
102 return ((targetLen == foundLen) && memcmp(found, target, foundLen) == 0);-
103}-
104-
105static void elfHash_continue(const char *name, uint &h)-
106{-
107 const uchar *k;-
108 uint g;-
109-
110 k = (const uchar *) name;-
111 while (*k) {-
112 h = (h << 4) + *k++;-
113 if ((g = (h & 0xf0000000)) != 0)-
114 h ^= g >> 24;-
115 h &= ~g;-
116 }-
117}-
118-
119static void elfHash_finish(uint &h)-
120{-
121 if (!h)-
122 h = 1;-
123}-
124-
125static uint elfHash(const char *name)-
126{-
127 uint hash = 0;-
128 elfHash_continue(name, hash);-
129 elfHash_finish(hash);-
130 return hash;-
131}-
132-
133/*-
134 \internal-
135-
136 Determines whether \a rules are valid "numerus rules". Test input with this-
137 function before calling numerusHelper, below.-
138 */-
139static bool isValidNumerusRules(const uchar *rules, uint rulesSize)-
140{-
141 // Disabled computation of maximum numerus return value-
142 // quint32 numerus = 0;-
143-
144 if (rulesSize == 0)-
145 return true;-
146-
147 quint32 offset = 0;-
148 do {-
149 uchar opcode = rules[offset];-
150 uchar op = opcode & Q_OP_MASK;-
151-
152 if (opcode & 0x80)-
153 return false; // Bad op-
154-
155 if (++offset == rulesSize)-
156 return false; // Missing operand-
157-
158 // right operand-
159 ++offset;-
160-
161 switch (op)-
162 {-
163 case Q_EQ:-
164 case Q_LT:-
165 case Q_LEQ:-
166 break;-
167-
168 case Q_BETWEEN:-
169 if (offset != rulesSize) {-
170 // third operand-
171 ++offset;-
172 break;-
173 }-
174 return false; // Missing operand-
175-
176 default:-
177 return false; // Bad op (0)-
178 }-
179-
180 // ++numerus;-
181 if (offset == rulesSize)-
182 return true;-
183-
184 } while (((rules[offset] == Q_AND)-
185 || (rules[offset] == Q_OR)-
186 || (rules[offset] == Q_NEWRULE))-
187 && ++offset != rulesSize);-
188-
189 // Bad op-
190 return false;-
191}-
192-
193/*-
194 \internal-
195-
196 This function does no validation of input and assumes it is well-behaved,-
197 these assumptions can be checked with isValidNumerusRules, above.-
198-
199 Determines which translation to use based on the value of \a n. The return-
200 value is an index identifying the translation to be used.-
201-
202 \a rules is a character array of size \a rulesSize containing bytecode that-
203 operates on the value of \a n and ultimately determines the result.-
204-
205 This function has O(1) space and O(rulesSize) time complexity.-
206 */-
207static uint numerusHelper(int n, const uchar *rules, uint rulesSize)-
208{-
209 uint result = 0;-
210 uint i = 0;-
211-
212 if (rulesSize == 0)-
213 return 0;-
214-
215 for (;;) {-
216 bool orExprTruthValue = false;-
217-
218 for (;;) {-
219 bool andExprTruthValue = true;-
220-
221 for (;;) {-
222 bool truthValue = true;-
223 int opcode = rules[i++];-
224-
225 int leftOperand = n;-
226 if (opcode & Q_MOD_10) {-
227 leftOperand %= 10;-
228 } else if (opcode & Q_MOD_100) {-
229 leftOperand %= 100;-
230 } else if (opcode & Q_LEAD_1000) {-
231 while (leftOperand >= 1000)-
232 leftOperand /= 1000;-
233 }-
234-
235 int op = opcode & Q_OP_MASK;-
236 int rightOperand = rules[i++];-
237-
238 switch (op) {-
239 case Q_EQ:-
240 truthValue = (leftOperand == rightOperand);-
241 break;-
242 case Q_LT:-
243 truthValue = (leftOperand < rightOperand);-
244 break;-
245 case Q_LEQ:-
246 truthValue = (leftOperand <= rightOperand);-
247 break;-
248 case Q_BETWEEN:-
249 int bottom = rightOperand;-
250 int top = rules[i++];-
251 truthValue = (leftOperand >= bottom && leftOperand <= top);-
252 }-
253-
254 if (opcode & Q_NOT)-
255 truthValue = !truthValue;-
256-
257 andExprTruthValue = andExprTruthValue && truthValue;-
258-
259 if (i == rulesSize || rules[i] != Q_AND)-
260 break;-
261 ++i;-
262 }-
263-
264 orExprTruthValue = orExprTruthValue || andExprTruthValue;-
265-
266 if (i == rulesSize || rules[i] != Q_OR)-
267 break;-
268 ++i;-
269 }-
270-
271 if (orExprTruthValue)-
272 return result;-
273-
274 ++result;-
275-
276 if (i == rulesSize)-
277 return result;-
278-
279 i++; // Q_NEWRULE-
280 }-
281-
282 Q_ASSERT(false);-
283 return 0;-
284}-
285-
286class QTranslatorPrivate : public QObjectPrivate-
287{-
288 Q_DECLARE_PUBLIC(QTranslator)-
289public:-
290 enum { Contexts = 0x2f, Hashes = 0x42, Messages = 0x69, NumerusRules = 0x88, Dependencies = 0x96 };-
291-
292 QTranslatorPrivate() :-
293#if defined(QT_USE_MMAP)-
294 used_mmap(0),-
295#endif-
296 unmapPointer(0), unmapLength(0), resource(0),-
297 messageArray(0), offsetArray(0), contextArray(0), numerusRulesArray(0),-
298 messageLength(0), offsetLength(0), contextLength(0), numerusRulesLength(0) {}-
299-
300#if defined(QT_USE_MMAP)-
301 bool used_mmap : 1;-
302#endif-
303 char *unmapPointer; // used memory (mmap, new or resource file)-
304 quint32 unmapLength;-
305-
306 // The resource object in case we loaded the translations from a resource-
307 QResource *resource;-
308-
309 // used if the translator has dependencies-
310 QList<QTranslator*> subTranslators;-
311-
312 // Pointers and offsets into unmapPointer[unmapLength] array, or user-
313 // provided data array-
314 const uchar *messageArray;-
315 const uchar *offsetArray;-
316 const uchar *contextArray;-
317 const uchar *numerusRulesArray;-
318 uint messageLength;-
319 uint offsetLength;-
320 uint contextLength;-
321 uint numerusRulesLength;-
322-
323 bool do_load(const QString &filename, const QString &directory);-
324 bool do_load(const uchar *data, int len, const QString &directory);-
325 QString do_translate(const char *context, const char *sourceText, const char *comment,-
326 int n) const;-
327 void clear();-
328};-
329-
330/*!-
331 \class QTranslator-
332 \inmodule QtCore-
333-
334 \brief The QTranslator class provides internationalization support for text-
335 output.-
336-
337 \ingroup i18n-
338-
339 An object of this class contains a set of translations from a-
340 source language to a target language. QTranslator provides-
341 functions to look up translations in a translation file.-
342 Translation files are created using \l{Qt Linguist}.-
343-
344 The most common use of QTranslator is to: load a translation-
345 file, install it using QCoreApplication::installTranslator(), and use-
346 it via QObject::tr(). Here's an example \c main() function using the-
347 QTranslator:-
348-
349 \snippet hellotrmain.cpp 0-
350-
351 Note that the translator must be created \e before the-
352 application's widgets.-
353-
354 Most applications will never need to do anything else with this-
355 class. The other functions provided by this class are useful for-
356 applications that work on translator files.-
357-
358 \section1 Looking up Translations-
359-
360 It is possible to look up a translation using translate() (as tr()-
361 and QCoreApplication::translate() do). The translate() function takes-
362 up to three parameters:-
363-
364 \list-
365 \li The \e context - usually the class name for the tr() caller.-
366 \li The \e {source text} - usually the argument to tr().-
367 \li The \e disambiguation - an optional string that helps disambiguate-
368 different uses of the same text in the same context.-
369 \endlist-
370-
371 For example, the "Cancel" in a dialog might have "Anuluj" when the-
372 program runs in Polish (in this case the source text would be-
373 "Cancel"). The context would (normally) be the dialog's class-
374 name; there would normally be no comment, and the translated text-
375 would be "Anuluj".-
376-
377 But it's not always so simple. The Spanish version of a printer-
378 dialog with settings for two-sided printing and binding would-
379 probably require both "Activado" and "Activada" as translations-
380 for "Enabled". In this case the source text would be "Enabled" in-
381 both cases, and the context would be the dialog's class name, but-
382 the two items would have disambiguations such as "two-sided printing"-
383 for one and "binding" for the other. The disambiguation enables the-
384 translator to choose the appropriate gender for the Spanish version,-
385 and enables Qt to distinguish between translations.-
386-
387 \section1 Using Multiple Translations-
388-
389 Multiple translation files can be installed in an application.-
390 Translations are searched for in the reverse order in which they were-
391 installed, so the most recently installed translation file is searched-
392 for translations first and the earliest translation file is searched-
393 last. The search stops as soon as a translation containing a matching-
394 string is found.-
395-
396 This mechanism makes it possible for a specific translation to be-
397 "selected" or given priority over the others; simply uninstall the-
398 translator from the application by passing it to the-
399 QCoreApplication::removeTranslator() function and reinstall it with-
400 QCoreApplication::installTranslator(). It will then be the first-
401 translation to be searched for matching strings.-
402-
403 \sa QCoreApplication::installTranslator(), QCoreApplication::removeTranslator(),-
404 QObject::tr(), QCoreApplication::translate(), {I18N Example},-
405 {Hello tr() Example}, {Arrow Pad Example}, {Troll Print Example}-
406*/-
407-
408/*!-
409 Constructs an empty message file object with parent \a parent that-
410 is not connected to any file.-
411*/-
412-
413QTranslator::QTranslator(QObject * parent)-
414 : QObject(*new QTranslatorPrivate, parent)-
415{-
416}-
417-
418/*!-
419 Destroys the object and frees any allocated resources.-
420*/-
421-
422QTranslator::~QTranslator()-
423{-
424 if (QCoreApplication::instance())-
425 QCoreApplication::removeTranslator(this);-
426 Q_D(QTranslator);-
427 d->clear();-
428}-
429-
430/*!-
431-
432 Loads \a filename + \a suffix (".qm" if the \a suffix is not-
433 specified), which may be an absolute file name or relative to \a-
434 directory. Returns \c true if the translation is successfully loaded;-
435 otherwise returns \c false.-
436-
437 If \a directory is not specified, the current directory is used-
438 (i.e., as \l{QDir::}{currentPath()}).-
439-
440 The previous contents of this translator object are discarded.-
441-
442 If the file name does not exist, other file names are tried-
443 in the following order:-
444-
445 \list 1-
446 \li File name without \a suffix appended.-
447 \li File name with text after a character in \a search_delimiters-
448 stripped ("_." is the default for \a search_delimiters if it is-
449 an empty string) and \a suffix.-
450 \li File name stripped without \a suffix appended.-
451 \li File name stripped further, etc.-
452 \endlist-
453-
454 For example, an application running in the fr_CA locale-
455 (French-speaking Canada) might call load("foo.fr_ca",-
456 "/opt/foolib"). load() would then try to open the first existing-
457 readable file from this list:-
458-
459 \list 1-
460 \li \c /opt/foolib/foo.fr_ca.qm-
461 \li \c /opt/foolib/foo.fr_ca-
462 \li \c /opt/foolib/foo.fr.qm-
463 \li \c /opt/foolib/foo.fr-
464 \li \c /opt/foolib/foo.qm-
465 \li \c /opt/foolib/foo-
466 \endlist-
467-
468 Usually, it is better to use the QTranslator::load(const QLocale &,-
469 const QString &, const QString &, const QString &, const QString &)-
470 function instead, because it uses \l{QLocale::uiLanguages()} and not simply-
471 the locale name, which refers to the formatting of dates and numbers and not-
472 necessarily the UI language.-
473*/-
474-
475bool QTranslator::load(const QString & filename, const QString & directory,-
476 const QString & search_delimiters,-
477 const QString & suffix)-
478{-
479 Q_D(QTranslator);-
480 d->clear();-
481-
482 QString prefix;-
483 if (QFileInfo(filename).isRelative()) {
QFileInfo(file...).isRelative()Description
TRUEevaluated 15 times by 1 test
Evaluated by:
  • tst_QTranslator
FALSEevaluated 3 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
3-15
484 prefix = directory;-
485 if (prefix.length() && !prefix.endsWith(QLatin1Char('/')))
prefix.length()Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • tst_QTranslator
FALSEevaluated 14 times by 1 test
Evaluated by:
  • tst_QTranslator
!prefix.endsWi...tin1Char('/'))Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • tst_QTranslator
FALSEnever evaluated
0-14
486 prefix += QLatin1Char('/');
executed 1 time by 1 test: prefix += QLatin1Char('/');
Executed by:
  • tst_QTranslator
1
487 }
executed 15 times by 1 test: end of block
Executed by:
  • tst_QTranslator
15
488-
489 const QString suffixOrDotQM = suffix.isNull() ? dotQmLiteral() : suffix;
suffix.isNull()Description
TRUEevaluated 18 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEnever evaluated
0-18
490 QString fname = filename;-
491 QString realname;-
492 QString delims;-
493 delims = search_delimiters.isNull() ? QString::fromLatin1QStringLiteral("_.") : search_delimiters;
executed 18 times by 2 tests: return qstring_literal_temp;
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
search_delimiters.isNull()Description
TRUEevaluated 18 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEnever evaluated
0-18
494-
495 for (;;) {-
496 QFileInfo fi;-
497-
498 realname = prefix + fname + (suffix.isNull() ? QString::fromLatin1(".qm") : suffix);suffixOrDotQM;-
499 fi.setFile(realname);-
500 if (fi.isReadable() && fi.isFile())
fi.isReadable()Description
TRUEevaluated 9 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEevaluated 9 times by 1 test
Evaluated by:
  • tst_QTranslator
fi.isFile()Description
TRUEevaluated 9 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEnever evaluated
0-9
501 break;
executed 9 times by 2 tests: break;
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
9
502-
503 realname = prefix + fname;-
504 fi.setFile(realname);-
505 if (fi.isReadable() && fi.isFile())
fi.isReadable()Description
TRUEevaluated 6 times by 1 test
Evaluated by:
  • tst_QTranslator
FALSEevaluated 3 times by 1 test
Evaluated by:
  • tst_QTranslator
fi.isFile()Description
TRUEevaluated 5 times by 1 test
Evaluated by:
  • tst_QTranslator
FALSEevaluated 1 time by 1 test
Evaluated by:
  • tst_QTranslator
1-6
506 break;
executed 5 times by 1 test: break;
Executed by:
  • tst_QTranslator
5
507-
508 int rightmost = 0;-
509 for (int i = 0; i < (int)delims.length(); i++) {
i < (int)delims.length()Description
TRUEevaluated 8 times by 1 test
Evaluated by:
  • tst_QTranslator
FALSEevaluated 4 times by 1 test
Evaluated by:
  • tst_QTranslator
4-8
510 int k = fname.lastIndexOf(delims[i]);-
511 if (k > rightmost)
k > rightmostDescription
TRUEnever evaluated
FALSEevaluated 8 times by 1 test
Evaluated by:
  • tst_QTranslator
0-8
512 rightmost = k;
never executed: rightmost = k;
0
513 }
executed 8 times by 1 test: end of block
Executed by:
  • tst_QTranslator
8
514-
515 // no truncations? fail-
516 if (rightmost == 0)
rightmost == 0Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • tst_QTranslator
FALSEnever evaluated
0-4
517 return false;
executed 4 times by 1 test: return false;
Executed by:
  • tst_QTranslator
4
518-
519 fname.truncate(rightmost);-
520 }
never executed: end of block
0
521-
522 // realname is now the fully qualified name of a readable file.-
523 return d->do_load(realname, directory);
executed 14 times by 2 tests: return d->do_load(realname, directory);
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
14
524}-
525-
526bool QTranslatorPrivate::do_load(const QString &realname, const QString &directory)-
527{-
528 QTranslatorPrivate *d = this;-
529 bool ok = false;-
530-
531 if (realname.startsWith(QLatin1Char(':'))))) {
realname.start...tin1Char(':'))Description
TRUEevaluated 3 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEevaluated 11 times by 1 test
Evaluated by:
  • tst_QTranslator
3-11
532 // If the translation is in a non-compressed resource file, the data is already in-
533 // memory, so no need to use QFile to copy it again.-
534 Q_ASSERT(!d->resource);-
535 d->resource = new QResource(realname);-
536 if (resource->isValid() && !resource->isCompressed() && resource->size() > MagicLength
resource->isValid()Description
TRUEevaluated 3 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEnever evaluated
!resource->isCompressed()Description
TRUEevaluated 2 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEevaluated 1 time by 1 test
Evaluated by:
  • tst_QKeySequence
resource->size() > MagicLengthDescription
TRUEevaluated 2 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEnever evaluated
0-3
537 && !memcmp(resource->data(), magic, MagicLength)) {
!memcmp(resour..., MagicLength)Description
TRUEevaluated 2 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEnever evaluated
0-2
538 d->unmapLength = resource->size();-
539 d->unmapPointer = reinterpret_cast<char *>(const_cast<uchar *>(resource->data()));-
540#if defined(QT_USE_MMAP)-
541 d->used_mmap = false;-
542#endif-
543 ok = true;-
544 } else {
executed 2 times by 2 tests: end of block
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
2
545 delete resource;-
546 resource = 0;-
547 }
executed 1 time by 1 test: end of block
Executed by:
  • tst_QKeySequence
1
548 }-
549-
550 if (!ok) {
!okDescription
TRUEevaluated 12 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEevaluated 2 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
2-12
551 QFile file(realname);-
552 if (!file.open(QIODevice::ReadOnly | QIODevice::Unbuffered))
!file.open(QIO...e::Unbuffered)Description
TRUEnever evaluated
FALSEevaluated 12 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
0-12
553 return false;
never executed: return false;
0
554-
555 qint64 fileSize = file.size();-
556 if (fileSize <= MagicLength || quint32(-1) <= fileSize)
fileSize <= MagicLengthDescription
TRUEnever evaluated
FALSEevaluated 12 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
quint32(-1) <= fileSizeDescription
TRUEnever evaluated
FALSEevaluated 12 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
0-12
557 return false;
never executed: return false;
0
558-
559 {-
560 char magicBuffer[MagicLength];-
561 if (MagicLength != file.read(magicBuffer, MagicLength)
MagicLength !=..., MagicLength)Description
TRUEnever evaluated
FALSEevaluated 12 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
0-12
562 || memcmp(magicBuffer, magic, MagicLength))
memcmp(magicBu..., MagicLength)Description
TRUEnever evaluated
FALSEevaluated 12 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
0-12
563 return false;
never executed: return false;
0
564 }-
565-
566 d->unmapLength = quint32(fileSize);-
567-
568#ifdef QT_USE_MMAP-
569-
570#ifndef MAP_FILE-
571#define MAP_FILE 0-
572#endif-
573#ifndef MAP_FAILED-
574#define MAP_FAILED -1-
575#endif-
576-
577 int fd = file.handle();-
578 if (fd >= 0) {
fd >= 0Description
TRUEevaluated 11 times by 1 test
Evaluated by:
  • tst_QTranslator
FALSEevaluated 1 time by 1 test
Evaluated by:
  • tst_QKeySequence
1-11
579 char *ptr;-
580 ptr = reinterpret_cast<char *>(-
581 mmap(0, d->unmapLength, // any address, whole file-
582 PROT_READ, // read-only memory-
583 MAP_FILE | MAP_PRIVATE, // swap-backed map from file-
584 fd, 0)); // from offset 0 of fd-
585 if (ptr && ptr != reinterpret_cast<char *>(MAP_FAILED)) {
ptrDescription
TRUEevaluated 11 times by 1 test
Evaluated by:
  • tst_QTranslator
FALSEnever evaluated
ptr != reinter...((void *) -1))Description
TRUEevaluated 11 times by 1 test
Evaluated by:
  • tst_QTranslator
FALSEnever evaluated
0-11
586 file.close();-
587 d->used_mmap = true;-
588 d->unmapPointer = ptr;-
589 ok = true;-
590 }
executed 11 times by 1 test: end of block
Executed by:
  • tst_QTranslator
11
591 }
executed 11 times by 1 test: end of block
Executed by:
  • tst_QTranslator
11
592#endif // QT_USE_MMAP-
593-
594 if (!ok) {
!okDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • tst_QKeySequence
FALSEevaluated 11 times by 1 test
Evaluated by:
  • tst_QTranslator
1-11
595 d->unmapPointer = new char[d->unmapLength];-
596 if (d->unmapPointer) {
d->unmapPointerDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • tst_QKeySequence
FALSEnever evaluated
0-1
597 file.seek(0);-
598 qint64 readResult = file.read(d->unmapPointer, d->unmapLength);-
599 if (readResult == qint64(unmapLength))
readResult == ...4(unmapLength)Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • tst_QKeySequence
FALSEnever evaluated
0-1
600 ok = true;
executed 1 time by 1 test: ok = true;
Executed by:
  • tst_QKeySequence
1
601 }
executed 1 time by 1 test: end of block
Executed by:
  • tst_QKeySequence
1
602 }
executed 1 time by 1 test: end of block
Executed by:
  • tst_QKeySequence
1
603 }
executed 12 times by 2 tests: end of block
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
12
604-
605 if (ok && d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength, directory))
okDescription
TRUEevaluated 14 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEnever evaluated
d->do_load(rei...th, directory)Description
TRUEevaluated 14 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEnever evaluated
0-14
606 return true;
executed 14 times by 2 tests: return true;
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
14
607-
608#if defined(QT_USE_MMAP)-
609 if (used_mmap) {
used_mmapDescription
TRUEnever evaluated
FALSEnever evaluated
0
610 used_mmap = false;-
611 munmap(unmapPointer, unmapLength);-
612 } else
never executed: end of block
0
613#endif-
614 if (!d->resource)
!d->resourceDescription
TRUEnever evaluated
FALSEnever evaluated
0
615 delete [] unmapPointer;
never executed: delete [] unmapPointer;
0
616-
617 delete d->resource;-
618 d->resource = 0;-
619 d->unmapPointer = 0;-
620 d->unmapLength = 0;-
621-
622 return false;
never executed: return false;
0
623}-
624-
625Q_NEVER_INLINE-
626static bool is_readable_file(const QString &name)-
627{-
628 const QFileInfo fi(name);-
629 return fi.isReadable() && fi.isFile();
never executed: return fi.isReadable() && fi.isFile();
0
630}-
631-
632static QString find_translation(const QLocale & locale,-
633 const QString & filename,-
634 const QString & prefix,-
635 const QString & directory,-
636 const QString & suffix)-
637{-
638 QString path;-
639 if (QFileInfo(filename).isRelative()) {
QFileInfo(file...).isRelative()Description
TRUEnever evaluated
FALSEnever evaluated
0
640 path = directory;-
641 if (!path.isEmpty() && !path.endsWith(QLatin1Char('/')))
!path.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
!path.endsWith...tin1Char('/'))Description
TRUEnever evaluated
FALSEnever evaluated
0
642 path += QLatin1Char('/');
never executed: path += QLatin1Char('/');
0
643 }
never executed: end of block
0
644 QFileInfo ficonst QString suffixOrDotQM = suffix.isNull() ? dotQmLiteral() : suffix;
suffix.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
645-
646 QString realname;-
647 realname += path + filename + prefix; // using += in the hope for some reserve capacity-
648 const int realNameBaseSize = realname.size();-
649 QStringList fuzzyLocales;-
650-
651 // see http://www.unicode.org/reports/tr35/#LanguageMatching for inspiration-
652-
653 QStringList languages = locale.uiLanguages();-
654#if defined(Q_OS_UNIX)-
655 for (int i = languages.size()-1; i >= 0; --i) {
i >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
656 QString lang = languages.at(i);-
657 QString lowerLang = lang.toLower();-
658 if (lang != lowerLang)
lang != lowerLangDescription
TRUEnever evaluated
FALSEnever evaluated
0
659 languages.insert(i+1, lowerLang);
never executed: languages.insert(i+1, lowerLang);
0
660 }
never executed: end of block
0
661#endif-
662-
663 // try explicit locales names first-
664 foreachfor (QString localeName ,: qAsConst(languages))) {-
665 localeName.replace(QLatin1Char('-'), QLatin1Char('_'));-
666-
667 realname = path + filename + prefix ++= localeName + (suffix.isNull() ? QLatin1StringsuffixOrDotQM;-
668 if
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
(".qm") : suffix);
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
0
fi.setFile
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
is_readable_file(realname);
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
if (fi.isReadable() && fi.isFile())
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
))
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
669 return realname;
never executed: return realname;
0
670-
671 realname= path + filename + prefix.truncate(realNameBaseSize + localeName;-
fi.setFile(realname);size());
672 if (fi.isReadable() && fi.isFile())is_readable_file(realname))
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
0
673 return realname;
never executed: return realname;
0
674-
675 realname.truncate(realNameBaseSize);-
676 fuzzyLocales.append(localeName);-
677 }
never executed: end of block
0
678-
679 // start guessing-
680 foreachfor (const QString localeName,&fuzzyLocale : qAsConst(fuzzyLocales))) {-
681 QStringRef localeName(&fuzzyLocale);-
682 for (;;) {-
683 int rightmost = localeName.lastIndexOf(QLatin1Char('_'));-
684 // no truncations? fail-
685 if (rightmost <= 0)
rightmost <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
686 break;
never executed: break;
0
687 localeName.truncate(rightmost);-
688-
689 realname = path + filename + prefix ++= localeName + (suffix.isNull() ? QLatin1StringsuffixOrDotQM;-
690 if
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
(".qm") : suffix);
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
0
fi.setFile
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
is_readable_file(realname);
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
if (fi.isReadable() && fi.isFile())
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
))
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
691 return realname;
never executed: return realname;
0
692-
693 realname= path + filename + prefix.truncate(realNameBaseSize + localeName;-
fi.setFile(realname);size());
694 if (fi.isReadable() && fi.isFile())is_readable_file(realname))
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
0
695 return realname;
never executed: return realname;
0
696-
697 realname.truncate(realNameBaseSize);-
698 }
never executed: end of block
0
699 }
never executed: end of block
0
700-
701 const int realNameBaseSizeFallbacks = path.size() + filename.size();-
702-
703 // realname == path + filename + prefix;-
704 if (!suffix.isNull()) {
!suffix.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
705 realname= path + filename + suffix;-
fi.setFilereplace(realnamerealNameBaseSizeFallbacks, prefix.size(), suffix);
706 // realname == path + filename;-
707 if (fi.isReadable() && fi.isFile())is_readable_file(realname))
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
0
708 return realname;
never executed: return realname;
0
709 }realname= path + filename + prefix;-
fi.setFilereplace(realnamerealNameBaseSizeFallbacks, suffix.size(), prefix);
710 }
never executed: end of block
0
711-
712 // realname == path + filename + prefix;-
713 if (fi.isReadable() && fi.isFile())is_readable_file(realname))
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
0
714 return realname;
never executed: return realname;
0
715-
716 realname= path + filename;-
fi.setFiletruncate(realnamerealNameBaseSizeFallbacks);
717 // realname == path + filename;-
718 if (fi.isReadable() && fi.isFile())is_readable_file(realname))
is_readable_file(realname)Description
TRUEnever evaluated
FALSEnever evaluated
0
719 return realname;
never executed: return realname;
0
720-
721 realname.truncate(0);-
722 return QString();realname;
never executed: return realname;
0
723}-
724-
725/*!-
726 \since 4.8-
727-
728 Loads \a filename + \a prefix + \l{QLocale::uiLanguages()}{ui language-
729 name} + \a suffix (".qm" if the \a suffix is not specified), which may be-
730 an absolute file name or relative to \a directory. Returns \c true if the-
731 translation is successfully loaded; otherwise returns \c false.-
732-
733 The previous contents of this translator object are discarded.-
734-
735 If the file name does not exist, other file names are tried-
736 in the following order:-
737-
738 \list 1-
739 \li File name without \a suffix appended.-
740 \li File name with ui language part after a "_" character stripped and \a suffix.-
741 \li File name with ui language part stripped without \a suffix appended.-
742 \li File name with ui language part stripped further, etc.-
743 \endlist-
744-
745 For example, an application running in the \a locale with the following-
746 \l{QLocale::uiLanguages()}{ui languages} - "es", "fr-CA", "de" might call-
747 load(QLocale(), "foo", ".", "/opt/foolib", ".qm"). load() would-
748 replace '-' (dash) with '_' (underscore) in the ui language and then try to-
749 open the first existing readable file from this list:-
750-
751 \list 1-
752 \li \c /opt/foolib/foo.es.qm-
753 \li \c /opt/foolib/foo.es-
754 \li \c /opt/foolib/foo.fr_CA.qm-
755 \li \c /opt/foolib/foo.fr_CA-
756 \li \c /opt/foolib/foo.de.qm-
757 \li \c /opt/foolib/foo.de-
758 \li \c /opt/foolib/foo.fr.qm-
759 \li \c /opt/foolib/foo.fr-
760 \li \c /opt/foolib/foo.qm-
761 \li \c /opt/foolib/foo.-
762 \li \c /opt/foolib/foo-
763 \endlist-
764-
765 On operating systems where file system is case sensitive, QTranslator also-
766 tries to load a lower-cased version of the locale name.-
767*/-
768bool QTranslator::load(const QLocale & locale,-
769 const QString & filename,-
770 const QString & prefix,-
771 const QString & directory,-
772 const QString & suffix)-
773{-
774 Q_D(QTranslator);-
775 d->clear();-
776 QString fname = find_translation(locale, filename, prefix, directory, suffix);-
777 return !fname.isEmpty() && d->do_load(fname, directory);-
778}-
779-
780/*!-
781 \overload load()-
782-
783 Loads the QM file data \a data of length \a len into the-
784 translator.-
785-
786 The data is not copied. The caller must be able to guarantee that \a data-
787 will not be deleted or modified.-
788-
789 \a directory is only used to specify the base directory when loading the dependencies-
790 of a QM file. If the file does not have dependencies, this argument is ignored.-
791*/-
792bool QTranslator::load(const uchar *data, int len, const QString &directory)-
793{-
794 Q_D(QTranslator);-
795 d->clear();-
796-
797 if (!data || len < MagicLength || memcmp(data, magic, MagicLength))-
798 return false;-
799-
800 return d->do_load(data, len, directory);-
801}-
802-
803static quint8 read8(const uchar *data)-
804{-
805 return qFromBigEndian<quint8>(data);-
806}-
807-
808static quint16 read16(const uchar *data)-
809{-
810 return qFromBigEndian<quint16>(data);-
811}-
812-
813static quint32 read32(const uchar *data)-
814{-
815 return qFromBigEndian<quint32>(data);-
816}-
817-
818bool QTranslatorPrivate::do_load(const uchar *data, int len, const QString &directory)-
819{-
820 bool ok = true;-
821 const uchar *end = data + len;-
822-
823 data += MagicLength;-
824-
825 QStringList dependencies;-
826 while (data < end - 4) {-
827 quint8 tag = read8(data++);-
828 quint32 blockLen = read32(data);-
829 data += 4;-
830 if (!tag || !blockLen)-
831 break;-
832 if (quint32(end - data) < blockLen) {-
833 ok = false;-
834 break;-
835 }-
836-
837 if (tag == QTranslatorPrivate::Contexts) {-
838 contextArray = data;-
839 contextLength = blockLen;-
840 } else if (tag == QTranslatorPrivate::Hashes) {-
841 offsetArray = data;-
842 offsetLength = blockLen;-
843 } else if (tag == QTranslatorPrivate::Messages) {-
844 messageArray = data;-
845 messageLength = blockLen;-
846 } else if (tag == QTranslatorPrivate::NumerusRules) {-
847 numerusRulesArray = data;-
848 numerusRulesLength = blockLen;-
849 } else if (tag == QTranslatorPrivate::Dependencies) {-
850 QDataStream stream(QByteArray::fromRawData((const char*)data, blockLen));-
851 QString dep;-
852 while (!stream.atEnd()) {-
853 stream >> dep;-
854 dependencies.append(dep);-
855 }-
856 }-
857-
858 data += blockLen;-
859 }-
860-
861 if (dependencies.isEmpty() && (!offsetArray || !messageArray))-
862 ok = false;-
863 if (ok && !isValidNumerusRules(numerusRulesArray, numerusRulesLength))-
864 ok = false;-
865 if (ok) {-
866 const int dependenciesCount = dependencies.count();-
867 subTranslators.reserve(dependenciesCount);-
868 for (int i = 0 ; i < dependenciesCount; ++i) {-
869 QTranslator *translator = new QTranslator;-
870 subTranslators.append(translator);-
871 ok = translator->load(dependencies.at(i), directory);-
872 if (!ok)-
873 break;-
874 }-
875-
876 // In case some dependencies fail to load, unload all the other ones too.-
877 if (!ok) {-
878 qDeleteAll(subTranslators);-
879 subTranslators.clear();-
880 }-
881 }-
882-
883 if (!ok) {-
884 messageArray = 0;-
885 contextArray = 0;-
886 offsetArray = 0;-
887 numerusRulesArray = 0;-
888 messageLength = 0;-
889 contextLength = 0;-
890 offsetLength = 0;-
891 numerusRulesLength = 0;-
892 }-
893-
894 return ok;-
895}-
896-
897static QString getMessage(const uchar *m, const uchar *end, const char *context,-
898 const char *sourceText, const char *comment, uint numerus)-
899{-
900 const uchar *tn = 0;-
901 uint tn_length = 0;-
902 const uint sourceTextLen = uint(strlen(sourceText));-
903 const uint contextLen = uint(strlen(context));-
904 const uint commentLen = uint(strlen(comment));-
905-
906 for (;;) {-
907 uchar tag = 0;-
908 if (m < end)-
909 tag = read8(m++);-
910 switch((Tag)tag) {-
911 case Tag_End:-
912 goto end;-
913 case Tag_Translation: {-
914 int len = read32(m);-
915 if (len % 1)-
916 return QString();-
917 m += 4;-
918 if (!numerus--) {-
919 tn_length = len;-
920 tn = m;-
921 }-
922 m += len;-
923 break;-
924 }-
925 case Tag_Obsolete1:-
926 m += 4;-
927 break;-
928 case Tag_SourceText: {-
929 quint32 len = read32(m);-
930 m += 4;-
931 if (!match(m, len, sourceText, sourceTextLen))-
932 return QString();-
933 m += len;-
934 }-
935 break;-
936 case Tag_Context: {-
937 quint32 len = read32(m);-
938 m += 4;-
939 if (!match(m, len, context, contextLen))-
940 return QString();-
941 m += len;-
942 }-
943 break;-
944 case Tag_Comment: {-
945 quint32 len = read32(m);-
946 m += 4;-
947 if (*m && !match(m, len, comment, commentLen))-
948 return QString();-
949 m += len;-
950 }-
951 break;-
952 default:-
953 return QString();-
954 }-
955 }-
956end:-
957 if (!tn)-
958 return QString();-
959 QString str = QString((const QChar *)tn, tn_length/2);-
960 if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {-
961 for (int i = 0; i < str.length(); ++i)-
962 str[i] = QChar((str.at(i).unicode() >> 8) + ((str.at(i).unicode() << 8) & 0xff00));-
963 }-
964 return str;-
965}-
966-
967QString QTranslatorPrivate::do_translate(const char *context, const char *sourceText,-
968 const char *comment, int n) const-
969{-
970 if (context == 0)
context == 0Description
TRUEnever evaluated
FALSEevaluated 260 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
0-260
971 context = "";
never executed: context = "";
0
972 if (sourceText == 0)
sourceText == 0Description
TRUEnever evaluated
FALSEevaluated 260 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
0-260
973 sourceText = "";
never executed: sourceText = "";
0
974 if (comment == 0)
comment == 0Description
TRUEevaluated 203 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEevaluated 57 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
57-203
975 comment = "";
executed 203 times by 2 tests: comment = "";
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
203
976-
977 uint numerus = 0;-
978 size_t numItems = 0;-
979-
980 if (!offsetLength)
!offsetLengthDescription
TRUEnever evaluated
FALSEevaluated 260 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
0-260
981 goto searchDependencies;
never executed: goto searchDependencies;
0
982-
983 /*-
984 Check if the context belongs to this QTranslator. If many-
985 translators are installed, this step is necessary.-
986 */-
987 if (contextLength) {
contextLengthDescription
TRUEnever evaluated
FALSEevaluated 260 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
0-260
988 quint16 hTableSize = read16(contextArray);-
989 uint g = elfHash(context) % hTableSize;-
990 const uchar *c = contextArray + 2 + (g << 1);-
991 quint16 off = read16(c);-
992 c += 2;-
993 if (off == 0)
off == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
994 return QString();
never executed: return QString();
0
995 c = contextArray + (2 + (hTableSize << 1) + (off << 1));-
996-
997 const uint contextLen = uint(strlen(context));-
998 for (;;) {-
999 quint8 len = read8(c++);-
1000 if (len == 0)
len == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1001 return QString();
never executed: return QString();
0
1002 if (match(c, len, context, contextLen))
match(c, len, ...t, contextLen)Description
TRUEnever evaluated
FALSEnever evaluated
0
1003 break;
never executed: break;
0
1004 c += len;-
1005 }
never executed: end of block
0
1006 }
never executed: end of block
0
1007-
1008 numItems = offsetLength / (2 * sizeof(quint32));-
1009 if (!numItems)
!numItemsDescription
TRUEnever evaluated
FALSEevaluated 260 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
0-260
1010 goto searchDependencies;
never executed: goto searchDependencies;
0
1011-
1012 if (n >= 0)
n >= 0Description
TRUEevaluated 9 times by 1 test
Evaluated by:
  • tst_QTranslator
FALSEevaluated 251 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
9-251
1013 numerus = numerusHelper(n, numerusRulesArray, numerusRulesLength);
executed 9 times by 1 test: numerus = numerusHelper(n, numerusRulesArray, numerusRulesLength);
Executed by:
  • tst_QTranslator
9
1014-
1015 for (;;) {-
1016 quint32 h = 0;-
1017 elfHash_continue(sourceText, h);-
1018 elfHash_continue(comment, h);-
1019 elfHash_finish(h);-
1020-
1021 const uchar *start = offsetArray;-
1022 const uchar *end = start + ((numItems-1) << 3);-
1023 while (start <= end) {
start <= endDescription
TRUEevaluated 2131 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEevaluated 139 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
139-2131
1024 const uchar *middle = start + (((end - start) >> 4) << 3);-
1025 uint hash = read32(middle);-
1026 if (h == hash) {
h == hashDescription
TRUEevaluated 173 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEevaluated 1958 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
173-1958
1027 start = middle;-
1028 break;
executed 173 times by 2 tests: break;
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
173
1029 } else if (hash < h) {
hash < hDescription
TRUEevaluated 745 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEevaluated 1213 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
745-1213
1030 start = middle + 8;-
1031 } else {
executed 745 times by 2 tests: end of block
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
745
1032 end = middle - 8;-
1033 }
executed 1213 times by 2 tests: end of block
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
1213
1034 }-
1035-
1036 if (start <= end) {
start <= endDescription
TRUEevaluated 173 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEevaluated 139 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
139-173
1037 // go back on equal key-
1038 while (start != offsetArray && read32(start) == read32(start-8))
start != offsetArrayDescription
TRUEevaluated 165 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEevaluated 8 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
read32(start) ...ead32(start-8)Description
TRUEnever evaluated
FALSEevaluated 165 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
0-165
1039 start -= 8;
never executed: start -= 8;
0
1040-
1041 while (start < offsetArray + offsetLength) {
start < offset...+ offsetLengthDescription
TRUEevaluated 202 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEnever evaluated
0-202
1042 quint32 rh = read32(start);-
1043 start += 4;-
1044 if (rh != h)
rh != hDescription
TRUEevaluated 29 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEevaluated 173 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
29-173
1045 break;
executed 29 times by 2 tests: break;
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
29
1046 quint32 ro = read32(start);-
1047 start += 4;-
1048 QString tn = getMessage(messageArray + ro, messageArray + messageLength, context,-
1049 sourceText, comment, numerus);-
1050 if (!tn.isNull())
!tn.isNull()Description
TRUEevaluated 144 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEevaluated 29 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
29-144
1051 return tn;
executed 144 times by 2 tests: return tn;
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
144
1052 }
executed 29 times by 2 tests: end of block
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
29
1053 }
executed 29 times by 2 tests: end of block
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
29
1054 if (!comment[0])
!comment[0]Description
TRUEevaluated 116 times by 2 tests
Evaluated by:
  • tst_QKeySequence
  • tst_QTranslator
FALSEevaluated 52 times by 1 test
Evaluated by:
  • tst_QKeySequence
52-116
1055 break;
executed 116 times by 2 tests: break;
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
116
1056 comment = "";-
1057 }
executed 52 times by 1 test: end of block
Executed by:
  • tst_QKeySequence
52
1058-
1059searchDependencies:
code before this statement executed 116 times by 2 tests: searchDependencies:
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
116
1060 foreachfor (QTranslator *translator ,: subTranslators) {-
1061 QString tn = translator->translate(context, sourceText, comment, n);-
1062 if (!tn.isNull())
!tn.isNull()Description
TRUEevaluated 5 times by 1 test
Evaluated by:
  • tst_QTranslator
FALSEnever evaluated
0-5
1063 return tn;
executed 5 times by 1 test: return tn;
Executed by:
  • tst_QTranslator
5
1064 }
never executed: end of block
0
1065 return QString();
executed 111 times by 2 tests: return QString();
Executed by:
  • tst_QKeySequence
  • tst_QTranslator
111
1066}-
1067-
1068/*!-
1069 Empties this translator of all contents.-
1070-
1071 This function works with stripped translator files.-
1072*/-
1073-
1074void QTranslatorPrivate::clear()-
1075{-
1076 Q_Q(QTranslator);-
1077 if (unmapPointer && unmapLength) {-
1078#if defined(QT_USE_MMAP)-
1079 if (used_mmap) {-
1080 used_mmap = false;-
1081 munmap(unmapPointer, unmapLength);-
1082 } else-
1083#endif-
1084 if (!resource)-
1085 delete [] unmapPointer;-
1086 }-
1087-
1088 delete resource;-
1089 resource = 0;-
1090 unmapPointer = 0;-
1091 unmapLength = 0;-
1092 messageArray = 0;-
1093 contextArray = 0;-
1094 offsetArray = 0;-
1095 numerusRulesArray = 0;-
1096 messageLength = 0;-
1097 contextLength = 0;-
1098 offsetLength = 0;-
1099 numerusRulesLength = 0;-
1100-
1101 qDeleteAll(subTranslators);-
1102 subTranslators.clear();-
1103-
1104 if (QCoreApplicationPrivate::isTranslatorInstalled(q))-
1105 QCoreApplication::postEvent(QCoreApplication::instance(),-
1106 new QEvent(QEvent::LanguageChange));-
1107}-
1108-
1109/*!-
1110 Returns the translation for the key (\a context, \a sourceText,-
1111 \a disambiguation). If none is found, also tries (\a context, \a-
1112 sourceText, ""). If that still fails, returns a null string.-
1113-
1114 \note Incomplete translations may result in unexpected behavior:-
1115 If no translation for (\a context, \a sourceText, "")-
1116 is provided, the method might in this case actually return a-
1117 translation for a different \a disambiguation.-
1118-
1119 If \a n is not -1, it is used to choose an appropriate form for-
1120 the translation (e.g. "%n file found" vs. "%n files found").-
1121-
1122 If you need to programatically insert translations into a-
1123 QTranslator, this function can be reimplemented.-
1124-
1125 \sa load()-
1126*/-
1127QString QTranslator::translate(const char *context, const char *sourceText, const char *disambiguation,-
1128 int n) const-
1129{-
1130 Q_D(const QTranslator);-
1131 return d->do_translate(context, sourceText, disambiguation, n);-
1132}-
1133-
1134/*!-
1135 Returns \c true if this translator is empty, otherwise returns \c false.-
1136 This function works with stripped and unstripped translation files.-
1137*/-
1138bool QTranslator::isEmpty() const-
1139{-
1140 Q_D(const QTranslator);-
1141 return !d->unmapPointer && !d->unmapLength && !d->messageArray &&-
1142 !d->offsetArray && !d->contextArray && d->subTranslators.isEmpty();-
1143}-
1144-
1145QT_END_NAMESPACE-
1146-
1147#endif // QT_NO_TRANSLATION-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9