| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The current synchronization mechanism was racy: decrementing waitingThreads
and then hoping that the wakeOne will wake a thread before its expiry
timeout happens. In other words, on timeout, a just-assigned task would
never run. And then no other task would run, if maxThreadCount is reached.
Fixed by using a queue of waiting threads (rather than just a count), and by
moving the wait condition into the thread itself, so we know precisely
which one we're waking up, and we can remove it from the set of waiting threads
before waking it up, and therefore it can determine on wakeup whether it
has work to do (caller removed it from the queue) or it expired (it's still
in the queue). This is reliable, whereas the return value from QWaitCondition::wait
isn't reliable, when the main thread has already decided that this thread
has work to do.
Task-number: QTBUG-3786
Change-Id: I1eac5d6c309daed7f483ac7a8074297bfda6ee32
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
|
|
|
|
| |
Change-Id: Ib88db7516fd7dd8f10a86444c506f3294948e79b
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I don't think I ever worked on a project of non-trivial
size that didn't at some point add a QSignalBlocker.
This commit adds code, tests and documentation. Later
commits will convert naked blockSignals() calls to use
QSignalBlocker.
The implementation is purely inline to avoid the heavy
overhead of cross-dll function calls for this miniscule
task. This should not be a problem because QSignalBlocker
only uses public API and a pattern that we anyway need
to keep working until Qt 6, at least, so even changing
the implementation later will be no problem as the old
implementation lurking in non-recompiled code will be
acceptable, too.
This implementation is an evolution from KDTools'
KDSignalBlocker, with the following changes:
- Implements unblock() and reblock()
- Uses the return value of blockSignals() instead of a
separate signalsBlocked() call.
Change-Id: I1933dfd72a0f5190324be377cfca3c54cf3d6828
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
|
|
|
|
|
|
|
|
|
|
| |
Specifically, note what paths can be empty and which ones can't (modulo
system mis-configuration, like an empty $HOME var) and describe what
implications there are for application-specific paths and for global
(user) paths.
Change-Id: If6c11aab466ba50f3a9685dce52dd51b86426f27
Reviewed-by: David Faure <david.faure@kdab.com>
|
|\
| |
| |
| | |
Change-Id: Ie56539b2e0be611a363b5f15ae5412a78d6945a2
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Currently Qt offers only debug, warning, critical message types for
general use. Most logging frameworks offer more ... let's save
some space for future message types.
Change-Id: Icb4333da5c8f5277fd10d8a01b06d95369662bdc
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
In QEventDispatcherBlackberry::select(), if an event handler called
through filterEvent() starts a nested event loop by creating a new
QEventLoop, we will recursively enter the select() method again.
However, each time bps_get_event() is called, it destroys the last
event it handed out before returning the next event. We don't want it
to destroy the event that triggered the nested event loop, since there
may still be more handlers that need to get that event, once the
nested event loop is done and control returns to the outer event loop.
So we move an event to a holding channel, which takes ownership of the
event. Putting the event on our own channel allows us to manage when
it is destroyed, keeping it alive until we know we are done with it.
Each recursive call of this function needs to have it's own holding
channel, since a channel is a queue, not a stack.
However, a recursive call into the select() method happens very rarely
compared to the many times this method is called. We don't want to
create a holding channel for each time this method is called, only
when it is called recursively. Thus we have the instance variable
d->holding_channel to use in the common case. We keep track of
recursive calls with d->loop_level. If we are in a recursive call,
then we create a new holding channel for this run.
Change-Id: Ib3584676d2db5a9a3754a1535d5fb6c9e14f5dbb
Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Added/Changed:
- Move content from the Thread Basics overview to the QThread class ref
- Rephrase bits for clarity
- Use more links
Removed:
- (threads-basics.qdoc) Warning against moveToThread(this): This usage
came about when people tried to add slots to a QThread subclass. This
patch adds a warning against the root cause.
- (threads-basics.qdoc) Note on sleep() et al.: They were made public in
Qt 5.0.
- (threads-basics.qdoc) The strategy for managing member variables:
Sounds error-prone. Pushing results through signals is safer.
- (qthread.cpp) The note about GUI classes: Irrelevant to QThread,
and it's already mentioned elsewhere.
Change-Id: I6bc53cc22b929523f9976d2b920f94c02bd7273e
Reviewed-by: Geir Vattekar <geir.vattekar@digia.com>
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
|
| |
| |
| |
| |
| |
| |
| |
| | |
The complaining compiler is:
gcc version 4.6.3 (crosstool-NG hg+default-ddc327ebaef2)
Change-Id: Iae488a89d75492e76a39a326b2db36548f8894d0
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
This potentially resolves the long-standing warning from GCC:
assuming signed overflow does not occur when assuming that (X + c) < X
is always false
GCC prints the warning to warn people that you can't check for overflow
with signed integers by doing that (signed integers don't overflow in
the standard).
If we change this to X < X - c, there's no overflow.
Task-number: QTBUG-33314
Change-Id: I5b166610a39559ec7b03c4c31ee5999efefa0c06
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
|
| |
| |
| |
| |
| |
| | |
Change-Id: I331966f6137a31f089425a639afe8f9f4088c0b6
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
Reviewed-by: hjk <hjk121@nokiamail.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The RFC 2822 date format should always use en_US locale for month and
day names instead of whatever the system locale is. Also remove some
duplicate code.
Change-Id: Ia2f7ee405b4e0e2f04980301783b9488628da73f
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| | |
Change-Id: I11e136eaede2a5dffeb10b5fe31023b9aef709cb
Reviewed-by: Sze Howe Koh <szehowe.koh@gmail.com>
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Add QWindowSystemInterface::GestureEvent and
QNativeGestureEvent to QtGui. These events are copies
of Qt4's QNativeGestureEvent, where it was an implementation
detail of QGestureManager.
Add gesture message handlers to QNSView and bring
back the Mac gesture recognizers for QGestureManager.
Task-number: QTBUG-28126
Change-Id: I1304e09e776fa7c44d133d54ca8b895ca2f544c5
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Custom allocators invoked by freeing the QString contents might change
it.
Task-number: QTBUG-34046
Task-number: QTBUG-32314
Change-Id: Ied5305c21fcce228448fe565899163997536ea7a
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
From the documentation of setScheme it was not clear if the scheme should
be terminated by a ':' or not. Documentation has been updated to clarify
the expected syntax for the scheme.
Change-Id: Ied8533beef7daa12e1d5e7da0649c184efb84522
Reviewed-by: David Faure <david.faure@kdab.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Changed the processing of non-character code handling in the UTF8 codec.
Non-character codes are now accepted in QStrings, QUrls and QJson strings.
Unit tests were adapted accordingly.
For more info about non-character codes,
see: http://www.unicode.org/versions/corrigendum9.html
[ChangeLog][QtCore][QUtf8]
UTF-8 now accepts non-character unicode points; these are not replaced
by the replacement character anymore
[ChangeLog][QtCore][QUrl]
QUrl now fully accepts non-character unicode points; they are encoded as
percent characters; they can also be pretty decoded
[ChangeLog][QtCore][QJson]
The Writer and the Parser now fully accept non-character unicode points.
Change-Id: I77cf4f0e6210741eac8082912a0b6118eced4f77
Task-number: QTBUG-33229
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Add qjson* implementation files from corelib/json
to the qmake build. Add a read-only compile mode,
enabled by defining QT_JSON_READONLY.
Add qmake built-in function parseJson(file, into)
which parses a json file into the given variable.
qmake uses a flat key -> value-list implementation
for storing variables, which means that some hackery
is need to represent arbitrarily nested JSON. Use a
special "_KEYS_" variable for arrays and objects:
Arrays:
["item1", "item2"]
$${array._KEYS_} -> 0 1 2
$${array.0} -> "item1"
$${array.1} -> "item2"
Objects:
{ "key1" : "value1", "key2" : "value2" }
$${object._KEYS_} -> key1 key2
$${object.key1} -> value1
$${object.key2} -> value2
Change-Id: I0aa2e4e4ae14fa25be8242bc16d3cffce32504d2
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
|
| |
| |
| |
| |
| |
| |
| | |
Fix some typos in the comments.
Change-Id: I14eed0ffed74f0a60b05441430158f71cb530c01
Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Android does not provide rand_r(), so we would fall back to rand()
and srand() which means we where not keeping the promise of qrand
and qsrand being thread-safe. As a replacement we can use the Java
api and have one Random object for each thread.
Task-number: QTBUG-32814
Change-Id: Id46d195a0bb122bc7a5a8de43bdf088e11a9c42e
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Check if the datetime is valid before converting it to a different time
spec. If it is invalid then just change the spec to keep behavior
consistent with 5.1.
Task-number: QTBUG-34020
Change-Id: I6630ec1d50f810a2178ab3222bd32af018085f81
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Those are not related to C++11, so move them to the Clang detection
block.
Change-Id: I80b298e1df5f74a865d743625895e0f01cb5fd6b
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>
Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Change the default output of the logging framework to prefix messages
with a 'category: ' in case the category is not "default", so that e.g.
QLoggingCategory cat("qt.core.codes.windows");
qCWarning(cat) << "MultiByteToWideChar: Cannot convert multibyte text";
will print
qt.core.codes.windows: MultiByteToWideChar: Cannot convert multibyte text
while output from qWarning etc will show unaltered output. This should
help users to discover categories, and to group output together.
Change-Id: Iac2e1514f7dc5671966c36a440a119c857564cfc
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: hjk <hjk121@nokiamail.com>
|
| |
| |
| |
| |
| |
| | |
Change-Id: I178bb6e75fba246932b318c2c0c5afd243575a92
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
Reviewed-by: hjk <hjk121@nokiamail.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Additions/Changes:
- Add QML's WorkerScript type
- Add QFuture + QFutureWatcher
- Clarify differences between QtConcurrent::run() and the map/filter/
reduce functions
- Reword table headings
- QThreadPool accepts a priority parameter too (although it's not OS-
level, unlike QThread)
Rows removed from the table:
- QThread can be "reused" and "task oriented" too, depending on the
program design. It's hard to convey this in a table though, so I just
removed it.
- "High level" is ambiguous and doesn't really help readers choose a
tool to use.
Task-number: QTBUG-33360
Change-Id: Idc5100eaf09033998c155572d44c6c0ad0ba9ef6
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Although the C++ language builds in the 'wchar_t' datatype, the
library functions such as wcscmp() which manipulate them are not
automatically available. For these, inclusion of the <cwhar> header
is still required.
This changeset fixes build breakage observed from failure to include
the requisite system header for accessing wcscmp() and other related
functions on non-GNU standard C++ library implementations.
Change-Id: I5b2f9148ea011004e5dd00cf41698339db172de8
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Those features have slightly different behavior as the C++11 keywords
that MSVC 2012 officially supports. When compiling in C++/CLI mode,
the "virtual" keyword must be present too.
We have not actually tested whether the official MSVC 2012 support for
C++/CLI still requires the virtual keyword. This is just going on the
assumption that C++/CLI follows the C++11 spec.
Task-number: QTBUG-34019
Change-Id: I148a443bfbff985033c555f5a9cfcd5be7f5f106
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
QStringBuilder will precalculate the size of the string for us, which
avoids extra realloc() and moving data around.
Change-Id: I4e31964bb9bfffbe2083b3cb8c120e602160dfd8
Reviewed-by: David Faure <david.faure@kdab.com>
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>
Reviewed-by: Kevin Ottens <kevin.ottens@kdab.com>
|
| |
| |
| |
| |
| |
| |
| | |
Extract the correct length sub-string from the /etc/sysconfig/clock file
Change-Id: I37b4f625a51b172ed11ecefbd1b7dc562c5bb89d
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
-many articles link to the page using the "and" or the "&"
version, causing missing links.
Change-Id: I6447149befce169cfafff29164172290a7c15f0c
Reviewed-by: Sze Howe Koh <szehowe.koh@gmail.com>
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@digia.com>
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
|
| |
| |
| |
| |
| |
| |
| | |
Task-number: QTBUG-34079
Change-Id: If61cc01ba70345b01f13072769d3a38f23e8cefc
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| | |
Change-Id: Ib6ad515ce4ba27d501538ba45fd65e60ce5332df
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
Reviewed-by: hjk <hjk121@nokiamail.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The compiler inserts __cxa_guard_acquire, __cxa_guard_release calls around
the initialization of local static objects to make the initialization
thread safe. However, the implementation of _cxa_guard_acquire in Apple's
libc++abi uses a global lock, which means that only one thread can
initialize a local static variable at a time. This can be a problem if
e.g. the constructor of the variable is blocking while waiting for another
thread ...
This behavior has caused issues so far in webkit and the qml debugging
infrastructure. Better avoid it by using our custom lock implementation.
__cxa_guard_acquire implementation:
http://www.opensource.apple.com/source/libcppabi/libcppabi-24.2/src/cxa_guard.cxx
Task-number: QTBUG-33967
Change-Id: I0d50531ed91ddd074aa07f61f6bf7791e23d990b
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| | |
The iOS bundles are "flat", do not insert "/Contents/"
like we do on OS X.
Change-Id: I4e848f4425482b92cac04d940e5bce06b7199fc6
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@digia.com>
|
| |
| |
| |
| |
| |
| |
| | |
Updates keycode mappings for evdev, directfb and android.
Change-Id: I6789f13dbb662da4261a3c947757644e12306dd9
Reviewed-by: BogDan Vatra <bogdan@kde.org>
|
| |
| |
| |
| |
| |
| | |
Change-Id: I8a361ef09c338bbba228fd774b2bfd938869adc5
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| | |
Task-number: QTBUG-27061
Change-Id: I66e000a9f59fda3654066013e6e78c3ba6fd27fe
Reviewed-by: Mitch Curtis <mitch.curtis@digia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Though some of it was mensioned in the introduction to the class,
we are not in O(1) if we modify a shared container.
Change-Id: If63b4cb4bdfc98d6b1333bae307e5650341e5484
Reviewed-by: Sze Howe Koh <szehowe.koh@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
When the QPolygonF type was added to QMetaType it did not bump up the
values in load() and save() for QVariant.
Task-number: QTBUG-33981
Change-Id: I7ad99cda70620c5449c15527c3daf920972d047f
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>
Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com>
|
| |
| |
| |
| |
| |
| |
| |
| | |
Change-Id: Ifda057d122a30d88749c6401185457f1900a913b
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
Reviewed-by: Richard J. Moore <rich@kde.org>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Use the the legacy file engine object created in static function
QFileInfo::exists() as the engine of the QFileInfo object to prevent
memory leak. This can also boost a little performance.
Change-Id: I06317d158d487be5ef15fe3244a917a371563ac9
Reviewed-by: hjk <hjk121@nokiamail.com>
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
|
| |
| |
| |
| |
| |
| |
| |
| | |
That enum got introduced in b6e9a8f21ac8b4cc3cc56232ce346ebd7ba17a70
Change-Id: I2d69179624cecff63549bfee66bc68bb4b27af8c
Reviewed-by: Topi Reiniö <topi.reinio@digia.com>
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
|
| |
| |
| |
| |
| | |
Change-Id: I40e4780bcabbca29425945a69d8a0781cd5c0e9f
Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
|
| |
| |
| |
| |
| |
| |
| |
| | |
The pointer can be null. Going trough the reference invokes undefined
behavior here.
Change-Id: Ia84e4e732cdcbbaee0f5f0679765d18069ea8b2d
Reviewed-by: Kai Koehne <kai.koehne@digia.com>
|
| |
| |
| |
| |
| | |
Change-Id: I761ef508672d5d4e8b9067a1b5f91debe09607d4
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@digia.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Trying to do as few operations as possible once the file got opened.
That includes generating the data which will go in the file. Indeed if
we crashed at that point the lock file is already emptied. Could happen
because of the qAppName call. It's then safer to prepare the data
upfront, and just open/write/close if possible.
Change-Id: Iad32fa822c6a5958ae89d84a2fe02ed5366ea278
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@digia.com>
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@digia.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Eases migration from QList to QVector.
Had to rename the 'length' parameter to mid() to suppress
-Wshadow warnings.
Task-number: QTBUG-3781
Change-Id: I755c6caefe4de81ea42a81b1c76aab728e639613
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
|
| |
| |
| |
| |
| |
| |
| |
| | |
Made all of the deprecated functions in QtAlgorithms now use
QT_DEPRECATED_X with helpful deprecation messages.
Change-Id: I3358e44b8c1f15eeb4689ab02b1802a07d04fc09
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
|
| |
| |
| |
| |
| |
| |
| | |
Defined the Q_DEPRECATED_X to use the Q_DECL_DEPRECATED_X macro.
Change-Id: I334328059c6a1e046f57470027b0d1086a35042c
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Apparently the __attribute__((__deprecated__(text))) feature for gcc was
introduced in version 4.5. Since Qt's minimum supported version of gcc
is 4.4, the declaration of the macro needed to check the compiler's
version number.
Since clang reports its __GNUC__ and __GNUC_MINOR__ as gcc 4.2, the
check for the compiler support had to be added in with
__has_feature(attribute_deprecated_with_message).
For icc, a check was added to see if __INTEL_COMPILER >= 1300, __GNUC__
is defined and Q_DECL_DEPRECATED_X was not defined. If this is true,
the gcc syntax is used in the define.
Change-Id: I23980ac28b79264e8fd657cd3bfd2af7674779a1
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
|